hydra-access-controls 7.0.2 → 7.1.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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
|