curation_concerns 1.7.0.beta1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/concerns/curation_concerns/application_controller_behavior.rb +2 -8
  3. data/app/controllers/concerns/curation_concerns/collections_controller_behavior.rb +13 -13
  4. data/app/controllers/concerns/curation_concerns/curation_concern_controller.rb +40 -3
  5. data/app/controllers/concerns/curation_concerns/selects_collections.rb +2 -0
  6. data/app/controllers/concerns/curation_concerns/single_use_links_controller_behavior.rb +9 -7
  7. data/app/models/concerns/curation_concerns/solr_document_behavior.rb +8 -0
  8. data/app/models/concerns/curation_concerns/suppressible.rb +31 -0
  9. data/app/models/concerns/curation_concerns/work_behavior.rb +1 -1
  10. data/app/presenters/curation_concerns/inspect_work_presenter.rb +52 -0
  11. data/app/presenters/curation_concerns/work_show_presenter.rb +4 -0
  12. data/app/search_builders/curation_concerns/README.md +69 -0
  13. data/app/search_builders/curation_concerns/collection_search_builder.rb +35 -17
  14. data/app/search_builders/curation_concerns/filter_suppressed.rb +15 -0
  15. data/app/search_builders/curation_concerns/filter_suppressed_with_roles.rb +30 -0
  16. data/app/search_builders/curation_concerns/search_filters.rb +1 -0
  17. data/app/search_builders/curation_concerns/single_collection_search_builder.rb +5 -0
  18. data/app/search_builders/curation_concerns/work_search_builder.rb +1 -0
  19. data/app/services/curation_concerns/actors/actor_factory.rb +0 -1
  20. data/app/services/curation_concerns/embargo_service.rb +0 -13
  21. data/app/services/curation_concerns/workflow/action_taken_service.rb +25 -15
  22. data/app/services/curation_concerns/workflow/activate_object.rb +9 -2
  23. data/app/services/curation_concerns/workflow/deactivate_object.rb +9 -4
  24. data/app/services/curation_concerns/workflow/{remove_depositor_permissions.rb → grant_edit_to_depositor.rb} +4 -4
  25. data/app/services/curation_concerns/workflow/workflow_action_service.rb +1 -1
  26. data/app/services/curation_concerns/working_directory.rb +1 -1
  27. data/app/views/curation_concerns/base/inspect_work.html.erb +37 -0
  28. data/app/views/curation_concerns/base/unavailable.html.erb +10 -0
  29. data/app/views/curation_concerns/operations/index.html.erb +1 -1
  30. data/app/views/curation_concerns/operations/show.html.erb +1 -1
  31. data/config/locales/curation_concerns.en.yml +3 -0
  32. data/curation_concerns.gemspec +3 -3
  33. data/lib/curation_concerns/rails/routes.rb +1 -0
  34. data/lib/curation_concerns/version.rb +1 -1
  35. data/lib/curation_concerns/workflow_authorization_exception.rb +4 -0
  36. data/lib/generators/curation_concerns/templates/workflow.json.erb +1 -0
  37. data/spec/controllers/curation_concerns/generic_works_controller_spec.rb +78 -16
  38. data/spec/controllers/selects_collections_controller_spec.rb +2 -4
  39. data/spec/factories/generic_works.rb +6 -0
  40. data/spec/factories/workflows.rb +1 -1
  41. data/spec/features/add_file_spec.rb +3 -0
  42. data/spec/features/create_child_work_spec.rb +13 -7
  43. data/spec/features/update_file_spec.rb +3 -2
  44. data/spec/forms/curation_concerns/forms/workflow_action_form_spec.rb +2 -4
  45. data/spec/indexers/work_indexer_spec.rb +11 -7
  46. data/spec/jobs/characterize_job_spec.rb +2 -2
  47. data/spec/models/curation_concerns/work_behavior_spec.rb +1 -1
  48. data/spec/models/generic_work_spec.rb +16 -7
  49. data/spec/models/solr_document_spec.rb +13 -0
  50. data/spec/presenters/curation_concerns/inspect_work_presenter_spec.rb +58 -0
  51. data/spec/presenters/curation_concerns/work_show_presenter_spec.rb +9 -0
  52. data/spec/presenters/curation_concerns/workflow_presenter_spec.rb +29 -15
  53. data/spec/routing/route_spec.rb +4 -0
  54. data/spec/services/curation_concerns/workflow/action_taken_service_spec.rb +5 -6
  55. data/spec/services/curation_concerns/workflow/activate_object_spec.rb +13 -12
  56. data/spec/services/curation_concerns/workflow/deactivate_object_spec.rb +14 -13
  57. data/spec/services/curation_concerns/workflow/grant_edit_to_depositor_spec.rb +20 -0
  58. data/spec/services/curation_concerns/workflow/permission_query_spec.rb +3 -3
  59. data/spec/services/curation_concerns/workflow/status_list_service_spec.rb +4 -1
  60. data/spec/services/curation_concerns/workflow/workflow_importer_spec.rb +2 -3
  61. data/spec/services/curation_concerns/working_directory_spec.rb +12 -0
  62. data/spec/views/curation_concerns/base/unavailable.html.erb_spec.rb +40 -0
  63. metadata +34 -20
  64. data/app/actors/curation_concerns/actors/grant_edit_to_depositor_actor.rb +0 -19
  65. data/app/models/concerns/curation_concerns/publishable.rb +0 -25
  66. data/app/models/curation_concerns/state_workflow.rb +0 -13
  67. data/app/views/curation_concerns/file_sets/_rights_modal.html.erb +0 -41
  68. data/app/views/records/_rights_modal.html.erb +0 -1
  69. data/spec/actors/curation_concerns/grant_edit_to_depositor_actor_spec.rb +0 -32
  70. data/spec/services/curation_concerns/workflow/remove_depositor_permissions_spec.rb +0 -21
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe CurationConcerns::InspectWorkPresenter, no_clean: true do
4
+ let(:solr_document) { SolrDocument.new(attributes) }
5
+ let(:attributes) do
6
+ { "id" => '888888',
7
+ "has_model_ssim" => ["GenericWork"] }
8
+ end
9
+
10
+ let(:user) { create(:user) }
11
+ let(:ability) { Ability.new(user) }
12
+ let(:presenter) { described_class.new(solr_document, ability) }
13
+ let(:entity) { instance_double(Sipity::Entity) }
14
+
15
+ describe "#workflow" do
16
+ let(:comments) do
17
+ { comment: 'comment', created_at: 'unknown' }
18
+ end
19
+ let(:roles) do
20
+ { id: '1', name: 'reviewing', users: ['user1', 'user2'] }
21
+ end
22
+ before do
23
+ allow(entity).to receive(:id).and_return('1')
24
+ allow(entity).to receive(:workflow_name).and_return('generic_workflow')
25
+ allow(entity).to receive(:workflow_id).and_return('1')
26
+ allow(entity).to receive(:proxy_for_global_id).and_return(attributes["id"])
27
+ allow(entity).to receive(:workflow_id).and_return('1')
28
+ allow(entity).to receive(:workflow_state_id).and_return('1')
29
+ allow(entity).to receive(:workflow_state_name).and_return('completed')
30
+ allow(presenter).to receive(:sipity_entity).and_return(entity)
31
+ allow(presenter).to receive(:workflow_comments).and_return(comments)
32
+ allow(presenter).to receive(:sipity_entity_roles).and_return(roles)
33
+ end
34
+
35
+ context "when a valid sipity_entity with workflow exists" do
36
+ subject { presenter.workflow }
37
+ it 'returns a hash of workflow related values for ispection' do
38
+ expect(subject[:entity_id]).to eq '1'
39
+ expect(subject[:workflow_name]).to eq 'generic_workflow'
40
+ expect(subject[:workflow_id]).to eq '1'
41
+ expect(subject[:proxy_for]).to eq attributes["id"]
42
+ expect(subject[:state_id]).to eq '1'
43
+ expect(subject[:state_name]).to eq 'completed'
44
+ expect(subject[:comments][:comment]).to eq 'comment'
45
+ expect(subject[:roles][:id]).to eq '1'
46
+ expect(subject[:roles][:name]).to eq 'reviewing'
47
+ expect(subject[:roles][:users][0]).to eq 'user1'
48
+ end
49
+ end
50
+
51
+ context "when no sipity_entity with workflow exists" do
52
+ let(:invalid) { described_class.new('no_solr_document', ability) }
53
+ it "raises PowerConverter::ConversionError" do
54
+ expect { invalid.workflow }.to raise_exception(PowerConverter::ConversionError)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -188,6 +188,15 @@ describe CurationConcerns::WorkShowPresenter do
188
188
  end
