From fab61e025bb8524b866995475f73c6ae9769c38f Mon Sep 17 00:00:00 2001 From: "Michael J. Giarlo" Date: Thu, 10 Aug 2017 14:21:46 -0700 Subject: [PATCH] Access-granting workflow services should work on member file sets Fixes #1477 --- app/jobs/hyrax/grant_edit_job.rb | 14 +++++++++++ app/jobs/hyrax/grant_edit_to_members_job.rb | 24 +++++++++++++++++++ app/jobs/hyrax/grant_read_job.rb | 14 +++++++++++ app/jobs/hyrax/grant_read_to_members_job.rb | 24 +++++++++++++++++++ .../hyrax/workflow/grant_edit_to_depositor.rb | 5 ++++ .../hyrax/workflow/grant_read_to_depositor.rb | 3 +++ .../workflow/grant_edit_to_depositor_spec.rb | 16 +++++++++++++ .../workflow/grant_read_to_depositor_spec.rb | 17 +++++++++++++ 8 files changed, 117 insertions(+) create mode 100644 app/jobs/hyrax/grant_edit_job.rb create mode 100644 app/jobs/hyrax/grant_edit_to_members_job.rb create mode 100644 app/jobs/hyrax/grant_read_job.rb create mode 100644 app/jobs/hyrax/grant_read_to_members_job.rb diff --git a/app/jobs/hyrax/grant_edit_job.rb b/app/jobs/hyrax/grant_edit_job.rb new file mode 100644 index 0000000000..22b23d8055 --- /dev/null +++ b/app/jobs/hyrax/grant_edit_job.rb @@ -0,0 +1,14 @@ +module Hyrax + # Grants the user's edit access on the provided FileSet + class GrantEditJob < ApplicationJob + queue_as Hyrax.config.ingest_queue_name + + # @param [String] file_set_id - the identifier of the object to grant access to + # @param [String] user_key - the user to add + def perform(file_set_id, user_key) + file_set = ::FileSet.find(file_set_id) + file_set.edit_users += [user_key] + file_set.save! + end + end +end diff --git a/app/jobs/hyrax/grant_edit_to_members_job.rb b/app/jobs/hyrax/grant_edit_to_members_job.rb new file mode 100644 index 0000000000..4ee0f0e9e2 --- /dev/null +++ b/app/jobs/hyrax/grant_edit_to_members_job.rb @@ -0,0 +1,24 @@ +module Hyrax + # Grants edit access for the supplied user for the members attached to a work + class GrantEditToMembersJob < ApplicationJob + queue_as Hyrax.config.ingest_queue_name + + # @param [ActiveFedora::Base] work - the work object + # @param [String] user_key - the user to add + def perform(work, user_key) + # Iterate over ids because reifying objects is slow. + file_set_ids(work).each do |file_set_id| + # Call this synchronously, since we're already in a job + GrantEditJob.perform_now(file_set_id, user_key) + end + end + + private + + # Filter the member ids and return only the FileSet ids (filter out child works) + # @return [Array] the file set ids + def file_set_ids(work) + ::FileSet.search_with_conditions(id: work.member_ids).map(&:id) + end + end +end diff --git a/app/jobs/hyrax/grant_read_job.rb b/app/jobs/hyrax/grant_read_job.rb new file mode 100644 index 0000000000..2c812abc8d --- /dev/null +++ b/app/jobs/hyrax/grant_read_job.rb @@ -0,0 +1,14 @@ +module Hyrax + # Grants the user's read access on the provided FileSet + class GrantReadJob < ApplicationJob + queue_as Hyrax.config.ingest_queue_name + + # @param [String] file_set_id - the identifier of the object to grant access to + # @param [String] user_key - the user to add + def perform(file_set_id, user_key) + file_set = ::FileSet.find(file_set_id) + file_set.read_users += [user_key] + file_set.save! + end + end +end diff --git a/app/jobs/hyrax/grant_read_to_members_job.rb b/app/jobs/hyrax/grant_read_to_members_job.rb new file mode 100644 index 0000000000..7b8df0e15f --- /dev/null +++ b/app/jobs/hyrax/grant_read_to_members_job.rb @@ -0,0 +1,24 @@ +module Hyrax + # Grants read access for the supplied user for the members attached to a work + class GrantReadToMembersJob < ApplicationJob + queue_as Hyrax.config.ingest_queue_name + + # @param [ActiveFedora::Base] work - the work object + # @param [String] user_key - the user to add + def perform(work, user_key) + # Iterate over ids because reifying objects is slow. + file_set_ids(work).each do |file_set_id| + # Call this synchronously, since we're already in a job + GrantReadJob.perform_now(file_set_id, user_key) + end + end + + private + + # Filter the member ids and return only the FileSet ids (filter out child works) + # @return [Array] the file set ids + def file_set_ids(work) + ::FileSet.search_with_conditions(id: work.member_ids).map(&:id) + end + end +end diff --git a/app/services/hyrax/workflow/grant_edit_to_depositor.rb b/app/services/hyrax/workflow/grant_edit_to_depositor.rb index 3f11ba57e4..b88c447e30 100644 --- a/app/services/hyrax/workflow/grant_edit_to_depositor.rb +++ b/app/services/hyrax/workflow/grant_edit_to_depositor.rb @@ -3,8 +3,13 @@ module Workflow # This is a built in function for workflow, so that a workflow action can be created that # grants the creator the ability to alter it. module GrantEditToDepositor + # @param [#read_users=, #read_users] target (likely an ActiveRecord::Base) to which we are adding edit_users for the depositor + # @return void def self.call(target:, **) target.edit_users += [target.depositor] + # If there are a lot of members, granting access to each could take a + # long time. Do this work in the background. + GrantEditToMembersJob.perform_later(target, target.depositor) end end end diff --git a/app/services/hyrax/workflow/grant_read_to_depositor.rb b/app/services/hyrax/workflow/grant_read_to_depositor.rb index ebf3f5a4a4..02515b850f 100644 --- a/app/services/hyrax/workflow/grant_read_to_depositor.rb +++ b/app/services/hyrax/workflow/grant_read_to_depositor.rb @@ -7,6 +7,9 @@ module GrantReadToDepositor # @return void def self.call(target:, **) target.read_users += [target.depositor] + # If there are a lot of members, granting access to each could take a + # long time. Do this work in the background. + GrantReadToMembersJob.perform_later(target, target.depositor) end end end diff --git a/spec/services/hyrax/workflow/grant_edit_to_depositor_spec.rb b/spec/services/hyrax/workflow/grant_edit_to_depositor_spec.rb index 9e5db32ae3..a141440f43 100644 --- a/spec/services/hyrax/workflow/grant_edit_to_depositor_spec.rb +++ b/spec/services/hyrax/workflow/grant_edit_to_depositor_spec.rb @@ -33,5 +33,21 @@ expect(work).to be_valid end end + + context "with attached FileSets" do + let(:work) { create(:work_with_one_file, user: depositor) } + let(:file_set) do + work.members.first.tap do |file_set| + # Manually remove edit_users to satisfy the pre-condition + file_set.update(edit_users: []) + end + end + + it "grants edit access" do + # We need to reload, because this work happens in a background job + expect { subject }.to change { file_set.reload.edit_users }.from([]).to([depositor.user_key]) + expect(work).to be_valid + end + end end end diff --git a/spec/services/hyrax/workflow/grant_read_to_depositor_spec.rb b/spec/services/hyrax/workflow/grant_read_to_depositor_spec.rb index 3522f1f26c..918ef4f71b 100644 --- a/spec/services/hyrax/workflow/grant_read_to_depositor_spec.rb +++ b/spec/services/hyrax/workflow/grant_read_to_depositor_spec.rb @@ -1,7 +1,13 @@ +require 'hyrax/specs/shared_specs' + RSpec.describe Hyrax::Workflow::GrantReadToDepositor do let(:depositor) { create(:user) } let(:user) { User.new } + let(:workflow_method) { described_class } + + it_behaves_like 'a Hyrax workflow method' + describe ".call" do subject do described_class.call(target: work, @@ -27,5 +33,16 @@ expect(work).to be_valid end end + + context "with attached FileSets" do + let(:work) { create(:work_with_one_file, user: depositor) } + let(:file_set) { work.members.first } + + it "grants read access" do + # We need to reload, because this work happens in a background job + expect { subject }.to change { file_set.reload.read_users }.from([]).to([depositor.user_key]) + expect(work).to be_valid + end + end end end