hyrax 3.0.0.pre.rc4 → 3.1.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 (271) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +41 -8
  3. data/.dassie/Gemfile +10 -5
  4. data/.dassie/config/cable.yml +1 -1
  5. data/.dassie/config/environments/development.rb +2 -0
  6. data/.dassie/config/environments/production.rb +1 -1
  7. data/.dassie/config/initializers/hyrax.rb +5 -0
  8. data/.dassie/config/initializers/riiif.rb +22 -20
  9. data/.dassie/config/redis.yml +1 -0
  10. data/.dassie/config/role_map.yml +2 -0
  11. data/.dassie/db/seeds.rb +9 -1
  12. data/.dassie/package.json +3 -5
  13. data/.dockerignore +4 -0
  14. data/.env +1 -2
  15. data/.rubocop.yml +4 -0
  16. data/CONTAINERS.md +21 -1
  17. data/Dockerfile +46 -17
  18. data/Gemfile +21 -27
  19. data/app/actors/hyrax/actors/base_actor.rb +1 -1
  20. data/app/actors/hyrax/actors/create_with_remote_files_actor.rb +89 -41
  21. data/app/actors/hyrax/actors/create_with_remote_files_ordered_members_actor.rb +7 -42
  22. data/app/actors/hyrax/actors/file_actor.rb +4 -2
  23. data/app/actors/hyrax/actors/file_set_actor.rb +18 -11
  24. data/app/controllers/concerns/hyrax/collections_controller_behavior.rb +20 -8
  25. data/app/controllers/concerns/hyrax/embargoes_controller_behavior.rb +21 -9
  26. data/app/controllers/concerns/hyrax/leases_controller_behavior.rb +14 -5
  27. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +38 -8
  28. data/app/controllers/hyrax/admin/permission_template_accesses_controller.rb +0 -4
  29. data/app/controllers/hyrax/admin/workflows_controller.rb +8 -2
  30. data/app/controllers/hyrax/dashboard/collection_members_controller.rb +13 -9
  31. data/app/controllers/hyrax/dashboard/collections_controller.rb +14 -14
  32. data/app/controllers/hyrax/file_sets_controller.rb +49 -13
  33. data/app/controllers/hyrax/permissions_controller.rb +3 -4
  34. data/app/controllers/hyrax/workflow_actions_controller.rb +3 -1
  35. data/app/forms/hyrax/forms/collection_form.rb +12 -6
  36. data/app/forms/hyrax/forms/dashboard/nest_collection_form.rb +24 -2
  37. data/app/forms/hyrax/forms/file_set_form.rb +46 -0
  38. data/app/forms/hyrax/forms/permission.rb +23 -0
  39. data/app/forms/hyrax/forms/permission_template_form.rb +8 -2
  40. data/app/forms/hyrax/forms/resource_form.rb +31 -13
  41. data/app/forms/hyrax/forms/work_form.rb +5 -2
  42. data/app/helpers/hyrax/batch_edits_helper.rb +3 -1
  43. data/app/helpers/hyrax/collections_helper.rb +88 -2
  44. data/app/helpers/hyrax/dashboard_helper_behavior.rb +16 -5
  45. data/app/helpers/hyrax/embargo_helper.rb +4 -0
  46. data/app/helpers/hyrax/file_set_helper.rb +25 -6
  47. data/app/helpers/hyrax/hyrax_helper_behavior.rb +8 -0
  48. data/app/helpers/hyrax/lease_helper.rb +4 -0
  49. data/app/helpers/hyrax/url_helper.rb +4 -1
  50. data/app/helpers/hyrax/work_form_helper.rb +53 -0
  51. data/app/indexers/hyrax/administrative_set_indexer.rb +18 -0
  52. data/app/indexers/hyrax/valkyrie_file_set_indexer.rb +118 -0
  53. data/app/indexers/hyrax/valkyrie_indexer.rb +10 -4
  54. data/app/indexers/hyrax/valkyrie_work_indexer.rb +3 -1
  55. data/app/inputs/controlled_vocabulary_input.rb +2 -5
  56. data/app/jobs/attach_files_to_work_job.rb +19 -10
  57. data/app/jobs/attach_files_to_work_with_ordered_members_job.rb +6 -5
  58. data/app/jobs/embargo_expiry_job.rb +7 -5
  59. data/app/jobs/file_set_attached_event_job.rb +6 -1
  60. data/app/jobs/ingest_local_file_job.rb +18 -2
  61. data/app/jobs/inherit_permissions_job.rb +9 -5
  62. data/app/jobs/lease_expiry_job.rb +6 -4
  63. data/app/models/admin_set.rb +6 -25
  64. data/app/models/collection_branding_info.rb +25 -9
  65. data/app/models/concerns/hyrax/ability.rb +14 -1
  66. data/app/models/concerns/hyrax/collection_behavior.rb +17 -44
  67. data/app/models/concerns/hyrax/embargoable.rb +24 -0
  68. data/app/models/concerns/hyrax/file_set/characterization.rb +18 -12
  69. data/app/models/concerns/hyrax/solr_document_behavior.rb +9 -46
  70. data/app/models/concerns/hyrax/suppressible.rb +5 -0
  71. data/app/models/concerns/hyrax/user.rb +9 -3
  72. data/app/models/concerns/hyrax/work_behavior.rb +1 -1
  73. data/app/models/hyrax/file_set.rb +7 -0
  74. data/app/models/hyrax/pcdm_collection.rb +1 -0
  75. data/app/models/hyrax/permission_template.rb +98 -12
  76. data/app/models/hyrax/virus_scanner.rb +27 -18
  77. data/app/models/hyrax/work.rb +2 -0
  78. data/app/models/job_io_wrapper.rb +1 -1
  79. data/app/models/sipity/agent.rb +1 -0
  80. data/app/models/sipity/entity.rb +30 -8
  81. data/app/models/sipity/workflow.rb +1 -0
  82. data/app/models/sipity.rb +42 -0
  83. data/app/presenters/hyrax/admin_set_options_presenter.rb +12 -8
  84. data/app/presenters/hyrax/admin_set_presenter.rb +5 -1
  85. data/app/presenters/hyrax/admin_set_selection_presenter.rb +116 -0
  86. data/app/presenters/hyrax/collection_presenter.rb +41 -20
  87. data/app/presenters/hyrax/file_set_presenter.rb +6 -1
  88. data/app/presenters/hyrax/file_usage.rb +3 -2
  89. data/app/presenters/hyrax/pcdm_member_presenter_factory.rb +119 -0
  90. data/app/presenters/hyrax/stats_usage_presenter.rb +2 -1
  91. data/app/presenters/hyrax/trophy_presenter.rb +33 -4
  92. data/app/presenters/hyrax/user_profile_presenter.rb +11 -1
  93. data/app/presenters/hyrax/version_list_presenter.rb +19 -0
  94. data/app/presenters/hyrax/version_presenter.rb +3 -2
  95. data/app/presenters/hyrax/work_show_presenter.rb +30 -5
  96. data/app/presenters/hyrax/work_usage.rb +5 -3
  97. data/app/renderers/hyrax/renderers/attribute_renderer.rb +10 -2
  98. data/app/search_builders/hyrax/admin_set_search_builder.rb +1 -1
  99. data/app/search_builders/hyrax/collection_member_search_builder.rb +6 -1
  100. data/app/search_builders/hyrax/my/collections_search_builder.rb +2 -2
  101. data/app/search_builders/hyrax/nested_collections_parent_search_builder.rb +1 -1
  102. data/app/search_builders/hyrax/single_collection_search_builder.rb +1 -1
  103. data/app/services/hyrax/access_control_list.rb +1 -1
  104. data/app/services/hyrax/adapters/nesting_index_adapter.rb +1 -1
  105. data/app/services/hyrax/admin_set_create_service.rb +3 -1
  106. data/app/services/hyrax/collections/collection_member_search_service.rb +72 -0
  107. data/app/services/hyrax/collections/collection_member_service.rb +112 -27
  108. data/app/services/hyrax/collections/migration_service.rb +4 -2
  109. data/app/services/hyrax/collections/nested_collection_persistence_service.rb +12 -13
  110. data/app/services/hyrax/collections/nested_collection_query_service.rb +2 -0
  111. data/app/services/hyrax/collections/permissions_create_service.rb +6 -4
  112. data/app/services/hyrax/contextual_path.rb +24 -1
  113. data/app/services/hyrax/custom_queries/find_file_metadata.rb +7 -5
  114. data/app/services/hyrax/custom_queries/navigators/parent_collections_navigator.rb +46 -0
  115. data/app/services/hyrax/edit_permissions_service.rb +74 -41
  116. data/app/services/hyrax/embargo_manager.rb +1 -1
  117. data/app/services/hyrax/find_objects_via_solr_service.rb +31 -0
  118. data/app/services/hyrax/graph_exporter.rb +1 -1
  119. data/app/services/hyrax/listeners/member_cleanup_listener.rb +26 -0
  120. data/app/services/hyrax/listeners/metadata_index_listener.rb +18 -1
  121. data/app/services/hyrax/listeners/object_lifecycle_listener.rb +1 -1
  122. data/app/services/hyrax/listeners/trophy_cleanup_listener.rb +17 -0
  123. data/app/services/hyrax/listeners.rb +2 -0
  124. data/app/services/hyrax/multiple_membership_checker.rb +53 -29
  125. data/app/services/hyrax/persist_derivatives.rb +3 -1
  126. data/app/services/hyrax/resource_status.rb +7 -0
  127. data/app/services/hyrax/search_service.rb +4 -2
  128. data/app/services/hyrax/solr_query_builder_service.rb +45 -8
  129. data/app/services/hyrax/solr_query_service.rb +224 -0
  130. data/app/services/hyrax/solr_service.rb +8 -1
  131. data/app/services/hyrax/statistics/depositors/summary.rb +2 -1
  132. data/app/services/hyrax/thumbnail_path_service.rb +1 -1
  133. data/app/services/hyrax/versioning_service.rb +1 -1
  134. data/app/services/hyrax/visibility_intention.rb +20 -2
  135. data/app/services/hyrax/visibility_propagator.rb +30 -1
  136. data/app/services/hyrax/work_uploads_handler.rb +22 -4
  137. data/app/services/hyrax/workflow/actionable_objects.rb +70 -0
  138. data/app/services/hyrax/workflow/object_in_workflow_decorator.rb +31 -0
  139. data/app/services/hyrax/workflow/status_list_service.rb +43 -13
  140. data/app/views/hyrax/admin/admin_sets/_show_document_list_row.html.erb +1 -1
  141. data/app/views/hyrax/base/_form_child_work_relationships.html.erb +1 -1
  142. data/app/views/hyrax/base/_form_relationships.html.erb +1 -2
  143. data/app/views/hyrax/base/_form_rendering.html.erb +1 -1
  144. data/app/views/hyrax/base/_form_representative.html.erb +1 -1
  145. data/app/views/hyrax/base/_form_share.html.erb +1 -5
  146. data/app/views/hyrax/base/_form_thumbnail.html.erb +1 -1
  147. data/app/views/hyrax/base/_form_visibility_error.html.erb +2 -0
  148. data/app/views/hyrax/base/_guts4form.html.erb +3 -3
  149. data/app/views/hyrax/base/_representative_media.html.erb +1 -1
  150. data/app/views/hyrax/base/_show_actions.html.erb +2 -2
  151. data/app/views/hyrax/base/_work_button_row.html.erb +1 -1
  152. data/app/views/hyrax/base/_workflow_actions.html.erb +1 -1
  153. data/app/views/hyrax/batch_edits/edit.html.erb +2 -2
  154. data/app/views/hyrax/batch_uploads/_form.html.erb +1 -1
  155. data/app/views/hyrax/collections/_list_collections.html.erb +1 -1
  156. data/app/views/hyrax/collections/_search_form.html.erb +1 -1
  157. data/app/views/hyrax/collections/show.html.erb +1 -1
  158. data/app/views/hyrax/dashboard/collections/_form.html.erb +3 -3
  159. data/app/views/hyrax/dashboard/collections/_form_branding.html.erb +1 -1
  160. data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +1 -1
  161. data/app/views/hyrax/dashboard/collections/edit.html.erb +4 -2
  162. data/app/views/hyrax/dashboard/collections/new.html.erb +4 -2
  163. data/app/views/hyrax/dashboard/collections/show.html.erb +1 -1
  164. data/app/views/hyrax/file_sets/_actions.html.erb +10 -0
  165. data/app/views/hyrax/file_sets/edit.html.erb +1 -1
  166. data/app/views/hyrax/file_sets/media_display/_audio.html.erb +1 -1
  167. data/app/views/hyrax/file_sets/media_display/_default.html.erb +1 -1
  168. data/app/views/hyrax/file_sets/media_display/_image.html.erb +1 -1
  169. data/app/views/hyrax/file_sets/media_display/_office_document.html.erb +1 -1
  170. data/app/views/hyrax/file_sets/media_display/_pdf.html.erb +1 -1
  171. data/app/views/hyrax/file_sets/media_display/_video.html.erb +1 -1
  172. data/app/views/hyrax/file_sets/show.html.erb +1 -1
  173. data/app/views/hyrax/my/_admin_set_action_menu.html.erb +0 -11
  174. data/app/views/hyrax/my/_collection_action_menu.html.erb +1 -2
  175. data/app/views/hyrax/my/collections/_list_collections.html.erb +1 -1
  176. data/app/views/hyrax/my/collections/_modal_add_subcollection.html.erb +3 -5
  177. data/app/views/hyrax/stats/file.html.erb +1 -1
  178. data/app/views/hyrax/stats/work.html.erb +1 -1
  179. data/app/views/hyrax/uploads/_js_templates.html.erb +4 -4
  180. data/app/views/hyrax/uploads/_js_templates_versioning.html.erb +4 -4
  181. data/app/views/hyrax/users/_contributions.html.erb +1 -1
  182. data/app/views/hyrax/users/_profile_tabs.html.erb +2 -2
  183. data/app/views/hyrax/users/_search_form.html.erb +1 -1
  184. data/app/views/hyrax/users/_user.html.erb +1 -1
  185. data/app/views/hyrax/users/_user_info.html.erb +9 -9
  186. data/bin/db-migrate-seed.sh +6 -2
  187. data/bin/hyrax-entrypoint.sh +0 -14
  188. data/bin/solrcloud-assign-configset.sh +35 -0
  189. data/bin/solrcloud-upload-configset.sh +42 -0
  190. data/chart/hyrax/Chart.yaml +12 -8
  191. data/chart/hyrax/README.md +94 -11
  192. data/chart/hyrax/templates/NOTES.txt +1 -1
  193. data/chart/hyrax/templates/_helpers.tpl +98 -0
  194. data/chart/hyrax/templates/branding-pvc.yaml +14 -0
  195. data/chart/hyrax/templates/configmap-env.yaml +21 -11
  196. data/chart/hyrax/templates/cron-embargo.yaml +24 -0
  197. data/chart/hyrax/templates/cron-lease.yaml +24 -0
  198. data/chart/hyrax/templates/deployment-worker.yaml +129 -0
  199. data/chart/hyrax/templates/deployment.yaml +125 -4
  200. data/chart/hyrax/templates/derivatives-pvc.yaml +14 -0
  201. data/chart/hyrax/templates/ingress.yaml +13 -4
  202. data/chart/hyrax/templates/secrets.yaml +12 -2
  203. data/chart/hyrax/templates/uploads-pvc.yaml +14 -0
  204. data/chart/hyrax/values.yaml +186 -2
  205. data/config/brakeman.ignore +2 -2
  206. data/config/features.rb +47 -43
  207. data/config/initializers/listeners.rb +4 -0
  208. data/config/initializers/valkryrie_storage.rb +7 -0
  209. data/config/locales/hyrax.de.yml +1 -1
  210. data/config/locales/hyrax.en.yml +1 -1
  211. data/config/locales/hyrax.es.yml +1 -1
  212. data/config/locales/hyrax.fr.yml +1 -1
  213. data/config/locales/hyrax.it.yml +1 -1
  214. data/config/locales/hyrax.pt-BR.yml +1 -1
  215. data/config/locales/hyrax.zh.yml +1 -1
  216. data/docker-compose.yml +39 -8
  217. data/documentation/developing-your-hyrax-based-app.md +4 -4
  218. data/documentation/legacyREADME.md +3 -3
  219. data/lib/generators/hyrax/templates/config/initializers/hyrax.rb +5 -0
  220. data/lib/generators/hyrax/templates/config/initializers/riiif.rb +22 -20
  221. data/lib/hyrax/active_fedora_dummy_model.rb +62 -0
  222. data/lib/hyrax/configuration.rb +28 -0
  223. data/lib/hyrax/engine.rb +3 -1
  224. data/lib/hyrax/errors.rb +2 -0
  225. data/lib/hyrax/resource_name.rb +1 -0
  226. data/lib/hyrax/specs/capybara.rb +5 -3
  227. data/lib/hyrax/specs/shared_specs/valkyrie_storage_versions.rb +9 -0
  228. data/lib/hyrax/transactions/container.rb +32 -1
  229. data/lib/hyrax/transactions/file_set_destroy.rb +21 -0
  230. data/lib/hyrax/transactions/steps/add_file_sets.rb +3 -2
  231. data/lib/hyrax/transactions/steps/add_to_parent.rb +36 -0
  232. data/lib/hyrax/transactions/steps/delete_resource.rb +38 -0
  233. data/lib/hyrax/transactions/steps/destroy_work.rb +1 -0
  234. data/lib/hyrax/transactions/steps/remove_file_set_from_work.rb +47 -0
  235. data/lib/hyrax/transactions/work_create.rb +2 -1
  236. data/lib/hyrax/transactions/work_destroy.rb +20 -0
  237. data/lib/hyrax/valkyrie_can_can_adapter.rb +3 -0
  238. data/lib/hyrax/valkyrie_simple_path_generator.rb +20 -0
  239. data/lib/hyrax/version.rb +1 -1
  240. data/lib/hyrax.rb +9 -0
  241. data/lib/tasks/collection_type_global_id.rake +1 -1
  242. data/lib/tasks/embargo_lease.rake +27 -0
  243. data/lib/tasks/regenerate_derivatives.rake +12 -0
  244. data/lib/wings/active_fedora_converter/default_work.rb +19 -0
  245. data/lib/wings/attribute_transformer.rb +29 -19
  246. data/lib/wings/converter_value_mapper.rb +2 -2
  247. data/lib/wings/model_transformer.rb +21 -20
  248. data/lib/wings/orm_converter.rb +42 -23
  249. data/lib/wings/setup.rb +2 -0
  250. data/lib/wings/valkyrie/persister.rb +8 -5
  251. data/lib/wings/valkyrie/query_service.rb +96 -41
  252. data/lib/wings/valkyrie/storage.rb +56 -1
  253. data/lib/wings.rb +0 -21
  254. data/template.rb +1 -1
  255. metadata +41 -21
  256. data/chart/fcrepo/.gitignore +0 -2
  257. data/chart/fcrepo/.helmignore +0 -23
  258. data/chart/fcrepo/Chart.yaml +0 -11
  259. data/chart/fcrepo/README.md +0 -50
  260. data/chart/fcrepo/templates/NOTES.txt +0 -21
  261. data/chart/fcrepo/templates/_helpers.tpl +0 -68
  262. data/chart/fcrepo/templates/configmap-env.yaml +0 -19
  263. data/chart/fcrepo/templates/deployment.yaml +0 -109
  264. data/chart/fcrepo/templates/ingress.yaml +0 -41
  265. data/chart/fcrepo/templates/pvc.yaml +0 -20
  266. data/chart/fcrepo/templates/secret.yaml +0 -12
  267. data/chart/fcrepo/templates/service.yaml +0 -15
  268. data/chart/fcrepo/templates/serviceaccount.yaml +0 -12
  269. data/chart/fcrepo/templates/tests/test-connection.yaml +0 -15
  270. data/chart/fcrepo/values.yaml +0 -79
  271. data/chart/hyrax/templates/fcrepo-secret.yaml +0 -13
