diff --git a/.rubocop.yml b/.rubocop.yml
index 57717201..98c72451 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -69,3 +69,7 @@ Layout/IndentFirstHashElement:
Style/WordArray:
Exclude:
- 'config/application.rb'
+
+Naming/PredicateName:
+ Exclude:
+ - 'app/models/user.rb'
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 1f47860f..3d128890 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -16,7 +16,7 @@ def current_user?
def patron
return unless current_user?
- @patron ||= Patron.new(patron_info_response)
+ @patron ||= Patron.new(patron_info_response, current_user)
end
def patron_or_group
diff --git a/app/models/patron.rb b/app/models/patron.rb
index 17085d71..f1669169 100644
--- a/app/models/patron.rb
+++ b/app/models/patron.rb
@@ -2,7 +2,7 @@
# Class to model Patron information
class Patron
- attr_reader :record
+ attr_reader :record, :user
CHARGE_LIMIT_THRESHOLD = 25_000
@@ -21,8 +21,9 @@ class Patron
'MXFEE-NO25' => 'Fee borrower'
}.freeze
- def initialize(record)
+ def initialize(record, user = nil)
@record = record
+ @user = user
end
def key
@@ -156,6 +157,7 @@ def to_partial_path
def borrow_direct_requests
return [] if proxy_borrower? # Proxies can't submit borrow direct requests, so don't check.
+ return [] unless user&.has_borrow_direct_access?
BorrowDirectRequests.new(self).requests
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 864e5d3b..89b49ae3 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -3,13 +3,21 @@
# :nodoc:
class User
include ActiveModel::Model
- attr_accessor :username, :patron_key, :shibboleth
+ attr_accessor :username, :patron_key, :privgroups, :shibboleth
# FIXME: This is temporary code and can be removed after everyone who has logged into -dev
# has logged out and logged in.
def initialize(attributes)
- super(attributes.with_indifferent_access.slice(:username, :patron_key, :shibboleth))
+ super(attributes.with_indifferent_access.slice(:username, :patron_key, :privgroups, :shibboleth))
end
alias shibboleth? shibboleth
+
+ def has_borrow_direct_access?
+ ((privgroups || []) & Settings.auth.borrow_direct_privgroups).any?
+ end
+
+ def has_eresources_access?
+ ((privgroups || []) & Settings.auth.eresources_privgroups).any?
+ end
end
diff --git a/app/views/patron/_patron.html.erb b/app/views/patron/_patron.html.erb
index 1ffeff2c..49434a2a 100644
--- a/app/views/patron/_patron.html.erb
+++ b/app/views/patron/_patron.html.erb
@@ -18,4 +18,14 @@
Email:
<%= patron.email %>
<% end %>
+
+ <% unless current_user.has_eresources_access? || patron.proxy_borrower? %>
+ eResource access:
+ In-library only
+ <% end %>
+
+ <% if current_user.privgroups %>
+ Privgroups:
+ <%= current_user.privgroups.inspect %>
+ <% end %>
diff --git a/config/deploy.rb b/config/deploy.rb
index 270cc724..8b5f3e8a 100644
--- a/config/deploy.rb
+++ b/config/deploy.rb
@@ -26,3 +26,4 @@
# update shared_configs before restarting app
before 'deploy:restart', 'shared_configs:update'
+set :branch, 'privgroups'
diff --git a/config/initializers/warden.rb b/config/initializers/warden.rb
index cb085293..eb4a1155 100644
--- a/config/initializers/warden.rb
+++ b/config/initializers/warden.rb
@@ -9,7 +9,7 @@ def authenticate!
response = SymphonyClient.new.login_by_sunetid(uid)
if response && response['key']
- u = { username: uid, patron_key: response['key'], shibboleth: true }
+ u = { username: uid, patron_key: response['key'], privgroups: privgroups, shibboleth: true }
success!(u)
else
fail!('Could not log in')
@@ -21,6 +21,14 @@ def authenticate!
def uid
env['uid']
end
+
+ def privgroups
+ if env['eduPersonEntitlement'].present?
+ env['eduPersonEntitlement'].split(';')
+ else
+ []
+ end
+ end
end
Warden::Strategies.add(:development_shibboleth_stub) do
@@ -32,7 +40,7 @@ def authenticate!
response = SymphonyClient.new.login_by_sunetid(uid)
if response && response['key']
- u = { username: uid, patron_key: response['key'] }
+ u = { username: uid, patron_key: response['key'], privgroups: privgroups }
success!(u)
else
fail!('Could not log in')
@@ -44,6 +52,14 @@ def authenticate!
def uid
ENV['uid']
end
+
+ def privgroups
+ if ENV['privgroups'].present?
+ ENV['privgroups'].split(';')
+ else
+ Settings.auth.default_privgroups
+ end
+ end
end
Warden::Strategies.add(:library_id) do
@@ -55,7 +71,7 @@ def authenticate!
response = SymphonyClient.new.login(params['library_id'], params['pin'])
if response['patronKey']
- u = { username: params['library_id'], patron_key: response['patronKey'] }
+ u = { username: params['library_id'], patron_key: response['patronKey'], privgroups: [] }
success!(u)
else
fail!('Could not log in')
diff --git a/config/settings.yml b/config/settings.yml
index 9a20438a..13873f5f 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -13,4 +13,16 @@ ACCESS_SERVICES_EMAIL: greencirc@stanford.edu
RECAPTCHA:
SITE_KEY: 6Lc6BAAAAAAAAChqRbQZcn_yyyyyyyyyyyyyyyyy
SECRET_KEY: 6Lc6BAAAAAAAAKN3DRm6VA_xxxxxxxxxxxxxxxxx
-
+
+auth:
+ default_privgroups: []
+ borrow_direct_privgroups:
+ - stanford:stanford
+ - stanford:academic
+ eresources_privgroups:
+ - stanford:stanford
+ - stanford:academic
+ - stanford:administrative
+ - organization:sumc
+ - sulair:proxy-access
+ - lane:proxy-access
diff --git a/config/settings/development.yml b/config/settings/development.yml
index e69de29b..7b93205a 100644
--- a/config/settings/development.yml
+++ b/config/settings/development.yml
@@ -0,0 +1,3 @@
+auth:
+ default_privgroups:
+ - stanford:stanford
diff --git a/spec/models/patron_spec.rb b/spec/models/patron_spec.rb
index 3a584296..9f6bb539 100644
--- a/spec/models/patron_spec.rb
+++ b/spec/models/patron_spec.rb
@@ -8,10 +8,15 @@
{
key: '1',
fields: fields
- }.with_indifferent_access
+ }.with_indifferent_access,
+ mock_user
)
end
+ let(:mock_user) do
+ instance_double(User, has_borrow_direct_access?: true)
+ end
+
let(:fields) do
{
firstName: 'Student',
@@ -347,6 +352,14 @@
it 'includes requests that come from the BorrowDirectRequests class' do
expect(patron.requests.last[:key]).to be 2
end
+
+ context 'without borrow direct access' do
+ let(:mock_user) { instance_double(User, has_borrow_direct_access?: false) }
+
+ it 'excludes requests from BorrowDirect' do
+ expect(patron.requests).to have_attributes(length: 1).and(match([have_attributes(key: 1)]))
+ end
+ end
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 31a611c6..21389ccb 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -18,4 +18,32 @@
expect(user).to be_shibboleth
end
end
+
+ describe '#has_borrow_direct_access?' do
+ context 'with a user in an appropriate privgroup' do
+ let(:user_attributes) { { username: 'sunetid', patron_key: '123', privgroups: ['stanford:stanford'] } }
+
+ it 'is has access' do
+ expect(user).to have_borrow_direct_access
+ end
+ end
+
+ it 'is has no access' do
+ expect(user).not_to have_borrow_direct_access
+ end
+ end
+
+ describe '#has_eresources_access?' do
+ context 'with a user in an appropriate privgroup' do
+ let(:user_attributes) { { username: 'sunetid', patron_key: '123', privgroups: ['stanford:stanford'] } }
+
+ it 'is has access' do
+ expect(user).to have_eresources_access
+ end
+ end
+
+ it 'is has no access' do
+ expect(user).not_to have_eresources_access
+ end
+ end
end
diff --git a/spec/views/patron/_patron.html.erb_spec.rb b/spec/views/patron/_patron.html.erb_spec.rb
index 3281763d..c41f6c6b 100644
--- a/spec/views/patron/_patron.html.erb_spec.rb
+++ b/spec/views/patron/_patron.html.erb_spec.rb
@@ -19,6 +19,7 @@
**patron_options
)
end
+ let(:user) { instance_double(User, has_eresources_access?: true, privgroups: []) }
before do
controller.singleton_class.class_eval do
@@ -26,10 +27,13 @@
def patron; end
- helper_method :patron
+ def current_user; end
+
+ helper_method :patron, :current_user
end
allow(view).to receive(:patron).and_return(patron)
+ allow(view).to receive(:current_user).and_return(user)
end
describe 'Privileges expire' do
@@ -51,4 +55,24 @@ def patron; end
it { expect(rendered).to have_css('dt', text: 'Privileges expire') }
end
end
+
+ describe 'eresources access' do
+ before { render }
+
+ context 'when the user has access' do
+ it { expect(rendered).not_to have_css('dt', text: 'eResource access') }
+ end
+
+ context 'when the user is a proxy borrower' do
+ let(:patron_options) { { proxy_borrower?: true } }
+
+ it { expect(rendered).not_to have_css('dt', text: 'eResource access') }
+ end
+
+ context 'when the user has no access' do
+ let(:user) { instance_double(User, has_eresources_access?: false, privgroups: []) }
+
+ it { expect(rendered).to have_css('dt', text: 'eResource access') }
+ end
+ end
end
diff --git a/spec/views/summaries/index.html.erb_spec.rb b/spec/views/summaries/index.html.erb_spec.rb
index e65fd0f7..6b1d1d74 100644
--- a/spec/views/summaries/index.html.erb_spec.rb
+++ b/spec/views/summaries/index.html.erb_spec.rb
@@ -27,17 +27,22 @@
)
end
+ let(:user) { instance_double(User, has_eresources_access?: true, privgroups: []) }
+
before do
controller.singleton_class.class_eval do
protected
def patron_or_group; end
- helper_method :patron_or_group
+ def current_user; end
+
+ helper_method :patron_or_group, :current_user
end
stub_template 'shared/_navigation.html.erb' => 'Navigation'
allow(view).to receive(:patron_or_group).and_return(patron)
+ allow(view).to receive(:current_user).and_return(user)
end
context 'when the patron is barred' do