ddr-models 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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