data/Gemfile CHANGED
@@ -1,44 +1,38 @@
1
1
  # frozen_string_literal: true
2
- source 'https://rubygems.org' do
3
- # Please see hyrax.gemspec for dependency information.
4
- gemspec
2
+ source 'https://rubygems.org'
3
+ # Please see hyrax.gemspec for dependency information.
4
+ gemspec
5
5
 
6
- group :development, :test do
7
- gem 'benchmark-ips'
8
- gem 'easy_translate'
9
- gem 'i18n-tasks'
10
- gem 'okcomputer'
11
- gem 'pry' unless ENV['CI']
12
- gem 'pry-byebug' unless ENV['CI']
13
- gem 'ruby-prof', require: false
14
- gem "simplecov", require: false
15
- end
6
+ group :development, :test do
7
+ gem 'benchmark-ips'
8
+ gem 'easy_translate'
9
+ gem 'i18n-tasks'
10
+ gem 'okcomputer'
11
+ gem 'pry' unless ENV['CI']
12
+ gem 'pry-byebug' unless ENV['CI']
13
+ gem 'ruby-prof', require: false
14
+ gem "simplecov", require: false
16
15
  end
17
16
 
18
17
  test_app_path = ENV['RAILS_ROOT'] ||
19
18
  ENV.fetch('ENGINE_CART_DESTINATION', File.expand_path('.internal_test_app', File.dirname(__FILE__)))
