ddr-models 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|