hyrax 3.0.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (287) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +46 -13
  3. data/.dassie/Gemfile +11 -6
  4. data/.dassie/app/controllers/catalog_controller.rb +6 -0
  5. data/.dassie/config/initializers/hyrax.rb +5 -0
  6. data/.dassie/config/initializers/riiif.rb +22 -20
  7. data/.dassie/config/role_map.yml +2 -0
  8. data/.dassie/db/seeds.rb +1 -1
  9. data/.dassie/package.json +3 -5
  10. data/.dockerignore +3 -0
  11. data/.env +1 -2
  12. data/.rubocop.yml +4 -0
  13. data/CONTAINERS.md +21 -1
  14. data/Dockerfile +42 -17
  15. data/Gemfile +21 -27
  16. data/app/actors/hyrax/actors/base_actor.rb +2 -2
  17. data/app/actors/hyrax/actors/collections_membership_actor.rb +3 -3
  18. data/app/actors/hyrax/actors/create_with_remote_files_actor.rb +85 -63
  19. data/app/actors/hyrax/actors/create_with_remote_files_ordered_members_actor.rb +7 -42
  20. data/app/actors/hyrax/actors/file_set_actor.rb +12 -5
  21. data/app/assets/stylesheets/hyrax/_styles.scss +5 -0
  22. data/app/controllers/concerns/hyrax/collections_controller_behavior.rb +30 -10
  23. data/app/controllers/concerns/hyrax/controller.rb +13 -2
  24. data/app/controllers/concerns/hyrax/embargoes_controller_behavior.rb +21 -9
  25. data/app/controllers/concerns/hyrax/leases_controller_behavior.rb +14 -5
  26. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +22 -3
  27. data/app/controllers/hyrax/admin/admin_sets_controller.rb +2 -19
  28. data/app/controllers/hyrax/admin/permission_template_accesses_controller.rb +5 -6
  29. data/app/controllers/hyrax/admin/workflows_controller.rb +8 -2
  30. data/app/controllers/hyrax/collections_controller.rb +3 -1
  31. data/app/controllers/hyrax/dashboard/collection_members_controller.rb +24 -17
  32. data/app/controllers/hyrax/dashboard/collections_controller.rb +99 -35
  33. data/app/controllers/hyrax/dashboard/nest_collections_controller.rb +75 -39
  34. data/app/controllers/hyrax/file_sets_controller.rb +49 -13
  35. data/app/controllers/hyrax/my_controller.rb +4 -4
  36. data/app/controllers/hyrax/permissions_controller.rb +3 -4
  37. data/app/controllers/hyrax/workflow_actions_controller.rb +11 -6
  38. data/app/forms/hyrax/forms/administrative_set_form.rb +62 -0
  39. data/app/forms/hyrax/forms/collection_form.rb +14 -8
  40. data/app/forms/hyrax/forms/dashboard/nest_collection_form.rb +38 -6
  41. data/app/forms/hyrax/forms/file_set_form.rb +46 -0
  42. data/app/forms/hyrax/forms/pcdm_collection_form.rb +64 -0
  43. data/app/forms/hyrax/forms/permission.rb +23 -0
  44. data/app/forms/hyrax/forms/permission_template_form.rb +8 -2
  45. data/app/forms/hyrax/forms/resource_form.rb +34 -26
  46. data/app/forms/hyrax/forms/work_form.rb +5 -2
  47. data/app/forms/hyrax/forms/workflow_action_form.rb +4 -0
  48. data/app/helpers/hyrax/batch_edits_helper.rb +3 -1
  49. data/app/helpers/hyrax/collections_helper.rb +88 -2
  50. data/app/helpers/hyrax/dashboard_helper_behavior.rb +16 -5
  51. data/app/helpers/hyrax/embargo_helper.rb +4 -0
  52. data/app/helpers/hyrax/file_set_helper.rb +25 -6
  53. data/app/helpers/hyrax/hyrax_helper_behavior.rb +9 -0
  54. data/app/helpers/hyrax/lease_helper.rb +4 -0
  55. data/app/helpers/hyrax/url_helper.rb +4 -1
  56. data/app/helpers/hyrax/work_form_helper.rb +53 -0
  57. data/app/indexers/hyrax/administrative_set_indexer.rb +18 -0
  58. data/app/indexers/hyrax/pcdm_collection_indexer.rb +2 -0
  59. data/app/indexers/hyrax/valkyrie_file_set_indexer.rb +2 -0
  60. data/app/indexers/hyrax/valkyrie_indexer.rb +4 -3
  61. data/app/indexers/hyrax/valkyrie_work_indexer.rb +1 -1
  62. data/app/inputs/controlled_vocabulary_input.rb +2 -5
  63. data/app/jobs/attach_files_to_work_job.rb +19 -10
  64. data/app/jobs/attach_files_to_work_with_ordered_members_job.rb +6 -5
  65. data/app/jobs/ingest_local_file_job.rb +18 -2
  66. data/app/jobs/inherit_permissions_job.rb +9 -5
  67. data/app/models/admin_set.rb +22 -30
  68. data/app/models/collection_branding_info.rb +25 -9
  69. data/app/models/concerns/hyrax/ability/admin_set_ability.rb +31 -7
  70. data/app/models/concerns/hyrax/ability/collection_ability.rb +35 -20
  71. data/app/models/concerns/hyrax/ability/collection_type_ability.rb +1 -1
  72. data/app/models/concerns/hyrax/ability.rb +5 -3
  73. data/app/models/concerns/hyrax/collection_behavior.rb +17 -44
  74. data/app/models/concerns/hyrax/embargoable.rb +24 -0
  75. data/app/models/concerns/hyrax/file_set/characterization.rb +18 -12
  76. data/app/models/concerns/hyrax/solr_document_behavior.rb +11 -54
  77. data/app/models/concerns/hyrax/suppressible.rb +5 -0
  78. data/app/models/concerns/hyrax/user.rb +9 -3
  79. data/app/models/concerns/hyrax/work_behavior.rb +1 -1
  80. data/app/models/hyrax/administrative_set.rb +7 -1
  81. data/app/models/hyrax/file_set.rb +6 -0
  82. data/app/models/hyrax/pcdm_collection.rb +1 -0
  83. data/app/models/hyrax/permission.rb +1 -1
  84. data/app/models/hyrax/permission_template.rb +112 -12
  85. data/app/models/hyrax/virus_scanner.rb +27 -18
  86. data/app/models/hyrax/work.rb +1 -0
  87. data/app/models/hyrax/workflow_action_info.rb +16 -0
  88. data/app/models/sipity/agent.rb +1 -0
  89. data/app/models/sipity/comment.rb +17 -0
  90. data/app/models/sipity/entity.rb +30 -8
  91. data/app/models/sipity/workflow.rb +1 -0
  92. data/app/models/sipity.rb +53 -2
  93. data/app/presenters/hyrax/admin_set_options_presenter.rb +12 -8
  94. data/app/presenters/hyrax/admin_set_presenter.rb +13 -4
  95. data/app/presenters/hyrax/admin_set_selection_presenter.rb +116 -0
  96. data/app/presenters/hyrax/collection_presenter.rb +44 -23
  97. data/app/presenters/hyrax/file_set_presenter.rb +6 -1
  98. data/app/presenters/hyrax/file_usage.rb +3 -2
  99. data/app/presenters/hyrax/pcdm_member_presenter_factory.rb +119 -0
  100. data/app/presenters/hyrax/stats_usage_presenter.rb +2 -1
  101. data/app/presenters/hyrax/trophy_presenter.rb +33 -4
  102. data/app/presenters/hyrax/user_profile_presenter.rb +11 -1
  103. data/app/presenters/hyrax/version_list_presenter.rb +19 -0
  104. data/app/presenters/hyrax/version_presenter.rb +3 -2
  105. data/app/presenters/hyrax/work_show_presenter.rb +32 -6
  106. data/app/presenters/hyrax/work_usage.rb +5 -3
  107. data/app/renderers/hyrax/renderers/attribute_renderer.rb +10 -2
  108. data/app/search_builders/hyrax/abstract_type_relation.rb +4 -2
  109. data/app/search_builders/hyrax/admin_set_search_builder.rb +1 -1
  110. data/app/search_builders/hyrax/collection_member_search_builder.rb +6 -1
  111. data/app/search_builders/hyrax/dashboard/collections_search_builder.rb +1 -1
  112. data/app/search_builders/hyrax/exposed_models_relation.rb +1 -1
  113. data/app/search_builders/hyrax/filter_by_type.rb +1 -2
  114. data/app/search_builders/hyrax/my/collections_search_builder.rb +2 -2
  115. data/app/search_builders/hyrax/nested_collections_parent_search_builder.rb +1 -1
  116. data/app/search_builders/hyrax/single_collection_search_builder.rb +1 -1
  117. data/app/services/hyrax/admin_set_create_service.rb +136 -52
  118. data/app/services/hyrax/collection_types/permissions_service.rb +1 -1
  119. data/app/services/hyrax/collections/collection_member_search_service.rb +72 -0
  120. data/app/services/hyrax/collections/collection_member_service.rb +122 -27
  121. data/app/services/hyrax/collections/migration_service.rb +4 -2
  122. data/app/services/hyrax/collections/nested_collection_persistence_service.rb +12 -13
  123. data/app/services/hyrax/collections/nested_collection_query_service.rb +2 -0
  124. data/app/services/hyrax/collections/permissions_create_service.rb +82 -78
  125. data/app/services/hyrax/collections/permissions_service.rb +1 -1
  126. data/app/services/hyrax/contextual_path.rb +24 -1
  127. data/app/services/hyrax/curation_concern.rb +24 -2
  128. data/app/services/hyrax/custom_queries/find_file_metadata.rb +7 -5
  129. data/app/services/hyrax/custom_queries/navigators/parent_collections_navigator.rb +46 -0
  130. data/app/services/hyrax/default_middleware_stack.rb +11 -0
  131. data/app/services/hyrax/edit_permissions_service.rb +74 -41
  132. data/app/services/hyrax/ensure_well_formed_admin_set_service.rb +3 -3
  133. data/app/services/hyrax/find_objects_via_solr_service.rb +31 -0
  134. data/app/services/hyrax/listeners/active_fedora_acl_index_listener.rb +1 -0
  135. data/app/services/hyrax/listeners/member_cleanup_listener.rb +26 -0
  136. data/app/services/hyrax/listeners/metadata_index_listener.rb +25 -9
  137. data/app/services/hyrax/listeners/object_lifecycle_listener.rb +1 -1
  138. data/app/services/hyrax/listeners/trophy_cleanup_listener.rb +17 -0
  139. data/app/services/hyrax/listeners.rb +2 -0
  140. data/app/services/hyrax/multiple_membership_checker.rb +53 -29
  141. data/app/services/hyrax/permission_manager.rb +4 -4
  142. data/app/services/hyrax/persist_derivatives.rb +3 -1
  143. data/app/services/hyrax/resource_status.rb +7 -0
  144. data/app/services/hyrax/search_service.rb +4 -2
  145. data/app/services/hyrax/solr_query_builder_service.rb +45 -8
  146. data/app/services/hyrax/solr_query_service.rb +224 -0
  147. data/app/services/hyrax/solr_service.rb +9 -2
  148. data/app/services/hyrax/statistics/collections/over_time.rb +2 -1
  149. data/app/services/hyrax/statistics/depositors/summary.rb +2 -1
  150. data/app/services/hyrax/thumbnail_path_service.rb +1 -1
  151. data/app/services/hyrax/visibility_intention.rb +20 -2
  152. data/app/services/hyrax/visibility_propagator.rb +30 -1
  153. data/app/services/hyrax/work_uploads_handler.rb +17 -2
  154. data/app/services/hyrax/workflow/abstract_notification.rb +2 -2
  155. data/app/services/hyrax/workflow/action_taken_service.rb +16 -4
  156. data/app/services/hyrax/workflow/actionable_objects.rb +70 -0
  157. data/app/services/hyrax/workflow/activate_object.rb +5 -4
  158. data/app/services/hyrax/workflow/changes_required_notification.rb +5 -4
  159. data/app/services/hyrax/workflow/deactivate_object.rb +7 -5
  160. data/app/services/hyrax/workflow/deposited_notification.rb +8 -4
  161. data/app/services/hyrax/workflow/grant_edit_to_depositor.rb +7 -3
  162. data/app/services/hyrax/workflow/grant_read_to_depositor.rb +10 -3
  163. data/app/services/hyrax/workflow/object_in_workflow_decorator.rb +31 -0
  164. data/app/services/hyrax/workflow/revoke_edit_from_depositor.rb +8 -2
  165. data/app/services/hyrax/workflow/status_list_service.rb +43 -13
  166. data/app/services/hyrax/workflow/workflow_action_service.rb +4 -1
  167. data/app/views/hyrax/admin/admin_sets/_form.html.erb +1 -1
  168. data/app/views/hyrax/base/_form_child_work_relationships.html.erb +1 -1
  169. data/app/views/hyrax/base/_form_relationships.html.erb +1 -2
  170. data/app/views/hyrax/base/_form_rendering.html.erb +1 -1
  171. data/app/views/hyrax/base/_form_representative.html.erb +1 -1
  172. data/app/views/hyrax/base/_form_thumbnail.html.erb +1 -1
  173. data/app/views/hyrax/base/_form_visibility_error.html.erb +2 -0
  174. data/app/views/hyrax/base/_guts4form.html.erb +3 -3
  175. data/app/views/hyrax/base/_representative_media.html.erb +1 -1
  176. data/app/views/hyrax/base/_show_actions.html.erb +2 -2
  177. data/app/views/hyrax/base/_work_button_row.html.erb +1 -1
  178. data/app/views/hyrax/batch_uploads/_form.html.erb +1 -1
  179. data/app/views/hyrax/collections/show.html.erb +1 -1
  180. data/app/views/hyrax/dashboard/collections/_collection_title.html.erb +1 -1
  181. data/app/views/hyrax/dashboard/collections/_form.html.erb +4 -4
  182. data/app/views/hyrax/dashboard/collections/_form_branding.html.erb +1 -1
  183. data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +1 -1
  184. data/app/views/hyrax/dashboard/collections/_sort_and_per_page.html.erb +1 -1
  185. data/app/views/hyrax/dashboard/collections/edit.html.erb +4 -2
  186. data/app/views/hyrax/dashboard/collections/new.html.erb +4 -2
  187. data/app/views/hyrax/dashboard/collections/show.html.erb +1 -1
  188. data/app/views/hyrax/file_sets/_actions.html.erb +10 -0
  189. data/app/views/hyrax/file_sets/edit.html.erb +1 -1
  190. data/app/views/hyrax/file_sets/media_display/_audio.html.erb +1 -1
  191. data/app/views/hyrax/file_sets/media_display/_default.html.erb +1 -1
  192. data/app/views/hyrax/file_sets/media_display/_image.html.erb +1 -1
  193. data/app/views/hyrax/file_sets/media_display/_office_document.html.erb +1 -1
  194. data/app/views/hyrax/file_sets/media_display/_pdf.html.erb +1 -1
  195. data/app/views/hyrax/file_sets/media_display/_video.html.erb +1 -1
  196. data/app/views/hyrax/file_sets/show.html.erb +1 -1
  197. data/app/views/hyrax/homepage/index.html.erb +1 -1
  198. data/app/views/hyrax/my/_admin_set_action_menu.html.erb +0 -11
  199. data/app/views/hyrax/my/_collection_action_menu.html.erb +1 -2
  200. data/app/views/hyrax/my/collections/_list_collections.html.erb +1 -1
  201. data/app/views/hyrax/my/collections/_modal_add_subcollection.html.erb +3 -5
  202. data/app/views/hyrax/my/collections/_modal_collection_types_to_create.html.erb +1 -1
  203. data/app/views/layouts/hyrax/dashboard.html.erb +1 -0
  204. data/app/views/layouts/hyrax.html.erb +1 -0
  205. data/app/views/shared/_read_only.html.erb +5 -0
  206. data/bin/db-migrate-seed.sh +3 -1
  207. data/bin/hyrax-entrypoint.sh +0 -14
  208. data/bin/solrcloud-assign-configset.sh +11 -3
  209. data/bin/solrcloud-upload-configset.sh +17 -6
  210. data/chart/hyrax/Chart.yaml +9 -5
  211. data/chart/hyrax/README.md +52 -5
  212. data/chart/hyrax/templates/_helpers.tpl +23 -1
  213. data/chart/hyrax/templates/branding-pvc.yaml +14 -0
  214. data/chart/hyrax/templates/configmap-env.yaml +14 -3
  215. data/chart/hyrax/templates/deployment-worker.yaml +129 -0
  216. data/chart/hyrax/templates/deployment.yaml +95 -0
  217. data/chart/hyrax/templates/derivatives-pvc.yaml +14 -0
  218. data/chart/hyrax/templates/ingress.yaml +13 -4
  219. data/chart/hyrax/templates/secrets.yaml +9 -0
  220. data/chart/hyrax/templates/uploads-pvc.yaml +14 -0
  221. data/chart/hyrax/values.yaml +114 -1
  222. data/config/brakeman.ignore +2 -2
  223. data/config/features.rb +50 -43
  224. data/config/initializers/1_healthz.rb +1 -0
  225. data/config/initializers/listeners.rb +4 -1
  226. data/config/initializers/valkryrie_storage.rb +7 -0
  227. data/config/locales/hyrax.de.yml +1 -1
  228. data/config/locales/hyrax.en.yml +2 -1
  229. data/config/locales/hyrax.es.yml +1 -1
  230. data/config/locales/hyrax.fr.yml +1 -1
  231. data/config/locales/hyrax.it.yml +1 -1
  232. data/config/locales/hyrax.pt-BR.yml +1 -1
  233. data/config/locales/hyrax.zh.yml +1 -1
  234. data/db/seeds.rb +1 -1
  235. data/docker-compose.yml +39 -8
  236. data/documentation/developing-your-hyrax-based-app.md +3 -3
  237. data/documentation/legacyREADME.md +3 -3
  238. data/hyrax.gemspec +1 -1
  239. data/lib/generators/hyrax/templates/catalog_controller.rb +3 -1
  240. data/lib/generators/hyrax/templates/config/initializers/hyrax.rb +15 -0
  241. data/lib/generators/hyrax/templates/config/initializers/riiif.rb +22 -20
  242. data/lib/generators/hyrax/work/templates/feature_spec.rb.erb +1 -1
  243. data/lib/generators/hyrax/work_resource/templates/indexer_spec.rb.erb +1 -0
  244. data/lib/hyrax/active_fedora_dummy_model.rb +62 -0
  245. data/lib/hyrax/collection_name.rb +6 -2
  246. data/lib/hyrax/configuration.rb +56 -0
  247. data/lib/hyrax/engine.rb +3 -1
  248. data/lib/hyrax/errors.rb +2 -0
  249. data/lib/hyrax/form_fields.rb +1 -0
  250. data/lib/hyrax/publisher.rb +12 -0
  251. data/lib/hyrax/resource_name.rb +1 -0
  252. data/lib/hyrax/resource_sync/change_list_writer.rb +2 -2
  253. data/lib/hyrax/resource_sync/resource_list_writer.rb +2 -2
  254. data/lib/hyrax/specs/capybara.rb +5 -3
  255. data/lib/hyrax/specs/shared_specs/hydra_works.rb +2 -0
  256. data/lib/hyrax/specs/shared_specs/indexers.rb +6 -0
  257. data/lib/hyrax/specs/shared_specs/valkyrie_storage_versions.rb +9 -0
  258. data/lib/hyrax/transactions/collection_create.rb +25 -0
  259. data/lib/hyrax/transactions/collection_update.rb +20 -0
  260. data/lib/hyrax/transactions/container.rb +47 -0
  261. data/lib/hyrax/transactions/file_set_destroy.rb +21 -0
  262. data/lib/hyrax/transactions/steps/add_file_sets.rb +3 -2
  263. data/lib/hyrax/transactions/steps/add_to_collections.rb +13 -1
  264. data/lib/hyrax/transactions/steps/add_to_parent.rb +36 -0
  265. data/lib/hyrax/transactions/steps/apply_collection_type_permissions.rb +29 -0
  266. data/lib/hyrax/transactions/steps/remove_file_set_from_work.rb +47 -0
  267. data/lib/hyrax/transactions/steps/save.rb +18 -6
  268. data/lib/hyrax/transactions/steps/set_collection_type_gid.rb +35 -0
  269. data/lib/hyrax/transactions/work_create.rb +2 -1
  270. data/lib/hyrax/valkyrie_can_can_adapter.rb +3 -0
  271. data/lib/hyrax/valkyrie_simple_path_generator.rb +20 -0
  272. data/lib/hyrax/version.rb +1 -1
  273. data/lib/hyrax.rb +9 -0
  274. data/lib/tasks/collection_type_global_id.rake +1 -1
  275. data/lib/tasks/default_admin_set.rake +12 -11
  276. data/lib/tasks/regenerate_derivatives.rake +12 -0
  277. data/lib/wings/active_fedora_converter/default_work.rb +15 -0
  278. data/lib/wings/converter_value_mapper.rb +2 -2
  279. data/lib/wings/model_transformer.rb +17 -1
  280. data/lib/wings/orm_converter.rb +18 -2
  281. data/lib/wings/setup.rb +2 -0
  282. data/lib/wings/valkyrie/persister.rb +7 -5
  283. data/lib/wings/valkyrie/query_service.rb +60 -17
  284. data/lib/wings/valkyrie/storage.rb +56 -1
  285. data/lib/wings.rb +0 -21
  286. data/template.rb +1 -1
  287. metadata +42 -9
