This repository has been archived by the owner on Nov 18, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding in the zotero controller so that I can pass the user id instea…
…d of the user object
- Loading branch information
1 parent
967bdbd
commit e8d6bc9
Showing
2 changed files
with
233 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, { 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, { 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 |