hydra-access-controls 0.0.2 → 0.0.3

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.
Files changed (43) hide show
  1. data/.gitignore +1 -0
  2. data/.gitmodules +3 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +6 -0
  5. data/README.textile +100 -0
  6. data/Rakefile +6 -3
  7. data/config/fedora.yml +8 -0
  8. data/config/jetty.yml +5 -0
  9. data/config/solr.yml +6 -0
  10. data/hydra-access-controls.gemspec +3 -2
  11. data/lib/ability.rb +1 -0
  12. data/lib/hydra-access-controls.rb +10 -0
  13. data/lib/hydra-access-controls/version.rb +1 -1
  14. data/lib/hydra/ability.rb +14 -13
  15. data/lib/hydra/access_controls_enforcement.rb +27 -16
  16. data/lib/hydra/admin_policy.rb +81 -0
  17. data/lib/hydra/datastream.rb +1 -0
  18. data/lib/hydra/datastream/inheritable_rights_metadata.rb +22 -0
  19. data/lib/hydra/policy_aware_ability.rb +128 -0
  20. data/lib/hydra/policy_aware_access_controls_enforcement.rb +70 -0
  21. data/lib/hydra/role_mapper_behavior.rb +16 -2
  22. data/lib/hydra/user.rb +42 -0
  23. data/lib/tasks/hydra-access-controls.rake +18 -0
  24. data/lib/tasks/hydra_jetty.rake +55 -0
  25. data/solr_conf/conf/schema.xml +124 -0
  26. data/solr_conf/conf/solrconfig.xml +329 -0
  27. data/solr_conf/solr.xml +35 -0
  28. data/spec/factories.rb +101 -0
  29. data/spec/spec_helper.rb +28 -0
  30. data/spec/support/blacklight.rb +7 -0
  31. data/spec/support/config/solr.yml +4 -0
  32. data/spec/support/mods_asset.rb +4 -1
  33. data/spec/support/rails.rb +10 -0
  34. data/spec/support/solr_document.rb +13 -0
  35. data/spec/support/user.rb +32 -0
  36. data/spec/unit/ability_spec.rb +338 -56
  37. data/spec/unit/access_controls_enforcement_spec.rb +180 -0
  38. data/spec/unit/admin_policy_spec.rb +89 -0
  39. data/spec/unit/inheritable_rights_metadata_spec.rb +66 -0
  40. data/spec/unit/policy_aware_ability_spec.rb +92 -0
  41. data/spec/unit/policy_aware_access_controls_enforcement_spec.rb +109 -0
  42. metadata +59 -4
  43. data/README.md +0 -29
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,12 @@
1
+ ENV["environment"] ||= "test"
2
+ module Hydra
3
+ # Stubbing Hydra.config[:policy_aware] so Hydra::PolicyAwareAbility will be loaded for tests.
4
+ def self.config
5
+ {:permissions=>{:policy_aware => true}}
6
+ end
7
+ end
8
+
9
+
1
10
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
11
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
12
 
@@ -14,7 +23,26 @@ end
14
23
  require 'rspec/autorun'
15
24
  require 'hydra-access-controls'
16
25
  require 'support/mods_asset'
26
+ require 'support/solr_document'
27
+ require "support/user"
28
+ require "factory_girl"
29
+ require "factories"
30
+
31
+ require 'support/blacklight'
32
+ require 'support/rails'
33
+
17
34
  RSpec.configure do |config|
18
35
 
19
36
  end
20
37
 
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
+ # Stubbing Devise
44
+ class Devise
45
+ def self.authentication_keys
46
+ ["uid"]
47
+ end
48
+ end
@@ -0,0 +1,7 @@
1
+ require 'blacklight'
2
+
3
+ module Blacklight
4
+ def self.solr_file
5
+ File.expand_path(File.join(File.dirname(__FILE__), "config", "solr.yml"))
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ development:
2
+ url: http://localhost:<%= ENV['TEST_JETTY_PORT'] || 8983 %>/solr/development
3
+ test:
4
+ url: http://localhost:<%= ENV['TEST_JETTY_PORT'] || 8983 %>/solr/test
@@ -2,5 +2,8 @@ require 'active-fedora'
2
2
  class ModsAsset < ActiveFedora::Base
3
3
  include Hydra::ModelMixins::RightsMetadata
4
4
  has_metadata :name => "rightsMetadata", :type => Hydra::Datastream::RightsMetadata
5
-
5
+
6
+ # This is how we're associating admin policies with assets.
7
+ # You can associate them however you want, just use the :is_governed_by relationship
8
+ belongs_to :admin_policy, :class_name=> "Hydra::AdminPolicy", :property=>:is_governed_by
6
9
  end
