acl9 0.11.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.
@@ -0,0 +1,758 @@
1
+ require 'ostruct'
2
+ require 'test_helper'
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'acl9', 'controller_extensions', 'dsl_base')
4
+
5
+ class FakeUser
6
+ def initialize
7
+ @roles = {}
8
+ end
9
+
10
+ def has_role?(role, object = nil)
11
+ @roles.include?([role.to_s, object])
12
+ end
13
+
14
+ def <<(role)
15
+ role = [role] unless role.is_a? Array
16
+
17
+ role << nil if role.size == 1
18
+ raise unless role[0]
19
+
20
+ role[0] = role[0].to_s
21
+
22
+ @roles[role] = true
23
+ end
24
+ end
25
+
26
+ class DslTester < Acl9::Dsl::Base
27
+ def initialize
28
+ super
29
+
30
+ @_subject = nil
31
+ @_objects = {}
32
+ @_current_action = nil
33
+ end
34
+
35
+ def permit(user, *args)
36
+ check_allowance(user, *args).should == true
37
+
38
+ self
39
+ end
40
+
41
+ def forbid(user, *args)
42
+ check_allowance(user, *args).should == false
43
+
44
+ self
45
+ end
46
+
47
+ def show_code
48
+ puts "\n", allowance_expression
49
+ self
50
+ end
51
+
52
+ protected
53
+
54
+ def check_allowance(subject, *args)
55
+ @_subject = subject
56
+ @_current_action = (args[0] || 'index').to_s
57
+ @_objects = args.last.is_a?(Hash) ? args.last : {}
58
+ @_callable = @_objects.delete(:call)
59
+
60
+ instance_eval(allowance_expression)
61
+ end
62
+
63
+ def _subject_ref
64
+ "@_subject"
65
+ end
66
+
67
+ def _object_ref(object)
68
+ "@_objects[:#{object}]"
69
+ end
70
+
71
+ def _action_ref
72
+ "@_current_action"
73
+ end
74
+
75
+ def _method_ref(method)
76
+ "@_callable.send(:#{method})"
77
+ end
78
+ end
79
+
80
+ #describe Acl9::Dsl::Base do
81
+ class DslBaseTest < Test::Unit::TestCase
82
+ class ThatFoo; end
83
+ class ThatBar; end
84
+
85
+ def arg_err(&block)
86
+ lambda do
87
+ acl(&block)
88
+ end.should raise_error(ArgumentError)
89
+ end
90
+
91
+ def acl(&block)
92
+ tester = DslTester.new
93
+ tester.acl_block!(&block)
94
+
95
+ tester
96
+ end
97
+
98
+ def permit_some(tester, user, actions, vars = {})
99
+ actions.each { |act| tester.permit(user, act, vars) }
100
+ (@all_actions - actions).each { |act| tester.forbid(user, act, vars) }
101
+ end
102
+
103
+ before do
104
+ @user = FakeUser.new
105
+ @user2 = FakeUser.new
106
+ @user3 = FakeUser.new
107
+ @foo = ThatFoo.new
108
+ @foo2 = ThatFoo.new
109
+ @foo3 = ThatFoo.new
110
+ end
111
+
112
+ describe "default" do
113
+ it "should set default action to deny if none specified" do
114
+ acl do end.default_action.should == :deny
115
+ end
116
+
117
+ it "should set default action to allow" do
118
+ acl do
119
+ default :allow
120
+ end.default_action.should == :allow
121
+ end
122
+
123
+ it "should set default action to deny" do
124
+ acl do
125
+ default :deny
126
+ end.default_action.should == :deny
127
+ end
128
+
129
+ it "should raise ArgumentError with unknown default_action" do
130
+ arg_err do
131
+ default 123
132
+ end
133
+ end
134
+
135
+ it "should raise ArgumentError when default is called more than once" do
136
+ arg_err do
137
+ default :deny
138
+ default :deny
139
+ end
140
+ end
141
+ end
142
+
143
+ describe "empty blocks" do
144
+ it "should deny everyone with default deny" do
145
+ acl do
146
+ end.forbid(nil).forbid(@user)
147
+ end
148
+
149
+ it "should allow everyone with default allow" do
150
+ acl do
151
+ default :allow
152
+ end.permit(nil).permit(@user)
153
+ end
154
+ end
155
+
156
+ describe "empty" do
157
+ it "allow should raise an ArgumentError" do
158
+ arg_err { allow }
159
+ end
160
+
161
+ it "deny should raise an ArgumentError" do
162
+ arg_err { deny }
163
+ end
164
+ end
165
+
166
+ describe "anonymous" do
167
+ it "'allow nil' should allow anonymous, but not logged in" do
168
+ acl do
169
+ allow nil
170
+ end.permit(nil).forbid(@user)
171
+ end
172
+
173
+ it "'allow anonymous' should allow anonymous, but not logged in" do
174
+ acl do
175
+ allow anonymous
176
+ end.permit(nil).forbid(@user)
177
+ end
178
+
179
+ it "'deny nil' should deny anonymous, but not logged in" do
180
+ acl do
181
+ default :allow
182
+ deny nil
183
+ end.forbid(nil).permit(@user)
184
+ end
185
+
186
+ it "'deny anonymous' should deny anonymous, but not logged in" do
187
+ acl do
188
+ default :allow
189
+ deny anonymous
190
+ end.forbid(nil).permit(@user)
191
+ end
192
+ end
193
+
194
+ describe "all" do
195
+ [:all, :everyone, :everybody, :anyone].each do |pseudorole|
196
+ it "'allow #{pseudorole}' should allow all" do
197
+ acl do
198
+ allow send(pseudorole)
199
+ end.permit(nil).permit(@user)
200
+ end
201
+
202
+ it "'deny #{pseudorole}' should deny all" do
203
+ acl do
204
+ default :allow
205
+ deny send(pseudorole)
206
+ end.forbid(nil).forbid(@user)
207
+ end
208
+ end
209
+ end
210
+
211
+ describe "default :allow" do
212
+ it "should allow when neither allow nor deny conditions are matched" do
213
+ acl do
214
+ default :allow
215
+ allow :blah
216
+ deny :bzz
217
+ end.permit(nil).permit(@user)
218
+ end
219
+
220
+ it "should deny when deny is matched, but allow is not" do
221
+ acl do
222
+ default :allow
223
+ deny all
224
+ allow :blah
225
+ end.forbid(nil).forbid(@user)
226
+ end
227
+
228
+ it "should allow when allow is matched, but deny is not" do
229
+ @user << :cool
230
+ acl do
231
+ default :allow
232
+ deny nil
233
+ allow :cool
234
+ end.permit(@user)
235
+ end
236
+
237
+ it "should allow both allow and deny conditions are matched" do
238
+ @user << :cool
239
+ acl do
240
+ default :allow
241
+ deny :cool
242
+ allow :cool
243
+ end.permit(@user)
244
+
245
+ acl do
246
+ default :allow
247
+ deny all
248
+ allow all
249
+ end.permit(@user).permit(nil).permit(@user2)
250
+ end
251
+ end
252
+
253
+ describe "logged_in" do
254
+ it "'allow logged_in' should allow logged in, but not anonymous" do
255
+ acl do
256
+ allow logged_in
257
+ end.forbid(nil).permit(@user)
258
+ end
259
+
260
+ it "'allow logged_in' should deny logged in, but not anonymous" do
261
+ acl do
262
+ default :allow
263
+ deny logged_in
264
+ end.permit(nil).forbid(@user)
265
+ end
266
+ end
267
+
268
+ describe "default :deny" do
269
+ it "should deny when neither allow nor deny conditions are matched" do
270
+ acl do
271
+ default :deny
272
+ allow :blah
273
+ deny :bzz
274
+ end.forbid(nil).forbid(@user)
275
+ end
276
+
277
+ it "should deny when deny is matched, but allow is not" do
278
+ acl do
279
+ default :deny
280
+ deny all
281
+ allow :blah
282
+ end.forbid(nil).forbid(@user)
283
+ end
284
+
285
+ it "should allow when allow is matched, but deny is not" do
286
+ @user << :cool
287
+ acl do
288
+ default :deny
289
+ deny nil
290
+ allow :cool
291
+ end.permit(@user)
292
+ end
293
+
294
+ it "should deny both allow and deny conditions are matched" do
295
+ @user << :cool
296
+ acl do
297
+ default :deny
298
+ deny :cool
299
+ allow :cool
300
+ end.forbid(@user)
301
+
302
+ acl do
303
+ default :deny
304
+ deny all
305
+ allow all
306
+ end.forbid(@user).forbid(nil).forbid(@user2)
307
+ end
308
+ end
309
+
310
+ describe "global roles" do
311
+ it "#allow with role" do
312
+ @user << :admin
313
+
314
+ acl { allow :admin }.permit(@user).forbid(nil).forbid(@user2)
315
+ end
316
+
317
+ it "#allow with plural role name" do
318
+ @user << :mouse
319
+
320
+ acl do
321
+ allow :mice
322
+ end.permit(@user).forbid(nil).forbid(@user2)
323
+ end
324
+
325
+ it "#allow with several roles" do
326
+ @user << :admin
327
+ @user << :cool
328
+
329
+ @user2 << :cool
330
+
331
+ @user3 << :super
332
+
333
+ acl do
334
+ allow :admin
335
+ allow :cool
336
+ end.permit(@user).permit(@user2).forbid(nil).forbid(@user3)
337
+ end
338
+
339
+ it "#deny with role" do
340
+ @user << :foo
341
+
342
+ acl { default :allow; deny :foo }.forbid(@user).permit(nil).permit(@user2)
343
+ end
344
+
345
+ it "#deny with plural role name" do
346
+ @user << :mouse
347
+
348
+ acl do
349
+ default :allow
350
+ deny :mice
351
+ end.forbid(@user).permit(nil).permit(@user2)
352
+ end
353
+
354
+ it "#deny with several roles" do
355
+ @user << :admin
356
+ @user << :cool
357
+
358
+ @user2 << :cool
359
+
360
+ @user3 << :super
361
+
362
+ acl do
363
+ default :allow
364
+ deny :admin
365
+ deny :cool
366
+ end.forbid(@user).forbid(@user2).permit(nil).permit(@user3)
367
+ end
368
+ end
369
+
370
+ describe "prepositions" do
371
+ [:of, :for, :in, :on, :at, :by].each do |prep|
372
+ it "#allow with object role (:#{prep}) should check controller's ivar" do
373
+ @user << [:manager, @foo]
374
+
375
+ acl do
376
+ allow :manager, prep => :foo
377
+ end.
378
+ permit(@user, :foo => @foo).
379
+ forbid(@user, :foo => @foo2).
380
+ forbid(@user, :foo => ThatFoo).
381
+ forbid(nil, :foo => @foo).
382
+ forbid(@user2, :foo => @foo)
383
+ end
384
+
385
+ it "#allow with invalid value for preposition :#{prep} should raise an ArgumentError" do
386
+ arg_err do
387
+ allow :hom, :by => 1
388
+ end
389
+ end
390
+ end
391
+
392
+ it "#allow with a class role should verify this role against a class" do
393
+ @user << [:owner, ThatFoo]
394
+
395
+ acl do
396
+ allow :owner, :of => ThatFoo
397
+ end.permit(@user).forbid(nil).forbid(@user2)
398
+ end
399
+
400
+ [:of, :for, :in, :on, :at, :by].each do |prep|
401
+ it "#deny with object role (:#{prep}) should check controller's ivar" do
402
+ @user << [:bastard, @foo]
403
+
404
+ acl do
405
+ default :allow
406
+ deny :bastard, prep => :foo
407
+ end.
408
+ forbid(@user, :foo => @foo).
409
+ permit(@user, :foo => @foo2).
410
+ permit(@user, :foo => ThatFoo).
411
+ permit(nil, :foo => @foo).
412
+ permit(@user2, :foo => @foo)
413
+ end
414
+
415
+ it "#deny with invalid value for preposition :#{prep} should raise an ArgumentError" do
416
+ arg_err do
417
+ deny :her, :for => "him"
418
+ end
419
+ end
420
+ end
421
+
422
+ it "#deny with a class role should verify this role against a class" do
423
+ @user << [:ignorant, ThatFoo]
424
+
425
+ acl do
426
+ default :allow
427
+ deny :ignorant, :of => ThatFoo
428
+ end.forbid(@user).permit(nil).permit(@user2)
429
+ end
430
+
431
+ it "#allow with several prepositions should raise an ArgumentError" do
432
+ arg_err do
433
+ allow :some, :by => :one, :for => :another
434
+ end
435
+ end
436
+
437
+ it "#deny with several prepositions should raise an ArgumentError" do
438
+ arg_err do
439
+ deny :some, :in => :here, :on => :today
440
+ end
441
+ end
442
+ end
443
+
444
+ describe ":to and :except" do
445
+ it "should raise an ArgumentError when both :to and :except are specified" do
446
+ arg_err do
447
+ allow all, :to => :index, :except => ['show', 'edit']
448
+ end
449
+ end
450
+
451
+ describe "" do
452
+ after do
453
+ %w(index show).each { |act| @list.permit(nil, act) }
454
+ %w(edit update delete destroy).each { |act| @list.forbid(nil, act) }
455
+
456
+ %w(index show edit update).each { |act| @list.permit(@user, act) }
457
+ %w(delete destroy).each { |act| @list.forbid(@user, act) }
458
+
459
+ %w(index show edit update delete destroy).each { |act| @list.permit(@user2, act) }
460
+ end
461
+
462
+ it ":to should limit rule scope to specified actions" do
463
+ @user << :manager
464
+ @user2 << :trusted
465
+
466
+ @list = acl do
467
+ allow all, :to => [:index, :show]
468
+
469
+ allow 'manager', :to => :edit
470
+ allow 'manager', :to => 'update'
471
+ allow 'trusted', :to => %w(edit update delete destroy)
472
+ end
473
+ end
474
+
475
+ it ":except should limit rule scope to all actions except specified" do
476
+ @user << :manager
477
+ @user2 << :trusted
478
+
479
+ @list = acl do
480
+ allow all, :except => %w(edit update delete destroy)
481
+
482
+ allow 'manager', :except => %w(delete destroy)
483
+ allow 'trusted'
484
+ end
485
+ end
486
+ end
487
+ end
488
+
489
+ describe "conditions" do
490
+ [:if, :unless].each do |cond|
491
+ it "should raise ArgumentError when #{cond} is not a Symbol" do
492
+ arg_err do
493
+ allow nil, cond => 123
494
+ end
495
+ end
496
+ end
497
+
498
+ it "allow ... :if" do
499
+ acl do
500
+ allow nil, :if => :meth
501
+ end.
502
+ permit(nil, :call => OpenStruct.new(:meth => true)).
503
+ forbid(nil, :call => OpenStruct.new(:meth => false))
504
+ end
505
+
506
+ it "allow ... :unless" do
507
+ acl do
508
+ allow nil, :unless => :meth
509
+ end.
510
+ permit(nil, :call => OpenStruct.new(:meth => false)).
511
+ forbid(nil, :call => OpenStruct.new(:meth => true))
512
+ end
513
+
514
+ it "deny ... :if" do
515
+ acl do
516
+ default :allow
517
+ deny nil, :if => :meth
518
+ end.
519
+ permit(nil, :call => OpenStruct.new(:meth => false)).
520
+ forbid(nil, :call => OpenStruct.new(:meth => true))
521
+ end
522
+
523
+ it "deny ... :unless" do
524
+ acl do
525
+ default :allow
526
+ deny nil, :unless => :meth
527
+ end.
528
+ permit(nil, :call => OpenStruct.new(:meth => true)).
529
+ forbid(nil, :call => OpenStruct.new(:meth => false))
530
+ end
531
+
532
+ end
533
+
534
+ describe "several roles as arguments" do
535
+ it "#allow should be able to receive a role list (global roles)" do
536
+ @user << :bzz
537
+ @user2 << :whoa
538
+
539
+ acl do
540
+ allow :bzz, :whoa
541
+ end.permit(@user).permit(@user2).forbid(nil).forbid(@user3)
542
+ end
543
+
544
+ it "#allow should be able to receive a role list (object roles)" do
545
+ @user << [:maker, @foo]
546
+ @user2 << [:faker, @foo2]
547
+
548
+ acl do
549
+ allow :maker, :faker, :of => :foo
550
+ end.
551
+ permit(@user, :foo => @foo).
552
+ forbid(@user, :foo => @foo2).
553
+ permit(@user2, :foo => @foo2).
554
+ forbid(@user2, :foo => @foo).
555
+ forbid(@user3, :foo => @foo).
556
+ forbid(@user3, :foo => @foo2).
557
+ forbid(nil)
558
+ end
559
+
560
+ it "#allow should be able to receive a role list (class roles)" do
561
+ @user << [:frooble, ThatFoo]
562
+ @user2 << [:oombigle, ThatFoo]
563
+ @user3 << :frooble
564
+
565
+ acl do
566
+ allow :frooble, :oombigle, :by => ThatFoo
567
+ end.
568
+ permit(@user).
569
+ permit(@user2).
570
+ forbid(@user3).
571
+ forbid(nil)
572
+ end
573
+
574
+ it "#deny should be able to receive a role list (global roles)" do
575
+ @user << :bzz
576
+ @user2 << :whoa
577
+
578
+ acl do
579
+ default :allow
580
+ deny :bzz, :whoa
581
+ end.forbid(@user).forbid(@user2).permit(nil).permit(@user3)
582
+ end
583
+
584
+ it "#deny should be able to receive a role list (object roles)" do
585
+ @user << [:maker, @foo]
586
+ @user2 << [:faker, @foo2]
587
+ @user3 = FakeUser.new
588
+
589
+ acl do
590
+ default :allow
591
+ deny :maker, :faker, :of => :foo
592
+ end.
593
+ forbid(@user, :foo => @foo).
594
+ permit(@user, :foo => @foo2).
595
+ forbid(@user2, :foo => @foo2).
596
+ permit(@user2, :foo => @foo).
597
+ permit(@user3, :foo => @foo).
598
+ permit(@user3, :foo => @foo2).
599
+ permit(nil)
600
+ end
601
+
602
+ it "#deny should be able to receive a role list (class roles)" do
603
+ @user << [:frooble, ThatFoo]
604
+ @user2 << [:oombigle, ThatFoo]
605
+ @user3 << :frooble
606
+
607
+ acl do
608
+ default :allow
609
+ deny :frooble, :oombigle, :by => ThatFoo
610
+ end.
611
+ forbid(@user).
612
+ forbid(@user2).
613
+ permit(@user3).
614
+ permit(nil)
615
+ end
616
+
617
+ it "should also respect :to and :except" do
618
+ class Moo; end
619
+
620
+ @user << :foo
621
+ @user2 << [:joo, @foo]
622
+ @user3 << [:qoo, Moo]
623
+
624
+ acl do
625
+ allow :foo, :boo, :to => [:index, :show]
626
+ allow :zoo, :joo, :by => :foo, :to => [:edit, :update]
627
+ allow :qoo, :woo, :of => Moo
628
+ deny :qoo, :woo, :of => Moo, :except => [:delete, :destroy]
629
+ end.
630
+ permit(@user, 'index').
631
+ permit(@user, 'show').
632
+ forbid(@user, 'edit').
633
+ permit(@user2, 'edit', :foo => @foo).
634
+ permit(@user2, 'update', :foo => @foo).
635
+ forbid(@user2, 'show', :foo => @foo).
636
+ forbid(@user2, 'show').
637
+ permit(@user3, 'delete').
638
+ permit(@user3, 'destroy').
639
+ forbid(@user3, 'edit').
640
+ forbid(@user3, 'show')
641
+ end
642
+ end
643
+
644
+ describe "actions block" do
645
+ it "should raise an ArgumentError when actions has no block" do
646
+ arg_err do
647
+ actions :foo, :bar
648
+ end
649
+ end
650
+
651
+ it "should raise an ArgumentError when actions has no arguments" do
652
+ arg_err do
653
+ actions do end
654
+ end
655
+ end
656
+
657
+ it "should raise an ArgumentError when actions is called inside actions block" do
658
+ arg_err do
659
+ actions :foo, :bar do
660
+ actions :foo, :bar do
661
+ end
662
+ end
663
+ end
664
+ end
665
+
666
+ it "should raise an ArgumentError when default is called inside actions block" do
667
+ arg_err do
668
+ actions :foo, :bar do
669
+ default :allow
670
+ end
671
+ end
672
+ end
673
+
674
+ [:to, :except].each do |opt|
675
+ it "should raise an ArgumentError when allow is called with #{opt} option" do
676
+ arg_err do
677
+ actions :foo do
678
+ allow all, opt => :bar
679
+ end
680
+ end
681
+ end
682
+
683
+ it "should raise an ArgumentError when deny is called with #{opt} option" do
684
+ arg_err do
685
+ actions :foo do
686
+ deny all, opt => :bar
687
+ end
688
+ end
689
+ end
690
+ end
691
+
692
+ it "empty actions block should do nothing" do
693
+ acl do
694
+ actions :foo do
695
+ end
696
+
697
+ allow all
698
+ end.permit(nil).permit(nil, :foo)
699
+ end
700
+
701
+ it "#allow should limit its scope to specified actions" do
702
+ @user << :bee
703
+
704
+ acl do
705
+ actions :edit do
706
+ allow :bee
707
+ end
708
+ end.
709
+ permit(@user, :edit).
710
+ forbid(@user, :update)
711
+ end
712
+
713
+ it "#deny should limit its scope to specified actions" do
714
+ @user << :bee
715
+
716
+ acl do
717
+ default :allow
718
+ actions :edit do
719
+ deny :bee
720
+ end
721
+ end.
722
+ forbid(@user, :edit).
723
+ permit(@user, :update)
724
+ end
725
+
726
+ it "#allow and #deny should work together inside actions block" do
727
+ @foo = ThatFoo.new
728
+ @user << [:owner, @foo]
729
+ @user2 << :hacker
730
+ @user2 << :the_destroyer
731
+ @user3 << [:owner, @foo]
732
+ @user3 << :hacker
733
+
734
+ list = acl do
735
+ actions :show, :index do
736
+ allow all
737
+ end
738
+
739
+ actions :edit, :update do
740
+ allow :owner, :of => :object
741
+ deny :hacker
742
+ end
743
+
744
+ actions :delete, :destroy do
745
+ allow :owner, :of => :object
746
+ allow :the_destroyer
747
+ end
748
+ end
749
+
750
+ @all_actions = %w(show index edit update delete destroy)
751
+
752
+ permit_some(list, @user, @all_actions, :object => @foo)
753
+ permit_some(list, @user2, %w(show index delete destroy))
754
+ permit_some(list, @user3, %w(show index delete destroy), :object => @foo)
755
+ end
756
+ end
757
+ end
758
+