Skip to content

Commit

Permalink
Copy the job and service to new classes
Browse files Browse the repository at this point in the history
so we can deprecate the old ones
  • Loading branch information
hackartisan committed Mar 18, 2022
1 parent f31dbf4 commit 631dbd8
Show file tree
Hide file tree
Showing 5 changed files with 323 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .rubocop_fixme.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ RSpec/ExampleLength:
- 'spec/jobs/content_restored_version_event_job_spec.rb'
- 'spec/jobs/content_new_version_event_job_spec.rb'
- 'spec/jobs/content_depositor_change_event_job_spec.rb'
- 'spec/jobs/change_depositor_event_job_spec.rb'
- 'spec/jobs/content_deposit_event_job_spec.rb'
- 'spec/jobs/content_delete_event_job_spec.rb'
- 'spec/jobs/ingest_file_job_spec.rb'
Expand Down Expand Up @@ -100,7 +101,6 @@ RSpec/SubjectStub:
- 'spec/models/hyrax/operation_spec.rb'
- 'spec/controllers/hyrax/accepts_batches_controller_spec.rb'
- 'spec/indexers/hyrax/repository_reindexer_spec.rb'
- 'spec/jobs/content_depositor_change_event_job_spec.rb'
- 'spec/lib/hyrax/analytics_spec.rb'
- 'spec/models/job_io_wrapper_spec.rb'
- 'spec/search_builders/hyrax/abstract_type_relation_spec.rb'
Expand Down
45 changes: 45 additions & 0 deletions app/jobs/change_depositor_event_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true
# Log work depositor change to activity streams
#
# This class simply logs the transfer, pulling data from the object that was
# just transferred. It does not perform the transfer.
class ChangeDepositorEventJob < ContentEventJob
include Rails.application.routes.url_helpers
include ActionDispatch::Routing::PolymorphicRoutes

# @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 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(repo_object)
end

# Log the event to the work's stream
def log_work_event(work)
work.log_event(event)
end
alias log_file_set_event log_work_event

# 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)
previous_owner.log_profile_event(event)
depositor.log_event(event)
end

private def previous_owner
::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
86 changes: 86 additions & 0 deletions app/services/hyrax/change_depositor_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# frozen_string_literal: true
module Hyrax
class ChangeDepositorService
# 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
# the given work
# @param reset [TrueClass, FalseClass] when true, first clear
# 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)
# 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

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)
work.proxy_depositor = work.depositor
work.permissions = [] if reset
work.apply_depositor_metadata(user)
work.file_sets.each do |f|
f.permissions = [] if reset
f.apply_depositor_metadata(user)
f.save!
end
work.save!
work
end
private_class_method :call_af

# @todo Should this include some dependency injection regarding
# the Hyrax.persister and Hyrax.custom_queries?
def self.call_valkyrie(work, user, reset)
if reset
work.permission_manager.acl.permissions = []
work.permission_manager.acl.save
end

work.proxy_depositor = work.depositor
apply_depositor_metadata(work, user)

apply_valkyrie_changes_to_file_sets(work: work, user: user, reset: reset)

Hyrax.persister.save(resource: work)
end
private_class_method :call_valkyrie

def self.apply_depositor_metadata(resource, depositor)
depositor_id = depositor.respond_to?(:user_key) ? depositor.user_key : depositor
resource.depositor = depositor_id if resource.respond_to? :depositor=
Hyrax::AccessControlList.new(resource: resource).grant(:edit).to(::User.find_by_user_key(depositor_id)).save
end
private_class_method :apply_depositor_metadata

def self.apply_valkyrie_changes_to_file_sets(work:, user:, reset:)
Hyrax.custom_queries.find_child_file_sets(resource: work).each do |f|
if reset
f.permission_manager.acl.permissions = []
f.permission_manager.acl.save
end
apply_depositor_metadata(f, user)
Hyrax.persister.save(resource: f)
end
end
private_class_method :apply_valkyrie_changes_to_file_sets
end
end
58 changes: 58 additions & 0 deletions spec/jobs/change_depositor_event_job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# frozen_string_literal: true
RSpec.describe ChangeDepositorEventJob do
let(:previous_user) { create(:user) }
let(:new_user) { create(:user) }
let(:mock_time) { Time.zone.at(1) }
let(:event) do
{ action:
"User <a href=\"/users/#{previous_user.to_param}\">#{previous_user.user_key}</a> " \
"has transferred <a href=\"/concern/generic_works/#{generic_work.id}\">BethsMac</a> " \
"to user <a href=\"/users/#{new_user.to_param}\">#{new_user.user_key}</a>",
timestamp: '1' }
end

before do
allow(Time).to receive(:now).at_least(:once).and_return(mock_time)
end

context "when passing an ActiveFedora work" do
let(:generic_work) { create(:generic_work, title: ['BethsMac'], user: new_user, proxy_depositor: previous_user.user_key) }

it "logs the event to the proxy depositor's profile, the depositor's dashboard, and the FileSet" do
expect { described_class.perform_now(generic_work) }
.to change { previous_user.profile_events.length }
.by(1)
.and change { new_user.events.length }
.by(1)
.and change { generic_work.events.length }
.by(1)
expect(previous_user.profile_events.first).to eq(event)
expect(new_user.events.first).to eq(event)
expect(generic_work.events.first).to eq(event)
end
end

context "when passing a valkyrie work" do
let(:monograph) { valkyrie_create(:monograph, title: ['BethsMac'], depositor: new_user.user_key, proxy_depositor: previous_user.user_key) }

