ddr-core 0.3.0 → 1.0.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 +4 -4
- data/app/models/concerns/ddr/has_admin_metadata.rb +8 -66
- data/app/models/concerns/ddr/has_children.rb +8 -0
- data/app/models/concerns/ddr/has_content.rb +1 -0
- data/app/models/concerns/ddr/solr_document_behavior.rb +11 -90
- data/app/models/ddr/admin_set.rb +3 -7
- data/app/models/ddr/alert.rb +16 -0
- data/app/models/ddr/auxiliary_resource.rb +24 -0
- data/app/models/ddr/contact.rb +1 -5
- data/app/models/ddr/finding_aid.rb +62 -0
- data/app/models/ddr/item.rb +0 -14
- data/app/models/ddr/language.rb +1 -6
- data/app/models/ddr/resource.rb +8 -0
- data/app/models/ddr/rights_statement.rb +2 -6
- data/config/locales/ddr-core.en.yml +2 -1
- data/lib/ddr/auth/ability_definitions/role_based_ability_definitions.rb +2 -2
- data/lib/ddr/auth/effective_permissions.rb +2 -1
- data/lib/ddr/auth/effective_roles.rb +6 -2
- data/lib/ddr/auth/failure_app.rb +1 -1
- data/lib/ddr/auth/grouper_gateway.rb +2 -2
- data/lib/ddr/auth/role_based_access_controls_enforcement.rb +0 -36
- data/lib/ddr/auth/roles/role.rb +0 -45
- data/lib/ddr/core.rb +5 -0
- data/lib/ddr/core/version.rb +1 -1
- data/lib/ddr/fits.rb +0 -91
- data/lib/ddr/index.rb +2 -2
- data/lib/ddr/index/fields.rb +1 -0
- data/lib/ddr/managers/technical_metadata_manager.rb +9 -4
- data/lib/ddr/structure.rb +2 -1
- metadata +22 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60adcaf5e15fb5ddb0ec7163481f5eb858ced50f7937a64574582c68fe37fa3c
|
4
|
+
data.tar.gz: c5cc93ef14e694f2a30f7e63879cef2a2ac7d19b496526ea13c07f1351652e64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7db02ca1d702c76c77327b877be521f6d894abcf209a0fa1d7cb65dc330b3bf192e046e3928a8acf4ba16b98fb474a45ce9db058ee98d4696b818fd25cb068d
|
7
|
+
data.tar.gz: ddb6721a92c1a73a69d7ef43a36445fb8fc94dfddfa0ede552bb2460f197e1ae053c7a861150b506ca3f5a4558a9154aece1c446065756c0d44d8a21ec39e5dd
|
@@ -54,47 +54,6 @@ module Ddr
|
|
54
54
|
workflow_state == Ddr::Workflow::UNPUBLISHED
|
55
55
|
end
|
56
56
|
|
57
|
-
##############
|
58
|
-
# Move to dul-hydra?
|
59
|
-
##############
|
60
|
-
# def lock
|
61
|
-
# self.is_locked = true
|
62
|
-
# end
|
63
|
-
#
|
64
|
-
# def unlock
|
65
|
-
# self.is_locked = false
|
66
|
-
# end
|
67
|
-
#
|
68
|
-
# def lock!
|
69
|
-
# lock
|
70
|
-
# save
|
71
|
-
# end
|
72
|
-
#
|
73
|
-
# def unlock!
|
74
|
-
# unlock
|
75
|
-
# save
|
76
|
-
# end
|
77
|
-
#
|
78
|
-
# Same with publish! and unpublish!, which is currently delegated to Ddr::Managers::WorkflowManager
|
79
|
-
#
|
80
|
-
###############
|
81
|
-
|
82
|
-
###############
|
83
|
-
# attribute defined in has_content, single-valued, stored in adminMetadata datastream
|
84
|
-
###############
|
85
|
-
# property :original_filename,
|
86
|
-
# predicate: Ddr::Vocab::PREMIS.hasOriginalName do |index|
|
87
|
-
# index.as :stored_sortable
|
88
|
-
# end
|
89
|
-
#
|
90
|
-
|
91
|
-
# included do
|
92
|
-
#
|
93
|
-
# delegate :publish!, :unpublish!, :published?, :unpublished?,
|
94
|
-
# to: :workflow
|
95
|
-
# end
|
96
|
-
#
|
97
|
-
|
98
57
|
def resource_roles
|
99
58
|
roles.select(&:in_resource_scope?)
|
100
59
|
end
|
@@ -107,36 +66,19 @@ module Ddr
|
|
107
66
|
( has_admin_policy? && admin_policy.policy_roles ) || []
|
108
67
|
end
|
109
68
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
# def workflow
|
115
|
-
# @workflow ||= Ddr::Managers::WorkflowManager.new(self)
|
116
|
-
# end
|
117
|
-
#
|
118
|
-
# def grant_roles_to_creator(creator)
|
119
|
-
# roles.grant type: Ddr::Auth::Roles::EDITOR,
|
120
|
-
# agent: creator,
|
121
|
-
# scope: Ddr::Auth::Roles::RESOURCE_SCOPE
|
122
|
-
# end
|
123
|
-
#
|
124
|
-
# def copy_resource_roles_from(other)
|
125
|
-
# roles.grant *(other.roles.in_resource_scope)
|
126
|
-
# end
|
127
|
-
#
|
69
|
+
def effective_roles(agents = nil)
|
70
|
+
Ddr::Auth::EffectiveRoles.call(self, agents)
|
71
|
+
end
|
128
72
|
|
129
73
|
def effective_permissions(agents)
|
130
74
|
Ddr::Auth::EffectivePermissions.call(self, agents)
|
131
75
|
end
|
132
76
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
# end
|
139
|
-
#
|
77
|
+
def finding_aid
|
78
|
+
if ead_id
|
79
|
+
FindingAid.new(ead_id)
|
80
|
+
end
|
81
|
+
end
|
140
82
|
|
141
83
|
end
|
142
84
|
end
|
@@ -6,5 +6,13 @@ module Ddr
|
|
6
6
|
Ddr.query_service.find_inverse_references_by(resource: self, property: 'parent_id')
|
7
7
|
end
|
8
8
|
|
9
|
+
def first_child
|
10
|
+
sorted_children.first
|
11
|
+
end
|
12
|
+
|
13
|
+
def sorted_children
|
14
|
+
children.sort_by{ |e| [ e.local_id || '', e.ingestion_date ] }
|
15
|
+
end
|
16
|
+
|
9
17
|
end
|
10
18
|
end
|
@@ -54,29 +54,9 @@ module Ddr
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def resource
|
57
|
-
@resource
|
57
|
+
@resource ||= Valkyrie::MetadataAdapter.find(:index_solr).query_service.find_by(id: id)
|
58
58
|
end
|
59
59
|
|
60
|
-
### DDRevo: Not sure if / where this is used
|
61
|
-
def to_partial_path
|
62
|
-
'document'
|
63
|
-
end
|
64
|
-
|
65
|
-
### DDRevo: This is probably no longer needed
|
66
|
-
def safe_id
|
67
|
-
id.sub(/:/, "-")
|
68
|
-
end
|
69
|
-
|
70
|
-
### DDRevo: No longer relevant
|
71
|
-
# def object_profile
|
72
|
-
# @object_profile ||= get_json(Ddr::Index::Fields::OBJECT_PROFILE)
|
73
|
-
# end
|
74
|
-
|
75
|
-
### DDRevo: No longer relevant
|
76
|
-
# def object_state
|
77
|
-
# object_profile["objState"]
|
78
|
-
# end
|
79
|
-
|
80
60
|
def object_create_date
|
81
61
|
parse_date(self[Ddr::Index::Fields::RESOURCE_CREATE_DATE])
|
82
62
|
end
|
@@ -93,23 +73,13 @@ module Ddr
|
|
93
73
|
get_date(Ddr::Index::Fields::LAST_VIRUS_CHECK_ON)
|
94
74
|
end
|
95
75
|
|
96
|
-
### DDRevo: No longer relevant
|
97
|
-
# def datastreams
|
98
|
-
# object_profile["datastreams"]
|
99
|
-
# end
|
100
|
-
|
101
|
-
### DDRevo: No longer relevant
|
102
|
-
# def has_datastream?(dsID)
|
103
|
-
# datastreams[dsID].present?
|
104
|
-
# end
|
105
|
-
|
106
76
|
def has_admin_policy?
|
107
77
|
admin_policy_id.present?
|
108
78
|
end
|
109
79
|
|
110
80
|
def admin_policy
|
111
81
|
if has_admin_policy?
|
112
|
-
self.class.find(admin_policy_id)
|
82
|
+
self.class.find(admin_policy_id.gsub(/^id-/,''))
|
113
83
|
end
|
114
84
|
end
|
115
85
|
|
@@ -117,11 +87,6 @@ module Ddr
|
|
117
87
|
resource.children.present?
|
118
88
|
end
|
119
89
|
|
120
|
-
### DDRevo: No longer relevant
|
121
|
-
# def label
|
122
|
-
# object_profile["objLabel"]
|
123
|
-
# end
|
124
|
-
|
125
90
|
def title_display
|
126
91
|
title
|
127
92
|
end
|
@@ -151,11 +116,6 @@ module Ddr
|
|
151
116
|
resource.has_extracted_text?
|
152
117
|
end
|
153
118
|
|
154
|
-
### DDRevo: Not relevant as coded. Not sure if comparable functionality is needed
|
155
|
-
# def content_ds
|
156
|
-
# datastreams[Ddr::Datastreams::CONTENT]
|
157
|
-
# end
|
158
|
-
|
159
119
|
def content_mime_type
|
160
120
|
resource.content_type
|
161
121
|
end
|
@@ -166,11 +126,6 @@ module Ddr
|
|
166
126
|
resource.content_human_size
|
167
127
|
end
|
168
128
|
|
169
|
-
### DDRevo: Not relevant as coded. Not sure if comparable functionality is needed
|
170
|
-
# def content_checksum
|
171
|
-
# content_ds["dsChecksum"] rescue nil
|
172
|
-
# end
|
173
|
-
|
174
129
|
def targets
|
175
130
|
@targets ||= query_service.find_inverse_references_by(resource: resource, property: 'for_collection_id')
|
176
131
|
end
|
@@ -183,11 +138,6 @@ module Ddr
|
|
183
138
|
targets_count > 0
|
184
139
|
end
|
185
140
|
|
186
|
-
### DDRevo Still relevant?
|
187
|
-
# def association(name)
|
188
|
-
# get_pid(ActiveFedora::SolrService.solr_name(name, :symbol))
|
189
|
-
# end
|
190
|
-
|
191
141
|
def tableized_name
|
192
142
|
resource_model.tableize
|
193
143
|
end
|
@@ -197,7 +147,6 @@ module Ddr
|
|
197
147
|
end
|
198
148
|
|
199
149
|
def roles
|
200
|
-
# @roles ||= Ddr::Auth::Roles::Role.from_json(access_role)
|
201
150
|
@roles ||= resource.roles
|
202
151
|
end
|
203
152
|
|
@@ -246,11 +195,8 @@ module Ddr
|
|
246
195
|
end
|
247
196
|
end
|
248
197
|
|
249
|
-
# DRY HasAdminMetadata
|
250
198
|
def finding_aid
|
251
|
-
|
252
|
-
FindingAid.new(ead_id)
|
253
|
-
end
|
199
|
+
resource.finding_aid
|
254
200
|
end
|
255
201
|
|
256
202
|
def intermediate_type
|
@@ -280,14 +226,18 @@ module Ddr
|
|
280
226
|
resource.captionable?
|
281
227
|
end
|
282
228
|
|
229
|
+
def captioned?
|
230
|
+
resource.captioned?
|
231
|
+
end
|
232
|
+
|
283
233
|
def caption_type
|
284
|
-
if
|
234
|
+
if captioned?
|
285
235
|
resource.caption_type
|
286
236
|
end
|
287
237
|
end
|
288
238
|
|
289
239
|
def caption_extension
|
290
|
-
if
|
240
|
+
if captioned?
|
291
241
|
extensions = Ddr.preferred_file_extensions
|
292
242
|
if extensions.include? caption_type
|
293
243
|
extensions[caption_type]
|
@@ -298,7 +248,7 @@ module Ddr
|
|
298
248
|
end
|
299
249
|
|
300
250
|
def caption_path
|
301
|
-
if
|
251
|
+
if captioned?
|
302
252
|
resource.caption_path
|
303
253
|
end
|
304
254
|
end
|
@@ -336,9 +286,8 @@ module Ddr
|
|
336
286
|
end
|
337
287
|
end
|
338
288
|
|
339
|
-
# FIXME - Probably need a more general solution mapping object reader methods to index field names.
|
340
289
|
def rights
|
341
|
-
|
290
|
+
resource.rights
|
342
291
|
end
|
343
292
|
|
344
293
|
def children
|
@@ -351,14 +300,6 @@ module Ddr
|
|
351
300
|
@query_service ||= Valkyrie::MetadataAdapter.find(:index_solr).query_service
|
352
301
|
end
|
353
302
|
|
354
|
-
# def targets_query
|
355
|
-
# "#{Ddr::Index::Fields::IS_EXTERNAL_TARGET_FOR}:#{internal_uri_for_query}"
|
356
|
-
# end
|
357
|
-
#
|
358
|
-
# def internal_uri_for_query
|
359
|
-
# ActiveFedora::SolrService.escape_uri_for_query(internal_uri)
|
360
|
-
# end
|
361
|
-
#
|
362
303
|
def get_date(field)
|
363
304
|
parse_date(self[field])
|
364
305
|
end
|
@@ -371,10 +312,6 @@ module Ddr
|
|
371
312
|
Time.parse(date).localtime if date
|
372
313
|
end
|
373
314
|
|
374
|
-
# def get_pid(field)
|
375
|
-
# ActiveFedora::Base.pid_from_uri(self[field]) rescue nil
|
376
|
-
# end
|
377
|
-
#
|
378
315
|
def inherited_research_help_contact
|
379
316
|
if doc = admin_policy
|
380
317
|
doc.research_help_contact
|
@@ -398,32 +335,16 @@ module Ddr
|
|
398
335
|
end
|
399
336
|
|
400
337
|
def intermediate_extension_default
|
401
|
-
# datastreams[Ddr::Datastreams::INTERMEDIATE_FILE].default_file_extension
|
402
338
|
resource.intermediate_file.default_file_extension
|
403
339
|
end
|
404
340
|
|
405
341
|
def caption_extension_default
|
406
|
-
# datastreams[Ddr::Datastreams::CAPTION].default_file_extension
|
407
342
|
resource.caption.default_file_extension
|
408
343
|
end
|
409
344
|
|
410
345
|
def streamable_media_extension_default
|
411
|
-
# datastreams[Ddr::Datastreams::STREAMABLE_MEDIA].default_file_extension
|
412
346
|
resource.streamable_media.default_file_extension
|
413
347
|
end
|
414
348
|
|
415
|
-
### DDRevo: Using resource.children rather than this query
|
416
|
-
# def children_query
|
417
|
-
# case self[Ddr::Index::Fields::RESOURCE_MODEL]
|
418
|
-
# when 'Ddr::Collection'
|
419
|
-
# Ddr::Index::Query.build(self) do |parent|
|
420
|
-
# is_member_of_collection parent.id
|
421
|
-
# end
|
422
|
-
# when 'Ddr::Item'
|
423
|
-
# Ddr::Index::Query.build(self) do |parent|
|
424
|
-
# is_part_of parent.id
|
425
|
-
# end
|
426
|
-
# end
|
427
|
-
# end
|
428
349
|
end
|
429
350
|
end
|
data/app/models/ddr/admin_set.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
|
-
require "active_resource"
|
2
|
-
|
3
1
|
module Ddr
|
4
|
-
class AdminSet <
|
5
|
-
|
6
|
-
self.site = ENV["DDR_AUX_API_URL"]
|
2
|
+
class AdminSet < AuxiliaryResource
|
7
3
|
|
8
4
|
def self.call(obj)
|
9
5
|
find_by_code(obj.admin_set)
|
@@ -13,11 +9,11 @@ module Ddr
|
|
13
9
|
|
14
10
|
def self.find_by_code(code)
|
15
11
|
return unless code
|
16
|
-
new get(:find, code: code)
|
12
|
+
fetch(code) { new get(:find, code: code) }
|
17
13
|
end
|
18
14
|
|
19
15
|
def self.keys
|
20
|
-
all.map(&:code)
|
16
|
+
fetch("codes") { all.map(&:code) }
|
21
17
|
end
|
22
18
|
|
23
19
|
def to_s
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Ddr
|
2
|
+
class Alert < AuxiliaryResource
|
3
|
+
|
4
|
+
ADMIN_SITE = 'admin'
|
5
|
+
PUBLIC_SITE = 'public'
|
6
|
+
|
7
|
+
# @param [String] the application ('admin' or 'public') for which to return active alerts
|
8
|
+
# @return [Array] the active alerts for the requested application site
|
9
|
+
def self.call(site)
|
10
|
+
get(:active, site: site).map { |resp| new(resp) }
|
11
|
+
rescue ActiveResource::ServerError => e
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_resource'
|
2
|
+
|
3
|
+
module Ddr
|
4
|
+
#
|
5
|
+
# Abstract superclass for resources bound to ddr-aux API data
|
6
|
+
#
|
7
|
+
class AuxiliaryResource < ActiveResource::Base
|
8
|
+
|
9
|
+
# ActiveResource freezes `site` in subclasses
|
10
|
+
self.site = Ddr.ddr_aux_api_url
|
11
|
+
|
12
|
+
class_attribute :cache_expiry, instance_accessor: false
|
13
|
+
self.cache_expiry = 1.hour
|
14
|
+
|
15
|
+
def self.fetch(value_key, &block)
|
16
|
+
Rails.cache.fetch(cache_key(value_key), expires_in: cache_expiry, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.cache_key(suffix)
|
20
|
+
[ model_name.cache_key, suffix ].join('/')
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
data/app/models/ddr/contact.rb
CHANGED
@@ -0,0 +1,62 @@
|
|
1
|
+
# TODO: 'https://duldev.atlassian.net/browse/DDR-1755'
|
2
|
+
|
3
|
+
module Ddr
|
4
|
+
class FindingAid
|
5
|
+
attr_reader :ead_id
|
6
|
+
|
7
|
+
EAD_XMLNS = "urn:isbn:1-931666-22-9"
|
8
|
+
|
9
|
+
def initialize(ead_id)
|
10
|
+
@ead_id = ead_id
|
11
|
+
end
|
12
|
+
|
13
|
+
def url
|
14
|
+
doc.css("eadid").attr("url").text
|
15
|
+
end
|
16
|
+
|
17
|
+
# The finding aid title
|
18
|
+
def title
|
19
|
+
doc.css("titleproper").children.first.text.strip
|
20
|
+
end
|
21
|
+
|
22
|
+
def repository
|
23
|
+
collection.xpath('ead:did/ead:repository/ead:corpname', ead: EAD_XMLNS).text
|
24
|
+
end
|
25
|
+
|
26
|
+
def collection_date_span
|
27
|
+
collection.xpath('ead:did/ead:unitdate[@type="inclusive"]', ead: EAD_XMLNS).text
|
28
|
+
end
|
29
|
+
|
30
|
+
def collection_number
|
31
|
+
collection.xpath('ead:did/ead:unitid', ead: EAD_XMLNS).text
|
32
|
+
end
|
33
|
+
|
34
|
+
def collection_title
|
35
|
+
collection.xpath('ead:did/ead:unittitle', ead: EAD_XMLNS).text
|
36
|
+
end
|
37
|
+
|
38
|
+
def extent
|
39
|
+
collection.xpath('ead:did/ead:physdesc/ead:extent', ead: EAD_XMLNS).map(&:text).join("; ")
|
40
|
+
end
|
41
|
+
|
42
|
+
def abstract
|
43
|
+
collection.xpath('ead:did/ead:abstract', ead: EAD_XMLNS).text
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def collection
|
49
|
+
doc.xpath('//ead:archdesc[@level="collection"]', ead: EAD_XMLNS)
|
50
|
+
end
|
51
|
+
|
52
|
+
# @raise [OpenURI::HTTPError] if 404, etc.
|
53
|
+
def doc
|
54
|
+
@doc ||= Nokogiri::XML(open(ead_xml_url))
|
55
|
+
end
|
56
|
+
|
57
|
+
def ead_xml_url
|
58
|
+
Ddr::Models.ead_xml_base_url + ead_id + ".xml"
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/app/models/ddr/item.rb
CHANGED
@@ -12,25 +12,11 @@ module Ddr
|
|
12
12
|
|
13
13
|
self.parent_class = Ddr::Collection
|
14
14
|
|
15
|
-
### DDRevo #####################
|
16
|
-
# TODO: We may want to revisit this alternate implementation once ddr-core is more fully baked
|
17
|
-
# or it may be fine just as it is
|
18
|
-
### DDRevo #####################
|
19
15
|
def children_having_extracted_text
|
20
|
-
# Ddr::Index::Query.build(self) do |item|
|
21
|
-
# is_part_of item
|
22
|
-
# where attached_files_having_content: "extractedText"
|
23
|
-
# fields :id, :extracted_text
|
24
|
-
# end
|
25
16
|
children.select { |child| child.attached_files_having_content.include?(:extracted_text) }
|
26
17
|
end
|
27
18
|
|
28
|
-
### DDRevo #####################
|
29
|
-
# TODO: We may want to revisit this alternate implementation once ddr-core is more fully baked
|
30
|
-
# or it may be fine just as it is
|
31
|
-
### DDRevo #####################
|
32
19
|
def all_text
|
33
|
-
# children_having_extracted_text.docs.map(&:extracted_text).flatten
|
34
20
|
children_having_extracted_text.map { |child| child.extracted_text.content }.to_a.flatten
|
35
21
|
end
|
36
22
|
|
data/app/models/ddr/language.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
|
-
require "active_resource"
|
2
|
-
|
3
1
|
module Ddr
|
4
|
-
class Language <
|
5
|
-
|
6
|
-
self.site = ENV["DDR_AUX_API_URL"]
|
2
|
+
class Language < AuxiliaryResource
|
7
3
|
|
8
4
|
def self.call(obj)
|
9
5
|
obj.language.map do |lang|
|
@@ -28,4 +24,3 @@ module Ddr
|
|
28
24
|
|
29
25
|
end
|
30
26
|
end
|
31
|
-
|
data/app/models/ddr/resource.rb
CHANGED
@@ -47,6 +47,10 @@ module Ddr
|
|
47
47
|
can_have_streamable_media?
|
48
48
|
end
|
49
49
|
|
50
|
+
def self.canonical_model_name(model_name)
|
51
|
+
model_name.starts_with?('Ddr::') ? model_name : "Ddr::#{model_name}"
|
52
|
+
end
|
53
|
+
|
50
54
|
def self.common_model_name
|
51
55
|
name.split('::').last
|
52
56
|
end
|
@@ -65,6 +69,10 @@ module Ddr
|
|
65
69
|
alias_method :new_record?, :new_record
|
66
70
|
alias_method :resource_model, :internal_resource
|
67
71
|
|
72
|
+
def rights_statement
|
73
|
+
RightsStatement.call(self)
|
74
|
+
end
|
75
|
+
|
68
76
|
def title_display
|
69
77
|
return title.first if title.present?
|
70
78
|
return identifier.first if identifier.present?
|
@@ -1,9 +1,5 @@
|
|
1
|
-
require "active_resource"
|
2
|
-
|
3
1
|
module Ddr
|
4
|
-
class RightsStatement <
|
5
|
-
|
6
|
-
self.site = ENV["DDR_AUX_API_URL"]
|
2
|
+
class RightsStatement < AuxiliaryResource
|
7
3
|
|
8
4
|
def self.call(obj)
|
9
5
|
if obj.rights.present?
|
@@ -22,4 +18,4 @@ module Ddr
|
|
22
18
|
end
|
23
19
|
|
24
20
|
end
|
25
|
-
end
|
21
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Ddr::Auth
|
2
2
|
class EffectivePermissions
|
3
3
|
|
4
|
-
# @param obj [Object] an object that receives :roles and returns
|
4
|
+
# @param obj [Object] an object that receives :roles and returns an Array
|
5
|
+
# of Ddr::Auth::Roles::Role.
|
5
6
|
# @param agents [String, Array<String>] agent(s) to match roles
|
6
7
|
# @return [Array<Symbol>]
|
7
8
|
def self.call(obj, agents)
|
@@ -1,8 +1,12 @@
|
|
1
1
|
module Ddr::Auth
|
2
2
|
class EffectiveRoles
|
3
3
|
|
4
|
-
def self.call(obj, agents)
|
5
|
-
( obj.resource_roles | obj.inherited_roles ).
|
4
|
+
def self.call(obj, agents = nil)
|
5
|
+
( obj.resource_roles | obj.inherited_roles ).tap do |roles|
|
6
|
+
if agents
|
7
|
+
roles.select! { |r| agents.include?(r.agent) }
|
8
|
+
end
|
9
|
+
end
|
6
10
|
end
|
7
11
|
|
8
12
|
end
|
data/lib/ddr/auth/failure_app.rb
CHANGED
@@ -25,7 +25,7 @@ module Ddr
|
|
25
25
|
|
26
26
|
# List of all grouper groups for the repository
|
27
27
|
def repository_groups(raw = false)
|
28
|
-
repo_groups = groups(
|
28
|
+
repo_groups = groups(Ddr::Auth.repository_group_filter)
|
29
29
|
if ok?
|
30
30
|
return repo_groups if raw
|
31
31
|
repo_groups.map do |g|
|
@@ -52,7 +52,7 @@ module Ddr
|
|
52
52
|
result = response["WsGetGroupsResults"]["results"].first
|
53
53
|
# Have to manually filter results b/c Grouper WS version 1.5 does not support filter parameter
|
54
54
|
if result && result["wsGroups"]
|
55
|
-
groups = result["wsGroups"].select { |g| g["name"] =~ /^#{
|
55
|
+
groups = result["wsGroups"].select { |g| g["name"] =~ /^#{Ddr::Auth.repository_group_filter}/ }
|
56
56
|
end
|
57
57
|
end
|
58
58
|
rescue StandardError => e
|
@@ -1,11 +1,5 @@
|
|
1
1
|
module Ddr
|
2
2
|
module Auth
|
3
|
-
#
|
4
|
-
# Hydra controller mixin for role-based access control
|
5
|
-
#
|
6
|
-
# Overrides Hydra::AccessControlsEnforcement#gated_discovery_filters
|
7
|
-
# to apply role filters instead of permissions filters.
|
8
|
-
#
|
9
3
|
module RoleBasedAccessControlsEnforcement
|
10
4
|
|
11
5
|
def self.included(controller)
|
@@ -17,36 +11,6 @@ module Ddr
|
|
17
11
|
@current_ability ||= AbilityFactory.call(current_user, request.env)
|
18
12
|
end
|
19
13
|
|
20
|
-
# List of URIs for policies on which any of the current user's agent has a role in policy scope
|
21
|
-
def policy_role_policies
|
22
|
-
@policy_role_policies ||= Array.new.tap do |uris|
|
23
|
-
filters = current_ability.agents.map do |agent|
|
24
|
-
"#{Ddr::Index::Fields::POLICY_ROLE}:\"#{agent}\""
|
25
|
-
end.join(" OR ")
|
26
|
-
query = "#{Ddr::Index::Fields::ACTIVE_FEDORA_MODEL}:Collection AND (#{filters})"
|
27
|
-
results = ActiveFedora::SolrService.query(query, rows: Collection.count, fl: Ddr::Index::Fields::INTERNAL_URI)
|
28
|
-
results.each_with_object(uris) { |r, memo| memo << r[Ddr::Index::Fields::INTERNAL_URI] }
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def policy_role_filters
|
33
|
-
if policy_role_policies.present?
|
34
|
-
rels = policy_role_policies.map { |pid| [:is_governed_by, pid] }
|
35
|
-
ActiveFedora::SolrService.construct_query_for_rel(rels, "OR")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def resource_role_filters
|
40
|
-
current_ability.agents.map do |agent|
|
41
|
-
ActiveFedora::SolrService.raw_query(Ddr::Index::Fields::RESOURCE_ROLE, agent)
|
42
|
-
end.join(" OR ")
|
43
|
-
end
|
44
|
-
|
45
|
-
def gated_discovery_filters
|
46
|
-
[resource_role_filters, policy_role_filters].compact
|
47
|
-
end
|
48
|
-
|
49
|
-
# Overrides Hydra::AccessControlsEnforcement
|
50
14
|
def enforce_show_permissions
|
51
15
|
authorize! :read, params[:id]
|
52
16
|
end
|
data/lib/ddr/auth/roles/role.rb
CHANGED
@@ -36,38 +36,6 @@ module Ddr
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
###############
|
40
|
-
# FIXME or remove serialization/deserialization
|
41
|
-
###############
|
42
|
-
#
|
43
|
-
# # Deserialize a Role from JSON
|
44
|
-
# # @param json [String] the JSON string
|
45
|
-
# # @return [Role] the role
|
46
|
-
# def from_json(json)
|
47
|
-
# build JSON.parse(json)
|
48
|
-
# end
|
49
|
-
|
50
|
-
# alias_method :deserialize, :from_json
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
#
|
55
|
-
# DELETEME
|
56
|
-
#
|
57
|
-
# def build_attributes(args={})
|
58
|
-
# # symbolize keys and stringify values
|
59
|
-
# attrs = args.each_with_object({}) do |(k, v), memo|
|
60
|
-
# memo[k.to_sym] = Array(v).first.to_s
|
61
|
-
# end
|
62
|
-
# # set default scope if necessary
|
63
|
-
# attrs[:scope] ||= DEFAULT_SCOPE
|
64
|
-
# # accept :type key for role_type attribute
|
65
|
-
# if attrs.key?(:type)
|
66
|
-
# attrs[:role_type] = attrs.delete(:type)
|
67
|
-
# end
|
68
|
-
# attrs
|
69
|
-
# end
|
70
|
-
|
71
39
|
end # class << self
|
72
40
|
|
73
41
|
# Roles are considered equal (==) if they
|
@@ -96,19 +64,6 @@ module Ddr
|
|
96
64
|
"agent=#{agent.inspect}, scope=#{scope.inspect}>"
|
97
65
|
end
|
98
66
|
|
99
|
-
# TODO refactor up?
|
100
|
-
def proper_attributes
|
101
|
-
attributes.slice(self.class.fields - self.class.reserved_attributes)
|
102
|
-
end
|
103
|
-
|
104
|
-
###############
|
105
|
-
# FIXME or remove serialization/deserialization
|
106
|
-
###############
|
107
|
-
#
|
108
|
-
# delegate :to_json, to: :proper_attributes
|
109
|
-
#
|
110
|
-
# alias_method :serialize, :to_json
|
111
|
-
|
112
67
|
# Returns the permissions associated with the role
|
113
68
|
# @return [Array<Symbol>] the permissions
|
114
69
|
def permissions
|
data/lib/ddr/core.rb
CHANGED
@@ -9,6 +9,7 @@ module Ddr
|
|
9
9
|
autoload :Files
|
10
10
|
autoload :NotFoundError, 'ddr/error'
|
11
11
|
autoload :Fits
|
12
|
+
autoload :FindingAid
|
12
13
|
autoload :Index
|
13
14
|
autoload :Managers
|
14
15
|
autoload :Utils
|
@@ -103,6 +104,10 @@ module Ddr
|
|
103
104
|
false
|
104
105
|
end
|
105
106
|
|
107
|
+
mattr_accessor :ddr_aux_api_url do
|
108
|
+
ENV["DDR_AUX_API_URL"]
|
109
|
+
end
|
110
|
+
|
106
111
|
module Core
|
107
112
|
|
108
113
|
end
|
data/lib/ddr/core/version.rb
CHANGED
data/lib/ddr/fits.rb
CHANGED
@@ -94,96 +94,5 @@ module Ddr
|
|
94
94
|
xpath('//fits:fits', fits: FITS_XMLNS).first
|
95
95
|
end
|
96
96
|
|
97
|
-
### DDRevo ##########################################
|
98
|
-
# From Ddr::Datastreams::FitsDatastream. Code above accounts for proxy terms from below and has a private 'root'
|
99
|
-
# method but does not (yet) provide methods for all the terms in the terminology. Thought it was better to wait
|
100
|
-
# and see which ones are actually needed.
|
101
|
-
### DDRevo ##########################################
|
102
|
-
# set_terminology do |t|
|
103
|
-
# t.root(path: "fits",
|
104
|
-
# xmlns: FITS_XMLNS,
|
105
|
-
# schema: FITS_SCHEMA)
|
106
|
-
# t.version(path: {attribute: "version"})
|
107
|
-
# t.timestamp(path: {attribute: "timestamp"})
|
108
|
-
# t.identification {
|
109
|
-
# t.identity {
|
110
|
-
# t.mimetype(path: {attribute: "mimetype"})
|
111
|
-
# t.format_label(path: {attribute: "format"})
|
112
|
-
# t.version
|
113
|
-
# t.externalIdentifier
|
114
|
-
# t.pronom_identifier(path: "externalIdentifier", attributes: {type: "puid"})
|
115
|
-
# }
|
116
|
-
# }
|
117
|
-
# t.fileinfo {
|
118
|
-
# t.created
|
119
|
-
# t.creatingApplicationName
|
120
|
-
# t.creatingos
|
121
|
-
# t.filename
|
122
|
-
# t.filepath
|
123
|
-
# t.fslastmodified
|
124
|
-
# t.lastmodified
|
125
|
-
# t.md5checksum
|
126
|
-
# t.size
|
127
|
-
# }
|
128
|
-
# t.filestatus {
|
129
|
-
# t.valid
|
130
|
-
# t.well_formed(path: "well-formed")
|
131
|
-
# }
|
132
|
-
# t.metadata {
|
133
|
-
# t.image {
|
134
|
-
# t.imageWidth
|
135
|
-
# t.imageHeight
|
136
|
-
# t.colorSpace
|
137
|
-
# t.iccProfileName
|
138
|
-
# t.iccProfileVersion
|
139
|
-
# }
|
140
|
-
# t.document {
|
141
|
-
# # TODO - configure to get from Tika?
|
142
|
-
# # t.encoding
|
143
|
-
# }
|
144
|
-
# t.text
|
145
|
-
# t.audio
|
146
|
-
# t.video
|
147
|
-
# }
|
148
|
-
#
|
149
|
-
# ## proxy terms
|
150
|
-
#
|
151
|
-
# # identification / identity
|
152
|
-
# t.format_label proxy: [:identification, :identity, :format_label]
|
153
|
-
# t.format_version proxy: [:identification, :identity, :version]
|
154
|
-
# t.media_type proxy: [:identification, :identity, :mimetype]
|
155
|
-
# t.pronom_identifier proxy: [:identification, :identity, :pronom_identifier]
|
156
|
-
#
|
157
|
-
# # filestatus
|
158
|
-
# t.valid proxy: [:filestatus, :valid]
|
159
|
-
# t.well_formed proxy: [:filestatus, :well_formed]
|
160
|
-
#
|
161
|
-
# # fileinfo
|
162
|
-
# t.created proxy: [:fileinfo, :created]
|
163
|
-
# t.creating_application proxy: [:fileinfo, :creatingApplicationName]
|
164
|
-
# t.extent proxy: [:fileinfo, :size]
|
165
|
-
# t.md5 proxy: [:fileinfo, :md5checksum]
|
166
|
-
#
|
167
|
-
# # image metadata
|
168
|
-
# t.color_space proxy: [:metadata, :image, :colorSpace]
|
169
|
-
# t.icc_profile_name proxy: [:metadata, :image, :iccProfileName]
|
170
|
-
# t.icc_profile_version proxy: [:metadata, :image, :iccProfileVersion]
|
171
|
-
# t.image_height proxy: [:metadata, :image, :imageHeight]
|
172
|
-
# t.image_width proxy: [:metadata, :image, :imageWidth]
|
173
|
-
# end
|
174
|
-
#
|
175
|
-
# def self.xml_template
|
176
|
-
# builder = Nokogiri::XML::Builder.new do |xml|
|
177
|
-
# xml.fits("xmlns"=>FITS_XMLNS,
|
178
|
-
# "xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
|
179
|
-
# "xsi:schemaLocation"=>"http://hul.harvard.edu/ois/xml/ns/fits/fits_output http://hul.harvard.edu/ois/xml/xsd/fits/fits_output.xsd")
|
180
|
-
# end
|
181
|
-
# builder.doc
|
182
|
-
# end
|
183
|
-
#
|
184
|
-
# def prefix
|
185
|
-
# "fits__"
|
186
|
-
# end
|
187
|
-
|
188
97
|
end
|
189
98
|
end
|
data/lib/ddr/index.rb
CHANGED
data/lib/ddr/index/fields.rb
CHANGED
@@ -38,6 +38,7 @@ module Ddr::Index
|
|
38
38
|
DISPLAY_FORMAT = Field.new :display_format, :stored_sortable
|
39
39
|
DOI = Field.new :doi, :symbol
|
40
40
|
EAD_ID = Field.new :ead_id, :stored_sortable
|
41
|
+
EFFECTIVE_ROLE = Field.new :effective_role, :symbol
|
41
42
|
ENGRAVER_FACET = Field.new :engraver_facet, :facetable
|
42
43
|
EXTRACTED_TEXT = Field.new :extracted_text, solr_name: "extracted_text_tsm"
|
43
44
|
FCREPO3_PID = Field.new :fcrepo3_pid, :stored_sortable
|
@@ -2,7 +2,9 @@ module Ddr
|
|
2
2
|
module Managers
|
3
3
|
class TechnicalMetadataManager < Manager
|
4
4
|
|
5
|
-
|
5
|
+
FITS_141_TIMESTAMP_FORMAT = "%D %l:%M %p" # Ex. 7/3/15 8:29 PM
|
6
|
+
FITS_150_TIMESTAMP_FORMAT = "%D, %l:%M %p" # Ex. 7/3/15, 8:29 PM
|
7
|
+
FITS_TIMESTAMP_FORMATS = [ FITS_141_TIMESTAMP_FORMAT, FITS_150_TIMESTAMP_FORMAT ]
|
6
8
|
|
7
9
|
delegate :content, to: :object
|
8
10
|
|
@@ -43,9 +45,12 @@ module Ddr
|
|
43
45
|
|
44
46
|
def fits_datetime
|
45
47
|
if fits_timestamp = fits.timestamp.first
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
parsed = nil
|
49
|
+
FITS_TIMESTAMP_FORMATS.each do |format|
|
50
|
+
parsed = Time.zone.strptime(fits_timestamp, format) rescue nil
|
51
|
+
break if parsed
|
52
|
+
end
|
53
|
+
parsed
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
data/lib/ddr/structure.rb
CHANGED
@@ -82,6 +82,7 @@ module Ddr
|
|
82
82
|
|
83
83
|
def add_filesec(id:nil)
|
84
84
|
filesec = Ddr::Structures::FileSec.build(id: id, document: as_xml_document)
|
85
|
+
|
85
86
|
root.add_child(filesec)
|
86
87
|
filesec
|
87
88
|
end
|
@@ -92,7 +93,7 @@ module Ddr
|
|
92
93
|
filegrp
|
93
94
|
end
|
94
95
|
|
95
|
-
def add_file(parent:, id:SecureRandom.uuid, use:nil)
|
96
|
+
def add_file(parent:, id: "id_" + SecureRandom.uuid, use:nil)
|
96
97
|
file = Ddr::Structures::File.build(id: id, use: use, document: as_xml_document)
|
97
98
|
parent.add_child(file)
|
98
99
|
file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ddr-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Coble
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2019-
|
14
|
+
date: 2019-11-18 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: activeresource
|
@@ -209,6 +209,20 @@ dependencies:
|
|
209
209
|
- - ">="
|
210
210
|
- !ruby/object:Gem::Version
|
211
211
|
version: '0'
|
212
|
+
- !ruby/object:Gem::Dependency
|
213
|
+
name: equivalent-xml
|
214
|
+
requirement: !ruby/object:Gem::Requirement
|
215
|
+
requirements:
|
216
|
+
- - ">="
|
217
|
+
- !ruby/object:Gem::Version
|
218
|
+
version: '0'
|
219
|
+
type: :development
|
220
|
+
prerelease: false
|
221
|
+
version_requirements: !ruby/object:Gem::Requirement
|
222
|
+
requirements:
|
223
|
+
- - ">="
|
224
|
+
- !ruby/object:Gem::Version
|
225
|
+
version: '0'
|
212
226
|
- !ruby/object:Gem::Dependency
|
213
227
|
name: factory_bot_rails
|
214
228
|
requirement: !ruby/object:Gem::Requirement
|
@@ -308,12 +322,15 @@ files:
|
|
308
322
|
- app/models/concerns/ddr/solr_document_behavior.rb
|
309
323
|
- app/models/concerns/ddr/streamable.rb
|
310
324
|
- app/models/ddr/admin_set.rb
|
325
|
+
- app/models/ddr/alert.rb
|
311
326
|
- app/models/ddr/attachment.rb
|
327
|
+
- app/models/ddr/auxiliary_resource.rb
|
312
328
|
- app/models/ddr/collection.rb
|
313
329
|
- app/models/ddr/component.rb
|
314
330
|
- app/models/ddr/contact.rb
|
315
331
|
- app/models/ddr/digest.rb
|
316
332
|
- app/models/ddr/file.rb
|
333
|
+
- app/models/ddr/finding_aid.rb
|
317
334
|
- app/models/ddr/item.rb
|
318
335
|
- app/models/ddr/language.rb
|
319
336
|
- app/models/ddr/media_type.rb
|
@@ -419,7 +436,8 @@ files:
|
|
419
436
|
homepage: https://gitlab.oit.duke.edu/ddr/ddr-core
|
420
437
|
licenses:
|
421
438
|
- BSD-3-Clause
|
422
|
-
metadata:
|
439
|
+
metadata:
|
440
|
+
allowed_push_host: https://rubygems.org
|
423
441
|
post_install_message:
|
424
442
|
rdoc_options: []
|
425
443
|
require_paths:
|
@@ -435,8 +453,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
435
453
|
- !ruby/object:Gem::Version
|
436
454
|
version: '0'
|
437
455
|
requirements: []
|
438
|
-
|
439
|
-
rubygems_version: 2.7.9
|
456
|
+
rubygems_version: 3.0.6
|
440
457
|
signing_key:
|
441
458
|
specification_version: 4
|
442
459
|
summary: Models used in the Duke Digital Repository
|