hyrax 3.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +5 -5
  3. data/.dassie/Gemfile +1 -1
  4. data/.dassie/app/controllers/catalog_controller.rb +6 -0
  5. data/Dockerfile +2 -3
  6. data/app/actors/hyrax/actors/base_actor.rb +1 -1
  7. data/app/actors/hyrax/actors/collections_membership_actor.rb +3 -3
  8. data/app/actors/hyrax/actors/file_set_actor.rb +2 -0
  9. data/app/assets/stylesheets/hyrax/_styles.scss +5 -0
  10. data/app/controllers/concerns/hyrax/collections_controller_behavior.rb +13 -5
  11. data/app/controllers/concerns/hyrax/controller.rb +13 -2
  12. data/app/controllers/hyrax/admin/admin_sets_controller.rb +2 -19
  13. data/app/controllers/hyrax/admin/permission_template_accesses_controller.rb +5 -2
  14. data/app/controllers/hyrax/collections_controller.rb +3 -1
  15. data/app/controllers/hyrax/dashboard/collection_members_controller.rb +12 -9
  16. data/app/controllers/hyrax/dashboard/collections_controller.rb +92 -28
  17. data/app/controllers/hyrax/dashboard/nest_collections_controller.rb +75 -39
  18. data/app/controllers/hyrax/my_controller.rb +4 -4
  19. data/app/controllers/hyrax/workflow_actions_controller.rb +8 -5
  20. data/app/forms/hyrax/forms/administrative_set_form.rb +62 -0
  21. data/app/forms/hyrax/forms/collection_form.rb +2 -2
  22. data/app/forms/hyrax/forms/dashboard/nest_collection_form.rb +14 -4
  23. data/app/forms/hyrax/forms/pcdm_collection_form.rb +64 -0
  24. data/app/forms/hyrax/forms/resource_form.rb +15 -10
  25. data/app/forms/hyrax/forms/workflow_action_form.rb +4 -0
  26. data/app/helpers/hyrax/hyrax_helper_behavior.rb +9 -0
  27. data/app/indexers/hyrax/administrative_set_indexer.rb +6 -6
  28. data/app/indexers/hyrax/pcdm_collection_indexer.rb +2 -0
  29. data/app/models/admin_set.rb +16 -5
  30. data/app/models/concerns/hyrax/ability/admin_set_ability.rb +31 -7
  31. data/app/models/concerns/hyrax/ability/collection_ability.rb +35 -20
  32. data/app/models/concerns/hyrax/ability/collection_type_ability.rb +1 -1
  33. data/app/models/concerns/hyrax/ability.rb +2 -2
  34. data/app/models/concerns/hyrax/solr_document_behavior.rb +2 -2
  35. data/app/models/hyrax/administrative_set.rb +7 -1
  36. data/app/models/hyrax/permission.rb +1 -1
  37. data/app/models/hyrax/permission_template.rb +19 -5
  38. data/app/models/hyrax/work.rb +1 -0
  39. data/app/models/hyrax/workflow_action_info.rb +16 -0
  40. data/app/models/sipity/comment.rb +17 -0
  41. data/app/models/sipity.rb +11 -2
  42. data/app/presenters/hyrax/admin_set_presenter.rb +8 -3
  43. data/app/presenters/hyrax/collection_presenter.rb +3 -3
  44. data/app/presenters/hyrax/work_show_presenter.rb +2 -1
  45. data/app/search_builders/hyrax/abstract_type_relation.rb +4 -2
  46. data/app/search_builders/hyrax/dashboard/collections_search_builder.rb +1 -1
  47. data/app/search_builders/hyrax/exposed_models_relation.rb +1 -1
  48. data/app/search_builders/hyrax/filter_by_type.rb +1 -2
  49. data/app/search_builders/hyrax/my/collections_search_builder.rb +1 -1
  50. data/app/services/hyrax/admin_set_create_service.rb +136 -54
  51. data/app/services/hyrax/collection_types/permissions_service.rb +1 -1
  52. data/app/services/hyrax/collections/collection_member_service.rb +12 -2
  53. data/app/services/hyrax/collections/permissions_create_service.rb +81 -79
  54. data/app/services/hyrax/collections/permissions_service.rb +1 -1
  55. data/app/services/hyrax/curation_concern.rb +24 -2
  56. data/app/services/hyrax/default_middleware_stack.rb +11 -0
  57. data/app/services/hyrax/ensure_well_formed_admin_set_service.rb +3 -3
  58. data/app/services/hyrax/listeners/active_fedora_acl_index_listener.rb +1 -0
  59. data/app/services/hyrax/listeners/metadata_index_listener.rb +25 -9
  60. data/app/services/hyrax/permission_manager.rb +4 -4
  61. data/app/services/hyrax/solr_service.rb +1 -1
  62. data/app/services/hyrax/statistics/collections/over_time.rb +2 -1
  63. data/app/services/hyrax/workflow/abstract_notification.rb +2 -2
  64. data/app/services/hyrax/workflow/action_taken_service.rb +16 -4
  65. data/app/services/hyrax/workflow/activate_object.rb +5 -4
  66. data/app/services/hyrax/workflow/changes_required_notification.rb +5 -4
  67. data/app/services/hyrax/workflow/deactivate_object.rb +7 -5
  68. data/app/services/hyrax/workflow/deposited_notification.rb +8 -4
  69. data/app/services/hyrax/workflow/grant_edit_to_depositor.rb +7 -3
  70. data/app/services/hyrax/workflow/grant_read_to_depositor.rb +10 -3
  71. data/app/services/hyrax/workflow/revoke_edit_from_depositor.rb +8 -2
  72. data/app/services/hyrax/workflow/workflow_action_service.rb +4 -1
  73. data/app/views/hyrax/admin/admin_sets/_form.html.erb +1 -1
  74. data/app/views/hyrax/dashboard/collections/_collection_title.html.erb +1 -1
  75. data/app/views/hyrax/dashboard/collections/_form.html.erb +1 -1
  76. data/app/views/hyrax/dashboard/collections/_sort_and_per_page.html.erb +1 -1
  77. data/app/views/hyrax/homepage/index.html.erb +1 -1
  78. data/app/views/hyrax/my/collections/_modal_collection_types_to_create.html.erb +1 -1
  79. data/app/views/layouts/hyrax/dashboard.html.erb +1 -0
  80. data/app/views/layouts/hyrax.html.erb +1 -0
  81. data/app/views/shared/_read_only.html.erb +5 -0
  82. data/chart/hyrax/Chart.yaml +2 -2
  83. data/chart/hyrax/templates/deployment.yaml +6 -0
  84. data/config/features.rb +3 -0
  85. data/config/initializers/1_healthz.rb +1 -0
  86. data/config/initializers/listeners.rb +2 -1
  87. data/config/locales/hyrax.en.yml +1 -0
  88. data/db/seeds.rb +1 -1
  89. data/documentation/developing-your-hyrax-based-app.md +1 -1
  90. data/documentation/legacyREADME.md +1 -1
  91. data/hyrax.gemspec +1 -1
  92. data/lib/generators/hyrax/templates/catalog_controller.rb +3 -1
  93. data/lib/generators/hyrax/templates/config/initializers/hyrax.rb +10 -0
  94. data/lib/generators/hyrax/work/templates/feature_spec.rb.erb +1 -1
  95. data/lib/generators/hyrax/work_resource/templates/indexer_spec.rb.erb +1 -0
  96. data/lib/hyrax/collection_name.rb +6 -2
  97. data/lib/hyrax/configuration.rb +28 -0
  98. data/lib/hyrax/form_fields.rb +1 -0
  99. data/lib/hyrax/publisher.rb +12 -0
  100. data/lib/hyrax/resource_sync/change_list_writer.rb +2 -2
  101. data/lib/hyrax/resource_sync/resource_list_writer.rb +2 -2
  102. data/lib/hyrax/specs/shared_specs/hydra_works.rb +2 -0
  103. data/lib/hyrax/specs/shared_specs/indexers.rb +6 -0
  104. data/lib/hyrax/transactions/collection_create.rb +25 -0
  105. data/lib/hyrax/transactions/collection_update.rb +20 -0
  106. data/lib/hyrax/transactions/container.rb +26 -0
  107. data/lib/hyrax/transactions/steps/add_to_collections.rb +13 -1
  108. data/lib/hyrax/transactions/steps/apply_collection_type_permissions.rb +29 -0
  109. data/lib/hyrax/transactions/steps/save.rb +18 -6
  110. data/lib/hyrax/transactions/steps/set_collection_type_gid.rb +35 -0
  111. data/lib/hyrax/version.rb +1 -1
  112. data/lib/tasks/default_admin_set.rake +12 -11
  113. data/template.rb +1 -1
  114. metadata +16 -9