20
19
  test_app_gemfile = File.expand_path('Gemfile', test_app_path)
21
20
 
21
+ # rubocop:disable Bundler/DuplicatedGem
22
22
  if File.exist?(test_app_gemfile)
23
23
  begin
24
+ Bundler.ui.info "[Hyrax] Including test application dependencies from #{test_app_gemfile}"
24
25
  eval_gemfile test_app_gemfile
25
26
  rescue Bundler::GemfileError => e
26
27
  Bundler.ui.warn '[Hyrax] Skipping Rails application dependencies:'
27
28
  Bundler.ui.warn e.message
28
29
  end
30
+ elsif ENV['RAILS_VERSION'] == 'edge'
31
+ gem 'rails', github: 'rails/rails', source: 'https://rubygems.org'
32
+ ENV['ENGINE_CART_RAILS_OPTIONS'] = '--edge --skip-turbolinks'
33
+ elsif ENV['RAILS_VERSION']
34
+ gem 'rails', ENV['RAILS_VERSION'], source: 'https://rubygems.org'
29
35
  else
30
- Bundler.ui.warn "[Hyrax] Unable to find test application dependencies in #{test_app_gemfile}, using placeholder dependencies"
31
-
32
- # rubocop:disable Bundler/DuplicatedGem
33
- if ENV['RAILS_VERSION']
34
- if ENV['RAILS_VERSION'] == 'edge'
35
- gem 'rails', github: 'rails/rails', source: 'https://rubygems.org'
36
- ENV['ENGINE_CART_RAILS_OPTIONS'] = '--edge --skip-turbolinks'
37
- else
38
- gem 'rails', ENV['RAILS_VERSION'], source: 'https://rubygems.org'
39
- end
40
- end
41
- # rubocop:enable Bundler/DuplicatedGem
42
-
43
- eval_gemfile File.expand_path('spec/test_app_templates/Gemfile.extra', File.dirname(__FILE__))
36
+ Bundler.ui.warn '[Hyrax] Skipping all Rails dependency injection'
44
37
  end