189
189
  end
190
190
 
191
+ context "with inspect_work" do
192
+ let(:user) { create(:user) }
193
+ let(:ability) { Ability.new(user) }
194
+ describe "#inspect_work" do
195
+ subject { presenter.inspect_work }
196
+ it { is_expected.to be_kind_of CurationConcerns::InspectWorkPresenter }
197
+ end
198
+ end
199
+
191
200
  describe "graph export methods" do
192
201
  let(:graph) do
193
202
  RDF::Graph.new.tap do |g|
@@ -14,26 +14,40 @@ RSpec.describe CurationConcerns::WorkflowPresenter, no_clean: true do
14
14
 
15
15
  describe "#actions" do
16
16
  let(:workflow) { create(:workflow, name: 'testing') }
17
- before do
18
- allow(CurationConcerns::Workflow::PermissionQuery).to receive(:scope_permitted_workflow_actions_available_for_current_state).and_return([Sipity::WorkflowAction.new(name: "complete", workflow: workflow)])
19
- allow(presenter).to receive(:sipity_entity).and_return(entity)
20
- end
21
-
22
17
  subject { presenter.actions }
23
- it "is an Array of Sipity::Action#name and translated names" do
24
- allow(I18n).to receive(:t).with('curation_concerns.workflow.testing.complete', default: 'Complete').and_return("Approve")
25
- is_expected.to eq [['complete', 'Approve']]
18
+ context 'with a Sipity::Entity' do
19
+ before do
20
+ allow(CurationConcerns::Workflow::PermissionQuery).to receive(:scope_permitted_workflow_actions_available_for_current_state).and_return([Sipity::WorkflowAction.new(name: "complete", workflow: workflow)])
21
+ allow(presenter).to receive(:sipity_entity).and_return(entity)
22
+ end
23
+ it "is an Array of Sipity::Action#name and translated names" do
24
+ allow(I18n).to receive(:t).with('curation_concerns.workflow.testing.complete', default: 'Complete').and_return("Approve")
25
+ is_expected.to eq [['complete', 'Approve']]
26
+ end
27
+ end
28
+ context 'without a Sipity::Entity' do
29
+ before do
30
+ allow(presenter).to receive(:sipity_entity).and_return(nil)
31
+ end
32
+ it { is_expected.to eq [] }
26
33
  end
