ddr-models 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +12 -0
- data/README.md +5 -0
- data/Rakefile +37 -0
- data/app/models/attachment.rb +7 -0
- data/app/models/collection.rb +54 -0
- data/app/models/component.rb +15 -0
- data/app/models/item.rb +19 -0
- data/app/models/solr_document.rb +36 -0
- data/app/models/target.rb +8 -0
- data/config/initializers/active_fedora_base.rb +77 -0
- data/config/initializers/active_fedora_datastream.rb +5 -0
- data/config/initializers/ddr.rb +8 -0
- data/config/initializers/devise.rb +245 -0
- data/config/initializers/devise.rb~ +245 -0
- data/config/initializers/subscriptions.rb +15 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20141021233359_create_events.rb +28 -0
- data/db/migrate/20141021234156_create_minted_ids.rb +19 -0
- data/db/migrate/20141103192146_create_workflow_state.rb +13 -0
- data/db/migrate/20141104181418_create_users.rb +34 -0
- data/db/migrate/20141104181418_create_users.rb~ +6 -0
- data/lib/ddr-models.rb +1 -0
- data/lib/ddr/actions.rb +8 -0
- data/lib/ddr/actions/fixity_check.rb +35 -0
- data/lib/ddr/auth.rb +45 -0
- data/lib/ddr/auth.rb~ +47 -0
- data/lib/ddr/auth/ability.rb +204 -0
- data/lib/ddr/auth/ability.rb~ +204 -0
- data/lib/ddr/auth/group_service.rb +53 -0
- data/lib/ddr/auth/group_service.rb~ +53 -0
- data/lib/ddr/auth/grouper_service.rb +76 -0
- data/lib/ddr/auth/grouper_service.rb~ +77 -0
- data/lib/ddr/auth/remote_group_service.rb +35 -0
- data/lib/ddr/auth/remote_group_service.rb~ +35 -0
- data/lib/ddr/auth/superuser.rb +13 -0
- data/lib/ddr/auth/superuser.rb~ +9 -0
- data/lib/ddr/auth/user.rb +71 -0
- data/lib/ddr/auth/user.rb~ +65 -0
- data/lib/ddr/configurable.rb +34 -0
- data/lib/ddr/datastreams.rb +32 -0
- data/lib/ddr/datastreams/content_metadata_datastream.rb +147 -0
- data/lib/ddr/datastreams/datastream_behavior.rb +95 -0
- data/lib/ddr/datastreams/descriptive_metadata_datastream.rb +84 -0
- data/lib/ddr/datastreams/properties_datastream.rb +25 -0
- data/lib/ddr/datastreams/role_assignments_datastream.rb +19 -0
- data/lib/ddr/events.rb +17 -0
- data/lib/ddr/events/creation_event.rb +12 -0
- data/lib/ddr/events/event.rb +163 -0
- data/lib/ddr/events/fixity_check_event.rb +43 -0
- data/lib/ddr/events/ingestion_event.rb +12 -0
- data/lib/ddr/events/preservation_event_behavior.rb +37 -0
- data/lib/ddr/events/preservation_event_type.rb +24 -0
- data/lib/ddr/events/reindex_object_after_save.rb +18 -0
- data/lib/ddr/events/update_event.rb +9 -0
- data/lib/ddr/events/validation_event.rb +11 -0
- data/lib/ddr/events/virus_check_event.rb +30 -0
- data/lib/ddr/index_fields.rb +39 -0
- data/lib/ddr/metadata.rb +22 -0
- data/lib/ddr/metadata/duke_terms.rb +15 -0
- data/lib/ddr/metadata/premis_event.rb +59 -0
- data/lib/ddr/metadata/rdf_vocabulary_parser.rb +45 -0
- data/lib/ddr/metadata/roles_vocabulary.rb +10 -0
- data/lib/ddr/metadata/sources/duketerms.rdf.xml +856 -0
- data/lib/ddr/metadata/vocabulary.rb +37 -0
- data/lib/ddr/models.rb +60 -0
- data/lib/ddr/models/access_controllable.rb +23 -0
- data/lib/ddr/models/base.rb +37 -0
- data/lib/ddr/models/describable.rb +81 -0
- data/lib/ddr/models/engine.rb +58 -0
- data/lib/ddr/models/error.rb +12 -0
- data/lib/ddr/models/event_loggable.rb +36 -0
- data/lib/ddr/models/file_management.rb +183 -0
- data/lib/ddr/models/fixity_checkable.rb +20 -0
- data/lib/ddr/models/governable.rb +48 -0
- data/lib/ddr/models/has_attachments.rb +12 -0
- data/lib/ddr/models/has_children.rb +21 -0
- data/lib/ddr/models/has_content.rb +114 -0
- data/lib/ddr/models/has_content_metadata.rb +16 -0
- data/lib/ddr/models/has_properties.rb +15 -0
- data/lib/ddr/models/has_role_assignments.rb +17 -0
- data/lib/ddr/models/has_thumbnail.rb +27 -0
- data/lib/ddr/models/has_workflow.rb +29 -0
- data/lib/ddr/models/indexing.rb +53 -0
- data/lib/ddr/models/licensable.rb +28 -0
- data/lib/ddr/models/minted_id.rb +10 -0
- data/lib/ddr/models/permanent_identification.rb +48 -0
- data/lib/ddr/models/solr_document.rb +193 -0
- data/lib/ddr/models/version.rb +5 -0
- data/lib/ddr/notifications.rb +15 -0
- data/lib/ddr/services.rb +8 -0
- data/lib/ddr/services/id_service.rb +48 -0
- data/lib/ddr/utils.rb +153 -0
- data/lib/ddr/workflow.rb +8 -0
- data/lib/ddr/workflow/workflow_state.rb +39 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/user.rb +5 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +29 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +78 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/assets.rb +8 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +56 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +80 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +4974 -0
- data/spec/dummy/log/test.log +55627 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/attachment_factories.rb +15 -0
- data/spec/factories/collection_factories.rb +16 -0
- data/spec/factories/component_factories.rb +15 -0
- data/spec/factories/event_factories.rb +7 -0
- data/spec/factories/item_factories.rb +16 -0
- data/spec/factories/target_factories.rb +11 -0
- data/spec/factories/test_model_factories.rb +133 -0
- data/spec/factories/user_factories.rb +7 -0
- data/spec/factories/user_factories.rb~ +7 -0
- data/spec/features/grouper_integration_spec.rb~ +21 -0
- data/spec/fixtures/contentMetadata.xml +37 -0
- data/spec/fixtures/image1.tiff +0 -0
- data/spec/fixtures/image2.tiff +0 -0
- data/spec/fixtures/image3.tiff +0 -0
- data/spec/fixtures/library-devil.tiff +0 -0
- data/spec/fixtures/sample.docx +0 -0
- data/spec/fixtures/sample.pdf +0 -0
- data/spec/fixtures/target.png +0 -0
- data/spec/models/ability_spec.rb +248 -0
- data/spec/models/ability_spec.rb~ +245 -0
- data/spec/models/active_fedora_base_spec.rb +107 -0
- data/spec/models/active_fedora_datastream_spec.rb +121 -0
- data/spec/models/attachment_spec.rb +13 -0
- data/spec/models/collection_spec.rb +33 -0
- data/spec/models/component_spec.rb +8 -0
- data/spec/models/descriptive_metadata_datastream_spec.rb +102 -0
- data/spec/models/events_spec.rb +64 -0
- data/spec/models/file_management_spec.rb +179 -0
- data/spec/models/has_role_assignments_spec.rb +29 -0
- data/spec/models/has_workflow_spec.rb +54 -0
- data/spec/models/item_spec.rb +8 -0
- data/spec/models/permanent_identification_spec.rb +65 -0
- data/spec/models/role_assignments_datastream_spec.rb +25 -0
- data/spec/models/superuser_spec.rb +13 -0
- data/spec/models/superuser_spec.rb~ +13 -0
- data/spec/models/target_spec.rb +8 -0
- data/spec/models/user_spec.rb +60 -0
- data/spec/models/user_spec.rb~ +56 -0
- data/spec/services/group_service_spec.rb +75 -0
- data/spec/services/group_service_spec.rb~ +71 -0
- data/spec/services/id_service_spec.rb +33 -0
- data/spec/spec_helper.rb +125 -0
- data/spec/support/shared_examples_for_access_controllables.rb +6 -0
- data/spec/support/shared_examples_for_associations.rb +8 -0
- data/spec/support/shared_examples_for_ddr_models.rb +7 -0
- data/spec/support/shared_examples_for_describables.rb +63 -0
- data/spec/support/shared_examples_for_event_loggables.rb +3 -0
- data/spec/support/shared_examples_for_events.rb +179 -0
- data/spec/support/shared_examples_for_governables.rb +17 -0
- data/spec/support/shared_examples_for_has_content.rb +136 -0
- data/spec/support/shared_examples_for_has_content_metadata.rb +74 -0
- data/spec/support/shared_examples_for_has_properties.rb +5 -0
- data/spec/support/shared_examples_for_indexing.rb +36 -0
- metadata +562 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
module Ddr
|
2
|
+
module Metadata
|
3
|
+
class Vocabulary
|
4
|
+
|
5
|
+
def self.label(rdf_vocabulary)
|
6
|
+
case rdf_vocabulary.to_uri
|
7
|
+
when RDF::DC.to_uri
|
8
|
+
"DC Terms"
|
9
|
+
when DukeTerms.to_uri
|
10
|
+
"Duke Terms"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.namespace_prefix(rdf_vocabulary)
|
15
|
+
case rdf_vocabulary.to_uri
|
16
|
+
when RDF::DC.to_uri
|
17
|
+
"dcterms"
|
18
|
+
when DukeTerms.to_uri
|
19
|
+
"duke"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.property_terms(rdf_vocabulary)
|
24
|
+
rdf_vocabulary.properties.select { |p| p.type.include?("http://www.w3.org/1999/02/22-rdf-syntax-ns#Property") }
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.term_names(rdf_vocabulary)
|
28
|
+
self.property_terms(rdf_vocabulary).map { |term| self.term_name(rdf_vocabulary, term) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.term_name(rdf_vocabulary, term)
|
32
|
+
term.to_s.gsub(rdf_vocabulary.to_uri.to_s, "").to_sym
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/ddr/models.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'ddr/models/engine'
|
2
|
+
require 'ddr/models/version'
|
3
|
+
|
4
|
+
# Awful hack to make Hydra::AccessControls::Permissions accessible
|
5
|
+
$: << Gem.loaded_specs['hydra-access-controls'].full_gem_path + "/app/models/concerns"
|
6
|
+
|
7
|
+
require 'active_record'
|
8
|
+
|
9
|
+
require 'hydra-core'
|
10
|
+
require 'hydra/derivatives'
|
11
|
+
require 'hydra/validations'
|
12
|
+
|
13
|
+
require 'ddr/actions'
|
14
|
+
require 'ddr/auth'
|
15
|
+
require 'ddr/configurable'
|
16
|
+
require 'ddr/datastreams'
|
17
|
+
require 'ddr/events'
|
18
|
+
require 'ddr/index_fields'
|
19
|
+
require 'ddr/metadata'
|
20
|
+
require 'ddr/notifications'
|
21
|
+
require 'ddr/services'
|
22
|
+
require 'ddr/utils'
|
23
|
+
require 'ddr/workflow'
|
24
|
+
|
25
|
+
module Ddr
|
26
|
+
module Models
|
27
|
+
extend ActiveSupport::Autoload
|
28
|
+
|
29
|
+
autoload :Configurable
|
30
|
+
|
31
|
+
autoload :Base
|
32
|
+
autoload :AccessControllable
|
33
|
+
autoload :Describable
|
34
|
+
autoload :EventLoggable
|
35
|
+
autoload :Error
|
36
|
+
autoload :ChecksumInvalid, 'ddr/models/error'
|
37
|
+
autoload :VirusFoundError, 'ddr/models/error'
|
38
|
+
autoload :FixityCheckable
|
39
|
+
autoload :Governable
|
40
|
+
autoload :HasAttachments
|
41
|
+
autoload :HasChildren
|
42
|
+
autoload :HasContent
|
43
|
+
autoload :HasContentMetadata
|
44
|
+
autoload :HasProperties
|
45
|
+
autoload :HasRoleAssignments
|
46
|
+
autoload :HasThumbnail
|
47
|
+
autoload :HasWorkflow
|
48
|
+
autoload :Indexing
|
49
|
+
autoload :FileManagement
|
50
|
+
autoload :Licensable
|
51
|
+
autoload :MintedId
|
52
|
+
autoload :PermanentIdentification
|
53
|
+
autoload :SolrDocument
|
54
|
+
|
55
|
+
include Ddr::Configurable
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
Dir[Ddr::Models::Engine.root.to_s + "/app/models/*.rb"].each { |m| require m }
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Ddr
|
2
|
+
module Models
|
3
|
+
module AccessControllable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
# adds methods for managing Hydra rightsMetadata content
|
8
|
+
include Hydra::AccessControls::Permissions unless include? Hydra::AccessControls::Permissions
|
9
|
+
end
|
10
|
+
|
11
|
+
def set_initial_permissions(user_creator = nil)
|
12
|
+
if user_creator
|
13
|
+
self.permissions_attributes = [{type: "user", access: "edit", name: user_creator.to_s}]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def copy_permissions_from(other)
|
18
|
+
# XXX active-fedora < 7.0
|
19
|
+
self.permissions_attributes = other.permissions.collect { |p| p.to_hash }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Ddr
|
2
|
+
module Models
|
3
|
+
class Base < ActiveFedora::Base
|
4
|
+
|
5
|
+
include Describable
|
6
|
+
include Governable
|
7
|
+
include AccessControllable
|
8
|
+
include Licensable
|
9
|
+
include HasProperties
|
10
|
+
include HasThumbnail
|
11
|
+
include ActiveFedora::Auditable
|
12
|
+
include EventLoggable
|
13
|
+
include FixityCheckable
|
14
|
+
include FileManagement
|
15
|
+
include Indexing
|
16
|
+
include PermanentIdentification
|
17
|
+
include HasRoleAssignments
|
18
|
+
include Hydra::Validations
|
19
|
+
include HasWorkflow
|
20
|
+
|
21
|
+
def copy_admin_policy_or_permissions_from(other)
|
22
|
+
copy_permissions_from(other) unless copy_admin_policy_from(other)
|
23
|
+
end
|
24
|
+
|
25
|
+
def association_query(association)
|
26
|
+
# XXX Ideally we would include a clause to limit by AF model, but this should suffice
|
27
|
+
ActiveFedora::SolrService.construct_query_for_rel(reflections[association].options[:property] => internal_uri)
|
28
|
+
end
|
29
|
+
|
30
|
+
# e.g., "Collection duke:1"
|
31
|
+
def model_pid
|
32
|
+
[self.class.to_s, pid].join(" ")
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Ddr
|
2
|
+
module Models
|
3
|
+
module Describable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
has_metadata name: Ddr::Datastreams::DESC_METADATA,
|
8
|
+
type: Ddr::Datastreams::DescriptiveMetadataDatastream,
|
9
|
+
versionable: true,
|
10
|
+
label: "Descriptive Metadata for this object",
|
11
|
+
control_group: 'M'
|
12
|
+
has_attributes *Ddr::Metadata::Vocabulary.term_names(RDF::DC11),
|
13
|
+
datastream: Ddr::Datastreams::DESC_METADATA,
|
14
|
+
multiple: true
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_desc_metadata?
|
18
|
+
descMetadata.has_content?
|
19
|
+
end
|
20
|
+
|
21
|
+
def desc_metadata_terms *args
|
22
|
+
return Ddr::Datastreams::DescriptiveMetadataDatastream.term_names if args.empty?
|
23
|
+
arg = args.pop
|
24
|
+
terms = case arg.to_sym
|
25
|
+
when :empty
|
26
|
+
desc_metadata_terms.select { |t| desc_metadata_values(t).empty? }
|
27
|
+
when :present
|
28
|
+
desc_metadata_terms.select { |t| desc_metadata_values(t).present? }
|
29
|
+
when :defined_attributes
|
30
|
+
desc_metadata_terms & desc_metadata_attributes
|
31
|
+
when :required
|
32
|
+
desc_metadata_terms(:defined_attributes).select {|t| required? t}
|
33
|
+
when :dcterms
|
34
|
+
Ddr::Metadata::Vocabulary.term_names(RDF::DC11) +
|
35
|
+
(Ddr::Metadata::Vocabulary.term_names(RDF::DC) - Ddr::Metadata::Vocabulary.term_names(RDF::DC11))
|
36
|
+
when :dcterms_elements11
|
37
|
+
Ddr::Metadata::Vocabulary.term_names(RDF::DC11)
|
38
|
+
when :duke
|
39
|
+
Ddr::Metadata::Vocabulary.term_names(Ddr::Metadata::DukeTerms)
|
40
|
+
else
|
41
|
+
raise ArgumentError, "Invalid argument: #{arg.inspect}"
|
42
|
+
end
|
43
|
+
if args.empty?
|
44
|
+
terms
|
45
|
+
else
|
46
|
+
terms | desc_metadata_terms(*args)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def desc_metadata_attributes
|
51
|
+
defattrs = self.class.defined_attributes
|
52
|
+
defattrs.keys.select {|k| defattrs[k].dsid == "descMetadata"}.map(&:to_sym)
|
53
|
+
end
|
54
|
+
|
55
|
+
def desc_metadata_values term
|
56
|
+
descMetadata.values term
|
57
|
+
end
|
58
|
+
|
59
|
+
def desc_metadata_vocabs
|
60
|
+
descMetadata.class.vocabularies
|
61
|
+
end
|
62
|
+
|
63
|
+
def set_desc_metadata_values term, values
|
64
|
+
descMetadata.set_values term, values
|
65
|
+
end
|
66
|
+
|
67
|
+
# Update all descMetadata terms with values in hash
|
68
|
+
# Note that term not having key in hash will be set to nil!
|
69
|
+
def set_desc_metadata term_values_hash
|
70
|
+
desc_metadata_terms.each { |t| set_desc_metadata_values(t, term_values_hash[t]) }
|
71
|
+
end
|
72
|
+
|
73
|
+
module ClassMethods
|
74
|
+
def find_by_identifier(identifier)
|
75
|
+
find(Ddr::IndexFields::IDENTIFIER => identifier)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rails'
|
2
|
+
|
3
|
+
module Ddr
|
4
|
+
module Models
|
5
|
+
class Engine < ::Rails::Engine
|
6
|
+
|
7
|
+
engine_name 'ddr_models'
|
8
|
+
|
9
|
+
config.generators do |g|
|
10
|
+
g.test_framework :rspec
|
11
|
+
g.fixture_replacement :factory_girl
|
12
|
+
g.assets false
|
13
|
+
g.helper false
|
14
|
+
end
|
15
|
+
|
16
|
+
# Add custom predicates to ActiveFedora
|
17
|
+
initializer 'ddr_models.predicates' do
|
18
|
+
ActiveFedora::Predicates.set_predicates(Ddr::Metadata::PREDICATES)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Configure devise-remote-user
|
22
|
+
initializer 'ddr_auth.remote_user' do
|
23
|
+
require 'devise_remote_user'
|
24
|
+
DeviseRemoteUser.configure do |config|
|
25
|
+
config.auto_create = true
|
26
|
+
config.attribute_map = {
|
27
|
+
email: 'mail',
|
28
|
+
first_name: 'givenName',
|
29
|
+
middle_name: 'duMiddleName1',
|
30
|
+
nickname: 'eduPersonNickname',
|
31
|
+
last_name: 'sn',
|
32
|
+
display_name: 'displayName'
|
33
|
+
}
|
34
|
+
config.auto_update = true
|
35
|
+
config.logout_url = "/Shibboleth.sso/Logout?return=https://shib.oit.duke.edu/cgi-bin/logout.pl"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Integration of remote (Grouper) groups via Shibboleth
|
40
|
+
initializer 'ddr_auth.grouper' do
|
41
|
+
# Load configuration for Grouper service, if present
|
42
|
+
if File.exists? "#{Rails.root}/config/grouper.yml"
|
43
|
+
Ddr::Auth::GrouperService.config = YAML.load_file("#{Rails.root}/config/grouper.yml")[Rails.env]
|
44
|
+
end
|
45
|
+
|
46
|
+
Warden::Manager.after_set_user do |user, auth, opts|
|
47
|
+
user.group_service = Ddr::Auth::RemoteGroupService.new(auth.env)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Set superuser group
|
52
|
+
initializer 'ddr_auth.superuser' do
|
53
|
+
Ddr::Auth.superuser_group = ENV["SUPERUSER_GROUP"]
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Ddr
|
2
|
+
module Models
|
3
|
+
module EventLoggable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def events
|
7
|
+
event_class.for_object(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
def update_events
|
11
|
+
event_class(:update).for_object(self)
|
12
|
+
end
|
13
|
+
|
14
|
+
# TESTME
|
15
|
+
def notify_event(type, args={})
|
16
|
+
Ddr::Notifications.notify_event(type, args.merge(pid: pid))
|
17
|
+
end
|
18
|
+
|
19
|
+
def has_events?
|
20
|
+
events.count > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def event_class_name(token=nil)
|
26
|
+
type = token ? "#{token.to_s.camelize}Event" : "Event"
|
27
|
+
"Ddr::Events::#{type}"
|
28
|
+
end
|
29
|
+
|
30
|
+
def event_class(token=nil)
|
31
|
+
event_class_name(token).constantize
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require "ddr-antivirus"
|
2
|
+
|
3
|
+
module Ddr
|
4
|
+
module Models
|
5
|
+
module FileManagement
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
EXTERNAL_FILE_PERMISSIONS = 0644
|
9
|
+
|
10
|
+
included do
|
11
|
+
attr_accessor :file_to_add
|
12
|
+
|
13
|
+
define_model_callbacks :add_file
|
14
|
+
before_add_file :virus_scan
|
15
|
+
|
16
|
+
after_save :notify_virus_scan_results
|
17
|
+
|
18
|
+
# Deleting the datastream external files on destroying the object can't
|
19
|
+
# be handled with a datastream around_destroy callback.
|
20
|
+
# See https://groups.google.com/d/msg/hydra-tech/xJaZr2wVhbg/4iafvso98w8J
|
21
|
+
around_destroy :cleanup_external_files_on_destroy
|
22
|
+
end
|
23
|
+
|
24
|
+
# add_file(file, dsid, opts={})
|
25
|
+
#
|
26
|
+
# Comparable to Hydra::ModelMethods#add_file(file, dsid, file_name)
|
27
|
+
#
|
28
|
+
# Options:
|
29
|
+
#
|
30
|
+
# :mime_type - Explicit mime type to set (otherwise discerned from file path or name)
|
31
|
+
#
|
32
|
+
# :original_name - A String value will be understood as the original name of the file.
|
33
|
+
# `false` or `nil` indicate that the file basename is not the original
|
34
|
+
# name. Default processing will take the file basename as the original
|
35
|
+
# name.
|
36
|
+
#
|
37
|
+
# :external - Add to file to external datastream. Not required for datastream specs
|
38
|
+
# where :control_group=>"E".
|
39
|
+
#
|
40
|
+
# :use_original - For external datastream file, do not copy file to new file path,
|
41
|
+
# but use in place (set dsLocation to file URI for current path.
|
42
|
+
def add_file file, dsid, opts={}
|
43
|
+
opts[:mime_type] ||= Ddr::Utils.mime_type_for(file)
|
44
|
+
|
45
|
+
# @file_to_add is set for callbacks to access the data
|
46
|
+
original_name = opts.fetch(:original_name, Ddr::Utils.file_name_for(file))
|
47
|
+
self.file_to_add = FileToAdd.new(file, dsid, original_name)
|
48
|
+
|
49
|
+
run_callbacks(:add_file) do
|
50
|
+
if opts.delete(:external) || datastreams.include?(dsid) && datastreams[dsid].external?
|
51
|
+
add_external_file(file, dsid, opts)
|
52
|
+
else
|
53
|
+
file = File.new(file, "rb") if Ddr::Utils.file_path?(file)
|
54
|
+
# ActiveFedora method accepts file-like objects, not paths
|
55
|
+
add_file_datastream(file, dsid: dsid, mimeType: opts[:mime_type])
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# clear the instance data
|
60
|
+
self.file_to_add = nil
|
61
|
+
end
|
62
|
+
|
63
|
+
# Normally this method should not be called directly. Call `add_file` with dsid for
|
64
|
+
# external datastream id, or with `:external=>true` option if no spec for dsid.
|
65
|
+
def add_external_file file, dsid, opts={}
|
66
|
+
file_path = Ddr::Utils.file_path(file) # raises ArgumentError
|
67
|
+
|
68
|
+
# Retrieve or create the datastream
|
69
|
+
ds = datastreams.include?(dsid) ? datastreams[dsid] : add_external_datastream(dsid)
|
70
|
+
|
71
|
+
unless ds.external?
|
72
|
+
raise ArgumentError, "Cannot add external file to datastream with controlGroup \"#{ds.controlGroup}\""
|
73
|
+
end
|
74
|
+
|
75
|
+
if ds.dsLocation_changed?
|
76
|
+
raise Ddr::Models::Error, "Cannot add external file to datastream when dsLocation change is pending."
|
77
|
+
end
|
78
|
+
|
79
|
+
# Set the MIME type
|
80
|
+
# The :mime_type option will be present when called from `add_file`.
|
81
|
+
# The fallback is there in case `add_external_file` is called directly.
|
82
|
+
ds.mimeType = opts[:mime_type] || Ddr::Utils.mime_type_for(file, file_path)
|
83
|
+
|
84
|
+
# Copy the file to storage unless we're using the original
|
85
|
+
if opts[:use_original]
|
86
|
+
raise Ddr::Models::Error, "Cannot add file to repository that is owned by another user." unless File.owned?(file_path)
|
87
|
+
store_path = file_path
|
88
|
+
else
|
89
|
+
# generate new storage path for file
|
90
|
+
store_path = create_external_file_path!
|
91
|
+
# copy the original file to the storage location
|
92
|
+
FileUtils.cp file_path, store_path
|
93
|
+
end
|
94
|
+
|
95
|
+
# set appropriate permissions on the file
|
96
|
+
set_external_file_permissions!(store_path)
|
97
|
+
|
98
|
+
# set dsLocation to file URI for storage path
|
99
|
+
ds.dsLocation = Ddr::Utils.path_to_uri(store_path)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Create directory (if necessary) for newly generated file path and return path
|
103
|
+
def create_external_file_path!
|
104
|
+
file_path = generate_external_file_path
|
105
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
106
|
+
file_path
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Generates a new external file storage location
|
111
|
+
#
|
112
|
+
# => {external_file_store}/1/e/69/1e691815-0631-4f9b-8e23-2dfb2eec9c70
|
113
|
+
#
|
114
|
+
def generate_external_file_path
|
115
|
+
file_name = generate_external_file_name
|
116
|
+
File.join(external_file_store, generate_external_directory_subpath(file_name), file_name)
|
117
|
+
end
|
118
|
+
|
119
|
+
def external_datastreams
|
120
|
+
datastreams.values.select { |ds| ds.external? }
|
121
|
+
end
|
122
|
+
|
123
|
+
def external_datastream_file_paths
|
124
|
+
external_datastreams.map(&:file_paths).flatten
|
125
|
+
end
|
126
|
+
|
127
|
+
def add_external_datastream dsid, opts={}
|
128
|
+
klass = self.class.datastream_class_for_name(dsid)
|
129
|
+
datastream = create_datastream(klass, dsid, controlGroup: "E")
|
130
|
+
add_datastream(datastream)
|
131
|
+
self.class.build_datastream_accessor(dsid)
|
132
|
+
datastream
|
133
|
+
end
|
134
|
+
|
135
|
+
protected
|
136
|
+
|
137
|
+
FileToAdd = Struct.new(:file, :dsid, :original_name)
|
138
|
+
|
139
|
+
def virus_scan_results
|
140
|
+
@virus_scan_results ||= []
|
141
|
+
end
|
142
|
+
|
143
|
+
def virus_scan
|
144
|
+
path = Ddr::Utils.file_path(file_to_add[:file])
|
145
|
+
virus_scan_results << Ddr::Antivirus::Scanner.scan(path)
|
146
|
+
rescue ArgumentError => e # file is a blob
|
147
|
+
logger.error(e)
|
148
|
+
end
|
149
|
+
|
150
|
+
def notify_virus_scan_results
|
151
|
+
while result = virus_scan_results.shift
|
152
|
+
ActiveSupport::Notifications.instrument(Ddr::Notifications::VIRUS_CHECK, result: result, pid: pid)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def external_file_store
|
157
|
+
Ddr::Models.external_file_store
|
158
|
+
end
|
159
|
+
|
160
|
+
def set_external_file_permissions! file_path
|
161
|
+
File.chmod(EXTERNAL_FILE_PERMISSIONS, file_path)
|
162
|
+
end
|
163
|
+
|
164
|
+
def generate_external_file_name
|
165
|
+
SecureRandom.uuid
|
166
|
+
end
|
167
|
+
|
168
|
+
def generate_external_directory_subpath(file_name)
|
169
|
+
m = Ddr::Models.external_file_subpath_regexp.match(file_name)
|
170
|
+
raise "File name does not match external file subpath pattern: #{file_name}" unless m
|
171
|
+
subpath_segments = m.to_a[1..-1]
|
172
|
+
File.join *subpath_segments
|
173
|
+
end
|
174
|
+
|
175
|
+
def cleanup_external_files_on_destroy
|
176
|
+
paths = external_datastream_file_paths
|
177
|
+
yield
|
178
|
+
File.unlink *paths
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|