hydra-access-controls 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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