27
34
  end
28
35
 
29
36
  describe "#comments" do
30
- let(:comment) { instance_double(Sipity::Comment) }
31
- before do
32
- allow(entity).to receive(:comments).and_return([comment])
33
- allow(presenter).to receive(:sipity_entity).and_return(entity)
34
- end
35
-
36
37
  subject { presenter.comments }
37
- it { is_expected.to eq [comment] }
38
+ context 'with a Sipity::Entity' do
39
+ let(:comment) { instance_double(Sipity::Comment) }
40
+ before do
41
+ allow(entity).to receive(:comments).and_return([comment])
42
+ allow(presenter).to receive(:sipity_entity).and_return(entity)
43
+ end
44
+ it { is_expected.to eq [comment] }
45
+ end
46
+ context 'without a Sipity::Entity' do
47
+ before do
48
+ allow(presenter).to receive(:sipity_entity).and_return(nil)
49
+ end
50
+ it { is_expected.to eq [] }
51
+ end
38
52
  end
39
53
  end
@@ -39,6 +39,10 @@ describe 'Routes', type: :routing do
39
39
  it 'routes to file_manager' do
40
40
  expect(get: 'concern/generic_works/6/file_manager').to route_to(controller: 'curation_concerns/generic_works', action: 'file_manager', id: '6')