38
+ # rubocop:enable Bundler/DuplicatedGem
@@ -95,7 +95,7 @@ module Hyrax
95
95
  def clean_attributes(attributes)
96
96
  attributes[:license] = Array(attributes[:license]) if attributes.key? :license
97
97
  attributes[:rights_statement] = Array(attributes[:rights_statement]) if attributes.key? :rights_statement
98
- remove_blank_attributes!(attributes)
98
+ remove_blank_attributes!(attributes).except('file_set')
99
99
  end
100
100
 
101
101
  # If any attributes are blank remove them
@@ -26,64 +26,112 @@ module Hyrax
26
26
 
27
27
  private
28
28
 
29
- def registered_ingest_dirs
30
- Hyrax.config.registered_ingest_dirs
29
+ def attach_files(env, remote_files)
30
+ ingest_remote_files_service_class.new(user: env.user,
31
+ curation_concern: env.curation_concern,
32
+ remote_files: remote_files,
33
+ file_set_actor_class: file_set_actor_class).attach!
31
34
  end
32
35
 
33
- # @param uri [URI] the uri fo the resource to import
34
- def validate_remote_url(uri)
35
- if uri.scheme == 'file'
36
- path = File.absolute_path(CGI.unescape(uri.path))
37
- registered_ingest_dirs.any? do |dir|
38
- path.start_with?(dir) && path.length > dir.length
36
+ class IngestRemoteFilesService
37
+ ##
38
+ # @parm user [User]
39
+ # @parm curation_concern [Hyrax::Work]
40
+ # @param remote_files [HashWithIndifferentAccess]
41
+ # @param file_set_actor_class
42
+ # @param ordered_members [Array]
43
+ # @param ordered [Boolean]
44
+ # rubocop:disable Metrics/ParameterLists
45
+ def initialize(user:, curation_concern:, remote_files:, file_set_actor_class:, ordered_members: [], ordered: false)
46
+ @remote_files = remote_files
47
+ @user = user
48
+ @curation_concern = curation_concern
49
+ @file_set_actor_class = file_set_actor_class
50
+ @ordered_members = ordered_members
51
+ @ordered = ordered
52
+ end
53
+ # rubocop:enable Metrics/ParameterLists
54
+ attr_reader :remote_files, :user, :curation_concern, :ordered_members, :ordered, :file_set_actor_class
55
+
56
+ ##
57
+ # @return true
58
+ def attach!
59
+ return true unless remote_files
60
+ remote_files.each do |file_info|
61
+ next if file_info.blank? || file_info[:url].blank?
62
+ # Escape any space characters, so that this is a legal URI
63
+ uri = URI.parse(Addressable::URI.escape(file_info[:url]))
64
+ unless self.class.validate_remote_url(uri)
65
+ Rails.logger.error "User #{user.user_key} attempted to ingest file from url #{file_info[:url]}, which doesn't pass validation"
66
+ return false
67
+ end
68
+ auth_header = file_info.fetch(:auth_header, {})
69
+ create_file_from_url(uri, file_info[:file_name], auth_header)
39
70
  end
