zuul 0.1.1 → 0.2.0

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 (80) hide show
  1. data/lib/generators/zuul/orm_helpers.rb +21 -0
  2. data/lib/generators/zuul/permission_generator.rb +57 -0
  3. data/lib/generators/zuul/permission_role_generator.rb +40 -0
  4. data/lib/generators/zuul/permission_subject_generator.rb +40 -0
  5. data/lib/generators/zuul/role_generator.rb +58 -0
  6. data/lib/generators/zuul/role_subject_generator.rb +40 -0
  7. data/lib/generators/zuul/subject_generator.rb +39 -0
  8. data/lib/generators/zuul/templates/permission.rb +18 -0
  9. data/lib/generators/zuul/templates/permission_existing.rb +25 -0
  10. data/lib/generators/zuul/templates/permission_role.rb +17 -0
  11. data/lib/generators/zuul/templates/permission_role_existing.rb +24 -0
  12. data/lib/generators/zuul/templates/permission_subject.rb +17 -0
  13. data/lib/generators/zuul/templates/permission_subject_existing.rb +24 -0
  14. data/lib/generators/zuul/templates/role.rb +20 -0
  15. data/lib/generators/zuul/templates/role_existing.rb +27 -0
  16. data/lib/generators/zuul/templates/role_subject.rb +17 -0
  17. data/lib/generators/zuul/templates/role_subject_existing.rb +24 -0
  18. data/lib/tasks/zuul.rake +56 -0
  19. data/lib/zuul.rb +14 -5
  20. data/lib/zuul/action_controller.rb +108 -0
  21. data/lib/zuul/action_controller/dsl.rb +384 -0
  22. data/lib/zuul/action_controller/evaluators.rb +60 -0
  23. data/lib/zuul/active_record.rb +338 -0
  24. data/lib/zuul/active_record/context.rb +38 -0
  25. data/lib/zuul/active_record/permission.rb +31 -0
  26. data/lib/zuul/active_record/permission_role.rb +29 -0
  27. data/lib/zuul/active_record/permission_subject.rb +29 -0
  28. data/lib/zuul/active_record/role.rb +117 -0
  29. data/lib/zuul/active_record/role_subject.rb +29 -0
  30. data/lib/zuul/active_record/scope.rb +71 -0
  31. data/lib/zuul/active_record/subject.rb +239 -0
  32. data/lib/zuul/configuration.rb +149 -0
  33. data/lib/zuul/context.rb +53 -0
  34. data/lib/zuul/exceptions.rb +3 -0
  35. data/lib/zuul/exceptions/access_denied.rb +9 -0
  36. data/lib/zuul/exceptions/invalid_context.rb +9 -0
  37. data/lib/zuul/exceptions/undefined_scope.rb +9 -0
  38. data/lib/zuul/railtie.rb +5 -0
  39. data/lib/zuul/version.rb +3 -0
  40. data/lib/zuul_viz.rb +195 -0
  41. data/spec/db/schema.rb +172 -0
  42. data/spec/spec_helper.rb +25 -0
  43. data/spec/support/capture_stdout.rb +12 -0
  44. data/spec/support/models.rb +167 -0
  45. data/spec/zuul/active_record/context_spec.rb +55 -0
  46. data/spec/zuul/active_record/permission_role_spec.rb +84 -0
  47. data/spec/zuul/active_record/permission_spec.rb +174 -0
  48. data/spec/zuul/active_record/permission_subject_spec.rb +84 -0
  49. data/spec/zuul/active_record/role_spec.rb +694 -0
  50. data/spec/zuul/active_record/role_subject_spec.rb +84 -0
  51. data/spec/zuul/active_record/scope_spec.rb +75 -0
  52. data/spec/zuul/active_record/subject_spec.rb +1186 -0
  53. data/spec/zuul/active_record_spec.rb +624 -0
  54. data/spec/zuul/configuration_spec.rb +254 -0
  55. data/spec/zuul/context_spec.rb +128 -0
  56. data/spec/zuul_spec.rb +15 -0
  57. metadata +181 -70
  58. data/.document +0 -5
  59. data/.gitignore +0 -23
  60. data/LICENSE +0 -20
  61. data/README.rdoc +0 -65
  62. data/Rakefile +0 -54
  63. data/VERSION +0 -1
  64. data/lib/zuul/restrict_access.rb +0 -104
  65. data/lib/zuul/valid_roles.rb +0 -37
  66. data/spec/rails_root/app/controllers/application_controller.rb +0 -2
  67. data/spec/rails_root/app/models/user.rb +0 -8
  68. data/spec/rails_root/config/boot.rb +0 -110
  69. data/spec/rails_root/config/database.yml +0 -5
  70. data/spec/rails_root/config/environment.rb +0 -7
  71. data/spec/rails_root/config/environments/test.rb +0 -7
  72. data/spec/rails_root/config/initializers/session_store.rb +0 -15
  73. data/spec/rails_root/config/routes.rb +0 -4
  74. data/spec/rails_root/db/test.sqlite3 +0 -0
  75. data/spec/rails_root/log/test.log +0 -5388
  76. data/spec/rails_root/spec/controllers/require_user_spec.rb +0 -138
  77. data/spec/rails_root/spec/controllers/restrict_access_spec.rb +0 -64
  78. data/spec/rails_root/spec/models/user_spec.rb +0 -37
  79. data/spec/rails_root/spec/spec_helper.rb +0 -34
  80. data/zuul.gemspec +0 -78
