Skip to content
This repository has been archived by the owner on Nov 18, 2020. It is now read-only.

Commit

Permalink
Adding in the zotero controller so that I can pass the user id instea…
Browse files Browse the repository at this point in the history
…d of the user object
  • Loading branch information
carolyncole committed Apr 20, 2017
1 parent 967bdbd commit 859b170
Show file tree
Hide file tree
Showing 2 changed files with 234 additions and 0 deletions.
75 changes: 75 additions & 0 deletions app/controllers/api/zotero_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true
# This entire file is being overriden for the change mentioned in the TODO below
require 'oauth'

module API
# Adds the ability to authenticate against Zotero's OAuth endpoint
class ZoteroController < ApplicationController
before_action :authenticate_user!
before_action :authorize_user!
before_action :validate_params, only: :callback

def initiate
request_token = client.get_request_token(oauth_callback: callback_url)
session[:request_token] = request_token
current_user.zotero_token = request_token
current_user.save
redirect_to request_token.authorize_url(identity: '1', oauth_callback: callback_url)
rescue OAuth::Unauthorized
redirect_to root_url, alert: 'Invalid Zotero client key pair'
end

def callback
access_token = current_token.get_access_token(oauth_verifier: params['oauth_verifier'])
# parse userID and API key out of token and store in user instance
current_user.zotero_userid = access_token.params[:userID]
current_user.save

# TODO: we are overriding this entire file to a .user_key on to the end of current_user
# This file should be removed once sufia or hyrax have this update and we are on that version
Sufia::Arkivo::CreateSubscriptionJob.perform_later(current_user.user_key)
redirect_to sufia.profile_path(current_user), notice: 'Successfully connected to Zotero!'
rescue OAuth::Unauthorized
redirect_to sufia.edit_profile_path(current_user.to_param), alert: 'Please re-authenticate with Zotero'
ensure
current_user.zotero_token = nil
current_user.save
end

private

def authorize_user!
authorize! :create, Sufia.primary_work_type
rescue CanCan::AccessDenied
return redirect_to root_url, alert: 'You are not authorized to perform this operation'
end

def validate_params
return redirect_to sufia.edit_profile_path(current_user.to_param), alert: "Malformed request from Zotero" if params[:oauth_token].blank? || params[:oauth_verifier].blank?
return redirect_to sufia.edit_profile_path(current_user.to_param), alert: "You have not yet connected to Zotero" if !current_token || current_token.params[:oauth_token] != params[:oauth_token]
end

def client
::OAuth::Consumer.new(Sufia::Zotero.config['client_key'], Sufia::Zotero.config['client_secret'], options)
end

def current_token
current_user.zotero_token
end

def callback_url
"#{request.base_url}/api/zotero/callback"
end

def options
{
site: 'https://www.zotero.org',
scheme: :query_string,
http_method: :get,
request_token_path: '/oauth/request',
access_token_path: '/oauth/access',
authorize_path: '/oauth/authorize'
}
end
end
end
159 changes: 159 additions & 0 deletions spec/controllers/zotero_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# frozen_string_literal: true
require 'rails_helper'

describe API::ZoteroController, type: :controller do
let(:user) { create(:user) }
routes { Sufia::Engine.routes }

subject { response }

context 'with an HTTP GET to /api/zotero' do
context 'with an unauthenticated client' do
before { get :initiate }

specify do
expect(subject).to have_http_status(302)
expect(subject).to redirect_to("https://webaccess.psu.edu/?cosign-localhost&https://localhost")
end
end

context 'with an unregistered user' do
before do
allow_any_instance_of(Ability).to receive(:can?).with(:create, GenericWork).and_return(false)
sign_in user
get :initiate
end

specify do
expect(subject).to have_http_status(302)
expect(subject).to redirect_to(root_path)
expect(flash[:alert]).to eq 'You are not authorized to perform this operation'
end
end

