ddr-models 2.0.1 → 2.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +23 -17
  3. data/app/models/collection.rb +1 -35
  4. data/ddr-models.gemspec +2 -1
  5. data/lib/ddr/actions.rb +1 -0
  6. data/lib/ddr/actions/virus_check.rb +28 -0
  7. data/lib/ddr/auth.rb +4 -0
  8. data/lib/ddr/auth/ability_definitions/datastream_ability_definitions.rb +7 -5
  9. data/lib/ddr/auth/grouper_gateway.rb +9 -1
  10. data/lib/ddr/auth/permissions.rb +2 -1
  11. data/lib/ddr/auth/role_based_access_controls_enforcement.rb +5 -5
  12. data/lib/ddr/auth/roles/role_types.rb +2 -1
  13. data/lib/ddr/datastreams.rb +2 -2
  14. data/lib/ddr/datastreams/administrative_metadata_datastream.rb +27 -14
  15. data/lib/ddr/datastreams/datastream_behavior.rb +13 -0
  16. data/lib/ddr/datastreams/fits_datastream.rb +88 -0
  17. data/lib/ddr/derivatives/png_generator.rb +2 -0
  18. data/lib/ddr/derivatives/ptif_generator.rb +2 -0
  19. data/lib/ddr/events/fixity_check_event.rb +2 -2
  20. data/lib/ddr/events/virus_check_event.rb +2 -14
  21. data/lib/ddr/index.rb +29 -0
  22. data/lib/ddr/index/abstract_query_result.rb +23 -0
  23. data/lib/ddr/index/connection.rb +17 -0
  24. data/lib/ddr/index/csv_query_result.rb +61 -0
  25. data/lib/ddr/index/document_builder.rb +9 -0
  26. data/lib/ddr/index/field.rb +23 -0
  27. data/lib/ddr/index/fields.rb +83 -0
  28. data/lib/ddr/index/filter.rb +48 -0
  29. data/lib/ddr/index/filters.rb +19 -0
  30. data/lib/ddr/index/legacy_license_fields.rb +14 -0
  31. data/lib/ddr/index/query.rb +35 -0
  32. data/lib/ddr/index/query_builder.rb +74 -0
  33. data/lib/ddr/index/query_clause.rb +52 -0
  34. data/lib/ddr/index/query_result.rb +70 -0
  35. data/lib/ddr/index/query_value.rb +16 -0
  36. data/lib/ddr/index/response.rb +13 -0
  37. data/lib/ddr/index/unique_key_field.rb +12 -0
  38. data/lib/ddr/index_fields.rb +7 -53
  39. data/lib/ddr/jobs.rb +1 -1
  40. data/lib/ddr/jobs/fits_file_characterization.rb +51 -0
  41. data/lib/ddr/managers.rb +1 -0
  42. data/lib/ddr/managers/technical_metadata_manager.rb +104 -0
  43. data/lib/ddr/models.rb +39 -23
  44. data/lib/ddr/models/base.rb +0 -2
  45. data/lib/ddr/models/describable.rb +1 -1
  46. data/lib/ddr/models/effective_license.rb +9 -0
  47. data/lib/ddr/models/engine.rb +13 -0
  48. data/lib/ddr/models/file_management.rb +157 -160
  49. data/lib/ddr/models/governable.rb +0 -4
  50. data/lib/ddr/models/has_admin_metadata.rb +80 -72
  51. data/lib/ddr/models/has_children.rb +1 -1
  52. data/lib/ddr/models/has_content.rb +18 -0
  53. data/lib/ddr/models/has_struct_metadata.rb +5 -1
  54. data/lib/ddr/models/indexing.rb +32 -20
  55. data/lib/ddr/models/inherited_license.rb +13 -0
  56. data/lib/ddr/models/license.rb +38 -0
  57. data/lib/ddr/models/solr_document.rb +195 -211
  58. data/lib/ddr/models/version.rb +1 -1
  59. data/lib/ddr/models/year_facet.rb +154 -0
  60. data/lib/ddr/utils.rb +13 -1
  61. data/lib/ddr/vocab/roles.rb +0 -10
  62. data/spec/controllers/including_role_based_access_controls_enforcement_spec.rb +4 -4
  63. data/spec/datastreams/fits_datastream_spec.rb +84 -0
  64. data/spec/fixtures/fits/document.xml +65 -0
  65. data/spec/fixtures/fits/image.xml +59 -0
  66. data/spec/index/filter_spec.rb +47 -0
  67. data/spec/index/filters_spec.rb +17 -0
  68. data/spec/index/query_spec.rb +19 -0
  69. data/spec/jobs/fits_file_characterization_spec.rb +52 -0
  70. data/spec/managers/technical_metadata_manager_spec.rb +140 -0
  71. data/spec/models/active_fedora_datastream_spec.rb +44 -0
  72. data/spec/models/collection_spec.rb +7 -12
  73. data/spec/models/component_spec.rb +3 -6
  74. data/spec/models/effective_license_spec.rb +49 -0
  75. data/spec/models/has_admin_metadata_spec.rb +143 -194
  76. data/spec/models/has_struct_metadata_spec.rb +2 -2
  77. data/spec/models/indexing_spec.rb +40 -0
  78. data/spec/models/solr_document_spec.rb +96 -37
  79. data/spec/models/year_facet_spec.rb +65 -0
  80. data/spec/spec_helper.rb +1 -7
  81. data/spec/support/shared_examples_for_ddr_models.rb +0 -2
  82. data/spec/support/shared_examples_for_has_content.rb +37 -3
  83. metadata +79 -32
  84. data/lib/ddr/datastreams/properties_datastream.rb +0 -25
  85. data/lib/ddr/jobs/migrate_legacy_authorization.rb +0 -23
  86. data/lib/ddr/models/has_properties.rb +0 -15
  87. data/lib/ddr/models/licensable.rb +0 -28
  88. data/spec/auth/legacy_authorization_spec.rb +0 -94
  89. data/spec/auth/legacy_roles_spec.rb +0 -32
  90. data/spec/jobs/migrate_legacy_authorization_spec.rb +0 -43
  91. data/spec/support/shared_examples_for_has_properties.rb +0 -5
  92. data/spec/support/shared_examples_for_licensable.rb +0 -15