@@ -0,0 +1,624 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Zuul::ActiveRecord" do
4
+
5
+ def prep_dummy
6
+ Dummy.send :include, Zuul::ActiveRecord
7
+ Dummy.send :instance_variable_set, :@auth_config, Zuul::Configuration.new
8
+ Dummy.send :instance_variable_set, :@auth_scopes, {:default => Zuul::ActiveRecord::Scope.new(Zuul::Configuration.new)}
9
+ Dummy.send :include, Zuul::ActiveRecord::AuthorizationMethods
10
+ end
11
+
12
+ it "should extend ActiveRecord::Base with Zuul::ActiveRecord" do
13
+ ActiveRecord::Base.ancestors.include?(Zuul::ActiveRecord).should be_true
14
+ end
15
+
16
+ it "should provide the acts_as_authorization_* and acts_as_authorization_*? methods" do
17
+ [:subject, :role, :permission, :context].each do |type|
18
+ ActiveRecord::Base.respond_to?("acts_as_authorization_#{type.to_s}").should be_true
19
+ ActiveRecord::Base.respond_to?("acts_as_authorization_#{type.to_s}?").should be_true
20
+ Dummy.new.respond_to?("acts_as_authorization_#{type.to_s}").should be_false
21
+ Dummy.new.respond_to?("acts_as_authorization_#{type.to_s}?").should be_true
22
+ end
23
+ end
24
+
25
+ describe "acts_as_authorization_*" do
26
+ it "should extend the model with Zuul::ActiveRecord::AuthorizationMethods" do
27
+ User.acts_as_authorization_subject
28
+ Role.acts_as_authorization_role
29
+ Permission.acts_as_authorization_permission
30
+ Context.acts_as_authorization_context
31
+ [User, Role, Permission, Context].each do |model|
32
+ model.ancestors.include?(Zuul::ActiveRecord::AuthorizationMethods).should be_true
33
+ end
34
+ end
35
+
36
+ # TODO maybe move these into 4 different specs for each method?
37
+ it "should allow passing class arguments to be used with reflections" do
38
+ Soldier.acts_as_authorization_subject :role_class => Rank, :permission_class => Skill
39
+ Soldier.auth_scope.role_class.should == Rank
40
+ Soldier.auth_scope.permission_class.should == Skill
41
+
42
+ Rank.acts_as_authorization_role :subject_class => Soldier, :permission_class => Skill
43
+ Rank.auth_scope.subject_class.should == Soldier
44
+ Rank.auth_scope.permission_class.should == Skill
45
+
46
+ Skill.acts_as_authorization_permission :subject_class => Soldier, :role_class => Rank
47
+ Skill.auth_scope.subject_class.should == Soldier
48
+ Skill.auth_scope.role_class.should == Rank
49
+
50
+ Weapon.acts_as_authorization_context :permission_class => Skill
51
+ Weapon.auth_scope.permission_class.should == Skill
52
+ end
53
+
54
+ it "should allow class arguments to be provided as classes, strings or symbols" do
55
+ Soldier.acts_as_authorization_subject :role_class => Rank, :permission_class => "Skill"
56
+ Soldier.auth_scope.role_class.should == Rank
57
+ Soldier.auth_scope.permission_class.should == Skill
58
+ Rank.acts_as_authorization_role :subject_class => :soldier, :permission_class => "skill"
59
+ Rank.auth_scope.subject_class.should == Soldier
60
+ Rank.auth_scope.permission_class.should == Skill
61
+ Skill.acts_as_authorization_permission :subject_class => Soldier, :role_class => :Rank
62
+ Skill.auth_scope.subject_class.should == Soldier
63
+ Skill.auth_scope.role_class.should == Rank
64
+ Weapon.acts_as_authorization_context :permission_class => Skill
65
+ Weapon.auth_scope.permission_class.should == Skill
66
+ end
67
+
68
+ it "should allow using namespaced classes" do
69
+ ZuulModels::User.acts_as_authorization_subject :role_class => ZuulModels::Role, :permission_class => "ZuulModels::Permission"
70
+ ZuulModels::User.auth_scope.role_class.should == ZuulModels::Role
71
+ ZuulModels::User.auth_scope.permission_class.should == ZuulModels::Permission
72
+ ZuulModels::User.auth_scope.role_subject_class.should == ZuulModels::RoleUser
73
+ ZuulModels::User.auth_scope.permission_subject_class.should == ZuulModels::PermissionUser
74
+ ZuulModels::User.auth_scope.permission_role_class.should == ZuulModels::PermissionRole
75
+
76
+ ZuulModels::Role.acts_as_authorization_role :subject_class => ZuulModels::User, :permission_class => ZuulModels::Permission
77
+ ZuulModels::Role.auth_scope.subject_class.should == ZuulModels::User
78
+ ZuulModels::Role.auth_scope.permission_class.should == ZuulModels::Permission
79
+ ZuulModels::Role.auth_scope.role_subject_class.should == ZuulModels::RoleUser
80
+ ZuulModels::Role.auth_scope.permission_subject_class.should == ZuulModels::PermissionUser
81
+ ZuulModels::Role.auth_scope.permission_role_class.should == ZuulModels::PermissionRole
82
+
83
+ ZuulModels::Permission.acts_as_authorization_permission :subject_class => "ZuulModels::User", :role_class => ZuulModels::Role
84
+ ZuulModels::Permission.auth_scope.subject_class.should == ZuulModels::User
85
+ ZuulModels::Permission.auth_scope.role_class.should == ZuulModels::Role
86
+ ZuulModels::Permission.auth_scope.role_subject_class.should == ZuulModels::RoleUser
87
+ ZuulModels::Permission.auth_scope.permission_subject_class.should == ZuulModels::PermissionUser
88
+ ZuulModels::Permission.auth_scope.permission_role_class.should == ZuulModels::PermissionRole
89
+ end
90
+
91
+ end
92
+
93
+ describe "acts_as_authorization_*?" do
94
+ it "should return false by default" do
95
+ [User, Role, Permission, Context].each do |model|
96
+ [:subject, :role, :permission, :context].each do |type|
97
+ model.send("acts_as_authorization_#{type.to_s}?").should be_false
98
+ model.new.send("acts_as_authorization_#{type.to_s}?").should be_false
99
+ end
100
+ end
101
+ end
102
+
103
+ it "should return true if the model acts_as_authorization_*" do
104
+ User.acts_as_authorization_subject
105
+ User.acts_as_authorization_subject?.should be_true
106
+ User.new.acts_as_authorization_subject?.should be_true
107
+
108
+ Role.acts_as_authorization_role
109
+ Role.acts_as_authorization_role?.should be_true
110
+ Role.new.acts_as_authorization_role?.should be_true
111
+
112
+ Permission.acts_as_authorization_permission
113
+ Permission.acts_as_authorization_permission?.should be_true
114
+ Permission.new.acts_as_authorization_permission?.should be_true
115
+
116
+ Context.acts_as_authorization_context
117
+ Context.acts_as_authorization_context?.should be_true
118
+ Context.new.acts_as_authorization_context?.should be_true
119
+ end
120
+
121
+ it "should return the same value from instances and their classes" do
122
+ User.acts_as_authorization_subject
123
+ Role.acts_as_authorization_role
124
+ Permission.acts_as_authorization_permission
125
+ Context.acts_as_authorization_context
126
+ [User, Role, Permission, Context].each do |model|
127
+ [:subject, :role, :permission, :context].each do |type|
128
+ model.new.send("acts_as_authorization_#{type.to_s}?").should == model.send("acts_as_authorization_#{type.to_s}?")
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ describe "acts_as_authorization_subject" do
135
+ it "should extend the model with Zuul::ActiveRecord::Subject" do
136
+ User.acts_as_authorization_subject
137
+ User.ancestors.include?(Zuul::ActiveRecord::Subject).should be_true
138
+ end
139
+
140
+ it "should extend the model with Zuul::ActiveRecord::Subject:RoleMethods" do
141
+ User.acts_as_authorization_subject
142
+ User.ancestors.include?(Zuul::ActiveRecord::Subject::RoleMethods).should be_true
143
+ end
144
+
145
+ it "should extend the model with Zuul::ActiveRecord::Subject:PermissionMethods if permissions enabled" do
146
+ User.acts_as_authorization_subject
147
+ User.ancestors.include?(Zuul::ActiveRecord::Subject::PermissionMethods).should be_true
148
+ end
149
+
150
+ it "should not extend the model with Zuul::ActiveRecord::Subject:PermissionMethods if permissions disabled" do
151
+ User.acts_as_authorization_subject :with_permissions => false
152
+ User.ancestors.include?(Zuul::ActiveRecord::Subject::PermissionMethods).should be_false
153
+ end
154
+ end
155
+
156
+ describe "acts_as_authorization_role" do
157
+ it "should extend the model with Zuul::ActiveRecord::Role" do
158
+ Role.acts_as_authorization_role
159
+ Role.ancestors.include?(Zuul::ActiveRecord::Role).should be_true
160
+ end
161
+
162
+ it "should extend the model with Zuul::ActiveRecord::ContextMethods" do
163
+ Role.acts_as_authorization_role
164
+ Role.ancestors.include?(Zuul::ActiveRecord::ContextMethods).should be_true
165
+ end
166
+
167
+ it "should extend the model with Zuul::ActiveRecord::Role::PermissionMethods if permissions enabled" do
168
+ Role.acts_as_authorization_role
169
+ Role.ancestors.include?(Zuul::ActiveRecord::Role::PermissionMethods).should be_true
170
+ end
171
+
172
+ it "should not extend the model with Zuul::ActiveRecord::Role::PermissionMethods if permissions disabled" do
173
+ Role.acts_as_authorization_role :with_permissions => false
174
+ Role.ancestors.include?(Zuul::ActiveRecord::Role::PermissionMethods).should be_false
175
+ end
176
+ end
177
+
178
+ describe "acts_as_authorization_permission" do
179
+ it "should extend the model with Zuul::ActiveRecord::Permission" do
180
+ Permission.acts_as_authorization_permission
181
+ Permission.ancestors.include?(Zuul::ActiveRecord::Permission).should be_true
182
+ end
183
+
184
+ it "should extend the model with Zuul::ActiveRecord::ContextMethods" do
185
+ Permission.acts_as_authorization_permission
186
+ Permission.ancestors.include?(Zuul::ActiveRecord::ContextMethods).should be_true
187
+ end
188
+ end
189
+
190
+ describe "acts_as_authorization_context" do
191
+ it "should extend the model with Zuul::ActiveRecord::Context" do
192
+ Context.acts_as_authorization_context
193
+ Context.ancestors.include?(Zuul::ActiveRecord::Context).should be_true
194
+ end
195
+ end
196
+
197
+ describe "AuthorizationMethods" do
198
+ describe "auth_scope" do
199
+ before(:each) do
200
+ Role.acts_as_authorization_role
201
+ Permission.acts_as_authorization_permission
202
+ User.acts_as_authorization_subject
203
+ Level.acts_as_authorization_role :permission_class => :ability
204
+ Ability.acts_as_authorization_permission :role_class => :level
205
+ User.acts_as_authorization_subject :scope => :character, :role_class => :level, :permission_class => :ability
206
+ end
207
+
208
+ context "class method" do
209
+ it "should return the requested scope" do
210
+ User.auth_scope.name.should == :default
211
+ User.auth_scope(:character).name.should == :character
212
+ end
213
+
214
+ it "should raise an exception if the scope doesn't exist" do
215
+ expect { User.auth_scope(:noscope) }.to raise_exception(Zuul::Exceptions::UndefinedScope)
216
+ end
217
+
218
+ context "when calling a method" do
219
+ it "should allow calling a method within the requested scope" do
220
+ User.instance_eval do
221
+ def scope_test_method
222
+ role_class_name
223
+ end
224
+ end
225
+ User.auth_scope(:character, :scope_test_method).should == User.auth_scope(:character).role_class_name
226
+ end
227
+
228
+ it "should allow calling a method with arguments within the requested scope" do
229
+ suffix = rand(100)*rand(100)
230
+ User.instance_eval do
231
+ def scope_test_method(suf)
232
+ "#{role_class_name}_#{suf}"
233
+ end
234
+ end
235
+ User.auth_scope(:character, :scope_test_method, suffix).should == "#{User.auth_scope(:character).role_class_name}_#{suffix}"
236
+ end
237
+ end
238
+
239
+ context "when passing a block" do
240
+ it "should allow executing a block within the requested scope" do
241
+ User.auth_scope(:character) do
242
+ role_class_name
243
+ end.should == User.auth_scope(:character).role_class_name
244
+ end
245
+
246
+ it "should allow executing a block with arguments within the requested scope" do
247
+ suffix = rand(100)*rand(100)
248
+ User.auth_scope(:character, suffix) do |suf|
249
+ "#{role_class_name}_#{suf}"
250
+ end.should == "#{User.auth_scope(:character).role_class_name}_#{suffix}"
251
+ end
252
+ end
253
+ end
254
+
255
+ context "instance method" do
256
+ before(:each) do
257
+ @user = User.create(:name => "Tester")
258
+ end
259
+
260
+ it "should return the requested scope" do
261
+ @user.auth_scope.name.should == :default
262
+ @user.auth_scope(:character).name.should == :character
263
+ end
264
+
265
+ it "should raise an exception if the scope doesn't exist" do
266
+ expect { @user.auth_scope(:noscope) }.to raise_exception(Zuul::Exceptions::UndefinedScope)
267
+ end
268
+
269
+ context "when calling a method" do
270
+ it "should allow calling a method within the requested scope" do
271
+ @user.instance_eval do
272
+ def scope_test_method
273
+ role_class_name
274
+ end
275
+ end
276
+ @user.auth_scope(:character, :scope_test_method).should == @user.auth_scope(:character).role_class_name
277
+ end
278
+
279
+ it "should allow calling a method with arguments within the requested scope" do
280
+ suffix = rand(100)*rand(100)
281
+ @user.instance_eval do
282
+ def scope_test_method(suf)
283
+ "#{role_class_name}_#{suf}"
284
+ end
285
+ end
286
+ @user.auth_scope(:character, :scope_test_method, suffix).should == "#{@user.auth_scope(:character).role_class_name}_#{suffix}"
287
+ end
288
+ end
289
+
290
+ context "when passing a block" do
291
+ it "should allow executing a block within the requested scope" do
292
+ @user.auth_scope(:character) do
293
+ role_class_name
294
+ end.should == @user.auth_scope(:character).role_class_name
295
+ end
296
+
297
+ it "should allow executing a block with arguments within the requested scope" do
298
+ suffix = rand(100)*rand(100)
299
+ @user.auth_scope(:character, suffix) do |suf|
300
+ "#{role_class_name}_#{suf}"
301
+ end.should == "#{@user.auth_scope(:character).role_class_name}_#{suffix}"
302
+ end
303
+ end
304
+ end
305
+ end
306
+
307
+ describe "target_role" do
308
+ before(:each) do
309
+ prep_dummy
310
+ end
311
+
312
+ it "should require a role object or slug and a context" do
313
+ expect { Dummy.new.target_role }.to raise_exception
314
+ expect { Dummy.new.target_role(:role) }.to raise_exception
315
+ expect { Dummy.new.target_role(:role, nil) }.to_not raise_exception
316
+ end
317
+
318
+ it "should accept a role object" do
319
+ expect { Dummy.new.target_role(Role.new, nil) }.to_not raise_exception
320
+ end
321
+
322
+ it "should accept a string or symbol" do
323
+ expect { Dummy.new.target_role(:role, nil) }.to_not raise_exception
324
+ expect { Dummy.new.target_role('role', nil) }.to_not raise_exception
325
+ end
326
+
327
+ it "should allow forcing context" do
328
+ expect { Dummy.new.target_role(:role, nil, true) }.to_not raise_exception
329
+ expect { Dummy.new.target_role('role', nil, false) }.to_not raise_exception
330
+ end
331
+
332
+ context "when looking up a role" do
333
+ it "should just return the role object if one is passed" do
334
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
335
+ Dummy.new.target_role(role, nil).should === role
336
+ end
337
+
338
+ it "should use the defined role_class for the lookup" do
339
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
340
+ Dummy.new.target_role(:admin, nil).should be_an_instance_of(Role)
341
+ # TODO add another example that uses different role class
342
+ end
343
+
344
+ it "should use the provided slug for the lookup" do
345
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
346
+ Dummy.new.target_role(:admin, nil).slug.should == 'admin'
347
+ Dummy.new.target_role('admin', nil).slug.should == 'admin'
348
+ end
349
+
350
+ it "should normalize symbols and strings to lowercase and underscored" do
351
+ role = Role.create(:name => 'My Cool Role', :slug => 'my_cool_role', :level => 40)
352
+ Dummy.new.target_role('MyCoolRole', nil).should == role
353
+ Dummy.new.target_role(:MyCoolRole, nil).should == role
354
+ end
355
+
356
+ context "within a context" do
357
+ it "should go up the context chain to find roles" do
358
+ context = Context.create(:name => "Test Context")
359
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
360
+ Dummy.new.target_role(:admin, nil).should == nil_role
361
+ Dummy.new.target_role(:admin, Context).should == nil_role
362
+ Dummy.new.target_role(:admin, context).should == nil_role
363
+ end
364
+
365
+ it "should use the closest contextual match" do
366
+ context = Context.create(:name => "Test Context")
367
+
368
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
369
+ Dummy.new.target_role(:admin, nil).should == nil_role
370
+ Dummy.new.target_role(:admin, Context).should == nil_role
371
+ Dummy.new.target_role(:admin, context).should == nil_role
372
+
373
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
374
+ Dummy.new.target_role(:admin, nil).should == nil_role
375
+ Dummy.new.target_role(:admin, Context).should == class_role
376
+ Dummy.new.target_role(:admin, context).should == class_role
377
+
378
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
379
+ Dummy.new.target_role(:admin, nil).should == nil_role
380
+ Dummy.new.target_role(:admin, Context).should == class_role
381
+ Dummy.new.target_role(:admin, context).should == inst_role
382
+ end
383
+
384
+ context "when forcing the context" do
385
+ it "should not go up the context chain" do
386
+ context = Context.create(:name => "Test Context")
387
+
388
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
389
+ Dummy.new.target_role(:admin, nil, true).should == nil_role
390
+ Dummy.new.target_role(:admin, Context, true).should be_nil
391
+ Dummy.new.target_role(:admin, context, true).should be_nil
392
+
393
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
394
+ Dummy.new.target_role(:admin, nil, true).should == nil_role
395
+ Dummy.new.target_role(:admin, Context, true).should == class_role
396
+ Dummy.new.target_role(:admin, context, true).should be_nil
397
+
398
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
399
+ Dummy.new.target_role(:admin, nil, true).should == nil_role
400
+ Dummy.new.target_role(:admin, Context, true).should == class_role
401
+ Dummy.new.target_role(:admin, context, true).should == inst_role
402
+ end
403
+ end
404
+ end
405
+ end
406
+ end
407
+
408
+ describe "target_permission" do
409
+ before(:each) do
410
+ prep_dummy
411
+ end
412
+
413
+ it "should require a permission object or slug and a context" do
414
+ expect { Dummy.new.target_permission }.to raise_exception
415
+ expect { Dummy.new.target_permission(:permission) }.to raise_exception
416
+ expect { Dummy.new.target_permission(:permission, nil) }.to_not raise_exception
417
+ end
418
+
419
+ it "should accept a permission object" do
420
+ expect { Dummy.new.target_permission(Permission.new, nil) }.to_not raise_exception
421
+ end
422
+
423
+ it "should accept a string or symbol" do
424
+ expect { Dummy.new.target_permission(:permission, nil) }.to_not raise_exception
425
+ expect { Dummy.new.target_permission('permission', nil) }.to_not raise_exception
426
+ end
427
+
428
+ it "should allow forcing context" do
429
+ expect { Dummy.new.target_permission(:permission, nil, true) }.to_not raise_exception
430
+ expect { Dummy.new.target_permission('permission', nil, false) }.to_not raise_exception
431
+ end
432
+
433
+ context "when looking up a permission" do
434
+ it "should just return the permission object if one is passed" do
435
+ permission = Permission.create(:name => 'Do Something', :slug => 'do_something')
436
+ Dummy.new.target_permission(permission, nil).should === permission
437
+ end
438
+
439
+ it "should use the defined permission_class for the lookup" do
440
+ permission = Permission.create(:name => 'Do Something', :slug => 'do_something')
441
+ Dummy.new.target_permission(:do_something, nil).should be_an_instance_of(Permission)
442
+ # TODO add another example that uses different permission class
443
+ end
444
+
445
+ it "should use the provided slug for the lookup" do
446
+ permission = Permission.create(:name => 'Do Something', :slug => 'do_something')
447
+ Dummy.new.target_permission(:do_something, nil).slug.should == 'do_something'
448
+ Dummy.new.target_permission('do_something', nil).slug.should == 'do_something'
449
+ end
450
+
451
+ it "should normalize symbols and strings to lowercase and underscored" do
452
+ permission = Permission.create(:name => 'My Cool Permission', :slug => 'my_cool_permission')
453
+ Dummy.new.target_permission('MyCoolPermission', nil).should == permission
454
+ Dummy.new.target_permission(:MyCoolPermission, nil).should == permission
455
+ end
456
+
457
+ context "within a context" do
458
+ it "should go up the context chain to find permissions" do
459
+ context = Context.create(:name => "Test Context")
460
+ nil_permission = Permission.create(:name => 'Do Something', :slug => 'do_something')
461
+ Dummy.new.target_permission(:do_something, nil).should == nil_permission
462
+ Dummy.new.target_permission(:do_something, Context).should == nil_permission
463
+ Dummy.new.target_permission(:do_something, context).should == nil_permission
464
+ end
465
+
466
+ it "should use the closest contextual match" do
467
+ context = Context.create(:name => "Test Context")
468
+
469
+ nil_permission = Permission.create(:name => 'Do Something', :slug => 'do_something')
470
+ Dummy.new.target_permission(:do_something, nil).should == nil_permission
471
+ Dummy.new.target_permission(:do_something, Context).should == nil_permission
472
+ Dummy.new.target_permission(:do_something, context).should == nil_permission
473
+
474
+ class_permission = Permission.create(:name => 'Do Something', :slug => 'do_something', :context_type => 'Context')
475
+ Dummy.new.target_permission(:do_something, nil).should == nil_permission
476
+ Dummy.new.target_permission(:do_something, Context).should == class_permission
477
+ Dummy.new.target_permission(:do_something, context).should == class_permission
478
+
479
+ inst_permission = Permission.create(:name => 'Do Something', :slug => 'do_something', :context_type => 'Context', :context_id => context.id)
480
+ Dummy.new.target_permission(:do_something, nil).should == nil_permission
481
+ Dummy.new.target_permission(:do_something, Context).should == class_permission
482
+ Dummy.new.target_permission(:do_something, context).should == inst_permission
483
+ end
484
+
485
+ context "when forcing the context" do
486
+ it "should not go up the context chain" do
487
+ context = Context.create(:name => "Test Context")
488
+
489
+ nil_permission = Permission.create(:name => 'Do Something', :slug => 'do_something')
490
+ Dummy.new.target_permission(:do_something, nil, true).should == nil_permission
491
+ Dummy.new.target_permission(:do_something, Context, true).should be_nil
492
+ Dummy.new.target_permission(:do_something, context, true).should be_nil
493
+
494
+ class_permission = Permission.create(:name => 'Do Something', :slug => 'do_something', :context_type => 'Context')
495
+ Dummy.new.target_permission(:do_something, nil, true).should == nil_permission
496
+ Dummy.new.target_permission(:do_something, Context, true).should == class_permission
497
+ Dummy.new.target_permission(:do_something, context, true).should be_nil
498
+
499
+ inst_permission = Permission.create(:name => 'Do Something', :slug => 'do_something', :context_type => 'Context', :context_id => context.id)
500
+ Dummy.new.target_permission(:do_something, nil, true).should == nil_permission
501
+ Dummy.new.target_permission(:do_something, Context, true).should == class_permission
502
+ Dummy.new.target_permission(:do_something, context, true).should == inst_permission
503
+ end
504
+ end
505
+ end
506
+ end
507
+ end
508
+
509
+ describe "verify_target_context" do
510
+ before(:each) do
511
+ Role.acts_as_authorization_role # this is to enable Role#context, can remove/rework this once those context methods are broken out
512
+ Permission.acts_as_authorization_permission # this is to enable Permission#context, can remove/rework this once those context methods are broken out
513
+ prep_dummy
514
+ end
515
+
516
+ it "should require a target role or permission and a context" do
517
+ expect { Dummy.new.verify_target_context }.to raise_exception
518
+ expect { Dummy.new.verify_target_context(nil) }.to raise_exception
519
+ end
520
+
521
+ it "should accept a role or a permission as the target" do
522
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
523
+ permission = Permission.create(:name => 'Do Something', :slug => 'do_something')
524
+ Dummy.new.verify_target_context(role, nil).should be_true
525
+ Dummy.new.verify_target_context(permission, nil).should be_true
526
+ end
527
+
528
+ it "should return false if a nil target is provided" do
529
+ Dummy.new.verify_target_context(nil, nil).should be_false
530
+ end
531
+
532
+ it "should allow forcing context" do
533
+ expect { Dummy.new.verify_target_context(nil, nil, true) }.to_not raise_exception
534
+ end
535
+
536
+ context "when not forcing context" do
537
+ it "should allow nil context targets to be used within any other context" do
538
+ context = Context.create(:name => "Test Context")
539
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
540
+ permission = Permission.create(:name => 'Do Something', :slug => 'do_something')
541
+ Dummy.new.verify_target_context(role, nil).should be_true
542
+ Dummy.new.verify_target_context(role, Context).should be_true
543
+ Dummy.new.verify_target_context(role, context).should be_true
544
+ Dummy.new.verify_target_context(permission, nil).should be_true
545
+ Dummy.new.verify_target_context(permission, Context).should be_true
546
+ Dummy.new.verify_target_context(permission, context).should be_true
547
+ end
548
+
549
+ it "should allow class context targets to be used within the context of their class or any instances of their class" do
550
+ context = Context.create(:name => "Test Context")
551
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
552
+ permission = Permission.create(:name => 'Do Something', :slug => 'do_something', :context_type => 'Context')
553
+ Dummy.new.verify_target_context(role, Context).should be_true
554
+ Dummy.new.verify_target_context(role, context).should be_true
555
+ Dummy.new.verify_target_context(permission, Context).should be_true
556
+ Dummy.new.verify_target_context(permission, context).should be_true
557
+ end
558
+
559
+ it "should allow instance targets to be used within their own instance context" do
560
+ context = Context.create(:name => "Test Context")
561
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
562
+ permission = Permission.create(:name => 'Do Something', :slug => 'do_something', :context_type => 'Context', :context_id => context.id)
563
+ Dummy.new.verify_target_context(role, context).should be_true
564
+ Dummy.new.verify_target_context(permission, context).should be_true
565
+ end
566
+
567
+ it "should not allow class context targets to be used within any other class or nil contexts" do
568
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
569
+ permission = Permission.create(:name => 'Do Something', :slug => 'do_something', :context_type => 'Context')
570
+ Dummy.new.verify_target_context(role, nil).should be_false
571
+ Dummy.new.verify_target_context(role, Weapon).should be_false
572
+ Dummy.new.verify_target_context(permission, nil).should be_false
573
+ Dummy.new.verify_target_context(permission, Weapon).should be_false
574
+ end
575
+
576
+ it "should not allow instance context targets to be used within any other class or instance contexts or a nil context" do
577
+ context = Context.create(:name => "Test Context")
578
+ other_context = Context.create(:name => "Another Test Context")
579
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
580
+ permission = Permission.create(:name => 'Do Something', :slug => 'do_something', :context_type => 'Context', :context_id => context.id)
581
+ Dummy.new.verify_target_context(role, nil).should be_false
582
+ Dummy.new.verify_target_context(role, Context).should be_false
583
+ Dummy.new.verify_target_context(role, Weapon).should be_false
584
+ Dummy.new.verify_target_context(role, other_context).should be_false
585
+ Dummy.new.verify_target_context(permission, nil).should be_false
586
+ Dummy.new.verify_target_context(permission, Context).should be_false
587
+ Dummy.new.verify_target_context(permission, Weapon).should be_false
588
+ Dummy.new.verify_target_context(permission, other_context).should be_false
589
+ end
590
+ end
591
+
592
+ context "when forcing context" do
593
+ it "should only allow the target to be used within the provided context" do
594
+ context = Context.create(:name => "Test Context")
595
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
596
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
597
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
598
+ Dummy.new.verify_target_context(nil_role, nil, true).should be_true
599
+ Dummy.new.verify_target_context(nil_role, Context, true).should be_false
600
+ Dummy.new.verify_target_context(nil_role, context, true).should be_false
601
+ Dummy.new.verify_target_context(class_role, nil, true).should be_false
602
+ Dummy.new.verify_target_context(class_role, Context, true).should be_true
603
+ Dummy.new.verify_target_context(class_role, context, true).should be_false
604
+ Dummy.new.verify_target_context(inst_role, nil, true).should be_false
605
+ Dummy.new.verify_target_context(inst_role, Context, true).should be_false
606
+ Dummy.new.verify_target_context(inst_role, context, true).should be_true
607
+ nil_permission = Permission.create(:name => 'Do Something', :slug => 'do_something')
608
+ class_permission = Permission.create(:name => 'Do Something', :slug => 'do_something', :context_type => 'Context')
609
+ inst_permission = Permission.create(:name => 'Do Something', :slug => 'do_something', :context_type => 'Context', :context_id => context.id)
610
+ Dummy.new.verify_target_context(nil_permission, nil, true).should be_true
611
+ Dummy.new.verify_target_context(nil_permission, Context, true).should be_false
612
+ Dummy.new.verify_target_context(nil_permission, context, true).should be_false
613
+ Dummy.new.verify_target_context(class_permission, nil, true).should be_false
614
+ Dummy.new.verify_target_context(class_permission, Context, true).should be_true
615
+ Dummy.new.verify_target_context(class_permission, context, true).should be_false
616
+ Dummy.new.verify_target_context(inst_permission, nil, true).should be_false
617
+ Dummy.new.verify_target_context(inst_permission, Context, true).should be_false
618
+ Dummy.new.verify_target_context(inst_permission, context, true).should be_true
619
+ end
620
+ end
621
+ end
622
+ end
623
+
624
+ end