curation_concerns 1.7.0.beta1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
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