hyrax 3.1.0 → 3.2.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 (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