@@ -5,8 +5,6 @@ module Ddr
5
5
  include Describable
6
6
  include Governable
7
7
  include AccessControllable
8
- include Licensable
9
- include HasProperties
10
8
  include HasThumbnail
11
9
  include EventLoggable
12
10
  include FixityCheckable
@@ -72,7 +72,7 @@ module Ddr
72
72
 
73
73
  module ClassMethods
74
74
  def find_by_identifier(identifier)
75
- find(Ddr::IndexFields::IDENTIFIER_ALL => identifier)
75
+ find(Ddr::Index::Fields::IDENTIFIER_ALL => identifier)
76
76
  end
77
77
  end
78
78
 
@@ -0,0 +1,9 @@
1
+ module Ddr::Models
2
+ class EffectiveLicense
3
+
4
+ def self.call(obj)
5
+ License.call(obj) || InheritedLicense.call(obj)
6
+ end
7
+
8
+ end
9
+ end
@@ -79,6 +79,19 @@ module Ddr
79
79
  end
80
80
  end
81
81
 
82
+ initializer "fits_home" do
83
+ Ddr::Models.fits_home = ENV["FITS_HOME"]
84
+ end
85
+
86
+ initializer "ddr_antivirus" do
87
+ require "ddr-antivirus"
88
+ if Rails.env.test?
89
+ Ddr::Antivirus.test_mode!
90
+ else
91
+ Ddr::Antivirus.scanner_adapter = :clamd
92
+ end
93
+ end
94
+
82
95
  end
83
96
  end
84
97
  end
@@ -1,198 +1,195 @@
1
- require "ddr-antivirus"
1
+ module Ddr::Models
2
+ module FileManagement
3
+ extend ActiveSupport::Concern
2
4
 
3
- module Ddr
4
- module Models
5
- module FileManagement
6
- extend ActiveSupport::Concern
5
+ EXTERNAL_FILE_PERMISSIONS = 0644
7
6
 