41
41
  end
42
+
43
+ it 'routes to inspect_work' do
44
+ expect(get: 'concern/generic_works/6/inspect_work').to route_to(controller: 'curation_concerns/generic_works', action: 'inspect_work', id: '6')
45
+ end
42
46
  end
43
47
 
44
48
  describe 'Permissions' do
@@ -6,18 +6,17 @@ RSpec.describe CurationConcerns::Workflow::ActionTakenService do
6
6
  it { is_expected.to respond_to(:handle_action_taken) }
7
7
  end
8
8
 
9
- let(:triggered_methods) { [instance_double(Sipity::Method, service_name: 'foo_bar')] }
9
+ let(:triggered_methods) { [instance_double(Sipity::Method, service_name: 'FooBar')] }
10
10
  let(:triggered_methods_rel) do
11
11
  instance_double(Sipity::Method::ActiveRecord_Relation,
12
12
  order: triggered_methods,
13
13
  any?: true)
14
14
  end
15
- let(:work) { instance_double(GenericWork) }
15
+ let(:work) { instance_double(GenericWork, id: '9999') }
16
16
  let(:action) { instance_double(Sipity::WorkflowAction, triggered_methods: triggered_methods_rel) }
17
- let(:entity) { instance_double(Sipity::Entity, id: 9999, proxy_for: work) }
18
17
  let(:user) { User.new }
19
18
  let(:instance) do
20
- described_class.new(entity: entity,
19
+ described_class.new(target: work,
21
20
  action: action,
22
21
  comment: "A pleasant read",
23
22
  user: user)
@@ -38,14 +37,14 @@ RSpec.describe CurationConcerns::Workflow::ActionTakenService do
38
37
  context "and the method succeedes" do
39
38
  it "calls the method and saves the object" do
40
39
  expect(work).to receive(:save)
41
- expect(FooBar).to receive(:call).with(entity: entity, user: user, comment: "A pleasant read").and_return(true)
40
+ expect(FooBar).to receive(:call).with(target: work, user: user, comment: "A pleasant read").and_return(true)
42
41
  subject
43
42
  end
44
43
  end
45
44
  context "and the method fails" do
46
45
  it "calls the method and saves the object" do
47
46
  expect(work).not_to receive(:save)
48
- expect(FooBar).to receive(:call).with(entity: entity, user: user, comment: "A pleasant read").and_return(false)
47
+ expect(FooBar).to receive(:call).with(target: work, user: user, comment: "A pleasant read").and_return(false)
49
48
  expect(Rails.logger).to receive(:error).with("Not all workflow methods were successful, so not saving (9999)")
50
49
  subject
51
50
  end
@@ -1,20 +1,21 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe CurationConcerns::Workflow::ActivateObject do
4
- let(:work) { instance_double(GenericWork) }
5
- let(:entity) { instance_double(Sipity::Entity, id: 9999, proxy_for: work) }
6
- let(:user) { User.new }
7
-
4
+ let(:work) { create(:generic_work) }
5
+ let(:user) { create(:user) }
8
6
  describe ".call" do
9
- subject do
10
- described_class.call(entity: entity,
11
- comment: "A pleasant read",
12
- user: user)
13
- end
14
-
15
7
  it "makes it active" do
16
- expect(work).to receive(:state=).with(Vocab::FedoraResourceStatus.active)
17
- subject
8
+ if RDF::VERSION.to_s < '2.0'
9
+ expect { described_class.call(target: work, comment: "A pleasant read", user: user) }
10
+ .to change { work.state }
11
+ .from(nil)
12
+ .to(instance_of(ActiveTriples::Resource))
13
+ else
14
+ expect { described_class.call(target: work, comment: "A pleasant read", user: user) }
15
+ .to change { work.state }
16
+ .from(nil)
17
+ .to(::RDF::URI('http://fedora.info/definitions/1/0/access/ObjState#active'))
18
+ end
18
19
  end
19
20
  end
20
21
  end
@@ -1,20 +1,21 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe CurationConcerns::Workflow::DeactivateObject do
4
- let(:work) { instance_double(GenericWork) }
5
- let(:entity) { instance_double(Sipity::Entity, id: 9999, proxy_for: work) }
6
- let(:user) { User.new }
7
-
4
+ let(:work) { create(:generic_work) }
5
+ let(:user) { create(:user) }
8
6
  describe ".call" do
9
- subject do
10
- described_class.call(entity: entity,
11
- comment: "A pleasant read",
12
- user: user)
13
- end
14
-
15
- it "makes it active" do
16
- expect(work).to receive(:state=).with(Vocab::FedoraResourceStatus.inactive)
17
- subject
7
+ it "makes it inactive" do
8
+ if RDF::VERSION.to_s < '2.0'
9
+ expect { described_class.call(target: work, comment: "A pleasant read", user: user) }
10
+ .to change { work.state }
11
+ .from(nil)
12
+ .to(instance_of(ActiveTriples::Resource))
13
+ else
14
+ expect { described_class.call(target: work, comment: "A pleasant read", user: user) }
15
+ .to change { work.state }
16
+ .from(nil)
17
+ .to(::RDF::URI('http://fedora.info/definitions/1/0/access/ObjState#inactive'))
18
+ end
18
19
  end
19
20
  end
20
21
  end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe CurationConcerns::Workflow::GrantEditToDepositor do
4
+ let(:depositor) { create(:user) }
5
+ let(:work) { create(:work_without_access, depositor: depositor.user_key) }
6
+ let(:user) { User.new }
7
+
8
+ describe ".call" do
9
+ subject do
10
+ described_class.call(target: work,
11
+ comment: "A pleasant read",
12
+ user: user)
13
+ end
14
+
15
+ it "adds edit access " do
16
+ expect { subject }.to change { work.edit_users }.from([]).to([depositor.user_key])
17
+ expect(work).to be_valid
18
+ end
19
+ end
20
+ end
@@ -24,7 +24,7 @@ module CurationConcerns
24
24
  workflow_state: PowerConverter.convert_to_sipity_workflow_state('initial', scope: sipity_workflow)
25
25
  )
