ddr-models 1.5.0 → 1.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fa0d6d02e9d75d08088ce93d1c11dc5b1456a069
4
- data.tar.gz: 2d42ecd5e033747bee3cfee78ba52e4afc9d3857
3
+ metadata.gz: 4b7c6859f35b96af9cad8b5b91ed7b10e977b661
4
+ data.tar.gz: 75abf6c0b0abf5744fa84b2340bb0bf22cc39879
5
5
  SHA512:
6
- metadata.gz: ec48a38252f3deafadce7a27fea0616464f7fe5308a0ec21a86a7990cef1b418a5f364f6958776a63d7e1f86e86b9e81317d51574293da7a42c18f3b17d01fb3
7
- data.tar.gz: 6345df75af88af8010e7ea961c75845c745fc375978926c3c7598d1d64099cf9513eb42237db616aa6f9c96e4c04e158c47585bc89c7b32cb58dca853e802a2d
6
+ metadata.gz: e53213dd9dd3d14e582ce2558b7e4efb0c66656de2f4a6232aa0c91bedbb12212eecad26982f32bfdd2b0218b15a5f6f002e92c92fdbb9887631a6cbb4871c48
7
+ data.tar.gz: eb9a5b39e08e90d70321ade9812d2f69440d4b4fa1f5cbd73e2450ca22f34f68edd6d23cbbdd50c46beb3681e026e8469f04c9a16abf9bee2a2f3ef75a93fbd5
data/README.md CHANGED
@@ -25,6 +25,7 @@ ddr-models has several runtime dependencies that are independently configurable:
25
25
  - [hydra-head](https://github.com/projecthydra/hydra-head)
26
26
  - [ddr-antivirus](https://github.com/duke-libraries/ddr-antivirus)
27
27
  - [devise-remote-user](https://github.com/duke-libraries/devise-remote-user)
28
+ - [ezid-client](https://github.com/duke-libaries/ezid-client)
28
29
 
29
30
  ddr-models configuration options:
30
31
 
@@ -0,0 +1,9 @@
1
+ class DropMintedIds < ActiveRecord::Migration
2
+ def up
3
+ drop_table :minted_ids
4
+ end
5
+
6
+ def down
7
+ raise ActiveRecord::IrreversibleMigration
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ class AddExceptionToEvents < ActiveRecord::Migration
2
+ def change
3
+ change_table :events do |t|
4
+ t.string :exception
5
+ end
6
+ end
7
+ end
@@ -24,6 +24,7 @@ module Ddr
24
24
 
25
25
  autoload :ContentMetadataDatastream
26
26
  autoload :DescriptiveMetadataDatastream
27
+ autoload :PreservationMetadataDatastream
27
28
  autoload :PropertiesDatastream
28
29
  autoload :DatastreamBehavior
29
30
  autoload :RoleAssignmentsDatastream
@@ -0,0 +1,13 @@
1
+ module Ddr
2
+ module Datastreams
3
+ class PreservationMetadataDatastream < ActiveFedora::NtriplesRDFDatastream
4
+
5
+ property :permanent_id,
6
+ predicate: Ddr::Vocab::Preservation.permanentId
7
+
8
+ property :permanent_url,
9
+ predicate: Ddr::Vocab::Preservation.permanentUrl
10
+
11
+ end
12
+ end
13
+ end
@@ -4,6 +4,11 @@ module Ddr
4
4
 
5
5
  belongs_to :user, inverse_of: :events
6
6
 
7
+ # ActiveSupport::Notifications::Instrumenter sets payload[:exception]
8
+ # to an array of [<exception class name>, <exception message>]
9
+ # and we want to store this data in a string field.
10
+ serialize :exception, JSON
11
+
7
12
  # Event date time - for PREMIS and Solr
8
13
  DATE_TIME_FORMAT = "%Y-%m-%dT%H:%M:%S.%LZ"
9
14
 
@@ -32,6 +37,7 @@ module Ddr
32
37
  validate :object_exists # unless/until we have a deaccession-type of event
33
38
 
34
39
  after_initialize :set_defaults
40
+ before_save { failure! if exception.present? }
35
41
 
36
42
  # Receive message sent by ActiveSupport::Notifications
37
43
  def self.call(*args)
@@ -32,6 +32,7 @@ module Ddr
32
32
  OBJECT_MODIFIED_DATE = solr_name :system_modified, :stored_sortable, type: :date
33
33
  ORIGINAL_FILENAME = solr_name :original_filename, :symbol
34
34
  PERMANENT_ID = solr_name :permanent_id, :stored_sortable, type: :string
35
+ PERMANENT_URL = solr_name :permanent_url, :stored_sortable, type: :string
35
36
  TITLE = solr_name :title, :stored_sortable
36
37
  WORKFLOW_STATE = solr_name :workflow_state, :stored_sortable
37
38
 
@@ -0,0 +1,8 @@
1
+ module Ddr
2
+ module Managers
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :PermanentIdManager
6
+
7
+ end
8
+ end
@@ -0,0 +1,93 @@
1
+ require "ezid-client"
2
+ require "resque"
3
+
4
+ module Ddr
5
+ module Managers
6
+ #
7
+ # PermanentIdManager is responsible for managing the permanent id for an object.
8
+ #
9
+ # @api private
10
+ class PermanentIdManager
11
+
12
+ PERMANENT_URL_BASE = "http://id.library.duke.edu/"
13
+ TARGET_URL_BASE = "http://repository.lib.duke.edu/"
14
+
15
+ ASSIGN_EVENT_SUMMARY = "Permanent ID assigned"
16
+
17
+ SOFTWARE = Ezid::Client.version
18
+
19
+ attr_reader :object
20
+
21
+ def initialize(object)
22
+ @object = object
23
+ end
24
+
25
+ def assign_later
26
+ Resque.enqueue(AssignmentJob, object.pid)
27
+ end
28
+
29
+ def assign
30
+ raise Ddr::Models::Error, "Permanent ID already assigned." if object.permanent_id
31
+ ActiveSupport::Notifications.instrument(Ddr::Notifications::UPDATE,
32
+ pid: object.pid,
33
+ software: SOFTWARE,
34
+ summary: ASSIGN_EVENT_SUMMARY
35
+ ) do |payload|
36
+
37
+ assign!
38
+ payload[:detail] = <<-EOS
39
+ Permanent ID: #{object.permanent_id}
40
+ Permanent URL: #{object.permanent_url}
41
+ EZID Metadata:
42
+ #{record.metadata}
43
+ EOS
44
+ end
45
+ end
46
+
47
+ # A job class for background execution
48
+ class AssignmentJob
49
+ @queue = :permanent_id
50
+
51
+ def self.perform(pid)
52
+ object = ActiveFedora::Base.find(pid)
53
+ object.permanent_id_manager.assign
54
+ end
55
+ end
56
+
57
+ def default_metadata
58
+ { profile: "dc",
59
+ export: "no"
60
+ }
61
+ end
62
+
63
+ def record
64
+ return @record if @record
65
+ if object.permanent_id
66
+ @record = Ezid::Identifier.find(object.permanent_id.to_s)
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def assign!
73
+ @record = mint
74
+ object.permanent_id = record.id
75
+ object.permanent_url = (PERMANENT_URL_BASE + object.permanent_id)
76
+ object.save
77
+ end
78
+
79
+ # @return [Ezid::Identifier]
80
+ def mint
81
+ ezid = Ezid::Identifier.create(default_metadata)
82
+ ezid.target = default_target_url(ezid.id)
83
+ ezid.save
84
+ ezid
85
+ end
86
+
87
+ def default_target_url(id)
88
+ TARGET_URL_BASE + id
89
+ end
90
+
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,13 @@
1
+ module Ddr
2
+ module Metadata
3
+ class PermanentIdRecord
4
+
5
+ def self.find(id)
6
+ Ezid::Identifier.find(id)
7
+ end
8
+
9
+
10
+
11
+ end
12
+ end
13
+ end
data/lib/ddr/models.rb CHANGED
@@ -15,9 +15,11 @@ require 'ddr/auth'
15
15
  require 'ddr/datastreams'
16
16
  require 'ddr/events'
17
17
  require 'ddr/index_fields'
18
+ require 'ddr/managers'
18
19
  require 'ddr/metadata'
19
20
  require 'ddr/notifications'
20
21
  require 'ddr/utils'
22
+ require 'ddr/vocab'
21
23
  require 'ddr/workflow'
22
24
 
23
25
  module Ddr
@@ -36,6 +38,7 @@ module Ddr
36
38
  autoload :HasChildren
37
39
  autoload :HasContent
38
40
  autoload :HasContentMetadata
41
+ autoload :HasPreservationMetadata
39
42
  autoload :HasProperties
40
43
  autoload :HasRoleAssignments
41
44
  autoload :HasThumbnail
@@ -43,16 +46,17 @@ module Ddr
43
46
  autoload :Indexing
44
47
  autoload :FileManagement
45
48
  autoload :Licensable
46
- autoload :MintedId
47
- autoload :PermanentIdentification
48
49
  autoload :SolrDocument
49
-
50
+
50
51
  # Base directory of external file store
51
- mattr_accessor :external_file_store
52
+ mattr_accessor :external_file_store
52
53
 
53
54
  # Regexp for building external file subpath from hex digest
54
55
  mattr_accessor :external_file_subpath_regexp
55
-
56
+
57
+ # Whether permanent IDs should be automatically assigned on create
58
+ mattr_accessor :auto_assign_permanent_ids
59
+
56
60
  # Yields an object with module configuration accessors
57
61
  def self.configure
58
62
  yield self
@@ -0,0 +1,26 @@
1
+ module Ddr
2
+ module Models
3
+ module HasEzidIdentifier
4
+
5
+ protected
6
+
7
+
8
+ def create_identifier
9
+ create_ezid
10
+ end
11
+
12
+ private
13
+
14
+ def create_ezid
15
+ metadata = Ddr::Metadata::Ezid.new(self)
16
+ ezid_identifier = Ezid::Identifier.create(metadata)
17
+ Ddr::Metadata::PermanentIdentifier.new(ezid_identifier.id)
18
+ end
19
+
20
+ def get_ezid
21
+ Ezid::Identifier.find(permanent_id.value)
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ module Ddr
2
+ module Models
3
+ module HasPermanentIdentifier
4
+
5
+
6
+
7
+ end
8
+ end
9
+ end
@@ -13,24 +13,24 @@ module Ddr
13
13
  include FixityCheckable
14
14
  include FileManagement
15
15
  include Indexing
16
- include PermanentIdentification
17
16
  include HasRoleAssignments
18
17
  include Hydra::Validations
19
18
  include HasWorkflow
20
-
19
+ include HasPreservationMetadata
20
+
21
21
  def copy_admin_policy_or_permissions_from(other)
22
22
  copy_permissions_from(other) unless copy_admin_policy_from(other)
23
23
  end
24
-
24
+
25
25
  def association_query(association)
26
26
  # XXX Ideally we would include a clause to limit by AF model, but this should suffice
27
27
  ActiveFedora::SolrService.construct_query_for_rel(reflections[association].options[:property] => internal_uri)
28
28
  end
29
-
29
+
30
30
  # e.g., "Collection duke:1"
31
31
  def model_pid
32
32
  [self.class.to_s, pid].join(" ")
33
- end
33
+ end
34
34
 
35
35
  end
36
36
  end
@@ -23,6 +23,10 @@ module Ddr
23
23
  ActiveFedora::Predicates.set_predicates(Ddr::Metadata::PREDICATES)
24
24
  end
25
25
 
26
+ initializer "ddr_models.permanent_ids" do
27
+ Ddr::Models.auto_assign_permanent_ids = Rails.env.production?
28
+ end
29
+
26
30
  # Configure devise-remote-user
27
31
  initializer "ddr_auth.remote_user" do
28
32
  require "devise_remote_user"
@@ -62,6 +66,13 @@ module Ddr
62
66
  Ddr::Auth.collection_creators_group = ENV["COLLECTION_CREATORS_GROUP"]
63
67
  end
64
68
 
69
+ initializer "ezid_client" do
70
+ unless Rails.env.production?
71
+ require "ezid/test_helper"
72
+ ezid_test_mode!
73
+ end
74
+ end
75
+
65
76
  end
66
77
  end
67
78
  end
@@ -0,0 +1,28 @@
1
+ module Ddr
2
+ module Models
3
+ module HasPreservationMetadata
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ has_metadata "preservationMetadata",
8
+ type: Ddr::Datastreams::PreservationMetadataDatastream,
9
+ versionable: true,
10
+ control_group: "M"
11
+
12
+ has_attributes :permanent_id, :permanent_url,
13
+ datastream: "preservationMetadata", multiple: false
14
+
15
+ after_create :assign_permanent_id!, if: "Ddr::Models.auto_assign_permanent_ids"
16
+ end
17
+
18
+ def permanent_id_manager
19
+ @permanent_id_manager ||= Ddr::Managers::PermanentIdManager.new(self)
20
+ end
21
+
22
+ def assign_permanent_id!
23
+ permanent_id_manager.assign_later
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -12,9 +12,14 @@ module Ddr
12
12
  Ddr::IndexFields::TITLE => title_display,
13
13
  Ddr::IndexFields::INTERNAL_URI => internal_uri,
14
14
  Ddr::IndexFields::IDENTIFIER => identifier_sort,
15
- Ddr::IndexFields::PERMANENT_ID => permanent_id,
16
15
  Ddr::IndexFields::WORKFLOW_STATE => workflow_state
17
16
  }
17
+ if permanent_id.present?
18
+ fields[Ddr::IndexFields::PERMANENT_ID] = permanent_id
19
+ end
20
+ if permanent_url.present?
21
+ fields[Ddr::IndexFields::PERMANENT_URL] = permanent_url
22
+ end
18
23
  if respond_to? :fixity_checks
19
24
  last_fixity_check = fixity_checks.last
20
25
  fields.merge!(last_fixity_check.to_solr) if last_fixity_check
@@ -50,4 +55,4 @@ module Ddr
50
55
 
51
56
  end
52
57
  end
53
- end
58
+ end
@@ -1,5 +1,5 @@
1
1
  module Ddr
2
2
  module Models
3
- VERSION = "1.5.0"
3
+ VERSION = "1.6.0"
4
4
  end
5
5
  end
data/lib/ddr/vocab.rb ADDED
@@ -0,0 +1,8 @@
1
+ module Ddr
2
+ module Vocab
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :Preservation
6
+
7
+ end
8
+ end
data/lib/ddr/vocab.rb~ ADDED
@@ -0,0 +1,9 @@
1
+ module Ddr
2
+ module Vocab
3
+ extend ActiveSupport::Autoload
4
+
5
+ autoload :PREMIS
6
+ autoload :Preservation
7
+
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module Ddr
2
+ module Vocab
3
+ class Preservation < RDF::StrictVocabulary("http://repository.lib.duke.edu/vocab/preservation/")
4
+
5
+ property "permanentId",
6
+ label: "Permanent Identifier",
7
+ subPropertyOf: RDF::DC.identifier
8
+
9
+ property "permanentUrl",
10
+ label: "Permanent URL"
11
+
12
+ end
13
+ end
14
+ end