-
Notifications
You must be signed in to change notification settings - Fork 124
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
Update depositors (proxies, transfers) synchronously #5537
Changes from all commits
3ea6965
56e1425
1802349
1f37f24
af782ec
7351d71
c007962
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,24 @@ | ||
# frozen_string_literal: true | ||
# Log work depositor change to activity streams | ||
# | ||
# @attr [Boolean] reset (false) should the access controls be reset. This means revoking edit access from the depositor | ||
# This class simply logs the transfer, pulling data from the object that was | ||
# just transferred. It does not perform the transfer. | ||
class ContentDepositorChangeEventJob < ContentEventJob | ||
include Rails.application.routes.url_helpers | ||
include ActionDispatch::Routing::PolymorphicRoutes | ||
|
||
attr_accessor :reset | ||
|
||
# @param [ActiveFedora::Base] work the work to be transfered | ||
# @param [User] user the user the work is being transfered to. | ||
# @param [TrueClass,FalseClass] reset (false) if true, reset the access controls. This revokes edit access from the depositor | ||
def perform(work, user, reset = false) | ||
@reset = reset | ||
super(work, user) | ||
# @param [ActiveFedora::Base] work the work that's been transfered | ||
def perform(work) | ||
# these get set to repo_object and depositor | ||
super(work, new_owner(work)) | ||
end | ||
|
||
def action | ||
"User #{link_to_profile work.proxy_depositor} has transferred #{link_to_work work.title.first} to user #{link_to_profile depositor}" | ||
"User #{link_to_profile repo_object.proxy_depositor} has transferred #{link_to_work repo_object.title.first} to user #{link_to_profile depositor}" | ||
end | ||
|
||
def link_to_work(text) | ||
link_to text, polymorphic_path(work) | ||
link_to text, polymorphic_path(repo_object) | ||
end | ||
|
||
# Log the event to the work's stream | ||
|
@@ -30,18 +27,19 @@ def log_work_event(work) | |
end | ||
alias log_file_set_event log_work_event | ||
|
||
def work | ||
@work ||= Hyrax::ChangeContentDepositorService.call(repo_object, depositor, reset) | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method call has been used for over 5 years. So it is making less sense to me now that this would be a problem. I originally thought this was moved here when the listener was created. Still not ruling out the various methods are chasing each other. |
||
|
||
# overriding default to log the event to the depositor instead of their profile | ||
# and to log the event for both users | ||
def log_user_event(depositor) | ||
# log the event to the proxy depositor's profile | ||
proxy_depositor.log_profile_event(event) | ||
previous_owner.log_profile_event(event) | ||
depositor.log_event(event) | ||
end | ||
|
||
def proxy_depositor | ||
@proxy_depositor ||= ::User.find_by_user_key(work.proxy_depositor) | ||
private def previous_owner | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just curious, I haven't seen including private on the line with the method def. Has this always worked or did this start in a specific Rails version? Typically, the private keyword is on a line by itself with all methods that follow being private. In Hyrax, that is the only pattern I see in use. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I'm not sure when. I've been thinking it would be nice to use it because it's more explicit than a |
||
::User.find_by_user_key(repo_object.proxy_depositor) | ||
end | ||
|
||
# used for @depositor | ||
private def new_owner(work) | ||
::User.find_by_user_key(work.depositor) | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,10 @@ class ChangeContentDepositorService | |
# Set the given `user` as the depositor of the given `work`; If | ||
# `reset` is true, first remove all previous permissions. | ||
# | ||
# Used to transfer a an existing work, and to set | ||
# depositor / proxy_depositor on a work newly deposited | ||
# on_behalf_of another user | ||
# | ||
# @param work [ActiveFedora::Base, Valkyrie::Resource] the work | ||
# that is receiving a change of depositor | ||
# @param user [User] the user that will "become" the depositor of | ||
|
@@ -12,13 +16,21 @@ class ChangeContentDepositorService | |
# permissions for the given work and contained file | ||
# sets; regardless of true/false make the given user | ||
# the depositor of the given work | ||
# @return work, updated if necessary | ||
def self.call(work, user, reset) | ||
case work | ||
when ActiveFedora::Base | ||
call_af(work, user, reset) | ||
when Valkyrie::Resource | ||
call_valkyrie(work, user, reset) | ||
end | ||
# user_key is nil when there was no `on_behalf_of` in the form | ||
return work unless user&.user_key | ||
# Don't transfer to self | ||
return work if user.user_key == work.depositor | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice to have exit checks and avoid unnecessary work |
||
|
||
work = case work | ||
when ActiveFedora::Base | ||
call_af(work, user, reset) | ||
when Valkyrie::Resource | ||
call_valkyrie(work, user, reset) | ||
end | ||
ContentDepositorChangeEventJob.perform_later(work) | ||
work | ||
end | ||
|
||
def self.call_af(work, user, reset) | ||
|
@@ -49,7 +61,6 @@ def self.call_valkyrie(work, user, reset) | |
apply_valkyrie_changes_to_file_sets(work: work, user: user, reset: reset) | ||
|
||
Hyrax.persister.save(resource: work) | ||
work | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good catch |
||
end | ||
private_class_method :call_valkyrie | ||
|
||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,44 @@ | ||||||||||
# frozen_string_literal: true | ||||||||||
require 'dry/monads' | ||||||||||
|
||||||||||
module Hyrax | ||||||||||
module Transactions | ||||||||||
module Steps | ||||||||||
## | ||||||||||
# Add a given `::User` as the `#depositor` | ||||||||||
# Move the previous value of that property to `#proxy_depositor` | ||||||||||
# | ||||||||||
# | ||||||||||
# If no user is given, simply passes as a `Success`. | ||||||||||
# | ||||||||||
# @since 3.4.0 | ||||||||||
class ChangeContentDepositor | ||||||||||
include Dry::Monads[:result] | ||||||||||
|
||||||||||
## | ||||||||||
# @param [Hyrax::Work] obj | ||||||||||
# @param user [User] the user that will "become" the depositor of | ||||||||||
# the given work | ||||||||||
# | ||||||||||
# @return [Dry::Monads::Result] | ||||||||||
def call(obj, user: NullUser.new, reset: false) | ||||||||||
obj = Hyrax::ChangeContentDepositorService.call(obj, user, reset) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this bail if user is null?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the service has this guard, do you think we should do it both places? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We agreed to add it to make the code more explicit. |
||||||||||
|
||||||||||
Success(obj) | ||||||||||
rescue StandardError => err | ||||||||||
Failure([err.message, obj]) | ||||||||||
end | ||||||||||
|
||||||||||
## | ||||||||||
# @api private | ||||||||||
class NullUser | ||||||||||
## | ||||||||||
# @return [nil] | ||||||||||
def user_key | ||||||||||
nil | ||||||||||
end | ||||||||||
end | ||||||||||
end | ||||||||||
end | ||||||||||
end | ||||||||||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# frozen_string_literal: true | ||
require 'spec_helper' | ||
require 'hyrax/transactions' | ||
|
||
RSpec.describe Hyrax::Transactions::Steps::ChangeContentDepositor, valkyrie_adapter: :test_adapter do | ||
subject(:step) { described_class.new } | ||
let(:work) { FactoryBot.valkyrie_create(:hyrax_work) } | ||
|
||
it 'gives Success(obj) in basic case' do | ||
expect(step.call(work).value!).to eql(work) | ||
end | ||
|
||
context "when the depositor update is successful" do | ||
it "calls the service" do | ||
allow(Hyrax::ChangeContentDepositorService).to receive(:call) | ||
step.call(work) | ||
|
||
expect(Hyrax::ChangeContentDepositorService).to have_received(:call) | ||
end | ||
end | ||
|
||
context "when there's an error" do | ||
it 'returns a Failure' do | ||
allow(Hyrax::ChangeContentDepositorService).to receive(:call).and_raise | ||
result = step.call(work) | ||
|
||
expect(result).to be_failure | ||
end | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this parameter be a Hyrax::Work (i.e., Valkyrie::Resource)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes thank you