hydra-access-controls 7.0.2 → 7.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/concerns/hydra/access_controls/access_right.rb +2 -0
- data/app/models/concerns/hydra/access_controls/embargoable.rb +139 -0
- data/app/models/concerns/hydra/access_controls/with_access_right.rb +1 -4
- data/app/models/concerns/hydra/access_controls.rb +1 -0
- data/app/services/hydra/embargo_service.rb +26 -0
- data/app/services/hydra/lease_service.rb +23 -0
- data/app/validators/hydra/future_date_validator.rb +20 -0
- data/lib/hydra/config.rb +42 -5
- data/lib/hydra/datastream/inheritable_rights_metadata.rb +4 -1
- data/lib/hydra/datastream/rights_metadata.rb +53 -27
- data/spec/services/embargo_service_spec.rb +38 -0
- data/spec/services/lease_service_spec.rb +37 -0
- data/spec/spec_helper.rb +8 -11
- data/spec/support/mods_asset.rb +2 -3
- data/spec/unit/access_controls_enforcement_spec.rb +1 -1
- data/spec/unit/admin_policy_spec.rb +1 -1
- data/spec/unit/config_spec.rb +1 -0
- data/spec/unit/embargoable_spec.rb +287 -0
- data/spec/unit/hydra_rights_metadata_spec.rb +91 -22
- data/spec/unit/inheritable_rights_metadata_spec.rb +20 -17
- data/spec/unit/policy_aware_ability_spec.rb +2 -2
- data/spec/unit/policy_aware_access_controls_enforcement_spec.rb +2 -2
- metadata +14 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb1a2767144b61de76cedcc965dcd1d88bd12f46
|
4
|
+
data.tar.gz: 16e60959b2f2782197a0833d365fa5ae815c19ba
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37b630c64ad0407ac2bd7f61dc690a543c746aad151a81d24e931c62dfe06343dd65cefa559b637702d3111fb670ec05f8273c4a1c08f73bf1d4e295e11c8bea
|
7
|
+
data.tar.gz: ad5aad6fbeaa457286db70a4d40e606b3b600d915eeca2fddd1cdf9979b44bad5f46825ff33ba38fba9725c065cb82a22cebbaa4b1030f9bda358093e123ce99
|
@@ -8,6 +8,8 @@ module Hydra
|
|
8
8
|
# The values that get drawn to the page
|
9
9
|
VISIBILITY_TEXT_VALUE_PUBLIC = 'open'.freeze
|
10
10
|
VISIBILITY_TEXT_VALUE_EMBARGO = 'open_with_embargo_release_date'.freeze
|
11
|
+
#VISIBILITY_TEXT_VALUE_EMBARGO = 'embargo'.freeze # << !! Will change to this in next major release !!
|
12
|
+
VISIBILITY_TEXT_VALUE_LEASE = 'lease'.freeze
|
11
13
|
VISIBILITY_TEXT_VALUE_AUTHENTICATED = 'authenticated'.freeze
|
12
14
|
VISIBILITY_TEXT_VALUE_PRIVATE = 'restricted'.freeze
|
13
15
|
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module Hydra
|
2
|
+
module AccessControls
|
3
|
+
module Embargoable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include Hydra::AccessControls::WithAccessRight
|
6
|
+
|
7
|
+
included do
|
8
|
+
validates :embargo_release_date, :'hydra/future_date' => true
|
9
|
+
|
10
|
+
has_attributes :visibility_during_embargo, :visibility_after_embargo,
|
11
|
+
:visibility_during_lease, :visibility_after_lease, :lease_expiration_date,
|
12
|
+
:embargo_release_date,
|
13
|
+
datastream: 'rightsMetadata', multiple: false
|
14
|
+
|
15
|
+
has_attributes :embargo_history, :lease_history, datastream: 'rightsMetadata', multiple:true
|
16
|
+
end
|
17
|
+
|
18
|
+
def under_embargo?
|
19
|
+
@under_embargo ||= rightsMetadata.under_embargo?
|
20
|
+
end
|
21
|
+
|
22
|
+
def active_lease?
|
23
|
+
@active_lease ||= rightsMetadata.active_lease?
|
24
|
+
end
|
25
|
+
|
26
|
+
# If changing away from embargo or lease, this will deactivate the lease/embargo before proceeding.
|
27
|
+
# The lease_visibility! and embargo_visibility! methods rely on this to deactivate the lease when applicable.
|
28
|
+
def visibility=(value)
|
29
|
+
# If changing from embargo or lease, deactivate the lease/embargo and wipe out the associated metadata before proceeding
|
30
|
+
if !embargo_release_date.nil?
|
31
|
+
deactivate_embargo! unless value == visibility_during_embargo
|
32
|
+
end
|
33
|
+
if !lease_expiration_date.nil?
|
34
|
+
deactivate_lease! unless value == visibility_during_lease
|
35
|
+
end
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
def apply_embargo(release_date, visibility_during=nil, visibility_after=nil)
|
40
|
+
self.embargo_release_date = release_date
|
41
|
+
self.visibility_during_embargo = visibility_during unless visibility_during.nil?
|
42
|
+
self.visibility_after_embargo = visibility_after unless visibility_after.nil?
|
43
|
+
self.embargo_visibility!
|
44
|
+
end
|
45
|
+
|
46
|
+
def deactivate_embargo!
|
47
|
+
embargo_state = under_embargo? ? "active" : "expired"
|
48
|
+
embargo_record = "An #{embargo_state} embargo was deactivated on #{Date.today}. Its release date was #{embargo_release_date}. Visibility during embargo was #{visibility_during_embargo} and intended visibility after embargo was #{visibility_after_embargo}"
|
49
|
+
self.embargo_release_date = nil
|
50
|
+
self.visibility_during_embargo = nil
|
51
|
+
self.visibility_after_embargo = nil
|
52
|
+
self.embargo_history += [embargo_record]
|
53
|
+
end
|
54
|
+
|
55
|
+
def validate_embargo
|
56
|
+
if embargo_release_date
|
57
|
+
if under_embargo?
|
58
|
+
expected_visibility = visibility_during_embargo
|
59
|
+
failure_message = "An embargo is in effect for this object until #{embargo_release_date}. Until that time the "
|
60
|
+
else
|
61
|
+
expected_visibility = visibility_after_embargo
|
62
|
+
failure_message = "The embargo expired on #{embargo_release_date}. The "
|
63
|
+
end
|
64
|
+
if visibility == expected_visibility
|
65
|
+
return true
|
66
|
+
else
|
67
|
+
failure_message << "visibility should be #{expected_visibility} but it is currently #{visibility}. Call embargo_visibility! on this object to repair."
|
68
|
+
self.errors[:embargo] << failure_message
|
69
|
+
return false
|
70
|
+
end
|
71
|
+
else
|
72
|
+
return true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def embargo_visibility!
|
77
|
+
if embargo_release_date
|
78
|
+
if under_embargo?
|
79
|
+
self.visibility_during_embargo = visibility_during_embargo ? visibility_during_embargo : Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
80
|
+
self.visibility_after_embargo = visibility_after_embargo ? visibility_after_embargo : Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
|
81
|
+
self.visibility = visibility_during_embargo
|
82
|
+
else
|
83
|
+
self.visibility = visibility_after_embargo ? visibility_after_embargo : Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def validate_lease
|
89
|
+
if lease_expiration_date
|
90
|
+
if active_lease?
|
91
|
+
expected_visibility = visibility_during_lease
|
92
|
+
failure_message = "A lease is in effect for this object until #{lease_expiration_date}. Until that time the "
|
93
|
+
else
|
94
|
+
expected_visibility = visibility_after_lease
|
95
|
+
failure_message = "The lease expired on #{lease_expiration_date}. The "
|
96
|
+
end
|
97
|
+
if visibility == expected_visibility
|
98
|
+
return true
|
99
|
+
else
|
100
|
+
failure_message << "visibility should be #{expected_visibility} but it is currently #{visibility}. Call lease_visibility! on this object to repair."
|
101
|
+
self.errors[:lease] << failure_message
|
102
|
+
return false
|
103
|
+
end
|
104
|
+
else
|
105
|
+
return true
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def apply_lease(release_date, visibility_during=nil, visibility_after=nil)
|
110
|
+
self.lease_expiration_date = release_date
|
111
|
+
self.visibility_during_lease = visibility_during unless visibility_during.nil?
|
112
|
+
self.visibility_after_lease = visibility_after unless visibility_after.nil?
|
113
|
+
self.lease_visibility!
|
114
|
+
end
|
115
|
+
|
116
|
+
def deactivate_lease!
|
117
|
+
lease_state = active_lease? ? "active" : "expired"
|
118
|
+
lease_record = "An #{lease_state} lease was deactivated on #{Date.today}. Its release date was #{lease_expiration_date}. Visibility during the lease was #{visibility_during_lease} and intended visibility after lease was #{visibility_after_lease}."
|
119
|
+
self.lease_expiration_date = nil
|
120
|
+
self.visibility_during_lease = nil
|
121
|
+
self.visibility_after_lease = nil
|
122
|
+
self.lease_history += [lease_record]
|
123
|
+
end
|
124
|
+
|
125
|
+
def lease_visibility!
|
126
|
+
if lease_expiration_date
|
127
|
+
if active_lease?
|
128
|
+
self.visibility_during_lease = visibility_during_lease ? visibility_during_lease : Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
|
129
|
+
self.visibility_after_lease = visibility_after_lease ? visibility_after_lease : Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
130
|
+
self.visibility = visibility_during_lease
|
131
|
+
else
|
132
|
+
self.visibility = visibility_after_lease ? visibility_after_lease : Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -2,10 +2,7 @@ module Hydra
|
|
2
2
|
module AccessControls
|
3
3
|
module WithAccessRight
|
4
4
|
extend ActiveSupport::Concern
|
5
|
-
|
6
|
-
def under_embargo?
|
7
|
-
@under_embargo ||= rightsMetadata.under_embargo?
|
8
|
-
end
|
5
|
+
include Hydra::AccessControls::Permissions
|
9
6
|
|
10
7
|
delegate :open_access?, :open_access_with_embargo_release_date?,
|
11
8
|
:authenticated_only_access?, :private_access?, to: :access_rights
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Hydra
|
2
|
+
module EmbargoService
|
3
|
+
class << self
|
4
|
+
#
|
5
|
+
# Methods for Querying Repository to find Embargoed Objects
|
6
|
+
#
|
7
|
+
|
8
|
+
# Returns all assets with embargo release date set to a date in the past
|
9
|
+
def assets_with_expired_embargoes
|
10
|
+
ActiveFedora::Base.where("#{Hydra.config.permissions.embargo.release_date}:[* TO NOW]")
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns all assets with embargo release date set
|
14
|
+
# (assumes that when lease visibility is applied to assets
|
15
|
+
# whose leases have expired, the lease expiration date will be removed from its metadata)
|
16
|
+
def assets_under_embargo
|
17
|
+
ActiveFedora::Base.where("#{Hydra.config.permissions.embargo.release_date}:*")
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns all assets that have had embargoes deactivated in the past.
|
21
|
+
def assets_with_deactivated_embargoes
|
22
|
+
ActiveFedora::Base.where("#{Hydra.config.permissions.embargo.history}:*")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Hydra
|
2
|
+
module LeaseService
|
3
|
+
class << self
|
4
|
+
# Returns all assets with lease expiration date set to a date in the past
|
5
|
+
def assets_with_expired_leases
|
6
|
+
ActiveFedora::Base.where("#{Hydra.config.permissions.lease.expiration_date}:[* TO NOW]")
|
7
|
+
end
|
8
|
+
|
9
|
+
# Returns all assets with lease expiration date set
|
10
|
+
# (assumes that when lease visibility is applied to assets
|
11
|
+
# whose leases have expired, the lease expiration date will be removed from its metadata)
|
12
|
+
def assets_under_lease
|
13
|
+
ActiveFedora::Base.where("#{Hydra.config.permissions.lease.expiration_date}:*")
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns all assets that have had embargoes deactivated in the past.
|
17
|
+
def assets_with_deactivated_leases
|
18
|
+
ActiveFedora::Base.where("#{Hydra.config.permissions.lease.history}:*")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Hydra
|
2
|
+
class FutureDateValidator < ActiveModel::EachValidator
|
3
|
+
|
4
|
+
def validate_each(record, attribute, value)
|
5
|
+
if value.present?
|
6
|
+
begin
|
7
|
+
if date = value.to_date
|
8
|
+
if date <= Date.today
|
9
|
+
record.errors[:embargo_release_date] << "Must be a future date"
|
10
|
+
end
|
11
|
+
else
|
12
|
+
record.errors[:embargo_release_date] << "Invalid Date Format"
|
13
|
+
end
|
14
|
+
rescue ArgumentError, NoMethodError
|
15
|
+
record.errors[:embargo_release_date] << "Invalid Date Format"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/hydra/config.rb
CHANGED
@@ -35,7 +35,7 @@ module Hydra
|
|
35
35
|
end
|
36
36
|
|
37
37
|
class PermissionsConfig
|
38
|
-
attr_accessor :
|
38
|
+
attr_accessor :policy_class, :embargo, :lease
|
39
39
|
def initialize
|
40
40
|
@values = {}
|
41
41
|
[:discover, :read, :edit].each do |key|
|
@@ -43,7 +43,13 @@ module Hydra
|
|
43
43
|
group: solr_name("#{prefix}#{key}_access_group", :symbol),
|
44
44
|
individual: solr_name("#{prefix}#{key}_access_person", :symbol))
|
45
45
|
end
|
46
|
-
@
|
46
|
+
@embargo = EmbargoConfig.new({}, prefix: prefix)
|
47
|
+
@lease = LeaseConfig.new({}, prefix: prefix)
|
48
|
+
end
|
49
|
+
|
50
|
+
def embargo_release_date
|
51
|
+
Deprecation.warn PermissionsConfig, "embargo_release_date is deprecated, use embargo.release_date instead"
|
52
|
+
embargo.release_date
|
47
53
|
end
|
48
54
|
|
49
55
|
def merge! values
|
@@ -54,14 +60,17 @@ module Hydra
|
|
54
60
|
case key
|
55
61
|
when :discover, :read, :edit
|
56
62
|
self.assign_value key, value
|
63
|
+
when :inheritable
|
64
|
+
inheritable.merge! value
|
57
65
|
when :embargo_release_date
|
58
|
-
|
66
|
+
Deprecation.warn PermissionsConfig, "[:embargo_release_date]= is deprecated, use embargo.release_date= instead"
|
67
|
+
embargo.release_date = value
|
59
68
|
when :policy_class
|
60
69
|
self.policy_class = value
|
61
70
|
when :owner
|
62
71
|
logger.warn "':owner' is no longer a valid configuration for Hydra. Please remove it from your configuration."
|
63
72
|
else
|
64
|
-
raise "Unknown key"
|
73
|
+
raise "Unknown key `#{key.inspect}`"
|
65
74
|
end
|
66
75
|
end
|
67
76
|
|
@@ -72,7 +81,8 @@ module Hydra
|
|
72
81
|
when :inheritable
|
73
82
|
inheritable
|
74
83
|
when :embargo_release_date
|
75
|
-
|
84
|
+
Deprecation.warn PermissionsConfig, "[:embargo_release_date] is deprecated, use embargo.release_date= instead"
|
85
|
+
embargo.release_date
|
76
86
|
when :policy_class
|
77
87
|
@policy_class
|
78
88
|
else
|
@@ -121,6 +131,33 @@ module Hydra
|
|
121
131
|
ActiveFedora::SolrService.solr_name(*args)
|
122
132
|
end
|
123
133
|
|
134
|
+
class EmbargoConfig
|
135
|
+
attr_accessor :release_date, :visibility_during, :visibility_after, :history
|
136
|
+
def initialize(values = {}, attributes={prefix:''})
|
137
|
+
@release_date = solr_name("#{attributes[:prefix]}embargo_release_date", :stored_sortable, type: :date)
|
138
|
+
@visibility_during = solr_name("visibility_during_embargo", :symbol)
|
139
|
+
@visibility_after = solr_name("visibility_after_embargo", :symbol)
|
140
|
+
@history = solr_name("embargo_history", :symbol)
|
141
|
+
end
|
142
|
+
|
143
|
+
def solr_name(*args)
|
144
|
+
ActiveFedora::SolrService.solr_name(*args)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class LeaseConfig
|
149
|
+
attr_accessor :expiration_date, :visibility_during, :visibility_after, :history
|
150
|
+
def initialize(values = {}, attributes={prefix:''})
|
151
|
+
@expiration_date = solr_name("#{attributes[:prefix]}lease_expiration_date", :stored_sortable, type: :date)
|
152
|
+
@visibility_during = solr_name("visibility_during_lease", :symbol)
|
153
|
+
@visibility_after = solr_name("visibility_after_lease", :symbol)
|
154
|
+
@history = solr_name("lease_history", :symbol)
|
155
|
+
end
|
156
|
+
|
157
|
+
def solr_name(*args)
|
158
|
+
ActiveFedora::SolrService.solr_name(*args)
|
159
|
+
end
|
160
|
+
end
|
124
161
|
|
125
162
|
class GroupPermission
|
126
163
|
attr_accessor :group, :individual
|
@@ -11,7 +11,10 @@ module Hydra
|
|
11
11
|
solr_doc[Hydra.config[:permissions][:inheritable][access][:group]] = send("#{access}_access").machine.group
|
12
12
|
solr_doc[Hydra.config[:permissions][:inheritable][access][:individual]] = send("#{access}_access").machine.person
|
13
13
|
end
|
14
|
-
|
14
|
+
if embargo_release_date.present?
|
15
|
+
key = Hydra.config.permissions.inheritable.embargo.release_date.sub(/_[^_]+$/, '') #Strip off the suffix
|
16
|
+
::Solrizer.insert_field(solr_doc, key, embargo_release_date, :stored_sortable)
|
17
|
+
end
|
15
18
|
return solr_doc
|
16
19
|
end
|
17
20
|
end
|
@@ -40,14 +40,38 @@ module Hydra
|
|
40
40
|
# t.access_group(:proxy=>[:access,:machine,:group])
|
41
41
|
|
42
42
|
t.embargo {
|
43
|
-
t.human_readable(:
|
43
|
+
t.human_readable(path: "human")
|
44
|
+
t.machine{
|
45
|
+
t.date(type: :time, attributes: {type: "release"})
|
46
|
+
t.date_deactivated(type: "deactivated")
|
47
|
+
t.visibility_during(path: "visibility", attributes: {scope: 'during'})
|
48
|
+
t.visibility_after(path: "visibility", attributes: {scope: 'after'})
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
t.lease {
|
53
|
+
t.human_readable(path: "human")
|
44
54
|
t.machine{
|
45
|
-
t.date(:type
|
55
|
+
t.date(type: :time, attributes: {type: "expire"})
|
56
|
+
t.date_deactivated(type: :time, attributes: {type: "deactivated"})
|
57
|
+
t.visibility_during(path: "visibility", attributes: {scope: 'during'})
|
58
|
+
t.visibility_after(path: "visibility", attributes: {scope: 'after'})
|
46
59
|
}
|
47
|
-
|
48
|
-
}
|
60
|
+
}
|
49
61
|
|
50
62
|
t.license(:ref=>[:copyright])
|
63
|
+
|
64
|
+
t.visibility_during_embargo ref: [:embargo, :machine, :visibility_during]
|
65
|
+
t.visibility_after_embargo ref: [:embargo, :machine, :visibility_after]
|
66
|
+
t.visibility_during_lease ref: [:lease, :machine, :visibility_during]
|
67
|
+
t.visibility_after_lease ref: [:lease, :machine, :visibility_after]
|
68
|
+
t.embargo_history ref: [:embargo, :human_readable]
|
69
|
+
t.lease_history ref: [:lease, :human_readable]
|
70
|
+
t.embargo_release_date ref: [:embargo, :machine, :date], type: :time
|
71
|
+
t.embargo_deactivation_date ref: [:embargo, :machine, :date_deactivated]
|
72
|
+
t.lease_expiration_date ref: [:lease, :machine, :date], type: :time
|
73
|
+
t.lease_deactivation_date ref: [:lease, :machine, :date_deactivated]
|
74
|
+
|
51
75
|
end
|
52
76
|
|
53
77
|
# Generates an empty Mods Article (used when you call ModsArticle.new without passing in existing xml)
|
@@ -75,7 +99,11 @@ module Hydra
|
|
75
99
|
xml.embargo{
|
76
100
|
xml.human
|
77
101
|
xml.machine
|
78
|
-
}
|
102
|
+
}
|
103
|
+
xml.lease{
|
104
|
+
xml.human
|
105
|
+
xml.machine
|
106
|
+
}
|
79
107
|
}
|
80
108
|
end
|
81
109
|
return builder.doc
|
@@ -172,37 +200,35 @@ module Hydra
|
|
172
200
|
return result
|
173
201
|
end
|
174
202
|
|
175
|
-
attr_reader :embargo_release_date
|
176
|
-
def embargo_release_date=(release_date)
|
177
|
-
release_date = release_date.to_s if release_date.is_a? Date
|
178
|
-
begin
|
179
|
-
release_date.nil? || Date.parse(release_date)
|
180
|
-
rescue
|
181
|
-
return "INVALID DATE"
|
182
|
-
end
|
183
|
-
self.update_values({[:embargo,:machine,:date]=>release_date})
|
184
|
-
end
|
185
|
-
def embargo_release_date(opts={})
|
186
|
-
embargo_release_date = self.find_by_terms(*[:embargo,:machine,:date]).first ? self.find_by_terms(*[:embargo,:machine,:date]).first.text : nil
|
187
|
-
if embargo_release_date.present? && opts[:format] && opts[:format] == :solr_date
|
188
|
-
embargo_release_date << "T23:59:59Z"
|
189
|
-
end
|
190
|
-
embargo_release_date
|
191
|
-
end
|
192
203
|
def under_embargo?
|
193
|
-
(embargo_release_date && Date.today < embargo_release_date.
|
204
|
+
(embargo_release_date.present? && Date.today < embargo_release_date.first) ? true : false
|
205
|
+
end
|
206
|
+
|
207
|
+
def active_lease?
|
208
|
+
lease_expiration_date.present? && Date.today < lease_expiration_date.first
|
194
209
|
end
|
195
210
|
|
196
211
|
def to_solr(solr_doc=Hash.new)
|
197
212
|
[:discover, :read, :edit].each do |access|
|
198
213
|
vals = send("#{access}_access").machine.group
|
199
|
-
solr_doc[Hydra.config
|
214
|
+
solr_doc[Hydra.config.permissions[access].group] = vals unless vals.empty?
|
200
215
|
vals = send("#{access}_access").machine.person
|
201
|
-
solr_doc[Hydra.config
|
216
|
+
solr_doc[Hydra.config.permissions[access].individual] = vals unless vals.empty?
|
217
|
+
end
|
218
|
+
if embargo_release_date.present?
|
219
|
+
key = Hydra.config.permissions.embargo.release_date.sub(/_[^_]+$/, '') #Strip off the suffix
|
220
|
+
::Solrizer.insert_field(solr_doc, key, embargo_release_date, :stored_sortable)
|
202
221
|
end
|
203
|
-
if
|
204
|
-
|
222
|
+
if lease_expiration_date.present?
|
223
|
+
key = Hydra.config.permissions.lease.expiration_date.sub(/_[^_]+$/, '') #Strip off the suffix
|
224
|
+
::Solrizer.insert_field(solr_doc, key, lease_expiration_date, :stored_sortable)
|
205
225
|
end
|
226
|
+
solr_doc[::Solrizer.solr_name("visibility_during_embargo", :symbol)] = visibility_during_embargo unless visibility_during_embargo.nil?
|
227
|
+
solr_doc[::Solrizer.solr_name("visibility_after_embargo", :symbol)] = visibility_after_embargo unless visibility_after_embargo.nil?
|
228
|
+
solr_doc[::Solrizer.solr_name("visibility_during_lease", :symbol)] = visibility_during_lease unless visibility_during_lease.nil?
|
229
|
+
solr_doc[::Solrizer.solr_name("visibility_after_lease", :symbol)] = visibility_after_lease unless visibility_after_lease.nil?
|
230
|
+
solr_doc[::Solrizer.solr_name("embargo_history", :symbol)] = embargo_history unless embargo_history.nil?
|
231
|
+
solr_doc[::Solrizer.solr_name("lease_history", :symbol)] = lease_history unless lease_history.nil?
|
206
232
|
solr_doc
|
207
233
|
end
|
208
234
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::EmbargoService do
|
4
|
+
let(:future_date) { 2.days.from_now }
|
5
|
+
let(:past_date) { 2.days.ago }
|
6
|
+
|
7
|
+
let!(:work_with_expired_embargo1) do
|
8
|
+
FactoryGirl.build(:asset, embargo_release_date: past_date.to_s).tap do |work|
|
9
|
+
work.save(validate:false)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let!(:work_with_expired_embargo2) do
|
14
|
+
FactoryGirl.build(:asset, embargo_release_date: past_date.to_s).tap do |work|
|
15
|
+
work.save(validate:false)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
let!(:work_with_embargo_in_effect) { FactoryGirl.create(:asset, embargo_release_date: future_date.to_s)}
|
20
|
+
let!(:work_without_embargo) { FactoryGirl.create(:asset)}
|
21
|
+
|
22
|
+
describe "#assets_with_expired_embargoes" do
|
23
|
+
it "returns an array of assets with expired embargoes" do
|
24
|
+
returned_pids = subject.assets_with_expired_embargoes.map {|a| a.pid}
|
25
|
+
expect(returned_pids).to include work_with_expired_embargo1.pid,work_with_expired_embargo2.pid
|
26
|
+
expect(returned_pids).to_not include work_with_embargo_in_effect.pid,work_without_embargo.pid
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#assets_under_embargo" do
|
31
|
+
it "returns all assets with embargo release date set" do
|
32
|
+
result = subject.assets_under_embargo
|
33
|
+
returned_pids = subject.assets_under_embargo.map {|a| a.pid}
|
34
|
+
expect(returned_pids).to include work_with_expired_embargo1.pid,work_with_expired_embargo2.pid,work_with_embargo_in_effect.pid
|
35
|
+
expect(returned_pids).to_not include work_without_embargo.pid
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::LeaseService do
|
4
|
+
let(:future_date) { 2.days.from_now }
|
5
|
+
let(:past_date) { 2.days.ago }
|
6
|
+
|
7
|
+
let!(:work_with_expired_lease1) do
|
8
|
+
FactoryGirl.build(:asset, lease_expiration_date: past_date.to_s).tap do |work|
|
9
|
+
work.save(validate: false)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let!(:work_with_expired_lease2) do
|
14
|
+
FactoryGirl.build(:asset, lease_expiration_date: past_date.to_s).tap do |work|
|
15
|
+
work.save(validate: false)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
let!(:work_with_lease_in_effect) { FactoryGirl.create(:asset, lease_expiration_date: future_date.to_s)}
|
20
|
+
let!(:work_without_lease) { FactoryGirl.create(:asset)}
|
21
|
+
|
22
|
+
describe "#assets_with_expired_leases" do
|
23
|
+
it "returns an array of assets with expired embargoes" do
|
24
|
+
returned_pids = subject.assets_with_expired_leases.map {|a| a.pid}
|
25
|
+
expect(returned_pids).to include work_with_expired_lease1.pid,work_with_expired_lease2.pid
|
26
|
+
expect(returned_pids).to_not include work_with_lease_in_effect.pid,work_without_lease.pid
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#assets_under_lease" do
|
31
|
+
it "returns an array of assets with expired embargoes" do
|
32
|
+
returned_pids = subject.assets_under_lease.map {|a| a.pid}
|
33
|
+
expect(returned_pids).to include work_with_expired_lease1.pid,work_with_expired_lease2.pid,work_with_lease_in_effect.pid
|
34
|
+
expect(returned_pids).to_not include work_without_lease.pid
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -16,11 +16,6 @@ if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.9/
|
|
16
16
|
SimpleCov.start
|
17
17
|
end
|
18
18
|
|
19
|
-
require 'support/mods_asset'
|
20
|
-
require 'support/solr_document'
|
21
|
-
require "support/user"
|
22
|
-
require "factory_girl"
|
23
|
-
require "factories"
|
24
19
|
|
25
20
|
require 'support/rails'
|
26
21
|
Object.logger = Logger.new(File.expand_path('../test.log', __FILE__))
|
@@ -28,18 +23,20 @@ Object.logger = Logger.new(File.expand_path('../test.log', __FILE__))
|
|
28
23
|
# Since we're not doing a Rails Engine test, we have to load these classes manually:
|
29
24
|
require_relative '../app/models/role_mapper'
|
30
25
|
require_relative '../app/models/ability'
|
31
|
-
|
26
|
+
require_relative '../app/services/hydra/lease_service'
|
27
|
+
require_relative '../app/services/hydra/embargo_service'
|
28
|
+
require_relative '../app/validators/hydra/future_date_validator'
|
29
|
+
require 'support/mods_asset'
|
30
|
+
require 'support/solr_document'
|
31
|
+
require "support/user"
|
32
|
+
require "factory_girl"
|
33
|
+
require "factories"
|
32
34
|
|
33
35
|
|
34
36
|
RSpec.configure do |config|
|
35
37
|
|
36
38
|
end
|
37
39
|
|
38
|
-
# Stubbing a deprecated class/method so it won't mess up tests.
|
39
|
-
class Hydra::SuperuserAttributes
|
40
|
-
cattr_accessor :silenced
|
41
|
-
end
|
42
|
-
|
43
40
|
# Stubbing Devise
|
44
41
|
class Devise
|
45
42
|
def self.authentication_keys
|
data/spec/support/mods_asset.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
require 'active-fedora'
|
2
1
|
class ModsAsset < ActiveFedora::Base
|
3
|
-
include Hydra::AccessControls::
|
2
|
+
include Hydra::AccessControls::Embargoable
|
4
3
|
|
5
4
|
# This is how we're associating admin policies with assets.
|
6
5
|
# You can associate them however you want, just use the :is_governed_by relationship
|
7
|
-
belongs_to :admin_policy, :
|
6
|
+
belongs_to :admin_policy, class_name: "Hydra::AdminPolicy", property: :is_governed_by
|
8
7
|
end
|
@@ -94,7 +94,7 @@ describe Hydra::AccessControlsEnforcement do
|
|
94
94
|
subject.params = {}
|
95
95
|
subject.should_receive(:can?).with(:edit, stub_doc).and_return(true)
|
96
96
|
subject.current_ability.should_receive(:get_permissions_solr_response_for_doc_id).and_return(stub_doc)
|
97
|
-
|
97
|
+
expect {subject.send(:enforce_show_permissions, {}) }.not_to raise_error Hydra::AccessDenied
|
98
98
|
end
|
99
99
|
it "should prevent a user w/o edit permissions from viewing an embargoed object" do
|
100
100
|
user = User.new :uid=>'testuser@example.com'
|
@@ -98,7 +98,7 @@ describe Hydra::AdminPolicy do
|
|
98
98
|
subject[inheritable_group].should include("africana-faculty", "cool-kids")
|
99
99
|
|
100
100
|
subject[Hydra.config[:permissions][:inheritable][:edit][:individual] ].should == ["julius_caesar"]
|
101
|
-
subject[Hydra.config[:permissions][:inheritable][:embargo_release_date] ].
|
101
|
+
expect(subject[Hydra.config[:permissions][:inheritable][:embargo_release_date] ]).to eq Date.parse("2102-10-01").to_time.utc.iso8601
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
data/spec/unit/config_spec.rb
CHANGED
@@ -42,6 +42,7 @@ describe Hydra::Config do
|
|
42
42
|
it "should have defaults" do
|
43
43
|
config.permissions.read.individual.should == 'read_access_person_ssim'
|
44
44
|
config.permissions.embargo_release_date.should == 'embargo_release_date_dtsi'
|
45
|
+
config.permissions.embargo.release_date.should == 'embargo_release_date_dtsi'
|
45
46
|
config.user_model.should == 'User'
|
46
47
|
end
|
47
48
|
|
@@ -0,0 +1,287 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hydra::AccessControls::Embargoable do
|
4
|
+
|
5
|
+
let(:model) {
|
6
|
+
Class.new(ActiveFedora::Base) {
|
7
|
+
def save(returning_value = true)
|
8
|
+
valid? && run_callbacks(:save) && !!returning_value
|
9
|
+
end
|
10
|
+
|
11
|
+
include Hydra::AccessControls::Embargoable
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
let(:future_date) { Date.today+2 }
|
16
|
+
let(:past_date) { Date.today-2 }
|
17
|
+
let(:persistence) {
|
18
|
+
subject.rightsMetadata
|
19
|
+
}
|
20
|
+
|
21
|
+
subject { model.new }
|
22
|
+
|
23
|
+
context 'visibility=' do
|
24
|
+
it "when changing from embargo, wipes out associated embargo metadata" do
|
25
|
+
subject.embargo_release_date = future_date.to_s
|
26
|
+
expect(subject).to receive(:deactivate_embargo!)
|
27
|
+
subject.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
28
|
+
end
|
29
|
+
it "when changing from lease, wipes out associated lease metadata" do
|
30
|
+
subject.lease_expiration_date = future_date.to_s
|
31
|
+
expect(subject).to receive(:deactivate_lease!)
|
32
|
+
subject.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
33
|
+
end
|
34
|
+
end
|
35
|
+
context 'apply_embargo' do
|
36
|
+
it "applies appropriate embargo_visibility settings" do
|
37
|
+
subject.apply_embargo(future_date.to_s, Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE, Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC)
|
38
|
+
expect(subject).to be_under_embargo
|
39
|
+
expect(subject.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
40
|
+
expect(subject.embargo_release_date).to eq future_date.to_time.utc
|
41
|
+
expect(subject.visibility_after_embargo).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
42
|
+
end
|
43
|
+
it "relies on default before/after visibility if none provided" do
|
44
|
+
subject.apply_embargo(future_date.to_s)
|
45
|
+
expect(subject).to be_under_embargo
|
46
|
+
expect(subject.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
47
|
+
expect(subject.embargo_release_date).to eq future_date.to_time.utc
|
48
|
+
expect(subject.visibility_after_embargo).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
|
49
|
+
end
|
50
|
+
end
|
51
|
+
context 'deactivate_embargo!' do
|
52
|
+
it "should remove the associated embargo information and record it in the object's embargo history" do
|
53
|
+
subject.embargo_release_date = past_date.to_s
|
54
|
+
subject.visibility_during_embargo = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
55
|
+
subject.visibility_after_embargo = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
56
|
+
subject.deactivate_embargo!
|
57
|
+
expect(subject.embargo_release_date).to be_nil
|
58
|
+
expect(subject.visibility_during_embargo).to be_nil
|
59
|
+
expect(subject.visibility_after_embargo).to be_nil
|
60
|
+
expect(subject.embargo_history.last).to include("An expired embargo was deactivated on #{Date.today}.")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'apply_lease' do
|
65
|
+
it "applies appropriate embargo_visibility settings" do
|
66
|
+
subject.apply_lease(future_date.to_s, Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC, Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE)
|
67
|
+
expect(subject).to be_active_lease
|
68
|
+
expect(subject.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
69
|
+
expect(subject.lease_expiration_date).to eq future_date.to_time.utc
|
70
|
+
expect(subject.visibility_after_lease).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
71
|
+
end
|
72
|
+
it "relies on default before/after visibility if none provided" do
|
73
|
+
subject.apply_lease(future_date.to_s)
|
74
|
+
expect(subject.visibility_during_lease).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
|
75
|
+
expect(subject.lease_expiration_date).to eq future_date.to_time.utc
|
76
|
+
expect(subject.visibility_after_lease).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'deactivate_lease!' do
|
81
|
+
it "should remove the associated embargo information and record it in the object's embargo history" do
|
82
|
+
subject.lease_expiration_date = past_date.to_s
|
83
|
+
subject.visibility_during_lease = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
84
|
+
subject.visibility_after_lease = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
85
|
+
subject.deactivate_lease!
|
86
|
+
expect(subject.lease_expiration_date).to be_nil
|
87
|
+
expect(subject.visibility_during_lease).to be_nil
|
88
|
+
expect(subject.visibility_after_lease).to be_nil
|
89
|
+
expect(subject.lease_history.last).to include("An expired lease was deactivated on #{Date.today}.")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'under_embargo?' do
|
94
|
+
context "when embargo date is past" do
|
95
|
+
it "should return false" do
|
96
|
+
subject.embargo_release_date = past_date.to_s
|
97
|
+
expect(subject).to_not be_under_embargo
|
98
|
+
end
|
99
|
+
end
|
100
|
+
context "when embargo date is in future" do
|
101
|
+
it "should return true" do
|
102
|
+
subject.embargo_release_date = future_date.to_s
|
103
|
+
expect(subject).to be_under_embargo
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context 'validate_embargo' do
|
109
|
+
before do
|
110
|
+
subject.visibility_during_embargo = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
111
|
+
subject.visibility_after_embargo = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
112
|
+
end
|
113
|
+
context "(embargo still in effect)" do
|
114
|
+
it 'returns true if current visibility matches visibility_during_embargo' do
|
115
|
+
subject.visibility = subject.visibility_during_embargo
|
116
|
+
subject.embargo_release_date = future_date.to_s
|
117
|
+
expect(subject.validate_embargo).to be true
|
118
|
+
end
|
119
|
+
it 'records a failures in record.errors[:embargo]' do
|
120
|
+
subject.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
|
121
|
+
subject.embargo_release_date = future_date.to_s
|
122
|
+
expect(subject.validate_embargo).to be false
|
123
|
+
expect(subject.errors[:embargo].first).to eq "An embargo is in effect for this object until #{subject.embargo_release_date}. Until that time the visibility should be #{Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE} but it is currently #{Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED}. Call embargo_visibility! on this object to repair."
|
124
|
+
end
|
125
|
+
end
|
126
|
+
context "(embargo expired)" do
|
127
|
+
it 'returns true if current visibility matches visibility_after_embargo' do
|
128
|
+
subject.visibility = subject.visibility_after_embargo
|
129
|
+
subject.embargo_release_date = past_date.to_s
|
130
|
+
expect(subject.validate_embargo).to be true
|
131
|
+
end
|
132
|
+
it '(embargo expired) records a failures in record.errors[:embargo]' do
|
133
|
+
subject.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
134
|
+
subject.embargo_release_date = past_date.to_s
|
135
|
+
expect(subject.validate_embargo).to be false
|
136
|
+
expect(subject.errors[:embargo].first).to eq "The embargo expired on #{subject.embargo_release_date}. The visibility should be #{Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC} but it is currently #{Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE}. Call embargo_visibility! on this object to repair."
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
context 'embargo_visibility!' do
|
143
|
+
let(:future_date) { 2.days.from_now }
|
144
|
+
let(:past_date) { 2.days.ago }
|
145
|
+
before do
|
146
|
+
subject.visibility_during_embargo = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
147
|
+
subject.visibility_after_embargo = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
148
|
+
end
|
149
|
+
context 'when embargo expired' do
|
150
|
+
it 'applies visibility_after_embargo and calls after_apply_embargo' do
|
151
|
+
subject.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
152
|
+
subject.embargo_release_date = past_date.to_s
|
153
|
+
expect(subject).to receive(:deactivate_embargo!)
|
154
|
+
subject.embargo_visibility!
|
155
|
+
expect(subject.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
156
|
+
end
|
157
|
+
it "defaults to private if visibility_after_embargo is not set" do
|
158
|
+
subject.visibility_after_embargo = nil
|
159
|
+
subject.embargo_release_date = past_date.to_s
|
160
|
+
subject.embargo_visibility!
|
161
|
+
expect(subject.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
|
162
|
+
end
|
163
|
+
end
|
164
|
+
context 'when embargo still in effect' do
|
165
|
+
it 'applies visibility_during_embargo' do
|
166
|
+
subject.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
167
|
+
subject.embargo_release_date = future_date.to_s
|
168
|
+
expect(subject).to_not receive(:deactivate_embargo!)
|
169
|
+
subject.embargo_visibility!
|
170
|
+
expect(subject.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
171
|
+
end
|
172
|
+
it 'sets before/after visibility to defaults if none provided' do
|
173
|
+
subject.visibility_during_embargo = nil
|
174
|
+
subject.visibility_after_embargo = nil
|
175
|
+
subject.embargo_release_date = future_date.to_s
|
176
|
+
subject.embargo_visibility!
|
177
|
+
expect(subject.visibility_during_embargo).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
178
|
+
expect(subject.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
179
|
+
expect(subject.visibility_after_embargo).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context 'validate_lease' do
|
185
|
+
let(:future_date) { 2.days.from_now }
|
186
|
+
let(:past_date) { 2.days.ago }
|
187
|
+
before do
|
188
|
+
subject.visibility_during_lease = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
189
|
+
subject.visibility_after_lease = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
190
|
+
end
|
191
|
+
context "(lease expired)" do
|
192
|
+
it 'returns true if current visibility matches visibility_after_lease' do
|
193
|
+
subject.visibility = subject.visibility_after_lease
|
194
|
+
subject.lease_expiration_date = past_date.to_s
|
195
|
+
expect(subject.validate_lease).to be true
|
196
|
+
end
|
197
|
+
it 'records a failures in record.errors[:lease]' do
|
198
|
+
subject.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
199
|
+
subject.lease_expiration_date = past_date.to_s
|
200
|
+
expect(subject.validate_lease).to be false
|
201
|
+
expect(subject.errors[:lease].first).to eq "The lease expired on #{subject.lease_expiration_date}. The visibility should be #{Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE} but it is currently #{Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC}. Call lease_visibility! on this object to repair."
|
202
|
+
end
|
203
|
+
end
|
204
|
+
context "(lease still in effect)" do
|
205
|
+
it 'returns true if current visibility matches visibility_during_embargo' do
|
206
|
+
subject.visibility = subject.visibility_during_lease
|
207
|
+
subject.lease_expiration_date = future_date.to_s
|
208
|
+
expect(subject.validate_lease).to be true
|
209
|
+
end
|
210
|
+
it 'records a failures in record.errors[:lease]' do
|
211
|
+
subject.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
|
212
|
+
subject.lease_expiration_date = future_date.to_s
|
213
|
+
expect(subject.validate_lease).to be false
|
214
|
+
expect(subject.errors[:lease].first).to eq "A lease is in effect for this object until #{subject.lease_expiration_date}. Until that time the visibility should be #{Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC} but it is currently #{Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED}. Call lease_visibility! on this object to repair."
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
context 'lease_visibility!' do
|
222
|
+
before do
|
223
|
+
subject.visibility_during_lease = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
224
|
+
subject.visibility_after_lease = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
225
|
+
end
|
226
|
+
context 'when lease expired' do
|
227
|
+
it 'applies visibility_after_lease and calls after_apply_lease' do
|
228
|
+
subject.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
229
|
+
subject.lease_expiration_date = past_date.to_s
|
230
|
+
expect(subject).to receive(:deactivate_lease!)
|
231
|
+
subject.lease_visibility!
|
232
|
+
expect(subject.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
233
|
+
end
|
234
|
+
it "defaults to private if visibility_after_lease is not set" do
|
235
|
+
subject.visibility_after_lease = nil
|
236
|
+
subject.lease_expiration_date = past_date.to_s
|
237
|
+
subject.lease_visibility!
|
238
|
+
expect(subject.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
239
|
+
end
|
240
|
+
end
|
241
|
+
context 'when lease still in effect' do
|
242
|
+
it 'applies visibility_during_lease and calls after_apply_lease' do
|
243
|
+
subject.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
244
|
+
subject.lease_expiration_date = future_date.to_s
|
245
|
+
expect(subject).to_not receive(:deactivate_lease!)
|
246
|
+
subject.lease_visibility!
|
247
|
+
expect(subject.visibility).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC
|
248
|
+
end
|
249
|
+
it 'sets before/after visibility to defaults if none provided' do
|
250
|
+
subject.visibility_during_lease = nil
|
251
|
+
subject.visibility_after_lease = nil
|
252
|
+
subject.lease_expiration_date = future_date.to_s
|
253
|
+
subject.lease_visibility!
|
254
|
+
expect(subject.visibility_during_lease).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED
|
255
|
+
expect(subject.visibility_after_lease).to eq Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
|
261
|
+
context 'persistence' do
|
262
|
+
let(:the_date) { 2.days.from_now }
|
263
|
+
|
264
|
+
it 'persists a date object' do
|
265
|
+
subject.embargo_release_date = the_date
|
266
|
+
expect(persistence.embargo_release_date.first).to be_kind_of DateTime
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'persists a valid string' do
|
270
|
+
subject.embargo_release_date = the_date.to_s
|
271
|
+
expect(persistence.embargo_release_date.first).to be_kind_of DateTime
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'raises an error on an empty string' do
|
275
|
+
expect {
|
276
|
+
subject.embargo_release_date = ''
|
277
|
+
}.to raise_error OM::TypeMismatch
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'does not persist an invalid string' do
|
281
|
+
expect {
|
282
|
+
subject.embargo_release_date = "Tim"
|
283
|
+
}.to raise_error OM::TypeMismatch
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
@@ -114,7 +114,7 @@ describe Hydra::Datastream::RightsMetadata do
|
|
114
114
|
it "should return a hash of all individuals with permissions set, along with their permission levels" do
|
115
115
|
@sample.permissions({"person"=>"person_123"}, "read")
|
116
116
|
@sample.permissions({"person"=>"person_456"}, "edit")
|
117
|
-
@sample.
|
117
|
+
expect(@sample.users).to eq("person_123"=>"read", "person_456"=>"edit")
|
118
118
|
end
|
119
119
|
end
|
120
120
|
|
@@ -140,8 +140,8 @@ describe Hydra::Datastream::RightsMetadata do
|
|
140
140
|
end
|
141
141
|
it "clears permissions" do
|
142
142
|
@sample.clear_permissions!
|
143
|
-
@sample.
|
144
|
-
@sample.groups.
|
143
|
+
expect(@sample.users).to eq({})
|
144
|
+
expect(@sample.groups).to eq({})
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
@@ -167,44 +167,113 @@ describe Hydra::Datastream::RightsMetadata do
|
|
167
167
|
solr_doc["read_access_group_ssim"].should == ["public"]
|
168
168
|
solr_doc["discover_access_group_ssim"].should == ["bob"]
|
169
169
|
end
|
170
|
+
|
171
|
+
it "should solrize embargo information if set" do
|
172
|
+
@sample.embargo_release_date = DateTime.parse("2010-12-01T23:59:59+0")
|
173
|
+
solr_doc = @sample.to_solr
|
174
|
+
expect(solr_doc["embargo_release_date_dtsi"]).to eq "2010-12-01T23:59:59Z"
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should solrize lease information if set" do
|
178
|
+
@sample.lease_expiration_date = DateTime.parse("2010-12-01T23:59:59Z")
|
179
|
+
solr_doc = @sample.to_solr
|
180
|
+
expect(solr_doc["lease_expiration_date_dtsi"]).to eq "2010-12-01T23:59:59Z"
|
181
|
+
end
|
170
182
|
end
|
183
|
+
|
184
|
+
#
|
185
|
+
# Embargo
|
186
|
+
#
|
171
187
|
describe "embargo_release_date=" do
|
172
188
|
it "should update the appropriate node with the value passed" do
|
173
|
-
@sample.embargo_release_date=("2010-12-01")
|
174
|
-
@sample.embargo_release_date.
|
175
|
-
end
|
176
|
-
it "should only accept valid date values" do
|
177
|
-
|
189
|
+
@sample.embargo_release_date = Date.parse("2010-12-01")
|
190
|
+
expect(@sample.embargo_release_date).to eq [Date.parse("2010-12-01").to_time.utc]
|
178
191
|
end
|
179
192
|
it "should accept a nil value after having a date value" do
|
180
|
-
@sample.embargo_release_date=("2010-12-01")
|
181
|
-
@sample.embargo_release_date=
|
182
|
-
@sample.embargo_release_date.
|
193
|
+
@sample.embargo_release_date = Date.parse("2010-12-01")
|
194
|
+
@sample.embargo_release_date = nil
|
195
|
+
expect(@sample.embargo_release_date).to be_empty
|
183
196
|
end
|
184
197
|
end
|
198
|
+
|
185
199
|
describe "embargo_release_date" do
|
186
200
|
it "should return solr formatted date" do
|
187
|
-
@sample.embargo_release_date=("2010-12-
|
188
|
-
@sample.embargo_release_date
|
189
|
-
end
|
190
|
-
|
191
|
-
# this test was returning '' under 1.9 and returning nil under ree and 1.8.7
|
192
|
-
it "should not return anything if the date is empty string" do
|
193
|
-
@sample.update_values({[:embargo,:machine,:date]=>''})
|
194
|
-
@sample.embargo_release_date(:format=>:solr_date).should be_blank
|
201
|
+
@sample.embargo_release_date = DateTime.parse("2010-12-01T23:59:59Z")
|
202
|
+
expect(@sample.embargo_release_date).to eq [DateTime.parse("2010-12-01T23:59:59Z")]
|
195
203
|
end
|
196
204
|
end
|
205
|
+
|
197
206
|
describe "under_embargo?" do
|
198
207
|
it "should return true if the current date is before the embargo release date" do
|
199
208
|
@sample.embargo_release_date=Date.today+1.month
|
200
|
-
@sample.
|
209
|
+
expect(@sample).to be_under_embargo
|
201
210
|
end
|
202
211
|
it "should return false if the current date is after the embargo release date" do
|
203
212
|
@sample.embargo_release_date=Date.today-1.month
|
204
|
-
@sample.
|
213
|
+
expect(@sample).to_not be_under_embargo
|
205
214
|
end
|
206
215
|
it "should return false if there is no embargo date" do
|
207
|
-
@sample.
|
216
|
+
@sample.embargo_release_date = nil
|
217
|
+
expect(@sample).to_not be_under_embargo
|
218
|
+
end
|
219
|
+
end
|
220
|
+
describe "visibility during/after embargo" do
|
221
|
+
it "should track visibility values and index them into solr" do
|
222
|
+
expect(@sample.visibility_during_embargo).to be_empty
|
223
|
+
expect(@sample.visibility_after_embargo).to be_empty
|
224
|
+
@sample.visibility_during_embargo = "private"
|
225
|
+
@sample.visibility_after_embargo = "restricted"
|
226
|
+
expect(@sample.visibility_during_embargo).to eq ["private"]
|
227
|
+
expect(@sample.visibility_after_embargo).to eq ["restricted"]
|
228
|
+
solr_doc = @sample.to_solr
|
229
|
+
expect(solr_doc["visibility_during_embargo_ssim"]).to eq ["private"]
|
230
|
+
expect(solr_doc["visibility_after_embargo_ssim"]).to eq ["restricted"]
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
#
|
235
|
+
# Leases
|
236
|
+
#
|
237
|
+
describe "lease_expiration_date=" do
|
238
|
+
it "should update the appropriate node with the value passed" do
|
239
|
+
@sample.lease_expiration_date = "2010-12-01"
|
240
|
+
expect(@sample.lease_expiration_date).to eq [Date.parse("2010-12-01").to_time.utc]
|
241
|
+
end
|
242
|
+
it "should only accept valid date values" do
|
243
|
+
|
244
|
+
end
|
245
|
+
it "should accept a nil value after having a date value" do
|
246
|
+
@sample.lease_expiration_date = "2010-12-01"
|
247
|
+
@sample.lease_expiration_date = nil
|
248
|
+
expect(@sample.lease_expiration_date).to be_empty
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
describe "active_lease?" do
|
253
|
+
it "should return true if the current date is after the lease expiration date" do
|
254
|
+
@sample.lease_expiration_date = Date.today-1.month
|
255
|
+
expect(@sample).to_not be_active_lease
|
256
|
+
end
|
257
|
+
it "should return false if the current date is before the lease expiration date" do
|
258
|
+
@sample.lease_expiration_date = Date.today+1.month
|
259
|
+
expect(@sample).to be_active_lease
|
260
|
+
end
|
261
|
+
it "should return false if there is no lease expiration date" do
|
262
|
+
@sample.lease_expiration_date = nil
|
263
|
+
expect(@sample).to_not be_active_lease
|
264
|
+
end
|
265
|
+
end
|
266
|
+
describe "visibility during/after lease" do
|
267
|
+
it "should track visibility values and index them into solr" do
|
268
|
+
expect(@sample.visibility_during_lease).to be_empty
|
269
|
+
expect(@sample.visibility_after_lease).to be_empty
|
270
|
+
@sample.visibility_during_lease = "restricted"
|
271
|
+
@sample.visibility_after_lease = "private"
|
272
|
+
expect(@sample.visibility_during_lease).to eq ["restricted"]
|
273
|
+
expect(@sample.visibility_after_lease).to eq ["private"]
|
274
|
+
solr_doc = @sample.to_solr
|
275
|
+
expect(solr_doc["visibility_during_lease_ssim"]).to eq ["restricted"]
|
276
|
+
expect(solr_doc["visibility_after_lease_ssim"]).to eq ["private"]
|
208
277
|
end
|
209
278
|
end
|
210
279
|
end
|
@@ -1,23 +1,26 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
-
require "nokogiri"
|
3
2
|
|
4
3
|
describe Hydra::Datastream::InheritableRightsMetadata do
|
5
4
|
before do
|
6
|
-
Hydra.stub(:config).and_return(
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
5
|
+
Hydra.stub(:config).and_return(
|
6
|
+
Hydra::Config.new.tap do |config|
|
7
|
+
config.permissions ={
|
8
|
+
:discover => {:group =>"discover_access_group_ssim", :individual=>"discover_access_person_ssim"},
|
9
|
+
:read => {:group =>"read_access_group_ssim", :individual=>"read_access_person_ssim"},
|
10
|
+
:edit => {:group =>"edit_access_group_ssim", :individual=>"edit_access_person_ssim"},
|
11
|
+
:owner => "depositor_ssim",
|
12
|
+
:embargo_release_date => "embargo_release_date_dtsi",
|
13
|
+
|
14
|
+
:inheritable => {
|
15
|
+
:discover => {:group =>"inheritable_discover_access_group_ssim", :individual=>"inheritable_discover_access_person_ssim"},
|
16
|
+
:read => {:group =>"inheritable_read_access_group_ssim", :individual=>"inheritable_read_access_person_ssim"},
|
17
|
+
:edit => {:group =>"inheritable_edit_access_group_ssim", :individual=>"inheritable_edit_access_person_ssim"},
|
18
|
+
:owner => "inheritable_depositor_ssim",
|
19
|
+
:embargo_release_date => "inheritable_embargo_release_date_dtsi"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
end
|
23
|
+
)
|
21
24
|
end
|
22
25
|
|
23
26
|
before(:each) do
|
@@ -55,7 +58,7 @@ describe Hydra::Datastream::InheritableRightsMetadata do
|
|
55
58
|
subject[Hydra.config[:permissions][:inheritable][:read][:individual] ].should == ["nero"]
|
56
59
|
subject[Hydra.config[:permissions][:inheritable][:edit][:group] ].should == ["africana-faculty", "cool-kids"]
|
57
60
|
subject[Hydra.config[:permissions][:inheritable][:edit][:individual] ].should == ["julius_caesar"]
|
58
|
-
subject[Hydra.config[:permissions][:inheritable][:embargo_release_date]
|
61
|
+
expect(subject[Hydra.config[:permissions][:inheritable][:embargo_release_date]]).to eq Date.parse("2102-10-01").to_time.utc.iso8601
|
59
62
|
end
|
60
63
|
end
|
61
64
|
|
@@ -167,7 +167,7 @@ describe Hydra::PolicyAwareAbility do
|
|
167
167
|
end
|
168
168
|
describe "edit_persons_from_policy" do
|
169
169
|
it "should retrieve the list of individuals with edit access from the policy" do
|
170
|
-
subject.
|
170
|
+
expect(subject.edit_users_from_policy(@policy.pid)).to eq ["julius_caesar"]
|
171
171
|
end
|
172
172
|
end
|
173
173
|
describe "read_groups_from_policy" do
|
@@ -179,7 +179,7 @@ describe Hydra::PolicyAwareAbility do
|
|
179
179
|
end
|
180
180
|
describe "read_persons_from_policy" do
|
181
181
|
it "should retrieve the list of individuals with read access from the policy" do
|
182
|
-
subject.
|
182
|
+
expect(subject.read_users_from_policy(@policy.pid)).to eq ["julius_caesar","nero"]
|
183
183
|
end
|
184
184
|
end
|
185
185
|
end
|
@@ -142,7 +142,7 @@ describe Hydra::PolicyAwareAccessControlsEnforcement do
|
|
142
142
|
it "should escape slashes in the group names" do
|
143
143
|
RoleMapper.stub(:roles).with(@user).and_return(["abc/123","cde/567"])
|
144
144
|
subject.stub(:current_user).and_return(@user)
|
145
|
-
user_access_filters = subject.
|
145
|
+
user_access_filters = subject.apply_policy_group_permissions
|
146
146
|
["edit","discover","read"].each do |type|
|
147
147
|
user_access_filters.should include("#{ActiveFedora::SolrService.solr_name("inheritable_#{type}_access_group", Hydra::Datastream::RightsMetadata.indexer )}\:abc\\\/123")
|
148
148
|
user_access_filters.should include("#{ActiveFedora::SolrService.solr_name("inheritable_#{type}_access_group", Hydra::Datastream::RightsMetadata.indexer )}\:cde\\\/567")
|
@@ -151,7 +151,7 @@ describe Hydra::PolicyAwareAccessControlsEnforcement do
|
|
151
151
|
it "should escape spaces in the group names" do
|
152
152
|
RoleMapper.stub(:roles).with(@user).and_return(["abc 123","cd/e 567"])
|
153
153
|
subject.stub(:current_user).and_return(@user)
|
154
|
-
user_access_filters = subject.
|
154
|
+
user_access_filters = subject.apply_policy_group_permissions
|
155
155
|
["edit","discover","read"].each do |type|
|
156
156
|
user_access_filters.should include("#{ActiveFedora::SolrService.solr_name("inheritable_#{type}_access_group", Hydra::Datastream::RightsMetadata.indexer )}\:abc\\ 123")
|
157
157
|
user_access_filters.should include("#{ActiveFedora::SolrService.solr_name("inheritable_#{type}_access_group", Hydra::Datastream::RightsMetadata.indexer )}\:cd\\\/e\\ 567")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hydra-access-controls
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.0.
|
4
|
+
version: 7.1.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Beer
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-05
|
13
|
+
date: 2014-06-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activesupport
|
@@ -137,11 +137,15 @@ files:
|
|
137
137
|
- app/models/ability.rb
|
138
138
|
- app/models/concerns/hydra/access_controls.rb
|
139
139
|
- app/models/concerns/hydra/access_controls/access_right.rb
|
140
|
+
- app/models/concerns/hydra/access_controls/embargoable.rb
|
140
141
|
- app/models/concerns/hydra/access_controls/permissions.rb
|
141
142
|
- app/models/concerns/hydra/access_controls/visibility.rb
|
142
143
|
- app/models/concerns/hydra/access_controls/with_access_right.rb
|
143
144
|
- app/models/concerns/hydra/admin_policy_behavior.rb
|
144
145
|
- app/models/role_mapper.rb
|
146
|
+
- app/services/hydra/embargo_service.rb
|
147
|
+
- app/services/hydra/lease_service.rb
|
148
|
+
- app/validators/hydra/future_date_validator.rb
|
145
149
|
- config/fedora.yml
|
146
150
|
- config/solr.yml
|
147
151
|
- hydra-access-controls.gemspec
|
@@ -163,6 +167,8 @@ files:
|
|
163
167
|
- lib/hydra/role_mapper_behavior.rb
|
164
168
|
- lib/hydra/user.rb
|
165
169
|
- spec/factories.rb
|
170
|
+
- spec/services/embargo_service_spec.rb
|
171
|
+
- spec/services/lease_service_spec.rb
|
166
172
|
- spec/spec_helper.rb
|
167
173
|
- spec/support/config/role_map.yml
|
168
174
|
- spec/support/config/solr.yml
|
@@ -176,6 +182,7 @@ files:
|
|
176
182
|
- spec/unit/accessible_by_spec.rb
|
177
183
|
- spec/unit/admin_policy_spec.rb
|
178
184
|
- spec/unit/config_spec.rb
|
185
|
+
- spec/unit/embargoable_spec.rb
|
179
186
|
- spec/unit/hydra_rights_metadata_persistence_spec.rb
|
180
187
|
- spec/unit/hydra_rights_metadata_spec.rb
|
181
188
|
- spec/unit/inheritable_rights_metadata_spec.rb
|
@@ -202,9 +209,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
202
209
|
version: 1.9.3
|
203
210
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
204
211
|
requirements:
|
205
|
-
- - "
|
212
|
+
- - ">"
|
206
213
|
- !ruby/object:Gem::Version
|
207
|
-
version:
|
214
|
+
version: 1.3.1
|
208
215
|
requirements: []
|
209
216
|
rubyforge_project:
|
210
217
|
rubygems_version: 2.2.2
|
@@ -213,6 +220,8 @@ specification_version: 4
|
|
213
220
|
summary: Access controls for project hydra
|
214
221
|
test_files:
|
215
222
|
- spec/factories.rb
|
223
|
+
- spec/services/embargo_service_spec.rb
|
224
|
+
- spec/services/lease_service_spec.rb
|
216
225
|
- spec/spec_helper.rb
|
217
226
|
- spec/support/config/role_map.yml
|
218
227
|
- spec/support/config/solr.yml
|
@@ -226,6 +235,7 @@ test_files:
|
|
226
235
|
- spec/unit/accessible_by_spec.rb
|
227
236
|
- spec/unit/admin_policy_spec.rb
|
228
237
|
- spec/unit/config_spec.rb
|
238
|
+
- spec/unit/embargoable_spec.rb
|
229
239
|
- spec/unit/hydra_rights_metadata_persistence_spec.rb
|
230
240
|
- spec/unit/hydra_rights_metadata_spec.rb
|
231
241
|
- spec/unit/inheritable_rights_metadata_spec.rb
|