diff --git a/app/services/tasks/group_permission_remediation_service.rb b/app/services/tasks/group_permission_remediation_service.rb new file mode 100644 index 000000000..f40644404 --- /dev/null +++ b/app/services/tasks/group_permission_remediation_service.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true +module Tasks + require 'tasks/migration_helper' + # Adjusts the permissions of a list of works and their filesets to grant permissions + # assigned to their admin set. + class GroupPermissionRemediationService + def self.run(id_list_file, admin_set_id) + GroupPermissionRemediationService.new(id_list_file, admin_set_id).run + end + + def initialize(id_list_file, admin_set_id) + @id_list_file = id_list_file + @admin_set_id = admin_set_id + end + + def run + work_id_list.each do |work_id| + start_time = Time.now + work_id = work_id.chomp + work = ActiveFedora::Base.find(work_id) + Rails.logger.info("Remediating groups for #{work_id}") + work.update permissions_attributes: group_permissions + work.file_sets.each do |file_set| + file_set.update permissions_attributes: group_permissions + end + Rails.logger.info("Completed remediation of #{work_id} in #{Time.now - start_time}") + end + end + + def work_id_list + @work_id_list ||= File.readlines(@id_list_file) + end + + def group_permissions + @group_permissions ||= MigrationHelper.get_permissions_attributes(@admin_set_id) + end + end +end diff --git a/lib/tasks/remediate_group_permissions.rake b/lib/tasks/remediate_group_permissions.rake new file mode 100644 index 000000000..ab7015af9 --- /dev/null +++ b/lib/tasks/remediate_group_permissions.rake @@ -0,0 +1,6 @@ +# frozen_string_literal: true +desc 'Remediate missing group permission assignments based on permissions of an admin set' +task :remediate_group_permissions, [:id_list_file, :admin_set_id] => [:environment] do |_t, args| + Rails.logger.warn('Prepapring to run GroupPermissionRemediationService') + Tasks::GroupPermissionRemediationService.run(args[:id_list_file], args[:admin_set_id]) +end diff --git a/spec/services/tasks/group_permission_remediation_service_spec.rb b/spec/services/tasks/group_permission_remediation_service_spec.rb new file mode 100644 index 000000000..d400bd70d --- /dev/null +++ b/spec/services/tasks/group_permission_remediation_service_spec.rb @@ -0,0 +1,96 @@ +# frozen_string_literal: true +require 'rails_helper' +include Warden::Test::Helpers + +describe Tasks::GroupPermissionRemediationService, :clean do + before do + ActiveFedora::Cleaner.clean! + end + + let(:admin) { FactoryBot.create(:admin) } + + let(:admin_set) do + AdminSet.create(title: ['proquest admin set'], + description: ['some description']) + end + + let(:permission_template) do + Hyrax::PermissionTemplate.create!(source_id: admin_set.id) + end + + let(:workflow) do + Sipity::Workflow.create(name: 'test', allows_access_grant: true, active: true, + permission_template_id: permission_template.id) + end + + describe '#run' do + context 'with groups assigned to admin set' do + let(:id_list_file) { Tempfile.new } + + let(:manager) do + FactoryBot.create(:user, email: 'manager@example.com', guest: false, uid: 'manager') + end + let(:viewer) do + FactoryBot.create(:user, email: 'viewer@example.com', guest: false, uid: 'viewer') + end + let(:manager_agent) { Sipity::Agent.where(proxy_for_id: 'oa_manager', proxy_for_type: 'Hyrax::Group').first_or_create } + let(:viewer_agent) { Sipity::Agent.where(proxy_for_id: 'oa_viewer', proxy_for_type: 'Hyrax::Group').first_or_create } + + let(:article) { FactoryBot.create(:article) } + let(:file_set1) { FactoryBot.create(:file_set) } + let(:file_set2) { FactoryBot.create(:file_set, visibility: Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE) } + + before do + Article.delete_all + + Hyrax::PermissionTemplateAccess.create(permission_template: permission_template, + agent_type: 'group', + agent_id: 'oa_manager', + access: 'manage') + Hyrax::PermissionTemplateAccess.create(permission_template: permission_template, + agent_type: 'group', + agent_id: 'oa_viewer', + access: 'view') + Hyrax::Workflow::PermissionGenerator.call(roles: 'managing', workflow: workflow, agents: manager_agent) + Hyrax::Workflow::PermissionGenerator.call(roles: 'viewing', workflow: workflow, agents: viewer_agent) + manager_role = Role.where(name: 'oa_manager').first_or_create + manager_role.users << manager + manager_role.save + viewer_role = Role.where(name: 'oa_viewer').first_or_create + viewer_role.users << viewer + viewer_role.save + + File.write(id_list_file, article.id) + + article.ordered_members << file_set1 + article.ordered_members << file_set2 + end + + after do + id_list_file.unlink + end + + + it 'adds group roles from admin set to work and file set' do + Tasks::GroupPermissionRemediationService.run(id_list_file.path, admin_set.id) + + article = Article.first + expect_to_have_permissions(article) + + article_file_sets = article.file_sets + expect(article_file_sets.length).to eq 2 + expect_to_have_permissions(article_file_sets[0]) + expect_to_have_permissions(article_file_sets[1]) + expect(article_file_sets[1].visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE + end + + def expect_to_have_permissions(item) + manager_perm = item.permissions.to_a.find { |perm| perm.agent.first.id == 'http://projecthydra.org/ns/auth/group#oa_manager' } + expect(manager_perm.mode.first.id).to eq 'http://www.w3.org/ns/auth/acl#Write' + + pub_perm = item.permissions.to_a.find { |perm| perm.agent.first.id == 'http://projecthydra.org/ns/auth/group#oa_viewer' } + expect(pub_perm.mode.first.id).to eq 'http://www.w3.org/ns/auth/acl#Read' + end + end + end +end