-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathrights_metadata.rb
276 lines (250 loc) · 11.2 KB
/
rights_metadata.rb
1
2
3
4
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
require 'active_support/core_ext/string'
module FedoraMigrate
# Implements Hydra RightsMetadata XML terminology for asserting access permissions
class RightsMetadata < ActiveFedora::OmDatastream
extend Deprecation
set_terminology do |t|
t.root(path: "rightsMetadata", xmlns: "http://hydra-collab.stanford.edu/schemas/rightsMetadata/v1", schema: "http://github.com/projecthydra/schemas/tree/v1/rightsMetadata.xsd")
t.copyright do
## BEGIN possible delete, justin 2012-06-22
t.machine do
t.cclicense
t.license
end
t.human_readable(path: "human")
t.license(proxy: [:machine, :license])
t.cclicense(proxy: [:machine, :cclicense])
## END possible delete
t.title(path: 'human', attributes: { type: 'title' })
t.description(path: 'human', attributes: { type: 'description' })
t.url(path: 'machine', attributes: { type: 'uri' })
end
t.access do
t.human_readable(path: "human")
t.machine do
t.group
t.person
end
t.person(proxy: [:machine, :person])
t.group(proxy: [:machine, :group])
# accessor :access_person, :term=>[:access, :machine, :person]
end
t.discover_access(ref: [:access], attributes: { type: "discover" })
t.read_access(ref: [:access], attributes: { type: "read" })
t.edit_access(ref: [:access], attributes: { type: "edit" })
# A bug in OM prevnts us from declaring proxy terms at the root of a Terminology
# t.access_person(:proxy=>[:access,:machine,:person])
# t.access_group(:proxy=>[:access,:machine,:group])
t.embargo do
t.human_readable(path: "human")
t.machine do
t.date(type: :time, attributes: { type: "release" })
t.date_deactivated(type: "deactivated")
t.visibility_during(path: "visibility", attributes: { scope: 'during' })
t.visibility_after(path: "visibility", attributes: { scope: 'after' })
end
end
t.lease do
t.human_readable(path: "human")
t.machine do
t.date(type: :time, attributes: { type: "expire" })
t.date_deactivated(type: :time, attributes: { type: "deactivated" })
t.visibility_during(path: "visibility", attributes: { scope: 'during' })
t.visibility_after(path: "visibility", attributes: { scope: 'after' })
end
end
t.license(ref: [:copyright])
t.visibility_during_embargo proxy: [:embargo, :machine, :visibility_during]
t.visibility_after_embargo proxy: [:embargo, :machine, :visibility_after]
t.visibility_during_lease proxy: [:lease, :machine, :visibility_during]
t.visibility_after_lease proxy: [:lease, :machine, :visibility_after]
t.embargo_history proxy: [:embargo, :human_readable]
t.lease_history proxy: [:lease, :human_readable]
t.embargo_release_date proxy: [:embargo, :machine, :date], type: :time
t.embargo_deactivation_date proxy: [:embargo, :machine, :date_deactivated]
t.lease_expiration_date proxy: [:lease, :machine, :date], type: :time
t.lease_deactivation_date proxy: [:lease, :machine, :date_deactivated]
end
# Generates an empty Mods Article (used when you call ModsArticle.new without passing in existing xml)
def self.xml_template
builder = Nokogiri::XML::Builder.new do |xml|
xml.rightsMetadata(:version => "0.1", "xmlns" => "http://hydra-collab.stanford.edu/schemas/rightsMetadata/v1") do
xml.copyright do
xml.human(type: 'title')
xml.human(type: 'description')
xml.machine(type: 'uri')
end
xml.access(type: "discover") do
xml.human
xml.machine
end
xml.access(type: "read") do
xml.human
xml.machine
end
xml.access(type: "edit") do
xml.human
xml.machine
end
xml.embargo do
xml.machine
end
xml.lease do
xml.machine
end
end
end
builder.doc
end
# Returns the permissions for the selected person/group
# If new_access_level is provided, updates the selected person/group access_level to the one specified
# A new_access_level of "none" will remove all access_levels for the selected person/group
# @param [Hash] selector hash in format {type => identifier}
# @param new_access_level (default nil)
# @return Hash in format {type => access_level}.
#
# ie.
# permissions({:person=>"person123"})
# => {"person123"=>"edit"}
# permissions({:person=>"person123"}, "read")
# => {"person123"=>"read"}
# permissions({:person=>"person123"})
# => {"person123"=>"read"}
def permissions(selector, new_access_level = nil)
type = selector.keys.first.to_sym
actor = selector.values.first
if new_access_level.nil?
xpath = xpath(type, actor)
nodeset = find_by_terms(xpath)
if nodeset.empty?
return "none"
else
return nodeset.first.ancestors("access").first.attributes["type"].text
end
else
remove_all_permissions(selector)
if new_access_level == "none"
self.content = to_xml
else
access_type_symbol = "#{new_access_level}_access".to_sym
current_values = term_values(access_type_symbol, type)
update_values([access_type_symbol, type] => current_values + [actor])
end
return new_access_level
end
end
# Reports on which groups have which permissions
# @return Hash in format {group_name => group_permissions, group_name => group_permissions}
def groups
quick_search_by_type(:group)
end
def individuals
Deprecation.warn(RightsMetadata, "The method `individuals' is deprecated and will be removed from Hydra::Datastream::RightsMetadata in hydra-head 8.0. Use `users' instead.", caller)
users
end
# Reports on which users have which permissions
# @return Hash in format {user_name => user_permissions, user_name => user_permissions}
def users
quick_search_by_type(:person)
end
# Updates permissions for all of the persons and groups in a hash
# @param params ex. {"group"=>{"group1"=>"discover","group2"=>"edit"}, "person"=>{"person1"=>"read","person2"=>"discover"}}
# Currently restricts actor type to group or person. Any others will be ignored
def update_permissions(params)
params.fetch("group", {}).each_pair { |group_id, access_level| permissions({ "group" => group_id }, access_level) }
params.fetch("person", {}).each_pair { |person_id, access_level| permissions({ "person" => person_id }, access_level) }
end
# Updates all permissions
# @param params ex. {"group"=>{"group1"=>"discover","group2"=>"edit"}, "person"=>{"person1"=>"read","person2"=>"discover"}}
# Restricts actor type to group or person. Any others will be ignored
def permissions=(params)
groups_for_update = params['group'] ? params['group'].keys : []
group_ids = groups.keys | groups_for_update
group_ids.each { |group_id| permissions({ "group" => group_id }, params['group'].fetch(group_id, 'none')) }
users_for_update = params['person'] ? params['person'].keys : []
user_ids = users.keys | users_for_update
user_ids.each { |person_id| permissions({ "person" => person_id }, params['person'].fetch(person_id, 'none')) }
end
# @param [Symbol] type (either :group or :person)
# @return
# This method limits the response to known access levels. Probably runs a bit faster than .permissions().
def quick_search_by_type(type)
result = {}
[{ discover_access: "discover" }, { read_access: "read" }, { edit_access: "edit" }].each do |access_levels_hash|
access_level = access_levels_hash.keys.first
access_level_name = access_levels_hash.values.first
find_by_terms(*[access_level, type]).each do |entry|
result[entry.text] = access_level_name
end
end
result
end
def under_embargo?
(embargo_release_date.present? && Date.today < embargo_release_date.first) ? true : false
end
def active_lease?
lease_expiration_date.present? && Date.today < lease_expiration_date.first
end
def to_solr(solr_doc = {})
[:discover, :read, :edit].each do |access|
vals = send("#{access}_access").machine.group
solr_doc[Hydra.config.permissions[access].group] = vals unless vals.empty?
vals = send("#{access}_access").machine.person
solr_doc[Hydra.config.permissions[access].individual] = vals unless vals.empty?
end
if embargo_release_date.present?
key = Hydra.config.permissions.embargo.release_date.sub(/_[^_]+$/, '') # Strip off the suffix
::Solrizer.insert_field(solr_doc, key, embargo_release_date, :stored_sortable)
end
if lease_expiration_date.present?
key = Hydra.config.permissions.lease.expiration_date.sub(/_[^_]+$/, '') # Strip off the suffix
::Solrizer.insert_field(solr_doc, key, lease_expiration_date, :stored_sortable)
end
solr_doc[::Solrizer.solr_name("visibility_during_embargo", :symbol)] = visibility_during_embargo unless visibility_during_embargo.nil?
solr_doc[::Solrizer.solr_name("visibility_after_embargo", :symbol)] = visibility_after_embargo unless visibility_after_embargo.nil?
solr_doc[::Solrizer.solr_name("visibility_during_lease", :symbol)] = visibility_during_lease unless visibility_during_lease.nil?
solr_doc[::Solrizer.solr_name("visibility_after_lease", :symbol)] = visibility_after_lease unless visibility_after_lease.nil?
solr_doc[::Solrizer.solr_name("embargo_history", :symbol)] = embargo_history unless embargo_history.nil?
solr_doc[::Solrizer.solr_name("lease_history", :symbol)] = lease_history unless lease_history.nil?
solr_doc
end
def indexer
self.class.indexer
end
def self.indexer
@indexer ||= Solrizer::Descriptor.new(:string, :stored, :indexed, :multivalued)
end
def date_indexer
self.class.date_indexer
end
def self.date_indexer
@date_indexer ||= Solrizer::Descriptor.new(:date, :stored, :indexed)
end
# Completely clear the permissions
def clear_permissions!
remove_all_permissions(person: true)
remove_all_permissions(group: true)
end
private
# Purge all access given group/person
def remove_all_permissions(selector)
return unless ng_xml
type = selector.keys.first.to_sym
actor = selector.values.first
xpath = xpath(type, actor)
nodes_to_purge = find_by_terms(xpath)
nodes_to_purge.each(&:remove)
end
# @param [Symbol] type (:group, :person)
# @param [String,TrueClass] actor the user we want to find. If actor is true, then don't query.
def xpath(type, actor)
raise ArgumentError, "Type must either be ':group' or ':person'. You provided: '#{type.inspect}'" unless [:group, :person].include?(type)
path = "//oxns:access/oxns:machine/oxns:#{type}"
if actor.is_a? String
clean_actor = actor.delete("'")
path += "[text() = '#{clean_actor}']"
end
path
end
end
end