Open labradford opened 1 year ago
Per client we won't be getting a time stamp but will require users to re-login after 24 hours
In the UCSD Virtual Reading Room, they have a WorkAuthorization model; this model describes which users have CDL rights to which Works. These rights are revoked via a cron
job.
There is an external process that provides a list of each loan request: a persona and a loaned object. From that list, we go through and process the request:
read
the given work.There is a view into the WorkAuthorizations for administrators of the site; they are able to see the WorkAuthorization records and thus see who has been assigned temporary read writes to what titles.
Much of what appears in code looks to be well-tested. The main variance I’d imagine is the initial input of the process. UCSD Virtual Reading Room relies on an external service to determine what authorizations to create. We could introduce a different “service” to look those things up. Or, more directly manually call Processors::NewRightsProcess#authorize
within the application. Put another way, there’s a nice and interface in play.
This is something that could be constructed as a gem; in this version I’d recommend that we directly incorporate this into the Hyku, but place all of this in a module, thus allowing easier extraction later.
# frozen_string_literal: true
module Processors
class NewRightsProcessor
def self.process_new
queue = Aeon::Queue.find(Aeon::Queue::NEW_STATUS)
queue.requests.each do |request|
request.set_to_processing
Processors::NewRightsProcessor.new(request).authorize
request.set_to_active
end
end
def self.revoke_old
WorkAuthorization.where('updated_at < ?', 1.month.ago).each do |auth|
params = { work_pid: auth.work_pid, email: auth.user.email, aeon_id: auth.aeon_id }
request = Processors::NewRightsProcessor.new(params)
request.revoke
end
end
def initialize(request_attributes)
@request_attributes = request_attributes
@work_title = @request_attributes[:itemTitle]
@work_pid = if ['development'].include? Rails.env
DamsObject.last.pid
else
@request_attributes[:subLocation]
end
@email = @request_attributes[:email].presence || @request_attributes[:username]
end
def authorize
return unless @email.present? && user.valid? && @work_pid.present? && work_obj
process_request(@request_attributes.id)
create_work_authorization
activate_request(@request_attributes.id)
send_email
rescue => e # rescue all errors to handle them manually
work_authorization.update_error 'Unable to Authorize Request'
raise e
end
def revoke
return unless user && work_obj
delete_work_authorization
expire_request(@request_attributes.id)
rescue => e # rescue all errors to handle them manually
work_authorization.update_error 'Unable to Revoke Request'
raise e
end
private
def user
return @user if @user
@user = User.where(email: @email).first_or_initialize do |user| # only hits the do on initialize
user.provider = 'auth_link'
user.uid = SecureRandom.uuid
user.ensure_authentication_token
end
@user.save
@user
end
def work_obj
return @work_obj if @work_obj
@work_obj = DamsObject.where(pid: @work_pid).first if @work_pid
end
def work_authorization
@work_authorization ||= user.work_authorizations.where(work_pid: @work_pid).first_or_create do |authorization|
authorization.aeon_id = @request_attributes.id
authorization.work_title = @work_title
end
end
def create_work_authorization
return unless work_authorization.valid?
# touch to get the updated authorizations
# disable rubocop because we run validations before calling .touch
work_authorization.touch # rubocop:disable SkipsModelValidations
work_obj.set_read_users([user.user_key], [user.user_key])
work_obj.save
end
def delete_work_authorization
work_authorization.destroy
work_obj.set_read_users([], [user.user_key])
work_obj.save
end
def send_email
AuthMailer.send_link(user).deliver_later
end
def process_request(request_id)
Aeon::Request.find(request_id).set_to_processing
end
def expire_request(request_id)
Aeon::Request.find(request_id).set_to_expired
end
def activate_request(request_id)
Aeon::Request.find(request_id).set_to_active
end
end
end
Here is the desired local workflow:
One challenge: When you are already logged in and go to a page that is private (e.g. you can’t see) the system notes that this is private and does not prompt you to authenticate.
I'm thinking about creating a development only service that is configured for after authentication to grant access to the work at the original URL. This would allow for continued local testing and help us move forward without all of the SSO work.
Story
A user is sent to a Hyku and will login using SSO. Once the user is signed in, they will be redirected to Hyku with a URL like this:
[https://vufind.reshare-dev.indexdata.com/east/cdl/auth?[response_type=token]&client_id=myconsortium-hyku&redirect_uri=https://indexdata.com/authorized&scope=BOOKURL[&state=XXX](https://vufind.reshare-dev.indexdata.com/east/cdl/auth?%5Bresponse_type=token%5D&client_id=myconsortium-hyku&redirect_uri=https://indexdata.com/authorized&scope=BOOKURL%5B&state=XXX)
This URL will also need an expiration date/time.
For this ticket, we will need to:
Acceptance Criteria
Testing
To be filled out by developer
Notes
Number 1 is partially blocked by:
497