context 'with an invalid key/secret combo' do
before do
allow(Sufia::Zotero).to receive(:config) { broken_config }
sign_in user
get :initiate
end

let(:broken_config) { Hash.new(client_key: 'foo', client_secret: 'bar') }

specify do
expect(subject).to have_http_status(302)
expect(subject).to redirect_to(root_path)
expect(flash[:alert]).to eq 'Invalid Zotero client key pair'
end
end

describe 'redirects to Zotero' do
before do
allow(controller).to receive(:client) { client }
allow(client).to receive(:get_request_token) { token }
allow_any_instance_of(User).to receive(:zotero_token=)
sign_in user
get :initiate
end

let(:token) { object_double(OAuth::RequestToken.new(client), authorize_url: 'https://www.zotero.org/oauth/authorize?identity=1&oauth_callback=http%3A%2F%2Ftest.host%2Fapi%2Fzotero%2Fcallback&oauth_token=bc2502f2750983c57224') }
let(:client) do
OAuth::Consumer.new(Sufia::Zotero.config['client_key'],
Sufia::Zotero.config['client_secret'],
site: 'https://www.zotero.org',
scheme: :query_string,
http_method: :get,
request_token_path: '/oauth/request',
access_token_path: '/oauth/access',
authorize_path: '/oauth/authorize')
end

specify do
expect(subject).to have_http_status(302)
expect(flash[:alert]).to be_nil
expect(subject.headers['Location']).to include('oauth_callback=http%3A%2F%2Ftest.host%2Fapi%2Fzotero%2Fcallback')
end
end
end

context 'with an HTTP POST/GET to /api/zotero/callback' do
context 'with an unauthenticated user' do
before { get :callback }

specify do
expect(subject).to have_http_status(302)
expect(subject).to redirect_to("https://webaccess.psu.edu/?cosign-localhost&https://localhost")
end
end

context 'with a user who is not permitted to make works' do
before do
allow_any_instance_of(Ability).to receive(:can?).with(:create, GenericWork).and_return(false)
sign_in user
get :callback
end

specify do
expect(subject).to have_http_status(302)
expect(subject).to redirect_to(root_path)
expect(flash[:alert]).to eq 'You are not authorized to perform this operation'
end
end

context 'with a request lacking an oauth_token' do
before do
sign_in user
get :callback
end

specify do
expect(subject).to have_http_status(302)
expect(subject).to redirect_to(routes.url_helpers.edit_profile_path(user))
expect(flash[:alert]).to eq 'Malformed request from Zotero'
end
end

context 'with a non-matching token' do
before do
sign_in user
get :callback, params: { oauth_token: 'woohoo', oauth_verifier: '12345' }
end

specify do
expect(subject).to have_http_status(302)
expect(subject).to redirect_to(routes.url_helpers.edit_profile_path(user))
expect(flash[:alert]).to eq 'You have not yet connected to Zotero'
end
end

context 'with a signed-in, valid user' do
before do
allow_any_instance_of(User).to receive(:zotero_token) { user_token }
allow(Sufia::Arkivo::CreateSubscriptionJob).to receive(:perform_later)
sign_in user
get :callback, params: { oauth_token: token_string, oauth_verifier: pin }
end

let(:token_string) { 'woohoo' }
let(:pin) { '12345' }
let(:user_token) do
double('token',
params: { oauth_token: token_string },
get_access_token: access_token)
end
let(:zuserid) { 'myzuser' }
let(:access_token) do
double('access', params: { userID: zuserid })
end

specify do
expect(subject).to have_http_status(302)
expect(Sufia::Arkivo::CreateSubscriptionJob).to have_received(:perform_later).with(user.user_key)
expect(subject).to redirect_to(routes.url_helpers.profile_path(user))
expect(flash[:alert]).to be_nil
expect(flash[:notice]).to eq 'Successfully connected to Zotero!'
expect(user.reload.zotero_userid).to eq zuserid
end
end
end
end

0 comments on commit 859b170

Please sign in to comment.