Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allows SymphonyClient to operate without the guests UserID and PIN #362

Merged
merged 14 commits into from
May 19, 2021
3 changes: 2 additions & 1 deletion .rubocop_todo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
# Offense count: 2
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 258
# TODO change only for SymphonyClient, or refactor SymphonyClient
Max: 280
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can add an exclude for SymphonyClient to https://github.com/psu-libraries/myaccount/blob/main/.rubocop.yml


# Offense count: 25
RSpec/NestedGroups:
Expand Down
5 changes: 4 additions & 1 deletion app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ def patron
MAX_INACTIVE_TIME = 2.hours - 5.minutes

def authenticate_webaccess
redirect_to Settings.symws.webaccess_url + request.base_url
# if we aren't given a REMOTE_USER variable we are unauthorized.
# this maybe should be a 401, however if apache is misconfigured
# there's no amount of retrying that will fix this for the guest
redirect_to '/500' unless request.env.fetch(Settings.remote_user_header, nil)
end

def symphony_client
Expand Down
5 changes: 4 additions & 1 deletion app/controllers/errors_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# frozen_string_literal: true

class ErrorsController < ApplicationController
before_action :authenticate_user!
# for users that are not able to auth, this before action was causing some heartache.
# perhaps there's a better way to do it. but for errors, i don't think it's unresonable to be
# unauthenticated
# before_action :authenticate_user!

def not_found
respond_to do |format|
Expand Down
6 changes: 4 additions & 2 deletions app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ def index
return redirect_to original_fullpath if original_fullpath.present?

redirect_to summaries_url
else
# if the symphony client returns no user we might want to redirect to a page that
# says that they don't have a record?
redirect_to '/500'
Copy link
Contributor

@banukutlu banukutlu May 13, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, we can redirect to a custom error page for this case as you mentioned @whereismyjetpack, we can add that in a later PR 👍 I will add an issue for that. I think it is good for now, we all would love to see this PR deployed.

end
end

Expand All @@ -25,7 +29,5 @@ def index
# GET /logout
def destroy
request.env['warden'].logout

redirect_to root_url
end
end
28 changes: 25 additions & 3 deletions app/services/symphony_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ class SymphonyClient
MAX_WAIT_TIME = 30
SAFE_PATRON_ADDRESS_FIELDS = [:email, :street1, :street2, :zip].freeze

def login(user_id, password)
response = request('/user/patron/login', method: :post, json: {
def login(user_id, password, remote_user = nil)
response = request('/user/staff/login', method: :post, json: {
login: user_id,
password: password
})
JSON.parse(response.body)
resp = JSON.parse(response.body)
session_token = resp['sessionToken']
get_patron_record(remote_user, session_token)
end

# This method is for validating user session_token
Expand Down Expand Up @@ -194,6 +196,26 @@ def get_all_locations

private

def get_patron_record(remote_user, session_token)
user = Hash.new

response = authenticated_request('/user/patron/search',
headers: { 'x-sirs-sessionToken': session_token },
params: {
q: "ALT_ID:#{remote_user.upcase}",
includeFields: '*'
})
return nil unless response.status == 200

parsed_response = JSON.parse(response.body)['result'].first
return nil unless parsed_response

user['patronKey'] = parsed_response['key']
user['fields'] = parsed_response['fields']
user['sessionToken'] = session_token
user
end

def patron_address(params)
params.permit(SAFE_PATRON_ADDRESS_FIELDS)
.to_h
Expand Down
4 changes: 4 additions & 0 deletions app/views/sessions/destroy.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

<h1>Logout</h1>

<p>thanks for stopping by</p>
21 changes: 16 additions & 5 deletions config/initializers/warden.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,27 @@

Warden::Strategies.add(:library_id) do
def valid?
params['user_id'].present? && params['password'].present?
remote_user
end

def remote_user
user = request.env.fetch(Settings.remote_user_header, false)
user = user.split('@')[0] if user

if request.params['masquerade'] && Settings.admin_users.include?(user)
user = request.params['masquerade']
end

user
end

def authenticate!
response = SymphonyClient.new.login(params['user_id'], params['password'])
response = SymphonyClient.new.login(Settings.symws.username, Settings.symws.pin, remote_user) || {}

if response['patronKey']
if response.fetch('patronKey', nil)
user = {
username: params['user_id'],
name: response['name'],
username: remote_user,
name: response['fields']['displayName'],
patron_key: response['patronKey'],
session_token: response['sessionToken']
}
Expand Down
17 changes: 13 additions & 4 deletions config/settings.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
maintenance_mode: false
show_announcement: false
remote_user_header: <%= ENV.fetch("REMOTE_USER_HEADER") { "HTTP_REMOTE_USER"} %>
# list of users that can masquerade as other users
admin_users: []
announcement:
icon:
message:
html_class:
symws:
webaccess_url:
url:
headers: {}
url: <%= ENV.fetch("SYMWS_URL") { nil } %>
username: <%= ENV.fetch("SYMWS_USERNAME") { nil } %>
pin: "<%= ENV.fetch("SYMWS_PIN") { nil } %>"
headers:
sd_originating_app_id: cs
x_sirs_clientID: PSUCATALOG
content_type: 'application/json'
accept: 'application/json'
redis:
sidekiq:
uri: redis://127.0.0.1:6379/1
uri: <%= ENV.fetch("REDIS_SIDEKIQ_URI") { "redis://127.0.0.1:6379/1" } %>
database:
uri: redis://127.0.0.1:6379/2
uri: <%= ENV.fetch("REDIS_DATABASE_URI") { "redis://127.0.0.1:6379/2" } %>
matomo_id: 11
pickup_locations:
UP-PAT: 'Pattee Commons Services Desk'
Expand Down
3 changes: 2 additions & 1 deletion config/settings/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ symws:
login_params:
login: 'fake_user'
password: 'some_password'
patron_key: 'some_patron_key'
patron_key: 'some_patron_key'
remote_user: 'remote_user'
2 changes: 1 addition & 1 deletion spec/controllers/sessions_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
end

it 'redirects to the root' do
expect(get(:destroy)).to redirect_to root_url
expect(get(:destroy)).to render_template 'destroy'
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/requests/errors_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
it 'goes to the application root' do
get '/bad_route'

expect(response).to redirect_to root_url
expect(response).to have_http_status(:not_found)
end
end

Expand Down
12 changes: 9 additions & 3 deletions spec/services/symphony_client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,20 @@

describe '#login' do
before do
stub_request(:post, "#{Settings.symws.url}/user/patron/login")
stub_request(:post, "#{Settings.symws.url}/user/staff/login")
.with(body: Settings.symws.login_params.to_h,
headers: Settings.symws.headers)
.to_return(body: { patronKey: Settings.symws.patron_key }.to_json)
.to_return(body: { sessionToken: user.session_token }.to_json)

stub_request(:get, "#{Settings.symws.url}/user/patron/search")
.with(headers: Settings.symws.headers.to_h.merge('X-Sirs-Sessiontoken': 'e0b5e1a3e86a399112b9eb893daeacfd'),
query: hash_including(includeFields: '*'))
.to_return(status: 200,
body: { result: [{ key: Settings.symws.patron_key, fields: '' }] }.to_json)
end

it 'logs the user in to symphony' do
expect(client.login('fake_user', 'some_password')).to include 'patronKey' => 'some_patron_key'
expect(client.login('fake_user', 'some_password', 'remote_user')).to include 'patronKey' => 'some_patron_key'
end
end

Expand Down