40
- else
41
- Rails.logger.debug "Assuming #{uri.scheme} uri is valid without a serious attempt to validate: #{uri}"
71
+ add_ordered_members! if ordered
42
72
  true
43
73
  end
44
- end
45
74
 
46
- # @param [HashWithIndifferentAccess] remote_files
47
- # @return [TrueClass]
48
- def attach_files(env, remote_files)
49
- return true unless remote_files
50
- remote_files.each do |file_info|
51
- next if file_info.blank? || file_info[:url].blank?
52
- # Escape any space characters, so that this is a legal URI
53
- uri = URI.parse(Addressable::URI.escape(file_info[:url]))
54
- unless validate_remote_url(uri)
55
- Rails.logger.error "User #{env.user.user_key} attempted to ingest file from url #{file_info[:url]}, which doesn't pass validation"
56
- return false
75
+ def self.registered_ingest_dirs
76
+ Hyrax.config.registered_ingest_dirs
77
+ end
78
+
79
+ # @param uri [URI] the uri fo the resource to import
80
+ def self.validate_remote_url(uri)
81
+ if uri.scheme == 'file'
82
+ path = File.absolute_path(CGI.unescape(uri.path))
83
+ registered_ingest_dirs.any? do |dir|
84
+ path.start_with?(dir) && path.length > dir.length
85
+ end
86
+ else
87
+ Rails.logger.debug "Assuming #{uri.scheme} uri is valid without a serious attempt to validate: #{uri}"
88
+ true
57
89
  end