26
26
  end
27
- let(:sipity_workflow) { Sipity::Workflow.first }
27
+ let(:sipity_workflow) { Sipity::Workflow.find_by(name: 'testing') }
28
28
 
29
29
  def expect_actions_for(user:, entity:, actions:)
30
30
  actions = Array.wrap(actions).map { |action| PowerConverter.convert_to_sipity_action(action, scope: entity.workflow) }
@@ -169,8 +169,8 @@ module CurationConcerns
169
169
  let(:user) { create(:user) }
170
170
  subject { described_class.scope_processing_agents_for(user: user) }
171
171
  it 'will equal [kind_of(Sipity::Agent)]' do
172
- is_expected.to eq([PowerConverter.convert_to_sipity_agent(user),
173
- PowerConverter.convert_to_sipity_agent(Group.new('registered'))])
172
+ is_expected.to contain_exactly(PowerConverter.convert_to_sipity_agent(user),
173
+ PowerConverter.convert_to_sipity_agent(Group.new('registered')))
174
174
  end
175
175
  end
176
176
  end
@@ -4,6 +4,7 @@ RSpec.describe CurationConcerns::Workflow::StatusListService do
4
4
  describe "#each" do
5
5
  let(:user) { create(:user) }
6
6
  let(:service) { described_class.new(user) }