8
- EXTERNAL_FILE_PERMISSIONS = 0644
7
+ included do
8
+ attr_accessor :file_to_add
9
9
 
10
- included do
11
- attr_accessor :file_to_add
10
+ define_model_callbacks :add_file
11
+ before_add_file :virus_scan
12
12
 
13
- define_model_callbacks :add_file
14
- before_add_file :virus_scan
13
+ after_save :notify_virus_scan_results
15
14
 
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
15
+ # Deleting the datastream external files on destroying the object can't
16
+ # be handled with a datastream around_destroy callback.
17
+ # See https://groups.google.com/d/msg/hydra-tech/xJaZr2wVhbg/4iafvso98w8J
18
+ around_destroy :cleanup_external_files_on_destroy
19
+ end
23
20
 
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
21
+ # add_file(file, dsid, opts={})
22
+ #
23
+ # Comparable to Hydra::ModelMethods#add_file(file, dsid, file_name)
24
+ #
25
+ # Options:
26
+ #
27
+ # :mime_type - Explicit mime type to set (otherwise discerned from file path or name)
28
+ #
29
+ # :original_name - A String value will be understood as the original name of the file.
30
+ # `false` or `nil` indicate that the file basename is not the original
31
+ # name. Default processing will take the file basename as the original
32
+ # name.
33
+ #
34
+ # :external - Add to file to external datastream. Not required for datastream specs
35
+ # where :control_group=>"E".
36
+ #
37
+ # :use_original - For external datastream file, do not copy file to new file path,
38
+ # but use in place (set dsLocation to file URI for current path.
39
+ def add_file file, dsid, opts={}
40
+ opts[:mime_type] ||= Ddr::Utils.mime_type_for(file)
41
+
42
+ # @file_to_add is set for callbacks to access the data
43
+ original_name = opts.fetch(:original_name, Ddr::Utils.file_name_for(file))
44
+ self.file_to_add = FileToAdd.new(file, dsid, original_name)
45
+
46
+ run_callbacks(:add_file) do
47
+ if opts.delete(:external) || datastreams.include?(dsid) && datastreams[dsid].external?
48
+ add_external_file(file, dsid, opts)
49
+ else
50
+ file = File.new(file, "rb") if Ddr::Utils.file_path?(file)
51
+ # ActiveFedora method accepts file-like objects, not paths
52
+ add_file_datastream(file, dsid: dsid, mimeType: opts[:mime_type])
57
53
  end
58
-
59
- # clear the instance data
60
- self.file_to_add = nil
61
54
  end
62
55
 
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)
56
+ # clear the instance data
57
+ self.file_to_add = nil
58
+ end
70
59
 
71
- unless ds.external?
72
- raise ArgumentError, "Cannot add external file to datastream with controlGroup \"#{ds.controlGroup}\""
73
- end
60
+ # Normally this method should not be called directly. Call `add_file` with dsid for
61
+ # external datastream id, or with `:external=>true` option if no spec for dsid.
62
+ def add_external_file file, dsid, opts={}
63
+ file_path = Ddr::Utils.file_path(file) # raises ArgumentError
74
64
 
75
- if ds.dsLocation_changed?
76
- raise Ddr::Models::Error, "Cannot add external file to datastream when dsLocation change is pending."
77
- end
65
+ # Retrieve or create the datastream
66
+ ds = datastreams.include?(dsid) ? datastreams[dsid] : add_external_datastream(dsid)
78
67
 
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)
68
+ unless ds.external?
69
+ raise ArgumentError, "Cannot add external file to datastream with controlGroup \"#{ds.controlGroup}\""
70
+ end
83
71
 
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!(ds)
91
- # copy the original file to the storage location
92
- FileUtils.cp file_path, store_path
93
- end
72
+ if ds.dsLocation_changed?
73
+ raise Ddr::Models::Error, "Cannot add external file to datastream when dsLocation change is pending."
74
+ end
94
75
 
95
- # set appropriate permissions on the file
96
- set_external_file_permissions!(store_path)
76
+ # Set the MIME type
77
+ # The :mime_type option will be present when called from `add_file`.
78
+ # The fallback is there in case `add_external_file` is called directly.
79
+ ds.mimeType = opts[:mime_type] || Ddr::Utils.mime_type_for(file, file_path)
97
80
 