@@ -0,0 +1,10 @@
1
+ class Rails
2
+ def self.env
3
+ ENV['environment']
4
+ end
5
+
6
+ def self.version
7
+ "0.0.0"
8
+ #"hydra-access-controls mock rails"
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ class SolrDocument
2
+ def initialize(source_doc={}, solr_response=nil)
3
+ @source_doc = source_doc
4
+ end
5
+ def fetch(field, default)
6
+ @source_doc[field]
7
+ end
8
+
9
+ def [](field)
10
+ @source_doc[field]
11
+ end
12
+ end
13
+
@@ -0,0 +1,32 @@
1
+ class User
2
+
3
+ include Hydra::User
4
+
5
+ attr_accessor :uid, :email, :password, :roles, :new_record
6
+
7
+ def initialize(params={})
8
+ self.email = params[:email] if params[:email]
9
+ end
10
+
11
+ def new_record?
12
+ new_record == true
13
+ end
14
+
15
+ def is_being_superuser?(session)
16
+ # do nothing -- stubbing deprecated behavior
17
+ end
18
+
19
+ def self.find_by_uid(uid)
20
+ nil
21
+ end
22
+
23
+ def save
24
+ # do nothing!
25
+ end
26
+
27
+ def save!
28
+ save
29
+ return self
30
+ end
31
+
32
+ end
@@ -3,44 +3,25 @@ require 'spec_helper'
3
3
  describe Ability do
4
4
  before do
5
5
  class Rails; end
6
- class User; end
7
- class Devise; end
8
- class SolrDocument
9
- def initialize(one, two)
10
- @one = one
11
- end
12
- def fetch(field, default)
13
- @one[field]
14
- end
15
- end
16
- class Hydra::SuperuserAttributes; end
17
- module Blacklight
18
- module Exceptions
19
- class InvalidSolrID < StandardError
20
- def initialize(opt)
21
- end
22
- end
23
- end
24
- end
25
- Devise.stub(:authentication_keys).and_return(['email'])
26
- # User.any_instance.stub(:email).and_return('archivist1@example.com')
27
- # User.any_instance.stub(:new_record?).and_return(false)
28
- # User.any_instance.stub(:is_being_superuser?).and_return(false)
29
- Hydra::SuperuserAttributes.stub(:silenced)
30
- Hydra::SuperuserAttributes.stub(:silenced=)
31
- @solr_resp = stub("solr response")
32
- Blacklight.stub(:solr).and_return(stub("solr", :find=>@solr_resp))
33
-
34
6
  Rails.stub(:root).and_return('spec/support')
35
7
  Rails.stub(:env).and_return('test')