let(:event) do
{ action: "User <a href=\"/users/#{previous_user.to_param}\">#{previous_user.user_key}</a> " \
"has transferred <a href=\"/concern/monographs/#{monograph.id}\">BethsMac</a> " \
"to user <a href=\"/users/#{new_user.to_param}\">#{new_user.user_key}</a>",
timestamp: '1' }
end

it "logs the event to the proxy depositor's profile, the depositor's dashboard, and the FileSet" do
expect { subject.perform(monograph) }
.to change { previous_user.profile_events.length }
.by(1)
.and change { new_user.events.length }
.by(1)
.and change { monograph.events.length }
.by(1)
expect(previous_user.profile_events.first).to eq(event)
expect(new_user.events.first).to eq(event)
expect(monograph.events.first).to eq(event)
end
end
end
133 changes: 133 additions & 0 deletions spec/services/hyrax/change_depositor_service_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# frozen_string_literal: true
RSpec.describe Hyrax::ChangeDepositorService do
let!(:depositor) { create(:user) }
let!(:receiver) { create(:user) }

context "for Active Fedora objects" do
let!(:file) do
create(:file_set, user: depositor)
end
let!(:work) do
create(:work, title: ['Test work'], user: depositor)
end

before do
work.members << file
described_class.call(work, receiver, reset)
end

context "by default, when permissions are not reset" do
let(:reset) { false }

it "changes the depositor and records an original depositor" do
work.reload
expect(work.depositor).to eq receiver.user_key
expect(work.proxy_depositor).to eq depositor.user_key
expect(work.edit_users).to include(receiver.user_key, depositor.user_key)
end

it "changes the depositor of the child file sets" do
file.reload
expect(file.depositor).to eq receiver.user_key
expect(file.edit_users).to include(receiver.user_key, depositor.user_key)
end
end

context "when permissions are reset" do
let(:reset) { true }

it "excludes the depositor from the edit users" do
work.reload
expect(work.depositor).to eq receiver.user_key
expect(work.proxy_depositor).to eq depositor.user_key
expect(work.edit_users).to contain_exactly(receiver.user_key)
end

it "changes the depositor of the child file sets" do
file.reload
expect(file.depositor).to eq receiver.user_key
expect(file.edit_users).to contain_exactly(receiver.user_key)
end
end
end

context "for Valkyrie objects" do
let!(:base_work) { valkyrie_create(:hyrax_work, :with_member_file_sets, title: ['SoonToBeSomeoneElses'], depositor: depositor.user_key, edit_users: [depositor]) }
before do
work_acl = Hyrax::AccessControlList.new(resource: base_work)
Hyrax.custom_queries.find_child_file_sets(resource: base_work).each do |file_set|
Hyrax::AccessControlList.copy_permissions(source: work_acl, target: file_set)
end
end

context "by default, when permissions are not reset" do
it "changes the depositor and records an original depositor" do
expect(ContentDepositorChangeEventJob).to receive(:perform_later)
described_class.call(base_work, receiver, false)
work = Hyrax.query_service.find_by_alternate_identifier(alternate_identifier: base_work.id, use_valkyrie: true)
expect(work.depositor).to eq receiver.user_key
expect(work.proxy_depositor).to eq depositor.user_key
expect(work.edit_users.to_a).to include(receiver.user_key, depositor.user_key)
end

it "changes the depositor of the child file sets" do
described_class.call(base_work, receiver, false)
file_sets = Hyrax.custom_queries.find_child_file_sets(resource: base_work)
expect(file_sets.size).not_to eq 0 # A quick check to make sure our each block works

file_sets.each do |file_set|
expect(file_set.depositor).to eq receiver.user_key
expect(file_set.edit_users.to_a).to include(receiver.user_key, depositor.user_key)
end
end
end

context "when permissions are reset" do
it "changes the depositor and records an original depositor" do
expect(ContentDepositorChangeEventJob).to receive(:perform_later)
described_class.call(base_work, receiver, true)
work = Hyrax.query_service.find_by_alternate_identifier(alternate_identifier: base_work.id, use_valkyrie: true)
expect(work.depositor).to eq receiver.user_key
expect(work.proxy_depositor).to eq depositor.user_key
expect(work.edit_users.to_a).to contain_exactly(receiver.user_key)
end

it "changes the depositor of the child file sets" do
described_class.call(base_work, receiver, true)
file_sets = Hyrax.custom_queries.find_child_file_sets(resource: base_work)
expect(file_sets.size).not_to eq 0 # A quick check to make sure our each block works

file_sets.each do |file_set|
expect(file_set.depositor).to eq receiver.user_key
expect(file_set.edit_users.to_a).to contain_exactly(receiver.user_key)
end
end
end

context "when no user is provided" do
it "does not update the work" do
expect(ContentDepositorChangeEventJob).not_to receive(:perform_later)
persister = double("Valkyrie Persister")
allow(Hyrax).to receive(:persister).and_return(persister)
allow(persister).to receive(:save)

described_class.call(base_work, nil, false)
expect(persister).not_to have_received(:save)
end
end

context "when transfer is requested to the existing owner" do
let!(:base_work) { valkyrie_create(:hyrax_work, :with_member_file_sets, title: ['AlreadyMine'], depositor: depositor.user_key, edit_users: [depositor]) }

it "does not update the work" do
expect(ContentDepositorChangeEventJob).not_to receive(:perform_later)
persister = double("Valkyrie Persister")
allow(Hyrax).to receive(:persister).and_return(persister)
allow(persister).to receive(:save)

described_class.call(base_work, depositor, false)
expect(persister).not_to have_received(:save)
end
end
end
end

0 comments on commit 631dbd8

Please sign in to comment.