98
- # set dsLocation to file URI for storage path
99
- ds.dsLocation = Ddr::Utils.path_to_uri(store_path)
81
+ # Copy the file to storage unless we're using the original
82
+ if opts[:use_original]
83
+ raise Ddr::Models::Error, "Cannot add file to repository that is owned by another user." unless File.owned?(file_path)
84
+ store_path = file_path
85
+ else
86
+ # generate new storage path for file
87
+ store_path = create_external_file_path!(ds)
88
+ # copy the original file to the storage location
89
+ FileUtils.cp file_path, store_path
100
90
  end
101
91
 
102
- # Create directory (if necessary) for newly generated file path and return path
103
- def create_external_file_path! ds
104
- file_path = generate_external_file_path(ds)
105
- FileUtils.mkdir_p(File.dirname(file_path))
106
- file_path
107
- end
92
+ # set appropriate permissions on the file
93
+ set_external_file_permissions!(store_path)
108
94
 
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 ds
115
- file_name = generate_external_file_name(ds)
116
- File.join(external_file_store(ds.dsid), generate_external_directory_subpath, file_name)
117
- end
95
+ # set dsLocation to file URI for storage path
96
+ ds.dsLocation = Ddr::Utils.path_to_uri(store_path)
97
+ end
118
98
 
119
- def external_datastreams
120
- datastreams.values.select { |ds| ds.external? }
121
- end
99
+ # Create directory (if necessary) for newly generated file path and return path
100
+ def create_external_file_path! ds
101
+ file_path = generate_external_file_path(ds)
102
+ FileUtils.mkdir_p(File.dirname(file_path))
103
+ file_path
104
+ end
122
105
 
123
- def external_datastream_file_paths
124
- external_datastreams.map(&:file_paths).flatten
125
- end
106
+ #
107
+ # Generates a new external file storage location
108
+ #
109
+ # => {external_file_store}/1/e/69/1e691815-0631-4f9b-8e23-2dfb2eec9c70
110
+ #
111
+ def generate_external_file_path ds
112
+ file_name = generate_external_file_name(ds)
113
+ File.join(external_file_store(ds.dsid), generate_external_directory_subpath, file_name)
114
+ end
126
115
 
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
116
+ def external_datastreams
117
+ datastreams.values.select { |ds| ds.external? }
118
+ end
134
119
 
135
- protected
120
+ def external_datastream_file_paths
121
+ external_datastreams.map(&:file_paths).flatten
122
+ end
136
123
 
137
- FileToAdd = Struct.new(:file, :dsid, :original_name)
124
+ def add_external_datastream dsid, opts={}
125
+ klass = self.class.datastream_class_for_name(dsid)
126
+ datastream = create_datastream(klass, dsid, controlGroup: "E")
127
+ add_datastream(datastream)
128
+ self.class.build_datastream_accessor(dsid)
129
+ datastream
130
+ end
138
131
 
139
- def virus_scan_results
140
- @virus_scan_results ||= []
141
- end
132
+ protected
142
133
 
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
134
+ FileToAdd = Struct.new(:file, :dsid, :original_name)
149
135
 
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
136
+ def virus_scan_results
137
+ @virus_scan_results ||= []
138
+ end
155
139
 
156
- def external_file_store dsid
157
- case dsid
158
- when Ddr::Datastreams::MULTIRES_IMAGE
159
- Ddr::Models.multires_image_external_file_store
160
- else
161
- Ddr::Models.external_file_store
162
- end
163
- end
140
+ def virus_scan
141
+ path = Ddr::Utils.file_path(file_to_add[:file])
142
+ virus_scan_results << Ddr::Actions::VirusCheck.call(path)
143
+ rescue ArgumentError => e # file is a blob
144
+ logger.error(e)
145
+ end
164
146
 
165
- def set_external_file_permissions! file_path
166
- File.chmod(EXTERNAL_FILE_PERMISSIONS, file_path)
147
+ def notify_virus_scan_results
148
+ while result = virus_scan_results.shift
149
+ result.merge! pid: pid
150
+ ActiveSupport::Notifications.instrument(Ddr::Notifications::VIRUS_CHECK, result)
167
151
  end