7
+ let!(:sipity_entity) { create(:sipity_entity) }
7
8
  let(:document) { { id: '33333',
8
9
  has_model_ssim: ['GenericWork'],
9
10
  actionable_workflow_roles_ssim: ["generic_work-approving", "generic_work-rejecting"],
@@ -15,7 +16,6 @@ RSpec.describe CurationConcerns::Workflow::StatusListService do
15
16
  let(:workflow_role) { instance_double(Sipity::Role, name: 'approving') }
16
17
  let(:workflow_roles) { [instance_double(Sipity::WorkflowRole, role: workflow_role)] }
17
18
  before do
18
- create(:sipity_entity)
19
19
  ActiveFedora::SolrService.add([document, ability], commit: true)
20
20
  end
21
21
 
@@ -24,6 +24,9 @@ RSpec.describe CurationConcerns::Workflow::StatusListService do
24
24
  context "when user has roles" do
25
25
  before do
26
26
  allow(CurationConcerns::Workflow::PermissionQuery).to receive(:scope_processing_workflow_roles_for_user_and_workflow).and_return(workflow_roles)
27
+ allow_any_instance_of(described_class).to receive(:roles_for_user) do
28
+ "generic_work-#{workflow_role.name}"
29
+ end
27
30
  end
28
31
 
29
32
  it "returns status rows" do
@@ -34,7 +34,6 @@ RSpec.describe CurationConcerns::Workflow::WorkflowImporter do
34
34
  end
35
35
 
36
36
  context 'data generation' do
37
- let(:path) { Rails.root.join('config/workflows/default_workflow.json').to_s }
38
37
  it 'creates the requisite data from the configuration' do
39
38
  expect(CurationConcerns::Workflow::WorkflowPermissionsGenerator).to receive(:call).and_call_original
40
39
  expect(CurationConcerns::Workflow::SipityActionsGenerator).to receive(:call).and_call_original
@@ -43,8 +42,8 @@ RSpec.describe CurationConcerns::Workflow::WorkflowImporter do
43
42
  result = described_class.generate_from_json_file(path: path)
44
43
  end.to change { Sipity::Workflow.count }.by(1)
45
44
  expect(result).to match_array(kind_of(Sipity::Workflow))
46
- expect(result.first.label).to eq "Default workflow"
47
- expect(result.first.description).to eq "A single submission step, default workflow"
45
+ expect(result.first.label).to eq "This is the label"
46
+ expect(result.first.description).to eq "This description could get really long"
48
47
  end
49
48
  end
50
49
  end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe CurationConcerns::WorkingDirectory do
4
+ let(:path1) { described_class.send(:full_filename, 'abcdefghijklmnop1', 'foo.tif') }
5
+ let(:path2) { described_class.send(:full_filename, 'abcdefghijklmnop2', 'foo.tif') }
6
+
7
+ describe "#full_filename" do
8
+ it "generates unique filenames for different files" do
9
+ expect(path1).not_to eq(path2)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'curation_concerns/base/unavailable.html.erb', type: :view do
4
+ let(:model) do
5
+ double('model',
6
+ persisted?: true,
7
+ to_param: '123',
8
+ model_name: GenericWork.model_name)
9
+ end
10
+ let(:workflow) do
11
+ double('workflow', state: 'deposited', state_label: 'really deposited')
12
+ end
13
+ let(:presenter) do
14
+ double('presenter',
15
+ to_s: 'super cool',
16
+ workflow: workflow,
17
+ human_readable_type: 'Generic Work')
18
+ end
19
+ let(:parent_presenter) do
20
+ double('parent_presenter',
21
+ to_s: 'parental remark',
22
+ to_model: model,
23
+ human_readable_type: 'Foo Bar')
24
+ end
25
+ before do
26
+ assign(:presenter, presenter)
27
+ assign(:parent_presenter, parent_presenter)
28
+ stub_template 'shared/_brand_bar.html.erb' => ''
29
+ stub_template 'shared/_title_bar.html.erb' => ''
30
+ flash[:notice] = I18n.t("curation_concerns.workflow.unauthorized")
31
+ render template: 'curation_concerns/base/unavailable.html.erb', layout: 'layouts/curation_concerns'
32
+ end
33
+ it "renders with the flash message" do
34
+ expect(rendered).to have_content 'super cool'
35
+ expect(rendered).to have_content 'really deposited'
36
+ expect(rendered).to have_content 'parental remark'
37
+ expect(rendered).to have_content 'Generic Work'
38
+ expect(rendered).to have_content 'The work is not currently available because it has not yet completed the approval process'
39
+ end
40
+ end