36
-
37
- Hydra.stub(:config).and_return({:permissions=>{
38
- :catchall => "access_t",
39
- :discover => {:group =>"discover_access_group_t", :individual=>"discover_access_person_t"},
40
- :read => {:group =>"read_access_group_t", :individual=>"read_access_person_t"},
41
- :edit => {:group =>"edit_access_group_t", :individual=>"edit_access_person_t"},
42
- :owner => "depositor_t",
43
- :embargo_release_date => "embargo_release_date_dt"
8
+ Hydra.stub(:config).and_return({
9
+ :permissions=>{
10
+ :catchall => "access_t",
11
+ :discover => {:group =>"discover_access_group_t", :individual=>"discover_access_person_t"},
12
+ :read => {:group =>"read_access_group_t", :individual=>"read_access_person_t"},
13
+ :edit => {:group =>"edit_access_group_t", :individual=>"edit_access_person_t"},
14
+ :owner => "depositor_t",
15
+ :embargo_release_date => "embargo_release_date_dt",
16
+
17
+ :inheritable => {
18
+ :catchall => "inheritable_access_t",
19
+ :discover => {:group =>"inheritable_discover_access_group_t", :individual=>"inheritable_discover_access_person_t"},
20
+ :read => {:group =>"inheritable_read_access_group_t", :individual=>"inheritable_read_access_person_t"},
21
+ :edit => {:group =>"inheritable_edit_access_group_t", :individual=>"inheritable_edit_access_person_t"},
22
+ :owner => "inheritable_depositor_t",
23
+ :embargo_release_date => "inheritable_embargo_release_date_dt"
24
+ }
44
25
  }})
45
26
  end
46
27
 
@@ -55,34 +36,335 @@ describe Ability do
55
36
  Ability.any_instance.should_receive(:custom_permissions)
56
37
  subject.can?(:delete, 7)
57
38
  end
58
- it "should be able to read objects that are public" do
59
- @solr_resp.stub(:docs).and_return([{'read_access_group_t' =>['public']}])
60
- public_object = ModsAsset.new
61
- subject.can?(:read, public_object).should be_true
62
- end
63
- it "should not be able to read objects that are registered" do
64
- registered_object = ModsAsset.new
65
- @solr_resp.stub(:docs).and_return([{'read_access_group_t' =>['registered']}])
66
- subject.can?(:read, registered_object).should_not be_true
67
- end
68
39
  it "should not be able to create objects" do
69
40
  subject.can?(:create, :any).should be_false
70
41
  end
71
42
  end
72
43
  context "for a signed in user" do
73
- subject { Ability.new(stub("user", :email=>'archivist1@example.com', :new_record? => false, :is_being_superuser? =>false)) }
74
- it "should be able to read objects that are public" do
75
- public_object = ModsAsset.new
76
- @solr_resp.stub(:docs).and_return([{'read_access_group_t' =>['public']}])
77
- subject.can?(:read, public_object).should be_true
78
- end
79
- it "should be able to read objects that are registered" do
80
- registered_object = ModsAsset.new
81
- @solr_resp.stub(:docs).and_return([{'read_access_group_t' =>['registered']}])
82
- subject.can?(:read, registered_object).should be_true
44
+ before do
45
+ @user = FactoryGirl.build(:registered_user)
83
46
  end
47
+ subject { Ability.new(@user) }
84
48
  it "should be able to create objects" do
85
49
  subject.can?(:create, :any).should be_true
86
50
  end
87
51
  end
52
+
53
+
54
+ # NOTES:
55
+ # See spec/requests/... for test coverage describing WHAT should appear on a page based on access permissions
56
+ # Test coverage for discover permission is in spec/requests/gated_discovery_spec.rb
57
+
58
+ describe "Given an asset that has been made publicly available (ie. open access)" do
59
+ before do
60
+ @asset = FactoryGirl.build(:open_access_asset)
61
+ @asset.save
62
+ end
63
+ context "Then a not-signed-in user" do
64
+ before do
65
+ @user = User.new
66
+ @user.new_record = true
67
+ end
68
+ subject { Ability.new(nil) }
69
+ it "should be able to view the asset" do
70
+ subject.can?(:read, @asset).should be_true
71
+ end
72
+ it "should not be able to edit, update and destroy the asset" do
73
+ subject.can?(:edit, @asset).should be_false
74
+ subject.can?(:update, @asset).should be_false
75
+ subject.can?(:destroy, @asset).should be_false
76
+ end
77
+ end
78
+ context "Then a registered user" do
79
+ before do
80
+ @user = FactoryGirl.build(:registered_user)
81
+ end
82
+ subject { Ability.new(@user) }
83
+ it "should be able to view the asset" do
84
+ subject.can?(:read, @asset).should be_true
85
+ end
86
+ it "should not be able to edit, update and destroy the asset" do
87
+ subject.can?(:edit, @asset).should be_false
88
+ subject.can?(:update, @asset).should be_false
89
+ subject.can?(:destroy, @asset).should be_false
90
+ end
91
+ end
92
+ end
93
+
94
+ describe "Given an asset with no custom access set" do
95
+ before do
96
+ @asset = FactoryGirl.build(:default_access_asset)
97
+ @asset.save
98
+ end
99
+ context "Then a not-signed-in user" do
100
+ before do
101
+ @user = User.new
102
+ @user.new_record = true
103
+ end
104
+ subject { Ability.new(@user) }
105
+ it "should not be able to view the asset" do
106
+ subject.can?(:read, @asset).should be_false
107
+ end
108
+ it "should not be able to edit, update and destroy the asset" do
109
+ subject.can?(:edit, @asset).should be_false
110
+ subject.can?(:update, @asset).should be_false
111
+ subject.can?(:destroy, @asset).should be_false
112
+ end
113
+ end
114
+ context "Then a registered user" do
115
+ before do
116
+ @user = FactoryGirl.build(:registered_user)
117
+ end
118
+ subject { Ability.new(@user) }
119
+ it "should not be able to view the asset" do
120
+ subject.can?(:read, @asset).should be_false
121
+ end
122
+ it "should not be able to edit, update and destroy the asset" do
123
+ subject.can?(:edit, @asset).should be_false
124
+ subject.can?(:update, @asset).should be_false
125
+ subject.can?(:destroy, @asset).should be_false
126
+ end
127
+ end
128
+ context "Then the Creator" do
129
+ before do
130
+ @user = FactoryGirl.build(:joe_creator)
131
+ end
132
+ subject { Ability.new(@user) }
133
+
134
+ it "should be able to view the asset" do
135
+ subject.can?(:read, @asset).should be_true
136
+ end
137
+ it "should be able to edit, update and destroy the asset" do
138
+ subject.can?(:edit, @asset).should be_true
139
+ subject.can?(:update, @asset).should be_true
140
+ subject.can?(:destroy, @asset).should be_true
141
+ end
142
+ it "should not be able to see the admin view of the asset" do
143
+ subject.can?(:admin, @asset).should be_false
144
+ end
145
+ end
146
+ end
147
+
148
+ describe "Given an asset which registered users have read access to" do
149
+ before do
150
+ @asset = FactoryGirl.build(:org_read_access_asset)
151
+ @asset.save
152
+ end
153
+ context "The a registered user" do
154
+ before do
155
+ @user = FactoryGirl.build(:registered_user)
156
+ end
157
+ subject { Ability.new(@user) }
158
+
159
+ it "should be able to view the asset" do
160
+ subject.can?(:read, @asset).should be_true
161
+ end
162
+ it "should not be able to edit, update and destroy the asset" do
163
+ subject.can?(:edit, @asset).should be_false
164
+ subject.can?(:update, @asset).should be_false
165
+ subject.can?(:destroy, @asset).should be_false
166
+ end
167
+ it "should not be able to see the admin view of the asset" do
168
+ subject.can?(:admin, @asset).should be_false
169
+ end
170
+ end
171
+ end
172
+
173
+ describe "Given an asset with collaborator" do
174
+ before do
175
+ @asset = FactoryGirl.build(:org_read_access_asset)
176
+ @asset.save
177
+ end
178
+ context "Then a collaborator with edit access" do
179
+ before do
180
+ @user = FactoryGirl.build(:calvin_collaborator)
181
+ end
182
+ subject { Ability.new(@user) }
183
+
184
+ it "should be able to view the asset" do
185
+ subject.can?(:read, @asset).should be_true
186
+ end
187
+ it "should be able to edit, update and destroy the asset" do
188
+ subject.can?(:edit, @asset).should be_true
189
+ subject.can?(:update, @asset).should be_true
190
+ subject.can?(:destroy, @asset).should be_true
191
+ end
192
+ it "should not be able to see the admin view of the asset" do
193
+ subject.can?(:admin, @asset).should be_false
194
+ end
195
+ end
196
+ end
197
+
198
+ describe "Given an asset where dept can read & registered users can discover" do
199
+ before do
200
+ @asset = FactoryGirl.build(:dept_access_asset)
201
+ @asset.save
202
+ end
203
+ context "Then a registered user" do
204
+ before do
205
+ @user = FactoryGirl.build(:registered_user)
206
+ end
207
+ subject { Ability.new(@user) }
208
+
209
+ it "should not be able to view the asset" do
210
+ subject.can?(:read, @asset).should be_false
211
+ end
212
+ it "should not be able to edit, update and destroy the asset" do
213
+ subject.can?(:edit, @asset).should be_false
214
+ subject.can?(:update, @asset).should be_false
215
+ subject.can?(:destroy, @asset).should be_false
216
+ end
217
+ it "should not be able to see the admin view of the asset" do
218
+ subject.can?(:admin, @asset).should be_false
219
+ end
220
+ end
221
+ context "Then someone whose role/group has read access" do
222
+ before do
223
+ @user = FactoryGirl.build(:martia_morocco)
224
+ RoleMapper.stub(:roles).with(@user.user_key).and_return(@user.roles)
225
+ end
226
+ subject { Ability.new(@user) }
227
+
228
+ it "should be able to view the asset" do
229
+ subject.can?(:read, @asset).should be_true
230
+ end
231
+ it "should not be able to edit, update and destroy the asset" do
232
+ subject.can?(:edit, @asset).should be_false
233
+ subject.can?(:update, @asset).should be_false
234
+ subject.can?(:destroy, @asset).should be_false
235
+ end
236
+ it "should not be able to see the admin view of the asset" do
237
+ subject.can?(:admin, @asset).should be_false
238
+ end
239
+ end
240
+ end
241
+
242
+ describe "a user" do
243
+ before do
244
+ @user = FactoryGirl.create(:staff)
245
+ end
246
+ subject { Ability.new(@user) }
247
+
248
+ it "should be able to create admin policies" do
249
+ subject.can?(:create, Hydra::AdminPolicy).should be_true
250
+ end
251
+
252
+ end
253
+
254
+ #
255
+ # Policy-based Access Controls
256
+ #
257
+ describe "When accessing assets with Policies associated" do
258
+ before do
259
+ @user = FactoryGirl.build(:martia_morocco)
260
+ RoleMapper.stub(:roles).with(@user.user_key).and_return(@user.roles)
261
+ end
262
+ subject { Ability.new(@user) }
263
+ context "Given a policy grants read access to a group I belong to" do
264
+ before do
265
+ @policy = Hydra::AdminPolicy.new
266
+ @policy.default_permissions = [{:type=>"group", :access=>"read", :name=>"africana-faculty"}]
267
+ @policy.save
268
+ end
269
+ after { @policy.delete }
270
+ context "And a subscribing asset does not grant access" do
271
+ before do
272
+ @asset = ModsAsset.new()
273
+ @asset.admin_policy = @policy
274
+ @asset.save
275
+ end
276
+ after { @asset.delete }
277
+ it "Then I should be able to view the asset" do
278
+ subject.can?(:read, @asset).should be_true
279
+ end
280
+ it "Then I should not be able to edit, update and destroy the asset" do
281
+ subject.can?(:edit, @asset).should be_false
282
+ subject.can?(:update, @asset).should be_false
283
+ subject.can?(:destroy, @asset).should be_false
284
+ end
285
+ end
286
+ end
287
+ context "Given a policy grants edit access to a group I belong to" do
288
+ before do
289
+ @policy = Hydra::AdminPolicy.new
290
+ @policy.default_permissions = [{:type=>"group", :access=>"edit", :name=>"africana-faculty"}]
291
+ @policy.save
292
+ end
293
+ after { @policy.delete }
294
+ context "And a subscribing asset does not grant access" do
295
+ before do
296
+ @asset = ModsAsset.new()
297
+ @asset.admin_policy = @policy
298
+ @asset.save
299
+ end
300
+ after { @asset.delete }
301
+ it "Then I should be able to view the asset" do
302
+ subject.can?(:read, @asset).should be_true
303
+ end
304
+ it "Then I should be able to edit/update/destroy the asset" do
305
+ subject.can?(:edit, @asset).should be_true
306
+ subject.can?(:update, @asset).should be_true
307
+ subject.can?(:destroy, @asset).should be_true
308
+ end
309
+ end
310
+ context "And a subscribing asset grants read access to me as an individual" do
311
+ before do
312
+ @asset = ModsAsset.new()
313
+ @asset.read_users = [@user.uid]
314
+ @asset.admin_policy = @policy
315
+ @asset.save
316
+ end
317
+ after { @asset.delete }
318
+ it "Then I should be able to view the asset" do
319
+ subject.can?(:read, @asset).should be_true
320
+ end
321
+ it "Then I should be able to edit/update/destroy the asset" do
322
+ subject.can?(:edit, @asset).should be_true
323
+ subject.can?(:update, @asset).should be_true
324
+ subject.can?(:destroy, @asset).should be_true
325
+ end
326
+ end
327
+ end
328
+
329
+ context "Given a policy does not grant access to any group I belong to" do
330
+ before do
331
+ @policy = Hydra::AdminPolicy.new
332
+ @policy.save
333
+ end
334
+ after { @policy.delete }
335
+ context "And a subscribing asset does not grant access" do
336
+ before do
337
+ @asset = ModsAsset.new()
338
+ @asset.admin_policy = @policy
339
+ @asset.save
340
+ end
341
+ after { @asset.delete }
342
+ it "Then I should not be able to view the asset" do
343
+ subject.can?(:read, @asset).should be_false
344
+ end
345
+ it "Then I should not be able to edit/update/destroy the asset" do
346
+ subject.can?(:edit, @asset).should be_false
347
+ subject.can?(:update, @asset).should be_false
348
+ subject.can?(:destroy, @asset).should be_false
349
+ end
350
+ end
351
+ context "And a subscribing asset grants read access to me as an individual" do
352
+ before do
353
+ @asset = ModsAsset.new()
354
+ @asset.read_users = [@user.uid]
355
+ @asset.admin_policy = @policy
356
+ @asset.save
357
+ end
358
+ after { @asset.delete }
359
+ it "Then I should be able to view the asset" do
360
+ subject.can?(:read, @asset).should be_true
361
+ end
362
+ it "Then I should not be able to edit/update/destroy the asset" do
363
+ subject.can?(:edit, @asset).should be_false
364
+ subject.can?(:update, @asset).should be_false
365
+ subject.can?(:destroy, @asset).should be_false
366
+ end
367
+ end
368
+ end
369
+ end
88
370
  end