152
+ end
168
153
 
169
- def generate_external_file_name ds
170
- content_file_name = Ddr::Utils::sanitize_filename(original_filename) || datastreams[ds.dsid].default_file_name
171
- case ds.dsid
172
- when Ddr::Datastreams::MULTIRES_IMAGE
173
- case ds.mimeType
174
- when "image/tiff"
175
- "#{File.basename(content_file_name, File.extname(content_file_name))}.ptif"
176
- end
177
- else
178
- content_file_name
179
- end
154
+ def external_file_store dsid
155
+ case dsid
156
+ when Ddr::Datastreams::MULTIRES_IMAGE
157
+ Ddr::Models.multires_image_external_file_store
158
+ else
159
+ Ddr::Models.external_file_store
180
160
  end
161
+ end
181
162
 
182
- def generate_external_directory_subpath
183
- subdir = SecureRandom.uuid
184
- m = Ddr::Models.external_file_subpath_regexp.match(subdir)
185
- raise "File name does not match external file subpath pattern: #{file_name}" unless m
186
- subpath_segments = m.to_a[1..-1]
187
- File.join *subpath_segments, subdir
188
- end
163
+ def set_external_file_permissions! file_path
164
+ File.chmod(EXTERNAL_FILE_PERMISSIONS, file_path)
165
+ end
189
166
 
190
- def cleanup_external_files_on_destroy
191
- paths = external_datastream_file_paths
192
- yield
193
- File.unlink *paths
167
+ def generate_external_file_name ds
168
+ content_file_name = Ddr::Utils::sanitize_filename(original_filename) || datastreams[ds.dsid].default_file_name
169
+ case ds.dsid
170
+ when Ddr::Datastreams::MULTIRES_IMAGE
171
+ case ds.mimeType
172
+ when "image/tiff"
173
+ "#{File.basename(content_file_name, File.extname(content_file_name))}.ptif"
174
+ end
175
+ else
176
+ content_file_name
194
177
  end
178
+ end
195
179
 
180
+ def generate_external_directory_subpath
181
+ subdir = SecureRandom.uuid
182
+ m = Ddr::Models.external_file_subpath_regexp.match(subdir)
183
+ raise "File name does not match external file subpath pattern: #{file_name}" unless m
184
+ subpath_segments = m.to_a[1..-1]
185
+ File.join *subpath_segments, subdir
196
186
  end
187
+
188
+ def cleanup_external_files_on_destroy
189
+ paths = external_datastream_file_paths
190
+ yield
191
+ File.unlink *paths
192
+ end
193
+
197
194
  end
198
195
  end
@@ -27,10 +27,6 @@ module Ddr
27
27
  end
28
28
  end
29
29
 
30
- def inherited_license
31
- admin_policy.default_license if admin_policy
32
- end
33
-
34
30
  def copy_admin_policy_from(other)
35
31
  # XXX In active-fedora 7.0 can do
36
32
  # self.admin_policy = other.admin_policy
@@ -1,78 +1,86 @@
1
1
  require "resque"
2
2
 