@@ -31,7 +31,8 @@ module Hyrax
31
31
  end
32
32
 
33
33
  def create_sipity_comment
34
- return true if comment_text.blank?
34
+ return Sipity::NullComment.new(entity: subject.entity, agent: subject.agent) if
35
+ comment_text.blank?
35
36
  Sipity::Comment.create!(entity: subject.entity, agent: subject.agent, comment: comment_text)
36
37
  end
37
38
 
@@ -44,7 +45,9 @@ module Hyrax
44
45
  )
45
46
  end
46
47
 
48
+ ##
47
49
  # Run any configured custom methods
50
+ #
48
51
  def handle_additional_sipity_workflow_action_processing(comment:)
49
52
  Hyrax::Workflow::ActionTakenService.handle_action_taken(
50
53
  target: subject.work,
@@ -26,7 +26,7 @@
26
26
  <% if f.object.persisted? && f.object.member_ids.present? %>
27
27
  <%# we're loading these values dynamically to speed page load %>
28
28
  <%= f.input :thumbnail_id,
29
- input_html: { data: { text: f.object.thumbnail_title } } %>
29
+ input_html: { data: { text: thumbnail_label_for(object: f.object) } } %>
30
30
  <% end %>
31
31
 
32
32
  </div>
@@ -3,7 +3,7 @@
3
3
  <section class="collection-title-row-wrapper"
4
4
  data-source="my"
5
5
  data-id="<%= id %>"
6
- data-colls-hash="<%= presenter.available_parent_collections(scope: controller) %>"
6
+ data-colls-hash="<%= available_parent_collections_data(collection: presenter) %>"
7
7
  data-post-url="<%= hyrax.dashboard_create_nest_collection_within_path(id) %>"
8
8
  data-post-delete-url="<%= hyrax.dashboard_collection_path(id) %>">
9
9
 
@@ -37,7 +37,7 @@
37
37
  <% if f.object.persisted? %>
38
38
  <%# we're loading these values dynamically to speed page load %>
39
39
  <%= f.input :thumbnail_id,
40
- input_html: { data: { text: f.object.thumbnail_title } } %>
40
+ input_html: { data: { text: thumbnail_label_for(object: f.object) } } %>
41
41
  <% end %>
42
42
  </div>
43
43
  <% if f.object.display_additional_fields? %>
@@ -23,7 +23,7 @@
23
23
  <button class="btn btn-info"><span class="glyphicon glyphicon-refresh"></span> <%= t('helpers.action.refresh') %></button>
24
24
  </fieldset>
25
25
  <div class="col-sm-3">
26
- <%= render 'view_type_group' %>
26
+ <%= render 'hyrax/collections/view_type_group' %>
27
27
  </div>
28
28
  </div>
29
29
  <% end %>
@@ -1,6 +1,6 @@
1
1
  <% provide :page_title, application_name %>
2
2
 
3
- <% if @presenter.display_share_button? %>
3
+ <% if @presenter.display_share_button? && !Flipflop.read_only? %>
4
4
  <div class="home-share-work text-center">
5
5
  <% if signed_in? %>
6
6
  <% if @presenter.create_many_work_types? %>
@@ -12,7 +12,7 @@
12
12
  <% @collection_type_list_presenter.each do |row_presenter| %>
13
13
  <div class="radio radio-button-list">
14
14
  <label>
15
- <input type="radio" name="collection_type"
15
+ <input type="radio" name="collection_type" value="<%= row_presenter.title.gsub(/\s+/, '') %>"
16
16
  <% if row_presenter.admin_set? %>
17
17
  data-path="<%= new_admin_admin_set_path %>"
18
18
  <% else %>
@@ -27,6 +27,7 @@
27
27
  <% end %>
28
28
 
29
29
  <a name="skip-to-content" id="skip-to-content"></a>
30
+ <%= render 'shared/read_only' if Flipflop.read_only? %>
30
31
  <%= content_for?(:content) ? yield(:content) : yield %>
31
32
 
32
33
  </div>
@@ -24,6 +24,7 @@
24
24
  <% end %>
25
25
 
26
26
  <a name="skip-to-content" id="skip-to-content"></a>
27
+ <%= render 'shared/read_only' if Flipflop.read_only? %>
27
28
  <%= content_for?(:content) ? yield(:content) : yield %>
28
29
  </div><!-- /#content-wrapper -->
29
30
  <%= render 'shared/footer' %>
@@ -0,0 +1,5 @@
1
+ <div class="row">
2
+ <div class="col-md-12 read-only text-center alert alert-warning">
3
+ <%= t('hyrax.read_only') %>
4
+ </div>
5
+ </div>
@@ -2,8 +2,8 @@ apiVersion: v2
2
2
  name: hyrax
3
3
  description: An open-source, Samvera-powered digital repository system
4
4
  type: application
5
- version: 0.22.0
6
- appVersion: 3.0.2
5
+ version: 1.0.0
6
+ appVersion: 3.1.0
7
7
  dependencies:
8
8
  - name: fcrepo
9
9
  version: 0.8.0
@@ -21,6 +21,9 @@ spec:
21
21
  {{- include "hyrax.selectorLabels" . | nindent 8 }}
22
22
  spec:
23
23
  initContainers:
24
+ {{- if .Values.solrPreSetupInitContainer }}
25
+ {{- toYaml .Values.solrPreSetupInitContainer | nindent 8 }}
26
+ {{- end }}
24
27
  {{- if .Values.loadSolrConfigSet }}
25
28
  - name: load-solr-config
26
29
  image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
@@ -43,6 +46,9 @@ spec:
43
46
  solrcloud-upload-configset.sh /app/samvera/hyrax-webapp/solr/conf &&
44
47
  solrcloud-assign-configset.sh
45
48
  {{- end }}
49
+ {{- if .Values.dbPreSetupInitContainer }}
50
+ {{- toYaml .Values.dbPreSetupInitContainer | nindent 8 }}
51
+ {{- end }}
46
52
  {{- if not .Values.skipDbMigrateSeed }}
47
53
  - name: db-setup
48
54
  image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
data/config/features.rb CHANGED
@@ -44,6 +44,9 @@ Flipflop.configure do
44
44
  feature :cache_work_iiif_manifest,
45
45
  default: false,
46
46
  description: "Use Rails.cache to cache the JSON document for IIIF manifests"
47
+ feature :read_only,
48
+ default: false,
49
+ description: "Put the system into read-only mode. Deposits, edits, approvals and anything that makes a change to the data will be disabled."
47
50
  rescue Flipflop::StrategyError, Flipflop::FeatureError => err
48
51
  Rails.logger.warn "Ignoring #{err}: #{err.message}"
49
52
  end
@@ -15,6 +15,7 @@ begin
15
15
  require 'hyrax/health_checks'
16
16
 
17
17
  OkComputer::Registry.register 'solr', Hyrax::HealthChecks::SolrCheck.new
18
+ OkComputer::Registry.register 'migrations', OkComputer::ActiveRecordMigrationsCheck.new
18
19
 
19
20
  # check cache
20
21
  if ENV['MEMCACHED_HOST']
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Hyrax.publisher.subscribe(Hyrax::Listeners::AclIndexListener.new)
4
- Hyrax.publisher.subscribe(Hyrax::Listeners::ActiveFedoraAclIndexListener.new)
4
+ Hyrax.publisher.subscribe(Hyrax::Listeners::ActiveFedoraAclIndexListener.new) unless
5
+ Hyrax.config.disable_wings
5
6
  Hyrax.publisher.subscribe(Hyrax::Listeners::MemberCleanupListener.new)
6
7
  Hyrax.publisher.subscribe(Hyrax::Listeners::MetadataIndexListener.new)
7
8
  Hyrax.publisher.subscribe(Hyrax::Listeners::BatchNotificationListener.new)
@@ -1305,6 +1305,7 @@ en:
1305
1305
  owner:
1306
1306
  edit: Edit access
1307
1307
  read: View/Download
1308
+ read_only: The repository is in read-only mode for maintenance. No submissions or edits can be made at this time.
1308
1309
  search:
1309
1310
  button:
1310
1311
  html: <span class="glyphicon glyphicon-search" aria-hidden="true"></span> Go
data/db/seeds.rb CHANGED
@@ -10,7 +10,7 @@ errors = Hyrax::Workflow::WorkflowImporter.load_errors
10
10
  abort("Failed to process all workflows:\n #{errors.join('\n ')}") unless errors.empty?
11
11
 
12
12
  puts "\n== Creating default admin set"
13
- admin_set_id = AdminSet.find_or_create_default_admin_set_id
13
+ admin_set_id = Hyrax::AdminSetCreateService.find_or_create_default_admin_set.id.to_s
14
14
 
15
15
  # I have found that when I come back to a development
16
16
  # environment, that I may have an AdminSet in Fedora, but it is
@@ -125,7 +125,7 @@ NOTE: The steps need to be done in order to create a new Hyrax based app.
125
125
  Generate a new Rails application using the template.
126
126
 
127
127
  ```
128
- rails _5.2.6_ new my_app -m https://raw.githubusercontent.com/samvera/hyrax/v3.1.0/template.rb
128
+ rails _5.2.6_ new my_app -m https://raw.githubusercontent.com/samvera/hyrax/v3.2.0/template.rb
129
129
  ```
130
130
 
131
131
  Generating a new Rails application using Hyrax's template above takes cares of a number of steps for you, including:
@@ -50,7 +50,7 @@ The Samvera community is here to help. Please see our [support guide](./.github/
50
50
  # Getting started
51
51
 
52
52
  This document contains instructions specific to setting up an app with __Hyrax
53
- v3.1.0__. If you are looking for instructions on installing a different
53
+ v3.2.0__. If you are looking for instructions on installing a different
54
54
  version, be sure to select the appropriate branch or tag from the drop-down
55
55
  menu above.
56
56
 
data/hyrax.gemspec CHANGED
@@ -82,7 +82,7 @@ SUMMARY
82
82
  spec.add_dependency 'select2-rails', '~> 3.5'
83
83
  spec.add_dependency 'signet'
84
84
  spec.add_dependency 'tinymce-rails'
85
- spec.add_dependency 'valkyrie', '>= 2.1.1', "< 3.0"
85
+ spec.add_dependency 'valkyrie', '~> 2', '>= 2.1.1'
86
86
 
87
87
  spec.add_development_dependency "capybara", '~> 3.29'
88
88
  spec.add_development_dependency 'capybara-screenshot', '~> 1.0'
@@ -5,6 +5,8 @@ class CatalogController < ApplicationController
5
5
 
6
6
  # This filter applies the hydra access controls
7
7
  before_action :enforce_show_permissions, only: :show
8
+ # Allow all search options when in read-only mode
9
+ skip_before_action :check_read_only
8
10
 
9
11
  def self.uploaded_field
10
12
  "system_create_dtsi"
@@ -22,7 +24,7 @@ class CatalogController < ApplicationController
22
24
  config.view.slideshow.partials = [:index]
23
25
 
24
26
  # Because too many times on Samvera tech people raise a problem regarding a failed query to SOLR.
25
- # Often, it's because they inadvertantly exceeded the character limit of a GET request.
27
+ # Often, it's because they inadvertently exceeded the character limit of a GET request.
26
28
  config.http_method = :post
27
29
 
28
30
  ## Default parameters to send to solr for all search-like requests. See also SolrHelper#solr_search_params
@@ -238,6 +238,16 @@ Hyrax.config do |config|
238
238
  # "#{ActiveFedora.fedora.host}#{ActiveFedora.fedora.base_path}/#{Noid::Rails.treeify(id)}"
239
239
  # end
240
240
 
241
+ # Identify the model class name that will be used for Collections in your app
242
+ # (i.e. ::Collection for ActiveFedora, Hyrax::PcdmCollection for Valkyrie)
243
+ # config.collection_model = '::Collection'
244
+ # config.collection_model = 'Hyrax::PcdmCollection'
245
+
246
+ # Identify the model class name that will be used for Admin Sets in your app
247
+ # (i.e. AdminSet for ActiveFedora, Hyrax::AdministrativeSet for Valkyrie)
248
+ # config.admin_set_model = 'AdminSet'
249
+ # config.admin_set_model = 'Hyrax::AdministrativeSet'
250
+
241
251
  # When your application is ready to use the valkyrie index instead of the one
242
252
  # maintained by active fedora, you will need to set this to true. You will
243
253
  # also need to update your Blacklight configuration.
@@ -12,7 +12,7 @@ RSpec.feature 'Create a <%= class_name %>', js: false do
12
12
  let(:user) do
13
13
  User.new(user_attributes) { |u| u.save(validate: false) }
14
14
  end
15
- let(:admin_set_id) { AdminSet.find_or_create_default_admin_set_id }
15
+ let(:admin_set_id) { Hyrax::AdminSetCreateService.find_or_create_default_admin_set.id.to_s }
16
16
  let(:permission_template) { Hyrax::PermissionTemplate.find_or_create_by!(source_id: admin_set_id) }
17
17
  let(:workflow) { Sipity::Workflow.create!(active: true, name: 'test-workflow', permission_template: permission_template) }
18
18
 
@@ -7,6 +7,7 @@ require 'hyrax/specs/shared_specs/indexers'
7
7
 
8
8
  RSpec.describe <%= class_name %>Indexer do
9
9
  let(:indexer_class) { described_class }
10
+ let(:resource) { <%= class_name %>.new }
10
11
 
11
12
  it_behaves_like 'a Hyrax::Resource indexer'
12
13
  end
@@ -8,8 +8,12 @@ module Hyrax
8
8
  def initialize(klass, namespace = nil, name = nil)
9
9
  super
10
10
 
11
- @route_key = Collection.model_name.route_key
12
- @singular_route_key = Collection.model_name.singular_route_key
11
+ @human = 'Collection'
12
+ @i18n_key = :collection
13
+ @param_key = 'collection'
14
+ @plural = 'collections'
15
+ @route_key = 'collections'
16
+ @singular_route_key = 'collection'
13
17
  end
14
18
  end
15
19
  end
@@ -666,6 +666,34 @@ module Hyrax
666
666
  @collection_type_index_field ||= 'collection_type_gid_ssim'
667
667
  end
668
668
 
669
+ attr_writer :collection_model
670
+ ##
671
+ # @return [#constantize] a string representation of the collection
672
+ # model
673
+ def collection_model
674
+ @collection_model ||= '::Collection'
675
+ end
676
+
677
+ ##
678
+ # @return [Class] the configured collection model class
679
+ def collection_class
680
+ collection_model.constantize
681
+ end
682
+
683
+ attr_writer :admin_set_model
684
+ ##
685
+ # @return [#constantize] a string representation of the admin set
686
+ # model
687
+ def admin_set_model
688
+ @admin_set_model ||= 'AdminSet'
689
+ end
690
+
691
+ ##
692
+ # @return [Class] the configured admin set model class
693
+ def admin_set_class
694
+ admin_set_model.constantize
695
+ end
696
+
669
697
  attr_writer :id_field
670
698
  def id_field
671
699
  @id_field || index_field_mapper.id_field
@@ -49,6 +49,7 @@ module Hyrax
49
49
 
50
50
  form_field_definitions.each do |field_name, options|
51
51
  descendant.property field_name.to_sym, options.merge(display: true, default: [])
52
+ descendant.validates field_name.to_sym, presence: true if options.fetch(:required, false)
52
53
  end
53
54
  end
54
55
  end
@@ -94,6 +94,18 @@ module Hyrax
94
94
  # @macro a_registered_event
95
95
  register_event('batch.created')
96
96
 
97
+ # @since 3.0.0
98
+ # @macro a_registered_event
99
+ register_event('collection.metadata.updated')
100
+
101
+ # @since 3.0.0
102
+ # @macro a_registered_event
103
+ register_event('collection.membership.updated')
104
+
105
+ # @since 3.3.0
106
+ # @macro a_registered_event
107
+ register_event('file.downloaded')
108
+
97
109
  # @since 3.0.0
98
110
  # @macro a_registered_event
99
111
  register_event('file.set.audited')
@@ -61,8 +61,8 @@ module Hyrax
61
61
 
62
62
  def build_resources(xml, doc_set)
63
63
  doc_set.each do |doc|
64
- model = doc.fetch('has_model_ssim', []).first.constantize
65
- if model == ::Collection
64
+ model = doc.fetch('has_model_ssim', []).first.safe_constantize
65
+ if model.try(:collection?) || model == Hyrax.config.collection_class
66
66
  build_resource(xml, doc, model, hyrax_routes)
67
67
  else
68
68
  build_resource(xml, doc, model, main_app_routes)
@@ -32,8 +32,8 @@ module Hyrax
32
32
  end
33
33
  end
34
34
 
35
- def build_collections(xml)
36
- ::Collection.search_in_batches(public_access) do |doc_set|
35
+ def build_collections(xml, searcher: AbstractTypeRelation.new(allowable_types: [::Collection, Hyrax.config.collection_class]))
36
+ searcher.search_in_batches(public_access) do |doc_set|
37
37
  build_resources(xml, doc_set, hyrax_routes)
38
38
  end
39
39
  end
@@ -152,6 +152,8 @@ end
152
152
  RSpec.shared_examples 'a Hyrax::AdministrativeSet' do
153
153
  subject(:admin_set) { described_class.new }
154
154
 
155
+ it_behaves_like 'a model with core metadata'
156
+
155
157
  it 'has an #alternative_title' do
156
158
  expect { admin_set.alternative_title = ['Moomin'] }
157
159
  .to change { admin_set.alternative_title }
@@ -188,5 +188,11 @@ RSpec.shared_examples 'a Collection indexer' do
188
188
  expect(indexer.to_solr)
189
189
  .to include(thumbnail_path_ss: include('assets/collection', '.png'))
190
190
  end
191
+
192
+ it 'indexes depositor' do
193
+ expect(indexer.to_solr)
194
+ .to include(depositor_ssim: [resource.depositor],
195
+ depositor_tesim: [resource.depositor])
196
+ end
191
197
  end
192
198
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ require 'hyrax/transactions/transaction'
3
+
4
+ module Hyrax
5
+ module Transactions
6
+ ##
7
+ # Creates a Collection from a ChangeSet
8
+ #
9
+ # @since 3.2.0
10
+ class CollectionCreate < Transaction
11
+ DEFAULT_STEPS = ['change_set.set_user_as_depositor',
12
+ 'change_set.set_collection_type_gid',
13
+ 'change_set.add_to_collections',
14
+ 'change_set.apply',
15
+ 'collection_resource.apply_collection_type_permissions',
16
+ 'collection_resource.save_acl'].freeze
17
+
18
+ ##
19
+ # @see Hyrax::Transactions::Transaction
20
+ def initialize(container: Container, steps: DEFAULT_STEPS)
21
+ super
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ require 'hyrax/transactions/transaction'
3
+
4
+ module Hyrax
5
+ module Transactions
6
+ ##
7
+ # Creates a Collection from a ChangeSet
8
+ #
9
+ # @since 3.2.0
10
+ class CollectionUpdate < Transaction
11
+ DEFAULT_STEPS = ['change_set.apply'].freeze
12
+
13
+ ##
14
+ # @see Hyrax::Transactions::Transaction
15
+ def initialize(container: Container, steps: DEFAULT_STEPS)
16
+ super
17
+ end
18
+ end
19
+ end
20
+ end
@@ -19,6 +19,8 @@ module Hyrax
19
19
  # @see https://dry-rb.org/gems/dry-container/
20
20
  class Container # rubocop:disable Metrics/ClassLength
21
21
  require 'hyrax/transactions/apply_change_set'
22
+ require 'hyrax/transactions/collection_create'
23
+ require 'hyrax/transactions/collection_update'
22
24
  require 'hyrax/transactions/create_work'
23
25
  require 'hyrax/transactions/destroy_work'
24
26
  require 'hyrax/transactions/file_set_destroy'
@@ -29,11 +31,13 @@ module Hyrax
29
31
  require 'hyrax/transactions/steps/add_to_collections'
30
32
  require 'hyrax/transactions/steps/add_to_parent'
31
33
  require 'hyrax/transactions/steps/apply_collection_permission_template'
34
+ require 'hyrax/transactions/steps/apply_collection_type_permissions'
32
35
  require 'hyrax/transactions/steps/apply_permission_template'
33
36
  require 'hyrax/transactions/steps/apply_visibility'
34
37
  require 'hyrax/transactions/steps/delete_resource'
35
38
  require 'hyrax/transactions/steps/destroy_work'
36
39
  require 'hyrax/transactions/steps/ensure_admin_set'
40
+ require 'hyrax/transactions/steps/set_collection_type_gid'
37
41
  require 'hyrax/transactions/steps/ensure_permission_template'
38
42
  require 'hyrax/transactions/steps/remove_file_set_from_work'
39
43
  require 'hyrax/transactions/steps/save'
@@ -58,6 +62,14 @@ module Hyrax
58
62
  ApplyChangeSet.new
59
63
  end
60
64
 
65
+ ops.register 'create_collection' do
66
+ CollectionCreate.new
67
+ end
68
+
69
+ ops.register 'update_collection' do
70
+ CollectionUpdate.new
71
+ end
72
+
61
73
  ops.register 'create_work' do
62
74
  WorkCreate.new
63
75
  end
@@ -70,6 +82,10 @@ module Hyrax
70
82
  Steps::Save.new
71
83
  end
72
84
 
85
+ ops.register 'set_collection_type_gid' do
86
+ Steps::SetCollectionTypeGid.new
87
+ end
88
+
73
89
  ops.register 'set_default_admin_set' do
74
90
  Steps::SetDefaultAdminSet.new
75
91
  end
@@ -109,6 +125,16 @@ module Hyrax
109
125
  end
110
126
  end
111
127
 
128
+ namespace 'collection_resource' do |ops| # valkyrie collection
129
+ ops.register 'apply_collection_type_permissions' do
130
+ Steps::ApplyCollectionTypePermissions.new
131
+ end
132
+
133
+ ops.register 'save_acl' do
134
+ Steps::SaveAccessControl.new
135
+ end
136
+ end
137
+
112
138
  namespace 'work_resource' do |ops| # valkyrie works
113
139
  ops.register 'add_file_sets' do
114
140
  Steps::AddFileSets.new
@@ -26,10 +26,22 @@ module Hyrax
26
26
  #
27
27
  # @return [Dry::Monads::Result]
28
28
  def call(change_set, collection_ids: [])
29
- change_set.member_of_collection_ids += collection_ids
29
+ multi_membership_messages = check_multi_membership(change_set, collection_ids)
30
+ return Failure(multi_membership_messages) if multi_membership_messages.present?
30
31
 
32
+ change_set.member_of_collection_ids += collection_ids
31
33
  Success(change_set)
32
34
  end
35
+
36
+ private
37
+
38
+ def check_multi_membership(change_set, collection_ids)
39
+ return if change_set.is_a? Hyrax::Forms::PcdmCollectionForm
40
+
41
+ Hyrax::MultipleMembershipChecker
42
+ .new(item: change_set)
43
+ .check(collection_ids: [collection_ids], include_current_members: true)
44
+ end
33
45
  end
34
46
  end
35
47
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module Transactions
4
+ module Steps
5
+ ##
6
+ # A `dry-transcation` step that applies permission templates from a
7
+ # collection type on a given collection.
8
+ #
9
+ # @since 3.2.0
10
+ class ApplyCollectionTypePermissions
11
+ include Dry::Monads[:result]
12
+
13
+ ##
14
+ # @param [Hyrax::PcdmCollection] collection with a collection type gid
15
+ # @param user [User] the user that created the collection
16
+ #
17
+ # @return [Dry::Monads::Result]
18
+ def call(collection, user: nil)
19
+ Hyrax::Collections::PermissionsCreateService.create_default(collection: collection,
20
+ creating_user: user)
21
+ Success(collection)
22
+ rescue URI::InvalidURIError => err
23
+ # will be raised if the collection_type_gid is invalid or doesn't exist
24
+ Failure(err)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -29,8 +29,12 @@ module Hyrax
29
29
  # applied and the resource is saved;
30
30
  # `Failure([#to_s, change_set.resource])`, otherwise.
31
31
  def call(change_set, user: nil)
32
- unsaved = change_set.sync
33
- saved = @persister.save(resource: unsaved)
32
+ begin
33
+ unsaved = change_set.sync
34
+ saved = @persister.save(resource: unsaved)
35
+ rescue StandardError => err
36
+ return Failure(["Failed save on #{change_set}\n\t#{err.message}", change_set.resource])
37
+ end
34
38
 
35
39
  # if we have a permission manager, it's acting as a local cache of another resource.
36
40
  # we want to resync changes that we had in progress so we can persist them later.
@@ -38,12 +42,20 @@ module Hyrax
38
42
  unsaved.respond_to?(:permission_manager)
39
43
 
40
44
  user ||= ::User.find_by_user_key(saved.depositor)
41
- Hyrax.publisher.publish('object.deposited', object: saved, user: user) if unsaved.new_record
42
- Hyrax.publisher.publish('object.metadata.updated', object: saved, user: user)
43
45
 
46
+ publish_changes(resource: saved, user: user, new: unsaved.new_record)
44
47
  Success(saved)
45
- rescue StandardError => err
46
- Failure([err.message, change_set.resource])
48
+ end
49
+
50
+ private
51
+
52
+ def publish_changes(resource:, user:, new: false)
53
+ if resource.collection?
54
+ Hyrax.publisher.publish('collection.metadata.updated', collection: resource, user: user)
55
+ else
56
+ Hyrax.publisher.publish('object.deposited', object: resource, user: user) if new
57
+ Hyrax.publisher.publish('object.metadata.updated', object: resource, user: user)
58
+ end
47
59
  end
48
60
  end
49
61
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+ module Hyrax
3
+ module Transactions
4
+ module Steps
5
+ ##
6
+ # A step that sets the `#collection_type_gid` in the change set.
7
+ #
8
+ # @since 3.2.0
9
+ class SetCollectionTypeGid
10
+ include Dry::Monads[:result]
11
+
12
+ ##
13
+ # @param [Hyrax::ChangeSet] change_set
14
+ # @param collection_type_gid [URI::GID] global id for the collection type
15
+ # @return [Dry::Monads::Result] `Failure` if there is no `collection_type_gid` or
16
+ # it can't be set to the default for the input; `Success(input)`, otherwise.
17
+ def call(change_set, collection_type_gid: default_collection_type_gid)
18
+ return Failure[:no_collection_type_gid, collection] unless
19
+ change_set.respond_to?(:collection_type_gid=)
20
+ return Success(change_set) if
21
+ change_set.collection_type_gid.present?
22
+
23
+ change_set.collection_type_gid = collection_type_gid
24
+ Success(change_set)
25
+ end
26
+
27
+ private
28
+
29
+ def default_collection_type_gid
30
+ Hyrax::CollectionType.find_or_create_default_collection_type.to_global_id
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end