58
- auth_header = file_info.fetch(:auth_header, {})
59
- create_file_from_url(env, uri, file_info[:file_name], auth_header)
60
90
  end
61
- true
62
- end
63
91
 
64
- # Generic utility for creating FileSet from a URL
65
- # Used in to import files using URLs from a file picker like browse_everything
66
- def create_file_from_url(env, uri, file_name, auth_header = {})
67
- import_url = URI.decode_www_form_component(uri.to_s)
68
- ::FileSet.new(import_url: import_url, label: file_name) do |fs|
69
- actor = Hyrax::Actors::FileSetActor.new(fs, env.user)
70
- actor.create_metadata(visibility: env.curation_concern.visibility)
71
- actor.attach_to_work(env.curation_concern)
72
- fs.save!
92
+ private
93
+
94
+ def create_file_from_url(uri, file_name, auth_header)
95
+ import_url = URI.decode_www_form_component(uri.to_s)
96
+ use_valkyrie = false
97
+ case curation_concern
98
+ when Valkyrie::Resource
99
+ file_set = Hyrax.persister.save(resource: Hyrax::FileSet.new(import_url: import_url, label: file_name))
100
+ use_valkyrie = true
101
+ else
102
+ file_set = ::FileSet.new(import_url: import_url, label: file_name)
103
+ end
104
+ __create_file_from_url(file_set: file_set, uri: uri, auth_header: auth_header, use_valkyrie: use_valkyrie)
105
+ end
106
+
107
+ def __create_file_from_url(file_set:, uri:, auth_header:, use_valkyrie: Hyrax.config.use_valkyrie?)
108
+ actor = file_set_actor_class.new(file_set, user, use_valkyrie: use_valkyrie)
109
+ actor.create_metadata(visibility: curation_concern.visibility)
110
+ actor.attach_to_work(curation_concern)
111
+ file_set.save! if file_set.respond_to?(:save!)
112
+ # We'll remember the order, but if it's not `@ordered` we won't do anything.
113
+ ordered_members << file_set
73
114
  if uri.scheme == 'file'
74
115
  # Turn any %20 into spaces.
75
116
  file_path = CGI.unescape(uri.path)
76
- IngestLocalFileJob.perform_later(fs, file_path, env.user)
117
+ IngestLocalFileJob.perform_later(file_set, file_path, user)
77
118
  else
78
- ImportUrlJob.perform_later(fs, operation_for(user: actor.user), auth_header)
119
+ ImportUrlJob.perform_later(file_set, operation_for(user: user), auth_header)
79
120
  end
80
121
  end
81
- end
82
122
 
83
- def operation_for(user:)
84
- Hyrax::Operation.create!(user: user,
85
- operation_type: "Attach Remote File")
123
+ def operation_for(user:)
124
+ Hyrax::Operation.create!(user: user,
125
+ operation_type: "Attach Remote File")
126
+ end
127
+
128
+ def add_ordered_members!
129
+ actor = Hyrax::Actors::OrderedMembersActor.new(ordered_members, user)
130
+ actor.attach_ordered_members_to_work(curation_concern)
131
+ end
86
132
  end
133
+ class_attribute :file_set_actor_class, default: ::Hyrax::Actors::FileSetActor
134
+ class_attribute :ingest_remote_files_service_class, default: ::Hyrax::Actors::CreateWithRemoteFilesActor::IngestRemoteFilesService
87
135
  end
88
136
  end
89
137
  end
@@ -39,54 +39,19 @@ module Hyrax
39
39
  # url property, it may have spaces, and not be a valid URI.
40
40
  class CreateWithRemoteFilesOrderedMembersActor < CreateWithRemoteFilesActor
41
41
  attr_reader :ordered_members
42
+ self.file_set_actor_class = Hyrax::Actors::FileSetOrderedMembersActor
42
43
 
43
44
  # @param [HashWithIndifferentAccess] remote_files
44
45
  # @return [TrueClass]
45
46
  def attach_files(env, remote_files)
46
- return true unless remote_files
47
47
  @ordered_members = env.curation_concern.ordered_members.to_a