3
- module Ddr
4
- module Models
5
- module HasAdminMetadata
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
- has_metadata "adminMetadata",
10
- type: Ddr::Datastreams::AdministrativeMetadataDatastream,
11
- versionable: true,
12
- control_group: "M"
13
-
14
- has_attributes :admin_set,
15
- :display_format,
16
- :local_id,
17
- :permanent_id,
18
- :permanent_url,
19
- :research_help_contact,
20
- :workflow_state,
21
- datastream: "adminMetadata",
22
- multiple: false
23
-
24
- delegate :publish, :publish!, :unpublish, :unpublish!, :published?, to: :workflow
25
-
26
- after_create :assign_permanent_id!, if: "Ddr::Models.auto_assign_permanent_ids"
27
- around_destroy :update_permanent_id_on_destroy, if: "permanent_id.present?"
28
- end
29
-
30
- def permanent_id_manager
31
- @permanent_id_manager ||= Ddr::Managers::PermanentIdManager.new(self)
32
- end
33
-
34
- def roles
35
- Ddr::Auth::Roles::PropertyRoleSet.new(adminMetadata.access_role)
36
- end
37
-
38
- def inherited_roles
39
- Ddr::Auth::InheritedRoles.call(self)
40
- end
41
-
42
- def workflow
43
- @workflow ||= Ddr::Managers::WorkflowManager.new(self)
44
- end
45
-
46
- def assign_permanent_id!
47
- permanent_id_manager.assign_later
48
- end
49
-
50
- def grant_roles_to_creator(creator)
51
- roles.grant type: Ddr::Auth::Roles::EDITOR,
52
- agent: creator,
53
- scope: Ddr::Auth::Roles::RESOURCE_SCOPE
54
- end
55
-
56
- def copy_resource_roles_from(other)
57
- roles.grant *(other.roles.in_resource_scope)
58
- end
59
-
60
- def effective_permissions(agents)
61
- Ddr::Auth::EffectivePermissions.call(self, agents)
62
- end
63
-
64
- def research_help
65
- Ddr::Contacts.get(research_help_contact) if research_help_contact
66
- end
67
-
68
- private
69
-
70
- def update_permanent_id_on_destroy
71
- @permanent_id = permanent_id
72
- yield
73
- Resque.enqueue(Ddr::Jobs::PermanentId::MakeUnavailable, @permanent_id, "deleted")
74
- end
3
+ module Ddr::Models
4
+ module HasAdminMetadata
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ has_metadata "adminMetadata",
9
+ type: Ddr::Datastreams::AdministrativeMetadataDatastream,
10
+ versionable: true,
11
+ control_group: "M"
12
+
13
+ has_attributes :admin_set,
14
+ :depositor,
15
+ :display_format,
16
+ :license,
17
+ :local_id,
18
+ :permanent_id,
19
+ :permanent_url,
20
+ :research_help_contact,
21
+ :workflow_state,
22
+ datastream: "adminMetadata",
23
+ multiple: false
24
+
25
+ delegate :publish, :publish!, :unpublish, :unpublish!, :published?, to: :workflow
26
+
27
+ after_create :assign_permanent_id!, if: "Ddr::Models.auto_assign_permanent_ids"
28
+ around_destroy :update_permanent_id_on_destroy, if: "permanent_id.present?"
29
+ end
30
+
31
+ def permanent_id_manager
32
+ @permanent_id_manager ||= Ddr::Managers::PermanentIdManager.new(self)
33
+ end
34
+
35
+ def roles
36
+ Ddr::Auth::Roles::PropertyRoleSet.new(adminMetadata.access_role)
37
+ end
38
+
39
+ def inherited_roles
40
+ Ddr::Auth::InheritedRoles.call(self)
41
+ end
42
+
43
+ def workflow
44
+ @workflow ||= Ddr::Managers::WorkflowManager.new(self)
45
+ end
46
+
47
+ def assign_permanent_id!
48
+ permanent_id_manager.assign_later
49
+ end
50
+
51
+ def grant_roles_to_creator(creator)
52
+ roles.grant type: Ddr::Auth::Roles::EDITOR,
53
+ agent: creator,
54
+ scope: Ddr::Auth::Roles::RESOURCE_SCOPE
55
+ end
75
56
 
57
+ def copy_resource_roles_from(other)
58
+ roles.grant *(other.roles.in_resource_scope)
76
59
  end
60
+
61
+ def effective_permissions(agents)
62
+ Ddr::Auth::EffectivePermissions.call(self, agents)
63
+ end
64
+
65
+ def research_help
66
+ Ddr::Contacts.get(research_help_contact) if research_help_contact
67
+ end
68
+
69
+ def effective_license
70
+ EffectiveLicense.call(self)
71
+ end
72
+
73
+ def inherited_license
74
+ InheritedLicense.call(self)
75
+ end
76
+
77
+ private
78
+
79
+ def update_permanent_id_on_destroy
80
+ @permanent_id = permanent_id
81
+ yield
82
+ Resque.enqueue(Ddr::Jobs::PermanentId::MakeUnavailable, @permanent_id, "deleted")
83
+ end
84
+
77
85
  end
78
86
  end