ddr-models 2.0.1 → 2.1.0.rc1
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 +4 -4
- data/README.md +23 -17
- data/app/models/collection.rb +1 -35
- data/ddr-models.gemspec +2 -1
- data/lib/ddr/actions.rb +1 -0
- data/lib/ddr/actions/virus_check.rb +28 -0
- data/lib/ddr/auth.rb +4 -0
- data/lib/ddr/auth/ability_definitions/datastream_ability_definitions.rb +7 -5
- data/lib/ddr/auth/grouper_gateway.rb +9 -1
- data/lib/ddr/auth/permissions.rb +2 -1
- data/lib/ddr/auth/role_based_access_controls_enforcement.rb +5 -5
- data/lib/ddr/auth/roles/role_types.rb +2 -1
- data/lib/ddr/datastreams.rb +2 -2
- data/lib/ddr/datastreams/administrative_metadata_datastream.rb +27 -14
- data/lib/ddr/datastreams/datastream_behavior.rb +13 -0
- data/lib/ddr/datastreams/fits_datastream.rb +88 -0
- data/lib/ddr/derivatives/png_generator.rb +2 -0
- data/lib/ddr/derivatives/ptif_generator.rb +2 -0
- data/lib/ddr/events/fixity_check_event.rb +2 -2
- data/lib/ddr/events/virus_check_event.rb +2 -14
- data/lib/ddr/index.rb +29 -0
- data/lib/ddr/index/abstract_query_result.rb +23 -0
- data/lib/ddr/index/connection.rb +17 -0
- data/lib/ddr/index/csv_query_result.rb +61 -0
- data/lib/ddr/index/document_builder.rb +9 -0
- data/lib/ddr/index/field.rb +23 -0
- data/lib/ddr/index/fields.rb +83 -0
- data/lib/ddr/index/filter.rb +48 -0
- data/lib/ddr/index/filters.rb +19 -0
- data/lib/ddr/index/legacy_license_fields.rb +14 -0
- data/lib/ddr/index/query.rb +35 -0
- data/lib/ddr/index/query_builder.rb +74 -0
- data/lib/ddr/index/query_clause.rb +52 -0
- data/lib/ddr/index/query_result.rb +70 -0
- data/lib/ddr/index/query_value.rb +16 -0
- data/lib/ddr/index/response.rb +13 -0
- data/lib/ddr/index/unique_key_field.rb +12 -0
- data/lib/ddr/index_fields.rb +7 -53
- data/lib/ddr/jobs.rb +1 -1
- data/lib/ddr/jobs/fits_file_characterization.rb +51 -0
- data/lib/ddr/managers.rb +1 -0
- data/lib/ddr/managers/technical_metadata_manager.rb +104 -0
- data/lib/ddr/models.rb +39 -23
- data/lib/ddr/models/base.rb +0 -2
- data/lib/ddr/models/describable.rb +1 -1
- data/lib/ddr/models/effective_license.rb +9 -0
- data/lib/ddr/models/engine.rb +13 -0
- data/lib/ddr/models/file_management.rb +157 -160
- data/lib/ddr/models/governable.rb +0 -4
- data/lib/ddr/models/has_admin_metadata.rb +80 -72
- data/lib/ddr/models/has_children.rb +1 -1
- data/lib/ddr/models/has_content.rb +18 -0
- data/lib/ddr/models/has_struct_metadata.rb +5 -1
- data/lib/ddr/models/indexing.rb +32 -20
- data/lib/ddr/models/inherited_license.rb +13 -0
- data/lib/ddr/models/license.rb +38 -0
- data/lib/ddr/models/solr_document.rb +195 -211
- data/lib/ddr/models/version.rb +1 -1
- data/lib/ddr/models/year_facet.rb +154 -0
- data/lib/ddr/utils.rb +13 -1
- data/lib/ddr/vocab/roles.rb +0 -10
- data/spec/controllers/including_role_based_access_controls_enforcement_spec.rb +4 -4
- data/spec/datastreams/fits_datastream_spec.rb +84 -0
- data/spec/fixtures/fits/document.xml +65 -0
- data/spec/fixtures/fits/image.xml +59 -0
- data/spec/index/filter_spec.rb +47 -0
- data/spec/index/filters_spec.rb +17 -0
- data/spec/index/query_spec.rb +19 -0
- data/spec/jobs/fits_file_characterization_spec.rb +52 -0
- data/spec/managers/technical_metadata_manager_spec.rb +140 -0
- data/spec/models/active_fedora_datastream_spec.rb +44 -0
- data/spec/models/collection_spec.rb +7 -12
- data/spec/models/component_spec.rb +3 -6
- data/spec/models/effective_license_spec.rb +49 -0
- data/spec/models/has_admin_metadata_spec.rb +143 -194
- data/spec/models/has_struct_metadata_spec.rb +2 -2
- data/spec/models/indexing_spec.rb +40 -0
- data/spec/models/solr_document_spec.rb +96 -37
- data/spec/models/year_facet_spec.rb +65 -0
- data/spec/spec_helper.rb +1 -7
- data/spec/support/shared_examples_for_ddr_models.rb +0 -2
- data/spec/support/shared_examples_for_has_content.rb +37 -3
- metadata +79 -32
- data/lib/ddr/datastreams/properties_datastream.rb +0 -25
- data/lib/ddr/jobs/migrate_legacy_authorization.rb +0 -23
- data/lib/ddr/models/has_properties.rb +0 -15
- data/lib/ddr/models/licensable.rb +0 -28
- data/spec/auth/legacy_authorization_spec.rb +0 -94
- data/spec/auth/legacy_roles_spec.rb +0 -32
- data/spec/jobs/migrate_legacy_authorization_spec.rb +0 -43
- data/spec/support/shared_examples_for_has_properties.rb +0 -5
- data/spec/support/shared_examples_for_licensable.rb +0 -15
data/lib/ddr/models/base.rb
CHANGED
data/lib/ddr/models/engine.rb
CHANGED
@@ -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
|
-
|
1
|
+
module Ddr::Models
|
2
|
+
module FileManagement
|
3
|
+
extend ActiveSupport::Concern
|
2
4
|
|
3
|
-
|
4
|
-
module Models
|
5
|
-
module FileManagement
|
6
|
-
extend ActiveSupport::Concern
|
5
|
+
EXTERNAL_FILE_PERMISSIONS = 0644
|
7
6
|
|
8
|
-
|
7
|
+
included do
|
8
|
+
attr_accessor :file_to_add
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
define_model_callbacks :add_file
|
11
|
+
before_add_file :virus_scan
|
12
12
|
|
13
|
-
|
14
|
-
before_add_file :virus_scan
|
13
|
+
after_save :notify_virus_scan_results
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
-
#
|
64
|
-
|
65
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
76
|
-
|
77
|
-
end
|
65
|
+
# Retrieve or create the datastream
|
66
|
+
ds = datastreams.include?(dsid) ? datastreams[dsid] : add_external_datastream(dsid)
|
78
67
|
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
-
|
85
|
-
|
86
|
-
|
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
|
-
|
96
|
-
|
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
|
-
|
99
|
-
|
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
|
-
#
|
103
|
-
|
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
|
-
|
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
|
-
|
120
|
-
|
121
|
-
|
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
|
-
|
124
|
-
|
125
|
-
|
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
|
-
|
128
|
-
|
129
|
-
|
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
|
-
|
120
|
+
def external_datastream_file_paths
|
121
|
+
external_datastreams.map(&:file_paths).flatten
|
122
|
+
end
|
136
123
|
|
137
|
-
|
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
|
-
|
140
|
-
@virus_scan_results ||= []
|
141
|
-
end
|
132
|
+
protected
|
142
133
|
|
143
|
-
|
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
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
154
|
-
end
|
136
|
+
def virus_scan_results
|
137
|
+
@virus_scan_results ||= []
|
138
|
+
end
|
155
139
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
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
|
-
|
166
|
-
|
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
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
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
|
-
|
183
|
-
|
184
|
-
|
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
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
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
|
@@ -1,78 +1,86 @@
|
|
1
1
|
require "resque"
|
2
2
|
|
3
|
-
module Ddr
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|