48
- remote_files.each do |file_info|
49
- next if file_info.blank? || file_info[:url].blank?
50
- # Escape any space characters, so that this is a legal URI
51
- uri = URI.parse(Addressable::URI.escape(file_info[:url]))
52
- unless validate_remote_url(uri)
53
- Rails.logger.error "User #{env.user.user_key} attempted to ingest file from url #{file_info[:url]}, which doesn't pass validation"
54
- return false
55
- end
56
- auth_header = file_info.fetch(:auth_header, {})
57
- create_file_from_url(env, uri, file_info[:file_name], auth_header)
58
- end
59
- add_ordered_members(env.user, env.curation_concern)
60
- true
61
- end
62
-
63
- # Generic utility for creating FileSet from a URL
64
- # Used in to import files using URLs from a file picker like browse_everything
65
- def create_file_from_url(env, uri, file_name, auth_header = {})
66
- ::FileSet.new(import_url: uri.to_s, label: file_name) do |fs|
67
- actor = file_set_actor_class.new(fs, env.user)
68
- actor.create_metadata(visibility: env.curation_concern.visibility)
69
- actor.attach_to_work(env.curation_concern)
70
- fs.save!
71
- ordered_members << fs
72
- if uri.scheme == 'file'
73
- # Turn any %20 into spaces.
74
- file_path = CGI.unescape(uri.path)
75
- IngestLocalFileJob.perform_later(fs, file_path, env.user)
76
- else
77
- ImportUrlJob.perform_later(fs, operation_for(user: actor.user), auth_header)
78
- end
79
- end
48
+ ingest_remote_files_service_class.new(user: env.user,
49
+ curation_concern: env.curation_concern,
50
+ remote_files: remote_files,
51
+ ordered_members: @ordered_members,
52
+ ordered: true,
53
+ file_set_actor_class: file_set_actor_class).attach!
80
54
  end
81
-
82
- # Add all file_sets as ordered_members in a single action
83
- def add_ordered_members(user, work)
84
- actor = Hyrax::Actors::OrderedMembersActor.new(ordered_members, user)
85
- actor.attach_ordered_members_to_work(work)
86
- end
87
-
88
- class_attribute :file_set_actor_class
89
- self.file_set_actor_class = Hyrax::Actors::FileSetOrderedMembersActor
90
55
  end
91
56
  end
92
57
  end
@@ -11,7 +11,7 @@ module Hyrax
11
11
  # @param [FileSet] file_set the parent FileSet
12
12
  # @param [Symbol, #to_sym] relation the type/use for the file
13
13
  # @param [User] user the user to record as the Agent acting upon the file
14
- def initialize(file_set, relation, user, use_valkyrie: false)
14
+ def initialize(file_set, relation, user, use_valkyrie: Hyrax.config.query_index_from_valkyrie)
15
15
  @use_valkyrie = use_valkyrie
16
16
  @file_set = file_set
17
17
  @relation = normalize_relation(relation)
@@ -75,7 +75,7 @@ module Hyrax
75
75
  CharacterizeJob.perform_later(file_set, repository_file.id, pathhint(io))
76
76
  end
77
77
 
78
- def perform_ingest_file_through_valkyrie(io)
78
+ def perform_ingest_file_through_valkyrie(io) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
79
79
  file =
80
80
  begin
81
81
  Hyrax.storage_adapter.upload(resource: file_set, file: io, original_filename: io.original_name, use: relation)
@@ -87,7 +87,9 @@ module Hyrax
87
87
  create_version(file_metadata, user)
88
88
  id = file_metadata.file_identifier
89
89
  file_set.file_ids << id
90
+ file_set.original_file_id = id
90
91
  Hyrax.persister.save(resource: file_set)
92
+ Hyrax.publisher.publish('object.metadata.updated', object: file_set, user: user)
91
93
  CharacterizeJob.perform_later(file_set, id.to_s, pathhint(io))
92
94
  file_metadata
93
95
  end
@@ -6,7 +6,7 @@ module Hyrax
6
6
  include Lockable
7
7
  attr_reader :file_set, :user, :attributes, :use_valkyrie
8
8
 
9
- def initialize(file_set, user, use_valkyrie: false)
9
+ def initialize(file_set, user, use_valkyrie: Hyrax.config.query_index_from_valkyrie)
10
10
  @use_valkyrie = use_valkyrie
11
11
  @file_set = file_set
12
12
  @user = user
@@ -31,10 +31,9 @@ module Hyrax
31
31
  # hand. Do this because we don't have the underlying UploadedFile instance
32
32
  file_actor = build_file_actor(relation)
33
33
  file_actor.ingest_file(wrapper!(file: file, relation: relation))
34
- # Copy visibility and permissions from parent (work) to
35
- # FileSets even if they come in from BrowseEverything
36
- VisibilityCopyJob.perform_later(file_set.parent)
37
- InheritPermissionsJob.perform_later(file_set.parent)
34
+ parent = parent_for(file_set: file_set)
35
+ VisibilityCopyJob.perform_later(parent)
36
+ InheritPermissionsJob.perform_later(parent)
38
37
  else
39
38
  IngestJob.perform_later(wrapper!(file: file, relation: relation))
40
39
  end
@@ -68,7 +67,6 @@ module Hyrax
68
67
  yield(file_set) if block_given?
69
68
  end
70
69
 
71
- # Adds a FileSet to the work using ore:Aggregations.
72
70
  # Locks to ensure that only one process is operating on the list at a time.
73
71
  def attach_to_work(work, file_set_params = {})
74
72
  acquire_lock_for(work.id) do
