zuul 0.1.1 → 0.2.0

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