data/lib/hyrax/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Hyrax
3
- VERSION = '3.0.0'
3
+ VERSION = '3.2.0'
4
4
  end
data/lib/hyrax.rb CHANGED
@@ -25,6 +25,13 @@ require 'valkyrie/indexing_adapter'
25
25
  require 'valkyrie/indexing/solr/indexing_adapter'
26
26
  require 'valkyrie/indexing/null_indexing_adapter'
27
27
 
28
+ ##
29
+ # Hyrax is a Ruby on Rails Engine built by the Samvera community. The engine
30
+ # provides a foundation for creating many different digital repository
31
+ # applications.
32
+ #
33
+ # @see https://samvera.org Samvera Community
34
+ # @see https://guides.rubyonrails.org/engines.html Rails Guides: Getting Started with Engines
28
35
  module Hyrax
29
36
  extend ActiveSupport::Autoload
30
37
 
@@ -46,6 +53,8 @@ module Hyrax
46
53
  def self.GlobalID(input) # rubocop:disable Naming/MethodName
47
54
  case input
48
55
  when Valkyrie::Resource
56
+ return input.to_global_id if input.respond_to?(:to_global_id)
57
+
49
58
  ValkyrieGlobalIdProxy.new(resource: input).to_global_id
50
59
  else
51
60
  input.to_global_id if input.respond_to?(:to_global_id)
@@ -2,7 +2,7 @@
2
2
  namespace :hyrax do
3
3
  namespace :collections do
4
4
  desc 'Update CollectionType global id references for Hyrax 3.0.0'
5
- task :update_collection_type_global_ids do
5
+ task update_collection_type_global_ids: :environment do
6
6
  puts 'Updating collection -> collection type GlobalId references.'
7
7
 
8
8
  count = 0
@@ -3,24 +3,25 @@ namespace :hyrax do
3
3
  namespace :default_admin_set do
4
4
  desc "Create the Default Admin Set"
5
5
  task create: :environment do
6
- id = AdminSet.find_or_create_default_admin_set_id
7
- # I have found that when I come back to a development
8
- # environment, that I may have an AdminSet in Fedora, but it is
9
- # not indexed in Solr. This remediates that situation by
10
- # ensuring we have an indexed AdminSet
11
- AdminSet.find(id).update_index
12
- if Hyrax::PermissionTemplate.find_by(source_id: id)
6
+ id = Hyrax::AdminSetCreateService.find_or_create_default_admin_set.id
7
+ if Hyrax::PermissionTemplate.find_by(source_id: id.to_s)
13
8
  puts "Successfully created default admin set"
14
9
  else
15
10
  warn "ERROR: Default admin set exists but it does not have an " \
16
11
  "associated permission template.\n\nThis may happen if you cleared your " \
17
- "database but you did not clear out Fedora and Solr.\n\n" \
12
+ "database but you did not clear out metadata datasource (e.g. Fedora, Postgres) " \
13
+ "and Solr.\n\n" \
18
14
  "You could manually create the permission template in the rails console" \
19
15
  " (non-destructive):\n\n" \
20
- " Hyrax::PermissionTemplate.create!(source_id: AdminSet::DEFAULT_ID)\n\n" \
21
- "OR you could start fresh by clearing Fedora and Solr (destructive):\n\n" \
16
+ " Hyrax::PermissionTemplate.create!(source_id: Hyrax::AdminSetCreateService::DEFAULT_ID)\n\n" \
17
+ "OR you could start fresh by clearing the metadata datasource and Solr (destructive):\n\n" \
18
+ " For ActiveFedora or Wings Valkryie adapter (default), use...\n" \
22
19
  " require 'active_fedora/cleaner'\n" \
23
- " ActiveFedora::Cleaner.clean!\n\n"
20
+ " ActiveFedora::Cleaner.clean!\n\n" \
21
+ " For Valkyrie, use...\n" \
22
+ " conn = Hyrax.index_adapter.connection\n" \
23
+ " conn.delete_by_query('*:*', params: { 'softCommit' => true })\n" \
24
+ " Hyrax.persister.wipe!\n"
24
25
  end
25
26
  end
26
27
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ namespace :hyrax do
4
+ namespace :file_sets do
5
+ desc 'Regenerate derivatives for all FileSets in the repository'
6
+ task regenerate_derivatives: :environment do
7
+ FileSet.all.each do |fs|
8
+ fs.files.each { |fi| CreateDerivativesJob.perform_later(fs, fi) }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -100,6 +100,9 @@ module Wings
100
100
  include Hydra::AccessControls::Embargoable
101
101
  property :nested_resource, predicate: ::RDF::URI("http://example.com/nested_resource"), class_name: "Wings::ActiveFedoraConverter::NestedResource"
102
102
 
103
+ validates :lease_expiration_date, 'hydra/future_date': true, on: :create
104
+ validates :embargo_release_date, 'hydra/future_date': true, on: :create
105
+
103
106
  class_attribute :valkyrie_class
104
107
  self.valkyrie_class = Hyrax::Resource
105
108
 
@@ -121,6 +124,18 @@ module Wings
121
124
  alias to_s inspect
122
125
  end
123
126
 
127
+ ##
128
+ # Override aggressive Hydra::AccessControls validation
129
+ def enforce_future_date_for_embargo?
130
+ false
131
+ end
132
+
133
+ ##
134
+ # Override aggressive Hydra::AccessControls validation
135
+ def enforce_future_date_for_lease?
136
+ false
137
+ end
138
+
124
139
  def indexing_service
125
140
  Hyrax::ValkyrieIndexer.for(resource: valkyrie_resource)
126
141
  end
@@ -73,7 +73,7 @@ module Wings
73
73
  end
74
74
 
75
75
  def result
76
- collections = value.last.map { |id| ActiveFedora::Base.find(id.id) }
76
+ collections = value.last.map { |id| ActiveFedora::Base.find(id.to_s) }
77
77
  [:member_of_collections, collections]
78
78
  end
79
79
  end
@@ -86,7 +86,7 @@ module Wings
86
86
  end
87
87
 
88
88
  def result
89
- members = value.last.map { |id| ActiveFedora::Base.find(id.id) }
89
+ members = value.last.map { |id| ActiveFedora::Base.find(id.to_s) }
90
90
  [:members, members]
91
91
  end
92
92
  end
@@ -110,7 +110,7 @@ module Wings
110
110
  private
111
111
 
112
112
  def mint_id
113
- id = pcdm_object.assign_id
113
+ id = pcdm_object.try(:assign_id)
114
114
 
115
115
  pcdm_object.id = id if id.present?
116
116
  end
@@ -121,6 +121,7 @@ module Wings
121
121
 
122
122
  append_embargo(result)
123
123
  append_lease(result)
124
+ append_permissions(result)
124
125
 
125
126
  result
126
127
  end
@@ -168,5 +169,20 @@ module Wings
168
169
 
169
170
  attrs[:lease] = Hyrax::Lease.new(**lease_attrs)
170
171
  end
172
+
173
+ def append_permissions(attrs)
174
+ return unless pcdm_object.try(:permissions)
175
+ attrs[:permissions] = pcdm_object.permissions.map do |permission|
176
+ agent = permission.type == 'group' ? "group/#{permission.agent_name}" : permission.agent_name
177
+
178
+ Hyrax::Permission.new(id: permission.id,
179
+ mode: permission.access.to_sym,
180
+ agent: agent,
181
+ access_to: ::Valkyrie::ID.new(permission.access_to_id),
182
+ new_record: permission.new_record?)
183
+ end
184
+
185
+ attrs[:access_to] = attrs[:permissions].find { |p| p.access_to&.id&.present? }&.access_to
186
+ end
171
187
  end
172
188
  end
@@ -40,6 +40,12 @@ module Wings
40
40
  _canonical_valkyrie_model&.name
41
41
  end
42
42
 
43
+ ##
44
+ # @return [String]
45
+ def to_s
46
+ internal_resource
47
+ end
48
+
43
49
  ##
44
50
  # @api private
45
51
  def _canonical_valkyrie_model
@@ -47,8 +53,18 @@ module Wings
47
53
  end
48
54
  end
49
55
 
50
- def self.to_s
51
- internal_resource
56
+ ##
57
+ # @return [URI::GID]
58
+ def to_global_id
59
+ URI::GID.build([GlobalID.app, internal_resource, id, {}])
60
+ end
61
+
62
+ ##
63
+ # @return [ActiveModel::Base]
64
+ def to_model
65
+ model_class = internal_resource.safe_constantize || self
66
+
67
+ Hyrax::ActiveFedoraDummyModel.new(model_class, id)
52
68
  end
53
69
 
54
70
  klass.properties.each_key do |property_name|
data/lib/wings/setup.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  ActiveFedora::Base.include Wings::Valkyrizable
4
4
  ActiveFedora::File.include Wings::Valkyrizable
5
+ Hydra::AccessControl.include Wings::Valkyrizable
5
6
 
6
7
  module ActiveTriples
7
8
  class NodeConfig
@@ -76,6 +77,7 @@ Valkyrie.config.storage_adapter = :active_fedora
76
77
  # A refactor is needed to add the default implementations to hyrax.rb and only handle the wings specific overrides here.
77
78
  custom_queries = [Hyrax::CustomQueries::Navigators::CollectionMembers,
78
79
  Hyrax::CustomQueries::Navigators::ChildCollectionsNavigator,
80
+ Hyrax::CustomQueries::Navigators::ParentCollectionsNavigator,
79
81
  Hyrax::CustomQueries::Navigators::ChildFilesetsNavigator,
80
82
  Hyrax::CustomQueries::Navigators::ChildWorksNavigator,
81
83
  Hyrax::CustomQueries::Navigators::FindFiles,
@@ -41,9 +41,10 @@ module Wings
41
41
  # @param [Valkyrie::Resource] resource
42
42
  # @return [Valkyrie::Resource] the persisted/updated resource
43
43
  def save_all(resources:)
44
- resources.map do |resource|
45
- save(resource: resource)
46
- end
44
+ resources.map { |resource| save(resource: resource) }
45
+ rescue ::Valkyrie::Persistence::StaleObjectError => _err
46
+ raise(::Valkyrie::Persistence::StaleObjectError,
47
+ "One or more resources have been updated by another process.")
47
48
  end
48
49
 
49
50
  # Deletes a resource persisted using ActiveFedora
@@ -51,7 +52,7 @@ module Wings
51
52
  # @return [Valkyrie::Resource] the deleted resource
52
53
  def delete(resource:)
53
54
  af_object = ActiveFedora::Base.new
54
- af_object.id = resource.alternate_ids.first.to_s
55
+ af_object.id = resource.id
55
56
  af_object.delete
56
57
  resource
57
58
  end
@@ -84,7 +85,8 @@ module Wings
84
85
  etag_lock_token_valid?(af_object: af_object, resource: resource) &&
85
86
  last_modified_lock_token_valid?(af_object: af_object, resource: resource)
86
87
 
87
- raise(::Valkyrie::Persistence::StaleObjectError, resource.id.to_s)
88
+ raise(::Valkyrie::Persistence::StaleObjectError,
89
+ "The object #{resource.id} has been updated by another process.")
88
90
  end
89
91
 
90
92
  ##
@@ -2,16 +2,32 @@
2
2
 
3
3
  module Wings
4
4
  module Valkyrie
5
+ ##
6
+ # @note does not support duplicates!
5
7
  class QueryService
6
8
  attr_reader :adapter
7
9
  extend Forwardable
8
10
  def_delegator :adapter, :resource_factory
9
11
 
10
- # @param adapter [Wings::Valkyrie::MetadataAdapter] The adapter which holds the resource_factory for this query_service.
12
+ ##
13
+ # @param adapter [Wings::Valkyrie::MetadataAdapter] The adapter which
14
+ # holds the resource_factory for this query_service.
11
15
  def initialize(adapter:)
12
16
  @adapter = adapter
13
17
  end
14
18
 
19
+ ##
20
+ # @param :model [Class]
21
+ #
22
+ # @return [Integer]
23
+ def count_all_of_model(model:)
24
+ ActiveFedora::Base
25
+ .where(has_model_ssim: [model_class_for(model).to_rdf_representation,
26
+ model.new.internal_resource.to_s])
27
+ .count
28
+ end
29
+
30
+ ##
15
31
  # WARNING: In general, prefer find_by_alternate_identifier over this
16
32
  # method.
17
33
  #
@@ -23,14 +39,17 @@ module Wings
23
39
  # start getting ObjectNotFoundErrors instead of the objects you wanted
24
40
  #
25
41
  # Find a record using a Valkyrie ID, and map it to a Valkyrie Resource
42
+ #
26
43
  # @param [Valkyrie::ID, String] id
27
44
  # @return [Valkyrie::Resource]
28
- # @raise [Hyrax::ObjectNotFoundError]
45
+ # @raise [Valkyrie::Persistence::ObjectNotFoundError]
29
46
  def find_by(id:)
30
47
  find_by_alternate_identifier(alternate_identifier: id)
31
48
  end
32
49
 
50
+ ##
33
51
  # Find all work/collection records, and map to Valkyrie Resources
52
+ #
34
53
  # @return [Array<Valkyrie::Resource>]
35
54
  def find_all
36
55
  ::ActiveFedora::Base.all.map do |obj|
@@ -38,7 +57,10 @@ module Wings
38
57
  end
39
58
  end
40
59
 
41
- # Find all work/collection records of a given model, and map to Valkyrie Resources
60
+ ##
61
+ # Find all work/collection records of a given model, and map to Valkyrie
62
+ # Resources
63
+ #
42
64
  # @param model [Class]
43
65
  # @return [Array<Valkyrie::Resource>]
44
66
  def find_all_of_model(model:)
@@ -73,11 +95,14 @@ module Wings
73
95
  end
74
96
  end
75
97
 
98
+ ##
76
99
  # Find a record using an alternate ID, and map it to a Valkyrie Resource
100
+ #
77
101
  # @param [Valkyrie::ID, String] id
78
102
  # @param [boolean] optionally return ActiveFedora object/errors
103
+ #
79
104
  # @return [Valkyrie::Resource]
80
- # @raise [Hyrax::ObjectNotFoundError]
105
+ # @raise [Valkyrie::Persistence::ObjectNotFoundError]
81
106
  def find_by_alternate_identifier(alternate_identifier:, use_valkyrie: true)
82
107
  raise(ArgumentError, 'id must be a Valkyrie::ID') unless
83
108
  alternate_identifier.respond_to?(:to_str)
@@ -87,12 +112,15 @@ module Wings
87
112
  use_valkyrie ? resource_factory.to_resource(object: af_object) : af_object
88
113
  rescue ActiveFedora::ObjectNotFoundError, Ldp::Gone => err
89
114
  raise err unless use_valkyrie
90
- raise Hyrax::ObjectNotFoundError
115
+ raise ::Valkyrie::Persistence::ObjectNotFoundError
91
116
  end
92
117
 
118
+ ##
93
119
  # Find all members of a given resource, and map to Valkyrie Resources
120
+ #
94
121
  # @param resource [Valkyrie::Resource]
95
122
  # @param model [Class]
123
+ #
96
124
  # @return [Array<Valkyrie::Resource>]
97
125
  def find_members(resource:, model: nil)
98
126
  return [] if resource.try(:member_ids).blank?
@@ -103,21 +131,27 @@ module Wings
103
131
  .select { |member_resource| model_class_for(member_resource.class) == find_model }
104
132
  end
105
133
 
134
+ ##
106
135
  # Find the Valkyrie Resources referenced by another Valkyrie Resource
136
+ #
107
137
  # @param resource [<Valkyrie::Resource>]
108
138
  # @param property [Symbol] the property holding the references to another resource
109
139
  # @return [Array<Valkyrie::Resource>]
110
- def find_references_by(resource:, property:)
111
- object = resource_factory.from_resource(resource: resource)
112
- object.send(property).map do |reference|
113
- af_id = find_id_for(reference)
114
- resource_factory.to_resource(object: ::ActiveFedora::Base.find(af_id))
140
+ def find_references_by(resource:, property:, model: nil)
141
+ return find_many_by_ids(ids: Array(resource.send(property))) unless model
142
+
143
+ results = resource.public_send(property).map do |reference|
144
+ resource_factory.to_resource(object: ::ActiveFedora::Base.find(reference))
115
145
  end
146
+
147
+ results.select { |r| r.class.name == model.name }
116
148
  rescue ActiveFedora::ObjectNotFoundError
117
149
  []
118
150
  end
119
151
 
152
+ ##
120
153
  # Get all resources which link to a resource or id with a given property.
154
+ #
121
155
  # @param resource [Valkyrie::Resource] The resource which is being referenced by
122
156
  # other resources.
123
157
  # @param resource [Valkyrie::ID] The id of the resource which is being referenced by
@@ -129,30 +163,37 @@ module Wings
129
163
  # @return [Array<Valkyrie::Resource>] All resources in the persistence backend
130
164
  # which have the ID of the given `resource` in their `property` property. Not
131
165
  # in order.
132
- def find_inverse_references_by(resource: nil, id: nil, property:)
166
+ def find_inverse_references_by(resource: nil, id: nil, model: nil, property:)
133
167
  raise ArgumentError, "Provide resource or id" unless resource || id
134
- id ||= resource.alternate_ids.first
168
+ id ||= resource.id
135
169
  raise ArgumentError, "Resource has no id; is it persisted?" unless id
136
- uri = Hyrax::Base.id_to_uri(id.to_s)
137
- ActiveFedora::Base.where("+(#{property}_ssim: \"#{uri}\" OR #{property}_ssim: \"#{id}\")").map do |obj|
170
+
171
+ active_fedora_model = model ? model_class_for(model) : ActiveFedora::Base
172
+
173
+ uri = active_fedora_model.id_to_uri(id.to_s)
174
+ active_fedora_model.where("+(#{property}_ssim: \"#{uri}\" OR #{property}_ssim: \"#{id}\")").map do |obj|
138
175
  resource_factory.to_resource(object: obj)
139
176
  end
140
177
  end
141
178
 
179
+ ##
142
180
  # Find all parents of a given resource.
181
+ #
143
182
  # @param resource [Valkyrie::Resource] The resource whose parents are being searched
144
183
  # for.
145
184
  # @return [Array<Valkyrie::Resource>] All resources which are parents of the given
146
185
  # `resource`. This means the resource's `id` appears in their `member_ids`
147
186
  # array.
148
187
  def find_parents(resource:)
149
- id = resource.alternate_ids.first
150
- ActiveFedora::Base.where("member_ids_ssim: \"#{id}\"").map do |obj|
188
+ ActiveFedora::Base.where("member_ids_ssim: \"#{resource.id}\"").map do |obj|
151
189
  resource_factory.to_resource(object: obj)
152
190
  end
153
191
  end
154
192
 
155
- # Constructs a Valkyrie::Persistence::CustomQueryContainer using this query service
193
+ ##
194
+ # Constructs a Valkyrie::Persistence::CustomQueryContainer using this
195
+ # query service
196
+ #
156
197
  # @return [Valkyrie::Persistence::CustomQueryContainer]
157
198
  def custom_queries
158
199
  @custom_queries ||= ::Valkyrie::Persistence::CustomQueryContainer.new(query_service: self)
@@ -160,7 +201,9 @@ module Wings
160
201
 
161
202
  private
162
203
 
204
+ ##
163
205
  # Determines whether or not an Object is a Valkyrie ID
206
+ #
164
207
  # @param [Object] id
165
208
  # @raise [ArgumentError]
166
209
  def validate_id(id)
@@ -19,6 +19,7 @@ module Wings
19
19
  DEFAULT_CTYPE = 'application/octet-stream'
20
20
  LINK_HEADER = "<http://www.w3.org/ns/ldp#NonRDFSource>; rel=\"type\""
21
21
  FILES_PATH = 'files'
22
+ VERSIONS_SLUG = '/fcr:versions'
22
23
 
23
24
  attr_reader :sha1
24
25
 
@@ -27,6 +28,14 @@ module Wings
27
28
  super
28
29
  end
29
30
 
31
+ ##
32
+ # @param key [Symbol] the key for plugin behavior to check support for
33
+ #
34
+ # @return [Boolean] whether
35
+ def supports?(key)
36
+ key == :versions
37
+ end
38
+
30
39
  def upload(file:, original_filename:, resource:, content_type: DEFAULT_CTYPE, # rubocop:disable Metrics/ParameterLists
31
40
  resource_uri_transformer: default_resource_uri_transformer, use: Hydra::PCDM::Vocab::PCDMTerms.File,
32
41
  id_hint: 'original', **extra_arguments)
@@ -41,7 +50,49 @@ module Wings
41
50
  id_hint: id_hint, **extra_arguments)
42
51
  end
43
52
 
44
- find_by(id: ::Valkyrie::ID.new(id.to_s.sub(/^.+\/\//, PROTOCOL)))
53
+ find_by(id: cast_to_valkyrie_id(id))
54
+ end
55
+
56
+ ##
57
+ # @return [Enumerable<Version> ordered list of versions
58
+ def find_versions(id:)
59
+ response = connection.http.get(fedora_identifier(id: id) + VERSIONS_SLUG)
60
+ return [] if response.status == 404
61
+
62
+ reader = RDF::Reader.for(content_type: response.headers['content-type'])
63
+ version_graph = RDF::Graph.new << reader.new(response.body)
64
+
65
+ version_graph.query(predicate: RDF::Vocab::Fcrepo4.hasVersion).objects.map do |uri|
66
+ timestamp =
67
+ version_graph.query([uri, RDF::Vocab::Fcrepo4.created, :created])
68
+ .first_object
69
+ .object
70
+ Version.new(cast_to_valkyrie_id(uri.to_s), timestamp, self)
71
+ end.sort
72
+ end
73
+
74
+ ##
75
+ # abstractly, {Version} objects should have an {#id} and be orderable
76
+ # over {#<=>} (allowing e.g. `#sort` to define a consistent order---
77
+ # oldest to newest---for a collection of versions). the {#id} should be a
78
+ # globally unique identifier for the version.
79
+ #
80
+ # this implementation uses an orderable {#version_token}. in practice
81
+ # the token is the fcrepo created date for the version, as extracted from
82
+ # the versions graph.
83
+ Version = Struct.new(:id, :version_token, :adapter) do
84
+ include Comparable
85
+
86
+ ##
87
+ # @return [#read]
88
+ def io
89
+ adapter.find_by(id: id)
90
+ end
91
+
92
+ def <=>(other)
93
+ raise ArgumentError unless other.respond_to?(:version_token)
94
+ version_token <=> other.version_token
95
+ end
45
96
  end
46
97
 
47
98
  private
@@ -87,6 +138,10 @@ module Wings
87
138
 
88
139
  Hyrax.config.translate_id_to_uri.call(created_file.id)
89
140
  end
141
+
142
+ def cast_to_valkyrie_id(id)
143
+ ::Valkyrie::ID.new(id.to_s.sub(/^.+\/\//, PROTOCOL))
144
+ end
90
145
  end
91
146
  end
92
147
 
data/lib/wings.rb CHANGED
@@ -98,27 +98,6 @@ require 'wings/valkyrie/persister'
98
98
  require 'wings/valkyrie/storage'
99
99
  require 'wings/valkyrie/query_service'
100
100
 
101
- Hydra::AccessControl.send(:define_method, :valkyrie_resource) do
102
- attrs = attributes.symbolize_keys
103
- attrs[:new_record] = new_record?
104
- attrs[:created_at] = create_date
105
- attrs[:updated_at] = modified_date
106
-
107
- attrs[:permissions] = permissions.map do |permission|
108
- agent = permission.type == 'group' ? "group/#{permission.agent_name}" : permission.agent_name
109
-
110
- Hyrax::Permission.new(id: permission.id,
111
- mode: permission.access.to_sym,
112
- agent: agent,
113
- access_to: Valkyrie::ID.new(permission.access_to_id),
114
- new_record: permission.new_record?)
115
- end
116
-
117
- attrs[:access_to] = attrs[:permissions].find { |p| p.access_to&.id&.present? }&.access_to
118
-
119
- Hyrax::AccessControl.new(**attrs)
120
- end
121
-
122
101
  begin
123
102
  require 'wings/setup'
124
103
  rescue NameError, Hyrax::SimpleSchemaLoader::UndefinedSchemaError => err
data/template.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  # Hack for https://github.com/rails/rails/issues/35153
3
3
  gsub_file 'Gemfile', /^gem ["']sqlite3["']$/, 'gem "sqlite3", "~> 1.3.0"'
4
- gem 'hyrax', '3.0.0'
4
+ gem 'hyrax', '3.2.0'
5
5
  run 'bundle install'
6
6
  generate 'hyrax:install', '-f'