@@ -87,15 +85,18 @@ module Hyrax
87
85
  def attach_to_valkyrie_work(work, file_set_params)
88
86
  work = Hyrax.query_service.find_by(id: work.id) unless work.new_record
89
87
  file_set.visibility = work.visibility unless assign_visibility?(file_set_params)
90
- Hyrax.persister.save(resource: file_set)
91
- work.member_ids << file_set.id
92
- work.representative_id = file_set.id if work.representative_id.blank?
93
- work.thumbnail_id = file_set.id if work.thumbnail_id.blank?
88
+ fs = Hyrax.persister.save(resource: file_set)
89
+ Hyrax.publisher.publish('object.metadata.updated', object: fs, user: user)
90
+ work.member_ids << fs.id
91
+ work.representative_id = fs.id if work.representative_id.blank?
92
+ work.thumbnail_id = fs.id if work.thumbnail_id.blank?
94
93
  # Save the work so the association between the work and the file_set is persisted (head_id)
95
94
  # NOTE: the work may not be valid, in which case this save doesn't do anything.
96
95
  Hyrax.persister.save(resource: work)
96
+ Hyrax.publisher.publish('object.metadata.updated', object: work, user: user)
97
97
  end
98
98
 
99
+ # Adds a FileSet to the work using ore:Aggregations.
99
100
  def attach_to_af_work(work, file_set_params)
100
101
  work.reload unless work.new_record?
101
102
  file_set.visibility = work.visibility unless assign_visibility?(file_set_params)
@@ -136,6 +137,12 @@ module Hyrax
136
137
  @ability ||= ::Ability.new(user)
137
138
  end
138
139
 
140
+ # @param file_set [FileSet]
141
+ # @return [ActiveFedora::Base]
142
+ def parent_for(file_set:)
143
+ file_set.parent
144
+ end
145
+
139
146
  def build_file_actor(relation)
140
147
  fs = use_valkyrie ? file_set.valkyrie_resource : file_set
141
148
  file_actor_class.new(fs, relation, user, use_valkyrie: use_valkyrie)
@@ -177,7 +184,7 @@ module Hyrax
177
184
  # Although ActiveFedora clears the children nodes it leaves those fields in Solr populated.
178
185
  # rubocop:disable Metrics/CyclomaticComplexity
179
186
  def unlink_from_work
180
- work = file_set.parent
187
+ work = parent_for(file_set: file_set)
181
188
  return unless work && (work.thumbnail_id == file_set.id || work.representative_id == file_set.id || work.rendering_ids.include?(file_set.id))
182
189
  work.thumbnail = nil if work.thumbnail_id == file_set.id
183
190
  work.representative = nil if work.representative_id == file_set.id
@@ -15,14 +15,17 @@ module Hyrax
15
15
  class_attribute :presenter_class,
16
16
  :form_class,
17
17
  :single_item_search_builder_class,
18
- :membership_service_class
18
+ :membership_service_class,
19
+ :parent_collection_query_service
19
20
 
20
21
  self.presenter_class = Hyrax::CollectionPresenter
21
22
 
22
23
  # The search builder to find the collection
23
24
  self.single_item_search_builder_class = SingleCollectionSearchBuilder
24
25
  # The search builder to find the collections' members
25
- self.membership_service_class = Collections::CollectionMemberService
26
+ self.membership_service_class = Collections::CollectionMemberSearchService
27
+ # A search service to use in finding parent collections
28
+ self.parent_collection_query_service = Collections::NestedCollectionQueryService
26
29
  end
27
30
 
28
31
  def show
@@ -74,9 +77,9 @@ module Hyrax
74
77
  end
75
78
 
76
79
  def query_collection_members
77
- member_works
78
- member_subcollections if collection.collection_type.nestable?
79
- parent_collections if collection.collection_type.nestable? && action_name == 'show'
80
+ load_member_works
81
+ load_member_subcollections if collection.collection_type.nestable?
82
+ load_parent_collections if collection.collection_type.nestable? && action_name == 'show'
80
83
  end
81
84
 
82
85
  # Instantiate the membership query service
@@ -89,12 +92,20 @@ module Hyrax
89
92
  @member_docs = @response.documents
90
93
  @members_count = @response.total
91
94
  end
95
+ alias load_member_works member_works
92
96
 
93
- def parent_collections
97
+ ##
98
+ # Handles paged loading for parent collections.
99
+ #
100
+ # @param the query service to use when searching for the parent collections.
101
+ # uses the class attribute +parent_collection_query_service+ by default.
102
+ def parent_collections(query_service: self.class.parent_collection_query_service)
94
103
  page = params[:parent_collection_page].to_i
95
- query = Hyrax::Collections::NestedCollectionQueryService
96
- collection.parent_collections = query.parent_collections(child: collection_object, scope: self, page: page)
104
+ collection.parent_collections = query_service.parent_collections(
105
+ child: collection_object, scope: self, page: page
106
+ )
97
107
  end
108
+ alias load_parent_collections parent_collections
98
109
 
99
110
  def collection_object
100
111
  action_name == 'show' ? Collection.find(collection.id) : collection
@@ -106,6 +117,7 @@ module Hyrax
106
117
  @subcollection_docs = results.documents
107
118
  @subcollection_count = @presenter.subcollection_count = results.total
108
119
  end
120
+ alias load_member_subcollections member_subcollections
109
121
 
110
122
  # You can override this method if you need to provide additional inputs to the search
111
123
  # builder. For example: