hyrax 3.0.2 → 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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +22 -0
- data/.dassie/Gemfile +10 -5
- data/.dassie/config/initializers/hyrax.rb +5 -0
- data/.dockerignore +3 -0
- data/.env +0 -1
- data/.rubocop.yml +4 -0
- data/CONTAINERS.md +1 -1
- data/Dockerfile +12 -6
- data/Gemfile +21 -27
- data/app/actors/hyrax/actors/base_actor.rb +1 -1
- data/app/actors/hyrax/actors/create_with_remote_files_actor.rb +85 -63
- data/app/actors/hyrax/actors/create_with_remote_files_ordered_members_actor.rb +7 -42
- data/app/controllers/concerns/hyrax/collections_controller_behavior.rb +20 -8
- data/app/controllers/concerns/hyrax/embargoes_controller_behavior.rb +21 -9
- data/app/controllers/concerns/hyrax/leases_controller_behavior.rb +14 -5
- data/app/controllers/concerns/hyrax/works_controller_behavior.rb +22 -3
- data/app/controllers/hyrax/admin/workflows_controller.rb +8 -2
- data/app/controllers/hyrax/dashboard/collection_members_controller.rb +13 -9
- data/app/controllers/hyrax/dashboard/collections_controller.rb +12 -10
- data/app/controllers/hyrax/file_sets_controller.rb +49 -13
- data/app/controllers/hyrax/permissions_controller.rb +3 -4
- data/app/controllers/hyrax/workflow_actions_controller.rb +3 -1
- data/app/forms/hyrax/forms/collection_form.rb +7 -3
- data/app/forms/hyrax/forms/dashboard/nest_collection_form.rb +24 -2
- data/app/forms/hyrax/forms/file_set_form.rb +46 -0
- data/app/forms/hyrax/forms/permission.rb +23 -0
- data/app/forms/hyrax/forms/permission_template_form.rb +8 -2
- data/app/forms/hyrax/forms/resource_form.rb +10 -17
- data/app/forms/hyrax/forms/work_form.rb +5 -2
- data/app/helpers/hyrax/batch_edits_helper.rb +3 -1
- data/app/helpers/hyrax/collections_helper.rb +88 -2
- data/app/helpers/hyrax/dashboard_helper_behavior.rb +3 -7
- data/app/helpers/hyrax/file_set_helper.rb +25 -6
- data/app/helpers/hyrax/work_form_helper.rb +53 -0
- data/app/indexers/hyrax/administrative_set_indexer.rb +18 -0
- data/app/indexers/hyrax/valkyrie_indexer.rb +3 -3
- data/app/inputs/controlled_vocabulary_input.rb +2 -5
- data/app/jobs/attach_files_to_work_job.rb +19 -10
- data/app/jobs/attach_files_to_work_with_ordered_members_job.rb +6 -5
- data/app/jobs/inherit_permissions_job.rb +9 -5
- data/app/models/admin_set.rb +6 -25
- data/app/models/concerns/hyrax/ability.rb +3 -1
- data/app/models/concerns/hyrax/collection_behavior.rb +17 -44
- data/app/models/concerns/hyrax/file_set/characterization.rb +18 -12
- data/app/models/concerns/hyrax/solr_document_behavior.rb +9 -52
- data/app/models/concerns/hyrax/suppressible.rb +5 -0
- data/app/models/concerns/hyrax/user.rb +9 -3
- data/app/models/hyrax/file_set.rb +6 -0
- data/app/models/hyrax/pcdm_collection.rb +1 -0
- data/app/models/hyrax/permission_template.rb +98 -12
- data/app/models/hyrax/virus_scanner.rb +27 -18
- data/app/models/sipity/agent.rb +1 -0
- data/app/models/sipity/entity.rb +30 -8
- data/app/models/sipity/workflow.rb +1 -0
- data/app/models/sipity.rb +42 -0
- data/app/presenters/hyrax/admin_set_options_presenter.rb +2 -10
- data/app/presenters/hyrax/admin_set_presenter.rb +5 -1
- data/app/presenters/hyrax/admin_set_selection_presenter.rb +116 -0
- data/app/presenters/hyrax/collection_presenter.rb +31 -6
- data/app/presenters/hyrax/file_set_presenter.rb +6 -1
- data/app/presenters/hyrax/file_usage.rb +3 -2
- data/app/presenters/hyrax/stats_usage_presenter.rb +2 -1
- data/app/presenters/hyrax/trophy_presenter.rb +33 -4
- data/app/presenters/hyrax/user_profile_presenter.rb +11 -1
- data/app/presenters/hyrax/version_list_presenter.rb +19 -0
- data/app/presenters/hyrax/version_presenter.rb +3 -2
- data/app/presenters/hyrax/work_show_presenter.rb +25 -4
- data/app/presenters/hyrax/work_usage.rb +5 -3
- data/app/renderers/hyrax/renderers/attribute_renderer.rb +10 -2
- data/app/search_builders/hyrax/admin_set_search_builder.rb +1 -1
- data/app/search_builders/hyrax/my/collections_search_builder.rb +1 -1
- data/app/services/hyrax/admin_set_create_service.rb +3 -1
- data/app/services/hyrax/collections/collection_member_search_service.rb +72 -0
- data/app/services/hyrax/collections/collection_member_service.rb +112 -27
- data/app/services/hyrax/collections/migration_service.rb +4 -2
- data/app/services/hyrax/collections/nested_collection_persistence_service.rb +12 -13
- data/app/services/hyrax/collections/nested_collection_query_service.rb +2 -0
- data/app/services/hyrax/collections/permissions_create_service.rb +6 -4
- data/app/services/hyrax/contextual_path.rb +23 -0
- data/app/services/hyrax/custom_queries/find_file_metadata.rb +7 -5
- data/app/services/hyrax/custom_queries/navigators/parent_collections_navigator.rb +46 -0
- data/app/services/hyrax/edit_permissions_service.rb +27 -20
- data/app/services/hyrax/find_objects_via_solr_service.rb +11 -7
- data/app/services/hyrax/multiple_membership_checker.rb +51 -31
- data/app/services/hyrax/resource_status.rb +7 -0
- data/app/services/hyrax/search_service.rb +4 -2
- data/app/services/hyrax/solr_query_builder_service.rb +29 -6
- data/app/services/hyrax/solr_query_service.rb +224 -0
- data/app/services/hyrax/solr_service.rb +8 -1
- data/app/services/hyrax/statistics/depositors/summary.rb +2 -1
- data/app/services/hyrax/work_uploads_handler.rb +17 -2
- data/app/services/hyrax/workflow/actionable_objects.rb +70 -0
- data/app/services/hyrax/workflow/object_in_workflow_decorator.rb +31 -0
- data/app/services/hyrax/workflow/status_list_service.rb +43 -13
- data/app/views/hyrax/base/_form_relationships.html.erb +1 -2
- data/app/views/hyrax/base/_form_rendering.html.erb +1 -1
- data/app/views/hyrax/base/_form_representative.html.erb +1 -1
- data/app/views/hyrax/base/_form_thumbnail.html.erb +1 -1
- data/app/views/hyrax/base/_guts4form.html.erb +2 -2
- data/app/views/hyrax/base/_representative_media.html.erb +1 -1
- data/app/views/hyrax/base/_show_actions.html.erb +1 -1
- data/app/views/hyrax/dashboard/collections/_form.html.erb +3 -3
- data/app/views/hyrax/dashboard/collections/_list_collections.html.erb +1 -1
- data/app/views/hyrax/dashboard/collections/edit.html.erb +4 -2
- data/app/views/hyrax/dashboard/collections/new.html.erb +4 -2
- data/app/views/hyrax/dashboard/collections/show.html.erb +1 -1
- data/app/views/hyrax/file_sets/edit.html.erb +1 -1
- data/app/views/hyrax/file_sets/media_display/_audio.html.erb +1 -1
- data/app/views/hyrax/file_sets/media_display/_default.html.erb +1 -1
- data/app/views/hyrax/file_sets/media_display/_image.html.erb +1 -1
- data/app/views/hyrax/file_sets/media_display/_office_document.html.erb +1 -1
- data/app/views/hyrax/file_sets/media_display/_pdf.html.erb +1 -1
- data/app/views/hyrax/file_sets/media_display/_video.html.erb +1 -1
- data/app/views/hyrax/file_sets/show.html.erb +1 -1
- data/app/views/hyrax/my/_admin_set_action_menu.html.erb +0 -11
- data/app/views/hyrax/my/_collection_action_menu.html.erb +1 -2
- data/app/views/hyrax/my/collections/_list_collections.html.erb +1 -1
- data/app/views/hyrax/my/collections/_modal_add_subcollection.html.erb +3 -5
- data/bin/solrcloud-assign-configset.sh +8 -5
- data/bin/solrcloud-upload-configset.sh +4 -2
- data/chart/hyrax/Chart.yaml +3 -3
- data/chart/hyrax/README.md +47 -1
- data/chart/hyrax/templates/_helpers.tpl +1 -1
- data/chart/hyrax/templates/configmap-env.yaml +1 -3
- data/chart/hyrax/templates/deployment-worker.yaml +6 -3
- data/chart/hyrax/templates/deployment.yaml +8 -3
- data/chart/hyrax/values.yaml +12 -0
- data/config/brakeman.ignore +2 -2
- data/config/locales/hyrax.de.yml +1 -1
- data/config/locales/hyrax.en.yml +1 -1
- data/config/locales/hyrax.es.yml +1 -1
- data/config/locales/hyrax.fr.yml +1 -1
- data/config/locales/hyrax.it.yml +1 -1
- data/config/locales/hyrax.pt-BR.yml +1 -1
- data/config/locales/hyrax.zh.yml +1 -1
- data/docker-compose.yml +1 -0
- data/documentation/developing-your-hyrax-based-app.md +1 -1
- data/documentation/legacyREADME.md +1 -1
- data/lib/generators/hyrax/templates/config/initializers/hyrax.rb +5 -0
- data/lib/hyrax/active_fedora_dummy_model.rb +62 -0
- data/lib/hyrax/configuration.rb +8 -0
- data/lib/hyrax/engine.rb +1 -0
- data/lib/hyrax/errors.rb +2 -0
- data/lib/hyrax/specs/capybara.rb +3 -1
- data/lib/hyrax/specs/shared_specs/valkyrie_storage_versions.rb +9 -0
- data/lib/hyrax/transactions/container.rb +21 -0
- data/lib/hyrax/transactions/file_set_destroy.rb +21 -0
- data/lib/hyrax/transactions/steps/add_file_sets.rb +3 -2
- data/lib/hyrax/transactions/steps/add_to_parent.rb +36 -0
- data/lib/hyrax/transactions/steps/remove_file_set_from_work.rb +47 -0
- data/lib/hyrax/transactions/work_create.rb +2 -1
- data/lib/hyrax/valkyrie_can_can_adapter.rb +1 -0
- data/lib/hyrax/version.rb +1 -1
- data/lib/hyrax.rb +9 -0
- data/lib/tasks/collection_type_global_id.rake +1 -1
- data/lib/tasks/regenerate_derivatives.rake +12 -0
- data/lib/wings/orm_converter.rb +18 -2
- data/lib/wings/setup.rb +1 -0
- data/lib/wings/valkyrie/storage.rb +56 -1
- data/template.rb +1 -1
- metadata +17 -2
|
@@ -10,6 +10,11 @@ module Hyrax
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
##
|
|
13
|
+
# @deprecated use `Hyrax::ResourceStatus` instead. in most cases,
|
|
14
|
+
# {#suppressed?} is being called on a {SolrDocumentBehavior}. we continue
|
|
15
|
+
# to index `suppressed_bsi` and expose its value as an attribute on solr
|
|
16
|
+
# document objects.
|
|
17
|
+
#
|
|
13
18
|
# Used to restrict visibility on search results for a work that is inactive. If the state is not set, the
|
|
14
19
|
# default behavior is to consider the work not to be suppressed.
|
|
15
20
|
#
|
|
@@ -31,7 +31,7 @@ module Hyrax::User
|
|
|
31
31
|
|
|
32
32
|
scope :guests, ->() { where(guest: true) }
|
|
33
33
|
scope :registered, ->() { where(guest: false) }
|
|
34
|
-
scope :without_system_accounts, -> { where("#{::User.user_key_field} not in (?)", [::User.batch_user_key, ::User.audit_user_key]) }
|
|
34
|
+
scope :without_system_accounts, -> { where("#{::User.user_key_field} not in (?)", [::User.batch_user_key, ::User.audit_user_key, ::User.system_user_key]) }
|
|
35
35
|
|
|
36
36
|
# Validate and normalize ORCIDs
|
|
37
37
|
validates_with OrcidValidator
|
|
@@ -145,7 +145,14 @@ module Hyrax::User
|
|
|
145
145
|
end
|
|
146
146
|
|
|
147
147
|
module ClassMethods
|
|
148
|
-
|
|
148
|
+
def system_user
|
|
149
|
+
find_or_create_system_user(system_user_key)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def system_user_key
|
|
153
|
+
Hyrax.config.system_user_key
|
|
154
|
+
end
|
|
155
|
+
|
|
149
156
|
def audit_user
|
|
150
157
|
find_or_create_system_user(audit_user_key)
|
|
151
158
|
end
|
|
@@ -158,7 +165,6 @@ module Hyrax::User
|
|
|
158
165
|
Hydra.config.user_key_field
|
|
159
166
|
end
|
|
160
167
|
|
|
161
|
-
# Override this method if you aren't using email/password
|
|
162
168
|
def batch_user
|
|
163
169
|
find_or_create_system_user(batch_user_key)
|
|
164
170
|
end
|
|
@@ -9,6 +9,12 @@ module Hyrax
|
|
|
9
9
|
include Hyrax::Schema(:core_metadata)
|
|
10
10
|
include Hyrax::Schema(:basic_metadata)
|
|
11
11
|
|
|
12
|
+
def self.model_name(name_class: Hyrax::Name)
|
|
13
|
+
@_model_name ||= begin
|
|
14
|
+
name_class.new(self, nil, 'FileSet')
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
12
18
|
attribute :file_ids, Valkyrie::Types::Array.of(Valkyrie::Types::ID) # id for FileMetadata resources
|
|
13
19
|
attribute :original_file_id, Valkyrie::Types::ID # id for FileMetadata resource
|
|
14
20
|
attribute :thumbnail_id, Valkyrie::Types::ID # id for FileMetadata resource
|
|
@@ -11,6 +11,7 @@ module Hyrax
|
|
|
11
11
|
|
|
12
12
|
attribute :collection_type_gid, Valkyrie::Types::String
|
|
13
13
|
attribute :member_ids, Valkyrie::Types::Array.of(Valkyrie::Types::ID).meta(ordered: true)
|
|
14
|
+
attribute :member_of_collection_ids, Valkyrie::Types::Set.of(Valkyrie::Types::ID)
|
|
14
15
|
|
|
15
16
|
##
|
|
16
17
|
# @api private
|
|
@@ -1,20 +1,61 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Hyrax
|
|
3
3
|
##
|
|
4
|
-
#
|
|
4
|
+
# Holds policy data about the workflow and permissions applied objects when
|
|
5
|
+
# they are deposited through an Administrative Set or a Collection. Each
|
|
6
|
+
# template record has a {#source} (through {#source_id}); the template's
|
|
7
|
+
# rules inform the behavior of objects deposited through that {#source_model}.
|
|
5
8
|
#
|
|
6
|
-
#
|
|
7
|
-
# * calculate embargo/lease release dates
|
|
9
|
+
# The {PermissionTemplate} specifies:
|
|
8
10
|
#
|
|
9
|
-
#
|
|
11
|
+
# - an {#active_workflow} that the object will enter and be processed through.
|
|
12
|
+
# - {#access_grants} that can be applied to each object (especially at deposit
|
|
13
|
+
# time).
|
|
14
|
+
# - an embargo configuration ({#release_date} {#release_period}) for default
|
|
15
|
+
# embargo behavior.
|
|
10
16
|
#
|
|
11
|
-
#
|
|
12
|
-
|
|
17
|
+
# Additionally, the {PermissionTemplate} grants authority to perform actions
|
|
18
|
+
# that relate to the Administrative Set/Collection itself. Rules for who can
|
|
19
|
+
# deposit to, view(?!), or manage the admin set are governed by related
|
|
20
|
+
# {PermissionTemplateAccess} records. Administrat Sets should have a manager
|
|
21
|
+
# granted by some such record.
|
|
22
|
+
#
|
|
23
|
+
# @todo write up what "default embargo behavior", when it is applied, and how
|
|
24
|
+
# it interacts with embargoes specified by user input.
|
|
25
|
+
#
|
|
26
|
+
# @example cerating a permission template and manager for an admin set
|
|
27
|
+
# admin_set = Hyrax::AdministrativeSet.new(title: 'My Admin Set')
|
|
28
|
+
# admin_set = Hyrax.persister.save(resource: admin_set)
|
|
29
|
+
#
|
|
30
|
+
# template = PermissionTemplate.create!(source_id: admin_set.id.to_s)
|
|
31
|
+
# Hyrax::PermissionTemplateAccess.create!(permission_template: template,
|
|
32
|
+
# agent_type: Hyrax::PermissionTemplateAccess::USER,
|
|
33
|
+
# agent_id: user.user_key,
|
|
34
|
+
# access: Hyrax::PermissionTemplateAccess::MANAGE)
|
|
35
|
+
#
|
|
36
|
+
# @see Hyrax::AdministrativeSet
|
|
37
|
+
class PermissionTemplate < ActiveRecord::Base # rubocop:disable Metrics/ClassLength
|
|
13
38
|
self.table_name = 'permission_templates'
|
|
14
39
|
|
|
40
|
+
##
|
|
41
|
+
# @!attribute [rw] source_id
|
|
42
|
+
# @return [String] identifier for the {Collection} or {AdministrativeSet}
|
|
43
|
+
# to which this template applies.
|
|
44
|
+
# @!attribute [rw] access_grants
|
|
45
|
+
# @return [Hyrax::PermissionTemplateAccess]
|
|
46
|
+
# @!attribute [rw] active_workflow
|
|
47
|
+
# @return [Sipity::Workflow]
|
|
48
|
+
# @!attribute [rw] available_workflows
|
|
49
|
+
# @return [Enumerable<Sipity::Workflow>]
|
|
15
50
|
has_many :access_grants, class_name: 'Hyrax::PermissionTemplateAccess', dependent: :destroy
|
|
16
51
|
accepts_nested_attributes_for :access_grants, reject_if: :all_blank
|
|
17
52
|
|
|
53
|
+
# The list of workflows that could be activated; It includes the active workflow
|
|
54
|
+
has_many :available_workflows, class_name: 'Sipity::Workflow', dependent: :destroy
|
|
55
|
+
|
|
56
|
+
# In a perfect world, there would be a join table that enforced uniqueness on the ID.
|
|
57
|
+
has_one :active_workflow, -> { where(active: true) }, class_name: 'Sipity::Workflow', foreign_key: :permission_template_id
|
|
58
|
+
|
|
18
59
|
##
|
|
19
60
|
# @api public
|
|
20
61
|
#
|
|
@@ -28,12 +69,6 @@ module Hyrax
|
|
|
28
69
|
access_grants.where(agent_type: agent_type, access: access).pluck(:agent_id)
|
|
29
70
|
end
|
|
30
71
|
|
|
31
|
-
# The list of workflows that could be activated; It includes the active workflow
|
|
32
|
-
has_many :available_workflows, class_name: 'Sipity::Workflow', dependent: :destroy
|
|
33
|
-
|
|
34
|
-
# In a perfect world, there would be a join table that enforced uniqueness on the ID.
|
|
35
|
-
has_one :active_workflow, -> { where(active: true) }, class_name: 'Sipity::Workflow', foreign_key: :permission_template_id
|
|
36
|
-
|
|
37
72
|
##
|
|
38
73
|
# @note this is a convenience method for +Hyrax.query_service.find_by(id: template.source_id)+
|
|
39
74
|
#
|
|
@@ -153,6 +188,57 @@ module Hyrax
|
|
|
153
188
|
visibility == value
|
|
154
189
|
end
|
|
155
190
|
|
|
191
|
+
##
|
|
192
|
+
# @return [Array<String>]
|
|
193
|
+
def edit_users
|
|
194
|
+
agent_ids_for(access: 'manage', agent_type: 'user')
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
##
|
|
198
|
+
# @return [Array<String>]
|
|
199
|
+
def edit_groups
|
|
200
|
+
agent_ids_for(access: 'manage', agent_type: 'group')
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
##
|
|
204
|
+
# @return [Array<String>]
|
|
205
|
+
def read_users
|
|
206
|
+
(agent_ids_for(access: 'view', agent_type: 'user') +
|
|
207
|
+
agent_ids_for(access: 'deposit', agent_type: 'user')).uniq
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
##
|
|
211
|
+
# @return [Array<String>]
|
|
212
|
+
def read_groups
|
|
213
|
+
(agent_ids_for(access: 'view', agent_type: 'group') +
|
|
214
|
+
agent_ids_for(access: 'deposit', agent_type: 'group')).uniq -
|
|
215
|
+
[::Ability.registered_group_name, ::Ability.public_group_name]
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
##
|
|
219
|
+
# @return [Boolean]
|
|
220
|
+
def reset_access_controls(interpret_visibility: false)
|
|
221
|
+
reset_access_controls_for(collection: source_model,
|
|
222
|
+
interpret_visibility: interpret_visibility)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
##
|
|
226
|
+
# @return [Boolean]
|
|
227
|
+
def reset_access_controls_for(collection:, interpret_visibility: false)
|
|
228
|
+
interpreted_read_groups = read_groups
|
|
229
|
+
|
|
230
|
+
if interpret_visibility
|
|
231
|
+
visibilities = Hyrax::VisibilityMap.instance
|
|
232
|
+
interpreted_read_groups -= visibilities.deletions_for(visibility: collection.visibility)
|
|
233
|
+
interpreted_read_groups += visibilities.additions_for(visibility: collection.visibility)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
collection.update!(edit_users: edit_users,
|
|
237
|
+
edit_groups: edit_groups,
|
|
238
|
+
read_users: read_users,
|
|
239
|
+
read_groups: interpreted_read_groups.uniq)
|
|
240
|
+
end
|
|
241
|
+
|
|
156
242
|
private
|
|
157
243
|
|
|
158
244
|
# If template requires no delays, check if date is exactly today
|
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# If ClamAV is present, it will be used to check for the presence of a virus. If ClamAV is not
|
|
4
|
-
# installed or otherwise not available to your application, Hyrax::Works does no virus checking
|
|
5
|
-
# add assumes files have no viruses.
|
|
6
|
-
#
|
|
7
|
-
# @example to use a virus checker other than Hyrax::VirusScanner:
|
|
8
|
-
# class MyScanner < Hyrax::Works::VirusScanner
|
|
9
|
-
# def infected?
|
|
10
|
-
# my_result = Scanner.check_for_viruses(file)
|
|
11
|
-
# [return true or false]
|
|
12
|
-
# end
|
|
13
|
-
# end
|
|
14
|
-
#
|
|
15
|
-
# # Then set Hyrax::Works to use your scanner either in a config file or initializer:
|
|
16
|
-
# Hyrax.config.virus_scanner = MyScanner
|
|
2
|
+
|
|
17
3
|
module Hyrax
|
|
4
|
+
##
|
|
5
|
+
# The default virus scanner ported from +Hyrax::Works+.
|
|
6
|
+
#
|
|
7
|
+
# If ClamAV is present, it will be used to check for the presence of a virus.
|
|
8
|
+
# If ClamAV is not installed or otherwise not available to your application,
|
|
9
|
+
# +Hyrax::Works+ does no virus checking add assumes files have no viruses.
|
|
10
|
+
#
|
|
11
|
+
# @example to use a virus checker other than Hyrax::VirusScanner:
|
|
12
|
+
# class MyScanner < Hyrax::Works::VirusScanner
|
|
13
|
+
# def infected?
|
|
14
|
+
# my_result = Scanner.check_for_viruses(file)
|
|
15
|
+
# [return true or false]
|
|
16
|
+
# end
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# # Then set Hyrax::Works to use your scanner either in a config file or initializer:
|
|
20
|
+
# Hyrax.config.virus_scanner = MyScanner
|
|
21
|
+
#
|
|
18
22
|
class VirusScanner
|
|
19
23
|
attr_reader :file
|
|
20
24
|
|
|
25
|
+
##
|
|
21
26
|
# @api public
|
|
22
27
|
# @param file [String]
|
|
23
28
|
def self.infected?(file)
|
|
@@ -28,7 +33,9 @@ module Hyrax
|
|
|
28
33
|
@file = file
|
|
29
34
|
end
|
|
30
35
|
|
|
31
|
-
|
|
36
|
+
##
|
|
37
|
+
# @note Override this method to use your own virus checking software
|
|
38
|
+
#
|
|
32
39
|
# @return [Boolean]
|
|
33
40
|
def infected?
|
|
34
41
|
defined?(ClamAV) ? clam_av_scanner : null_scanner
|
|
@@ -41,8 +48,10 @@ module Hyrax
|
|
|
41
48
|
true
|
|
42
49
|
end
|
|
43
50
|
|
|
44
|
-
|
|
45
|
-
#
|
|
51
|
+
##
|
|
52
|
+
# Always return zero if there's nothing available to check for viruses.
|
|
53
|
+
# This means that we assume all files have no viruses because we can't
|
|
54
|
+
# conclusively say if they have or not.
|
|
46
55
|
def null_scanner
|
|
47
56
|
warning "Unable to check #{file} for viruses because no virus scanner is defined" unless
|
|
48
57
|
Rails.env.test?
|
data/app/models/sipity/agent.rb
CHANGED
data/app/models/sipity/entity.rb
CHANGED
|
@@ -1,19 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Sipity
|
|
3
|
-
|
|
3
|
+
##
|
|
4
|
+
# A proxy for the entity (e.g. a repository Object) that is being processed
|
|
5
|
+
# via workflows.
|
|
4
6
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
+
# Objects of this class (and their underlying database records) represent
|
|
8
|
+
# another object in the context of the workflow process. By using a proxy,
|
|
9
|
+
# we can avoid polluting the repository object's data and behavior with
|
|
10
|
+
# things related to workflow processing. This means we can move an object into
|
|
11
|
+
# and through a workflow without making changes independently from curatorial
|
|
12
|
+
# considerations (e.g. metadata changes).
|
|
13
|
+
#
|
|
14
|
+
# Keeping this object and interface separate also presents a clear seam for
|
|
15
|
+
# alternative solutions.
|
|
16
|
+
#
|
|
17
|
+
# The {Sipity::Entity} relates to repository objects via a +GlobalID+ URI via
|
|
18
|
+
# {#proxy_for_global_id}. Since the repository objects aren't assumed to be
|
|
19
|
+
# +ActiveRecord+ or +ActiveModel+ compatible, we use the URI-based system
|
|
20
|
+
# provided by +GlobalID+ to ensure that this relationship functions independent
|
|
21
|
+
# of the modelling system used for the respository objects. {#proxy_for} is
|
|
22
|
+
# provided as a convenience method for retrieving the underlying repository
|
|
23
|
+
# object.
|
|
24
|
+
#
|
|
25
|
+
# Each {Sipity::Entity} holds a relationship to a {Sipity::Workflow}, which is
|
|
26
|
+
# the active workflow on the object represented by the {Entity}. It also holds
|
|
27
|
+
# a reference to a {Sipity::WorkflowState}, which is the current state of the
|
|
28
|
+
# object within the workflow.
|
|
7
29
|
#
|
|
8
|
-
# The goal is to keep this behavior separate, so that we can possibly
|
|
9
|
-
# extract the information.
|
|
10
30
|
# @example To get the Sipity::Entity for a work
|
|
11
31
|
# work = GenericWork.first
|
|
12
|
-
#
|
|
13
|
-
# => "gid://whatever/GenericWork/3x816m604"
|
|
14
|
-
# Sipity::Entity.where(proxy_for_global_id: work_global_id).first
|
|
32
|
+
# Sipity::Entity(work)
|
|
15
33
|
# => #<Sipity::Entity id: 1, proxy_for_global_id: "gid://whatever/GenericWork/3x816m604",
|
|
16
34
|
# workflow_id: 8, workflow_state_id: 20, created_at: "2017-07-07 13:39:42", updated_at: "2017-07-07 13:39:42">
|
|
35
|
+
#
|
|
36
|
+
# @see https://github.com/rails/globalid Rails' GlobalID library
|
|
17
37
|
class Entity < ActiveRecord::Base
|
|
18
38
|
self.table_name = 'sipity_entities'
|
|
19
39
|
|
|
@@ -35,6 +55,8 @@ module Sipity
|
|
|
35
55
|
# Defines the method #workflow_name
|
|
36
56
|
delegate :name, to: :workflow, prefix: :workflow
|
|
37
57
|
|
|
58
|
+
##
|
|
59
|
+
# @return [Object] the thing this +Entity+ represents.
|
|
38
60
|
def proxy_for
|
|
39
61
|
@proxy_for ||= GlobalID::Locator.locate(proxy_for_global_id)
|
|
40
62
|
end
|
data/app/models/sipity.rb
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
##
|
|
4
|
+
# {Sipity} is a workflow/state engine.
|
|
5
|
+
#
|
|
6
|
+
# This module and the classes namespaced within it provide a domain model and
|
|
7
|
+
# implementation for managing the movement of repository objects through a
|
|
8
|
+
# defined workflow. The workflows themselves are configured using JSON documents
|
|
9
|
+
# and loaded into the database/domain model as {Sipity::Workflow}. Each workflow
|
|
10
|
+
# can be understood as finite sets of {Sipity::WorkflowState},
|
|
11
|
+
# {Sipity::WorkflowAction} (transitions from state to state), and {Sipity::Role}
|
|
12
|
+
# authorized to carry out each action.
|
|
13
|
+
#
|
|
14
|
+
# Any uniquely identifiable object can be managed by a {Sipity::Workflow}.
|
|
15
|
+
# Normally Hyrax uses workflows to handle the deposit process and maintenance
|
|
16
|
+
# lifecycle of repository objects at the level of the Work (within the Hydra
|
|
17
|
+
# Works model). Objects are represented within the Sipity engine's domain model
|
|
18
|
+
# by a {Sipity::Entity}. Each object has at most one {Sipity::Entity}, is
|
|
19
|
+
# governed by one {Sipity::Workflow}, and in one {Sipity::WorkflowState} at any
|
|
20
|
+
# given time.
|
|
21
|
+
#
|
|
22
|
+
# Some use cases for Sipity workflows include:
|
|
23
|
+
#
|
|
24
|
+
# * Simple unmediated deposit with on-deposit notifications and actions;
|
|
25
|
+
# * Mediated deposit with one or more review steps;
|
|
26
|
+
# * Publication workflows requiring multiple levels of editorial approval
|
|
27
|
+
# and/or peer review;
|
|
28
|
+
# * Preservation processes involving post-deposit selection of objects for
|
|
29
|
+
# replication to external preservation platforms and/or required action
|
|
30
|
+
# in case of failed fixity checks;
|
|
31
|
+
# * Electronic Thesis & Dissertation submission processes involving (e.g.)
|
|
32
|
+
# student deposit, committee and/or departmental approval, centralized/
|
|
33
|
+
# graduate school review, and a final graduation step.
|
|
34
|
+
#
|
|
3
35
|
module Sipity
|
|
36
|
+
##
|
|
37
|
+
# Cast a given input (e.g. a +::User+ or {Hyrax::Group} to a {Sipity::Agent}).
|
|
38
|
+
#
|
|
39
|
+
# @param input [Object]
|
|
40
|
+
#
|
|
41
|
+
# @return [Sipity::Agent]
|
|
4
42
|
def Agent(input, &block) # rubocop:disable Naming/MethodName
|
|
5
43
|
result = case input
|
|
6
44
|
when Sipity::Agent
|
|
@@ -13,6 +51,10 @@ module Sipity
|
|
|
13
51
|
|
|
14
52
|
##
|
|
15
53
|
# Cast an object to an Entity
|
|
54
|
+
#
|
|
55
|
+
# @param input [Object]
|
|
56
|
+
#
|
|
57
|
+
# @return [Sipity::Entity]
|
|
16
58
|
# rubocop:disable Naming/MethodName, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
|
17
59
|
def Entity(input, &block)
|
|
18
60
|
result = case input
|
|
@@ -59,16 +59,8 @@ module Hyrax
|
|
|
59
59
|
# > remove files from a work, and add new works to the set.
|
|
60
60
|
return true if @current_ability.can?(:manage, permission_template)
|
|
61
61
|
|
|
62
|
-
# Otherwise, we check if the workflow
|
|
63
|
-
|
|
64
|
-
wf = workflow(permission_template: permission_template)
|
|
65
|
-
return false unless wf
|
|
66
|
-
wf.allows_access_grant?
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def workflow(permission_template:)
|
|
70
|
-
return unless permission_template.active_workflow
|
|
71
|
-
Sipity::Workflow.find_by!(id: permission_template.active_workflow.id)
|
|
62
|
+
# Otherwise, we check if the active workflow allows access grants
|
|
63
|
+
!!permission_template.active_workflow&.allows_access_grant?
|
|
72
64
|
end
|
|
73
65
|
end
|
|
74
66
|
end
|
|
@@ -12,7 +12,11 @@ module Hyrax
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def total_viewable_items
|
|
15
|
-
|
|
15
|
+
field_pairs = { "isPartOf_ssim" => id.to_s }
|
|
16
|
+
SolrQueryService.new
|
|
17
|
+
.with_field_pairs(field_pairs: field_pairs)
|
|
18
|
+
.accessible_by(ability: current_ability)
|
|
19
|
+
.count
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
# AdminSet cannot be deleted if default set or non-empty
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Hyrax
|
|
3
|
+
##
|
|
4
|
+
# @api public
|
|
5
|
+
# @since 3.1.0
|
|
6
|
+
#
|
|
7
|
+
# Presents select options for admin sets.
|
|
8
|
+
#
|
|
9
|
+
# Each entry in the {#select_options} return value provides a label for
|
|
10
|
+
# display, an id to serve as the value, and a data hash which is used as HTML5
|
|
11
|
+
# data entries. The data entries can be used as hooks for Javascript
|
|
12
|
+
# to control input validation taking into account the Admin Set and
|
|
13
|
+
# `PermissionTemplate` rules (`visibility_component.es6` does this, for
|
|
14
|
+
# example).
|
|
15
|
+
#
|
|
16
|
+
# @note this supersedes the older +Hyrax::AdminSetOptionsPresenter+, which
|
|
17
|
+
# actied more like a "service" sending database queries to Solr and
|
|
18
|
+
# ActiveRecord. this version seeks only to present the input data and
|
|
19
|
+
# relies on its caller to pass in the right data.
|
|
20
|
+
class AdminSetSelectionPresenter
|
|
21
|
+
##
|
|
22
|
+
# @param [Array<#id>]
|
|
23
|
+
def initialize(admin_sets:)
|
|
24
|
+
@admin_sets = admin_sets
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# @return [Array<Array<String, String, Hash>>] an array suitable for a form
|
|
29
|
+
# input `collection:` parameter. it should contain a label, an id, and a
|
|
30
|
+
# hash of HTML5 data attributes.
|
|
31
|
+
def select_options
|
|
32
|
+
@admin_sets.map do |admin_set|
|
|
33
|
+
case admin_set
|
|
34
|
+
when OptionsEntry
|
|
35
|
+
admin_set.result
|
|
36
|
+
else
|
|
37
|
+
OptionsEntry.new(admin_set: admin_set).result
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# @api public
|
|
44
|
+
class OptionsEntry
|
|
45
|
+
##
|
|
46
|
+
# @!attribute [rw] admin_set
|
|
47
|
+
# @return [AdministrativeSet, SolrDocument]
|
|
48
|
+
# @!attribute [rw] permission_template
|
|
49
|
+
# @return [PermissionTemplate]
|
|
50
|
+
# @!attribute [rw] permit_sharing
|
|
51
|
+
# @return [Boolean]
|
|
52
|
+
attr_accessor :admin_set, :permission_template, :permit_sharing
|
|
53
|
+
|
|
54
|
+
##
|
|
55
|
+
# @param [AdministrativeSet, SolrDocument] admin_set
|
|
56
|
+
# @param [PermissionTemplate] permission_template
|
|
57
|
+
# @param [Boolean] permit_sharing
|
|
58
|
+
def initialize(admin_set:, permission_template: nil, permit_sharing: false)
|
|
59
|
+
@admin_set = admin_set
|
|
60
|
+
@permission_template = permission_template
|
|
61
|
+
@permit_sharing = permit_sharing
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
##
|
|
65
|
+
# @return [Array<String, String, Hash>]
|
|
66
|
+
def result
|
|
67
|
+
[label, id, data]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
# @return [String]
|
|
72
|
+
def label
|
|
73
|
+
Array(admin_set.title).first || admin_set.to_s
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# @return [String]
|
|
78
|
+
def id
|
|
79
|
+
admin_set.id.to_s
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
##
|
|
83
|
+
# @return [Hash{String => Object}]
|
|
84
|
+
def data
|
|
85
|
+
{}.tap do |data|
|
|
86
|
+
data['data-sharing'] = permit_sharing
|
|
87
|
+
|
|
88
|
+
if permission_template
|
|
89
|
+
data.merge!(data_for(permission_template))
|
|
90
|
+
else
|
|
91
|
+
data['data-release-no-delay'] = true
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
private
|
|
97
|
+
|
|
98
|
+
##
|
|
99
|
+
# @api private
|
|
100
|
+
def data_for(template)
|
|
101
|
+
{}.tap do |data|
|
|
102
|
+
if template.release_no_delay?
|
|
103
|
+
data['data-release-no-delay'] = true
|
|
104
|
+
elsif template.release_date.present?
|
|
105
|
+
data['data-release-date'] = template.release_date
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
data['data-release-before-date'] = true if
|
|
109
|
+
template.release_before_date?
|
|
110
|
+
data['data-visibility'] = template.visibility if
|
|
111
|
+
template.visibility.present?
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|