be9-acl9 0.9.1

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,27 @@
1
+ module Acl9
2
+ module ModelExtensions
3
+ module Object
4
+ def accepts_role?(role_name, subject)
5
+ subject.has_role? role_name, self
6
+ end
7
+
8
+ def accepts_role!(role_name, subject)
9
+ subject.has_role! role_name, self
10
+ end
11
+
12
+ def accepts_no_role!(role_name, subject)
13
+ subject.has_no_role! role_name, self
14
+ end
15
+
16
+ def accepts_roles_by?(subject)
17
+ subject.has_roles_for? self
18
+ end
19
+
20
+ alias :accepts_role_by? :accepts_roles_by?
21
+
22
+ def accepted_roles_by(subject)
23
+ subject.roles_for self
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,107 @@
1
+ module Acl9
2
+ module ModelExtensions
3
+ module Subject
4
+ def has_role?(role_name, object = nil)
5
+ !! if object.nil?
6
+ self.roles.find_by_name(role_name.to_s) ||
7
+ self.roles.member?(get_role(role_name, nil))
8
+ else
9
+ role = get_role(role_name, object)
10
+ role && self.roles.exists?(role.id)
11
+ end
12
+ end
13
+
14
+ def has_role!(role_name, object = nil)
15
+ role = get_role(role_name, object)
16
+
17
+ if role.nil?
18
+ role_attrs = case object
19
+ when Class then { :authorizable_type => object.to_s }
20
+ when nil then {}
21
+ else { :authorizable => object }
22
+ end.merge( { :name => role_name.to_s })
23
+
24
+ role = self._auth_role_class.create(role_attrs)
25
+ end
26
+
27
+ self.roles << role if role && !self.roles.exists?( role.id )
28
+ end
29
+
30
+ def has_no_role!(role_name, object = nil)
31
+ delete_role(get_role(role_name, object))
32
+ end
33
+
34
+ def has_roles_for?(object)
35
+ !!self.roles.detect(&role_selecting_lambda(object))
36
+ end
37
+
38
+ alias :has_role_for? :has_roles_for?
39
+
40
+ def roles_for(object)
41
+ self.roles.select(&role_selecting_lambda(object))
42
+ end
43
+
44
+ def has_no_roles_for!(object = nil)
45
+ roles_for(object).each { |role| delete_role(role) }
46
+ end
47
+
48
+ def has_no_roles!
49
+ # for some reason simple
50
+ #
51
+ # self.roles.each { |role| delete_role(role) }
52
+ #
53
+ # doesn't work. seems like a bug in ActiveRecord
54
+ self.roles.map(&:id).each do |role_id|
55
+ delete_role self._auth_role_class.find(role_id)
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def role_selecting_lambda(object)
62
+ case object
63
+ when Class
64
+ lambda { |role| role.authorizable_type == object.to_s }
65
+ when nil
66
+ lambda { |role| role.authorizable.nil? }
67
+ else
68
+ lambda do |role|
69
+ role.authorizable_type == object.class.base_class.to_s && role.authorizable == object
70
+ end
71
+ end
72
+ end
73
+
74
+ def get_role(role_name, object)
75
+ role_name = role_name.to_s
76
+
77
+ cond = case object
78
+ when Class
79
+ [ 'name = ? and authorizable_type = ? and authorizable_id IS NULL', role_name, object.to_s ]
80
+ when nil
81
+ [ 'name = ? and authorizable_type IS NULL and authorizable_id IS NULL', role_name ]
82
+ else
83
+ [
84
+ 'name = ? and authorizable_type = ? and authorizable_id = ?',
85
+ role_name, object.class.base_class.to_s, object.id
86
+ ]
87
+ end
88
+
89
+ self._auth_role_class.first :conditions => cond
90
+ end
91
+
92
+ def delete_role(role)
93
+ if role
94
+ self.roles.delete role
95
+
96
+ role.destroy if role.users.empty?
97
+ end
98
+ end
99
+
100
+ protected
101
+
102
+ def _auth_role_class
103
+ self.class._auth_role_class_name.constantize
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,54 @@
1
+ module Acl9 # :nodoc:
2
+ # = Version
3
+ #
4
+ # A class for describing the current version of a library. The version
5
+ # consists of three parts: the +major+ number, the +minor+ number, and the
6
+ # +tiny+ (or +patch+) number.
7
+ class Version
8
+
9
+ include Comparable
10
+
11
+ # A convenience method for instantiating a new Version instance with the
12
+ # given +major+, +minor+, and +tiny+ components.
13
+ def self.[](major, minor, tiny)
14
+ new(major, minor, tiny)
15
+ end
16
+
17
+ attr_reader :major, :minor, :tiny
18
+
19
+ # Create a new Version object with the given components.
20
+ def initialize(major, minor, tiny)
21
+ @major, @minor, @tiny = major, minor, tiny
22
+ end
23
+
24
+ # Compare this version to the given +version+ object.
25
+ def <=>(version)
26
+ to_i <=> version.to_i
27
+ end
28
+
29
+ # Converts this version object to a string, where each of the three
30
+ # version components are joined by the '.' character. E.g., 2.0.0.
31
+ def to_s
32
+ @to_s ||= [@major, @minor, @tiny].join(".")
33
+ end
34
+
35
+ # Converts this version to a canonical integer that may be compared
36
+ # against other version objects.
37
+ def to_i
38
+ @to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
39
+ end
40
+
41
+ def to_a
42
+ [@major, @minor, @tiny]
43
+ end
44
+
45
+ MAJOR = 0
46
+ MINOR = 9
47
+ TINY = 1
48
+
49
+ # The current version as a Version instance
50
+ CURRENT = new(MAJOR, MINOR, TINY)
51
+ # The current version as a String
52
+ STRING = CURRENT.to_s
53
+ end
54
+ end
@@ -0,0 +1,185 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'acl9')
3
+
4
+ class EmptyController < ActionController::Base
5
+ attr_accessor :current_user
6
+ before_filter :set_current_user
7
+
8
+ [:index, :show, :new, :edit, :update, :delete, :destroy].each do |act|
9
+ define_method(act) {}
10
+ end
11
+
12
+ private
13
+
14
+ def set_current_user
15
+ if params[:user]
16
+ self.current_user = params[:user]
17
+ end
18
+ end
19
+ end
20
+
21
+ class Admin
22
+ def has_role?(role, obj = nil)
23
+ role == "admin"
24
+ end
25
+ end
26
+
27
+ # all these controllers behave the same way
28
+
29
+ class AccessControllingController1 < EmptyController
30
+ access_control do
31
+ allow all, :to => [:index, :show]
32
+ allow :admin
33
+ end
34
+ end
35
+
36
+ class AccessControllingController2 < EmptyController
37
+ access_control :as_method => :acl do
38
+ allow all, :to => [:index, :show]
39
+ allow :admin, :except => [:index, :show]
40
+ end
41
+ end
42
+
43
+ class AccessControllingController3 < EmptyController
44
+ access_control :except => [:index, :show] do
45
+ allow :admin
46
+ end
47
+ end
48
+
49
+ class AccessControllingController4 < EmptyController
50
+ access_control :as_method => :acl, :filter => false do
51
+ allow all, :to => [:index, :show]
52
+ allow :admin
53
+ end
54
+
55
+ before_filter :check_acl
56
+
57
+ def check_acl
58
+ if self.acl
59
+ true
60
+ else
61
+ raise Acl9::AccessDenied
62
+ end
63
+ end
64
+ end
65
+
66
+ describe "permit anonymous to index and show and admin everywhere else", :shared => true do
67
+ [:index, :show].each do |act|
68
+ it "should permit anonymous to #{act}" do
69
+ get act
70
+ end
71
+ end
72
+
73
+ [:new, :edit, :update, :delete, :destroy].each do |act|
74
+ it "should forbid anonymous to #{act}" do
75
+ lambda do
76
+ get act
77
+ end.should raise_error(Acl9::AccessDenied)
78
+ end
79
+ end
80
+
81
+ [:index, :show, :new, :edit, :update, :delete, :destroy].each do |act|
82
+ it "should permit admin to #{act}" do
83
+ get act, :user => Admin.new
84
+ end
85
+ end
86
+ end
87
+
88
+ describe AccessControllingController1, :type => :controller do
89
+ it_should_behave_like "permit anonymous to index and show and admin everywhere else"
90
+ end
91
+
92
+ describe AccessControllingController2, :type => :controller do
93
+ it "should add :acl as a method" do
94
+ controller.should respond_to(:acl)
95
+ end
96
+
97
+ it_should_behave_like "permit anonymous to index and show and admin everywhere else"
98
+ end
99
+
100
+ describe AccessControllingController3, :type => :controller do
101
+ it_should_behave_like "permit anonymous to index and show and admin everywhere else"
102
+ end
103
+
104
+ describe AccessControllingController4, :type => :controller do
105
+ it_should_behave_like "permit anonymous to index and show and admin everywhere else"
106
+ end
107
+
108
+ class MyDearFoo
109
+ include Singleton
110
+ end
111
+
112
+ class VenerableBar; end
113
+
114
+ class AccessControllingController5 < EmptyController
115
+ before_filter :set_ivars
116
+
117
+ access_control do
118
+ action :destroy do
119
+ allow :owner, :of => :foo
120
+ allow :bartender, :at => VenerableBar
121
+ end
122
+ end
123
+
124
+ private
125
+
126
+ def set_ivars
127
+ @foo = MyDearFoo.instance
128
+ end
129
+ end
130
+
131
+ describe AccessControllingController5, :type => :controller do
132
+ class OwnerOfFoo
133
+ def has_role?(role, obj)
134
+ role == 'owner' && obj == MyDearFoo.instance
135
+ end
136
+ end
137
+
138
+ class Bartender
139
+ def has_role?(role, obj)
140
+ role == 'bartender' && obj == VenerableBar
141
+ end
142
+ end
143
+
144
+ it "should allow owner of foo to destroy" do
145
+ delete :destroy, :user => OwnerOfFoo.new
146
+ end
147
+
148
+ it "should allow bartender to destroy" do
149
+ delete :destroy, :user => Bartender.new
150
+ end
151
+ end
152
+
153
+ class TheOnlyUser
154
+ include Singleton
155
+
156
+ def has_role?(role, subj)
157
+ role == "the_only_one"
158
+ end
159
+ end
160
+
161
+ class AccessControllingController6 < ActionController::Base
162
+ access_control :subject_method => :the_only_user do
163
+ allow :the_only_one
164
+ end
165
+
166
+ def index; end
167
+
168
+ private
169
+
170
+ def the_only_user
171
+ params[:user]
172
+ end
173
+ end
174
+
175
+ describe AccessControllingController6, :type => :controller do
176
+ it "should allow the only user to index" do
177
+ get :index, :user => TheOnlyUser.instance
178
+ end
179
+
180
+ it "should deny anonymous to index" do
181
+ lambda do
182
+ get :index
183
+ end.should raise_error(Acl9::AccessDenied)
184
+ end
185
+ end
data/spec/db/schema.rb ADDED
@@ -0,0 +1,47 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table "roles", :force => true do |t|
3
+ t.string "name", :limit => 40
4
+ t.string "authorizable_type", :limit => 40
5
+ t.integer "authorizable_id"
6
+ t.datetime "created_at"
7
+ t.datetime "updated_at"
8
+ end
9
+
10
+ create_table "another_roles", :force => true do |t|
11
+ t.string "name", :limit => 40
12
+ t.string "authorizable_type", :limit => 40
13
+ t.integer "authorizable_id"
14
+ t.datetime "created_at"
15
+ t.datetime "updated_at"
16
+ end
17
+
18
+ create_table "users", :force => true do |t| end
19
+ create_table "another_subjects", :force => true do |t| end
20
+
21
+ create_table "roles_users", :id => false, :force => true do |t|
22
+ t.integer "user_id"
23
+ t.integer "role_id"
24
+ t.datetime "created_at"
25
+ t.datetime "updated_at"
26
+ end
27
+
28
+ create_table "another_roles_another_subjects", :id => false, :force => true do |t|
29
+ t.integer "another_subject_id"
30
+ t.integer "another_role_id"
31
+ t.datetime "created_at"
32
+ t.datetime "updated_at"
33
+ end
34
+ create_table "foos", :force => true do |t|
35
+ t.datetime "created_at"
36
+ t.datetime "updated_at"
37
+ end
38
+
39
+ create_table "bars", :force => true do |t|
40
+ t.datetime "created_at"
41
+ t.datetime "updated_at"
42
+ end
43
+ create_table "foo_bars", :force => true do |t|
44
+ t.datetime "created_at"
45
+ t.datetime "updated_at"
46
+ end
47
+ end
@@ -0,0 +1,707 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'acl9', 'controller_extensions', 'filter_producer')
3
+
4
+ class FakeUser
5
+ def initialize
6
+ @roles = {}
7
+ end
8
+
9
+ def has_role?(role, object = nil)
10
+ @roles.include?([role.to_s, object])
11
+ end
12
+
13
+ def <<(role)
14
+ role = [role] unless role.is_a? Array
15
+
16
+ role << nil if role.size == 1
17
+ raise unless role[0]
18
+
19
+ role[0] = role[0].to_s
20
+
21
+ @roles[role] = true
22
+ end
23
+ end
24
+
25
+ class FakeFoo; end
26
+ class FakeBar; end
27
+
28
+ module PermissionChecks
29
+ class FakeController
30
+ attr_reader :current_user, :action_name
31
+
32
+ def initialize(user, *args)
33
+ @current_user = user
34
+ @action_name = (args[0] || 'index').to_s
35
+
36
+ ivars = args.last.is_a?(Hash) ? args.last : {}
37
+
38
+ for name, value in ivars
39
+ instance_variable_set "@#{name}", value
40
+ end
41
+ end
42
+ end
43
+
44
+ def permit(user, *args)
45
+ run(user, *args).should_not == false
46
+
47
+ self
48
+ end
49
+
50
+ def forbid(user, *args)
51
+ begin
52
+ run(user, *args)
53
+
54
+ raise "User #{user.inspect} was permitted, but should not have been to"
55
+ rescue Acl9::AccessDenied
56
+ # ok here
57
+ end
58
+
59
+ self
60
+ end
61
+
62
+ def show_code
63
+ puts "\n", self.to_s
64
+ self
65
+ end
66
+
67
+ private
68
+
69
+ def run(user, *args)
70
+ self.to_proc.call(FakeController.new(user, *args))
71
+ end
72
+
73
+ end
74
+
75
+ describe Acl9::FilterProducer do
76
+ describe "dsl" do
77
+ before do
78
+ @user = FakeUser.new
79
+ @user2 = FakeUser.new
80
+ @user3 = FakeUser.new
81
+ @foo = FakeFoo.new
82
+ @foo2 = FakeFoo.new
83
+ @foo3 = FakeFoo.new
84
+ end
85
+
86
+ describe "default" do
87
+ it "should set default action to deny if none specified" do
88
+ acl do end.default_action.should == :deny
89
+ end
90
+
91
+ it "should set default action to allow" do
92
+ acl do
93
+ default :allow
94
+ end.default_action.should == :allow
95
+ end
96
+
97
+ it "should set default action to deny" do
98
+ acl do
99
+ default :deny
100
+ end.default_action.should == :deny
101
+ end
102
+
103
+ it "should raise ArgumentError with unknown default_action" do
104
+ arg_err do
105
+ default 123
106
+ end
107
+ end
108
+
109
+ it "should raise ArgumentError when default is called more than once" do
110
+ arg_err do
111
+ default :deny
112
+ default :deny
113
+ end
114
+ end
115
+ end
116
+
117
+ describe "empty blocks" do
118
+ it "should deny everyone with default deny" do
119
+ acl do
120
+ end.forbid(nil).forbid(@user)
121
+ end
122
+
123
+ it "should allow everyone with default allow" do
124
+ acl do
125
+ default :allow
126
+ end.permit(nil).permit(@user)
127
+ end
128
+ end
129
+
130
+ describe "empty" do
131
+ it "allow should raise an ArgumentError" do
132
+ arg_err { allow }
133
+ end
134
+
135
+ it "deny should raise an ArgumentError" do
136
+ arg_err { deny }
137
+ end
138
+ end
139
+
140
+ describe "anonymous" do
141
+ it "'allow nil' should allow anonymous, but not logged in" do
142
+ acl do
143
+ allow nil
144
+ end.permit(nil).forbid(@user)
145
+ end
146
+
147
+ it "'allow anonymous' should allow anonymous, but not logged in" do
148
+ acl do
149
+ allow anonymous
150
+ end.permit(nil).forbid(@user)
151
+ end
152
+
153
+ it "'deny nil' should deny anonymous, but not logged in" do
154
+ acl do
155
+ default :allow
156
+ deny nil
157
+ end.forbid(nil).permit(@user)
158
+ end
159
+
160
+ it "'deny anonymous' should deny anonymous, but not logged in" do
161
+ acl do
162
+ default :allow
163
+ deny anonymous
164
+ end.forbid(nil).permit(@user)
165
+ end
166
+ end
167
+
168
+ describe "all" do
169
+ it "'allow all' should allow all" do
170
+ acl do
171
+ allow all
172
+ end.permit(nil).permit(@user)
173
+ end
174
+
175
+ it "'deny all' should deny all" do
176
+ acl do
177
+ default :allow
178
+ deny all
179
+ end.forbid(nil).forbid(@user)
180
+ end
181
+ end
182
+
183
+ describe "default :allow" do
184
+ it "should allow when neither allow nor deny conditions are matched" do
185
+ acl do
186
+ default :allow
187
+ allow :blah
188
+ deny :bzz
189
+ end.permit(nil).permit(@user)
190
+ end
191
+
192
+ it "should deny when deny is matched, but allow is not" do
193
+ acl do
194
+ default :allow
195
+ deny all
196
+ allow :blah
197
+ end.forbid(nil).forbid(@user)
198
+ end
199
+
200
+ it "should allow when allow is matched, but deny is not" do
201
+ @user << :cool
202
+ acl do
203
+ default :allow
204
+ deny nil
205
+ allow :cool
206
+ end.permit(@user)
207
+ end
208
+
209
+ it "should allow both allow and deny conditions are matched" do
210
+ @user << :cool
211
+ acl do
212
+ default :allow
213
+ deny :cool
214
+ allow :cool
215
+ end.permit(@user)
216
+
217
+ acl do
218
+ default :allow
219
+ deny all
220
+ allow all
221
+ end.permit(@user).permit(nil).permit(@user2)
222
+ end
223
+ end
224
+
225
+ describe "logged_in" do
226
+ it "'allow logged_in' should allow logged in, but not anonymous" do
227
+ acl do
228
+ allow logged_in
229
+ end.forbid(nil).permit(@user)
230
+ end
231
+
232
+ it "'allow logged_in' should deny logged in, but not anonymous" do
233
+ acl do
234
+ default :allow
235
+ deny logged_in
236
+ end.permit(nil).forbid(@user)
237
+ end
238
+ end
239
+
240
+ describe "default :deny" do
241
+ it "should deny when neither allow nor deny conditions are matched" do
242
+ acl do
243
+ default :deny
244
+ allow :blah
245
+ deny :bzz
246
+ end.forbid(nil).forbid(@user)
247
+ end
248
+
249
+ it "should deny when deny is matched, but allow is not" do
250
+ acl do
251
+ default :deny
252
+ deny all
253
+ allow :blah
254
+ end.forbid(nil).forbid(@user)
255
+ end
256
+
257
+ it "should allow when allow is matched, but deny is not" do
258
+ @user << :cool
259
+ acl do
260
+ default :deny
261
+ deny nil
262
+ allow :cool
263
+ end.permit(@user)
264
+ end
265
+
266
+ it "should deny both allow and deny conditions are matched" do
267
+ @user << :cool
268
+ acl do
269
+ default :deny
270
+ deny :cool
271
+ allow :cool
272
+ end.forbid(@user)
273
+
274
+ acl do
275
+ default :deny
276
+ deny all
277
+ allow all
278
+ end.forbid(@user).forbid(nil).forbid(@user2)
279
+ end
280
+ end
281
+
282
+ describe "global roles" do
283
+ it "#allow with role" do
284
+ @user << :admin
285
+
286
+ acl { allow :admin }.permit(@user).forbid(nil).forbid(@user2)
287
+ end
288
+
289
+ it "#allow with plural role name" do
290
+ @user << :mouse
291
+
292
+ acl do
293
+ allow :mice
294
+ end.permit(@user).forbid(nil).forbid(@user2)
295
+ end
296
+
297
+ it "#allow with several roles" do
298
+ @user << :admin
299
+ @user << :cool
300
+
301
+ @user2 << :cool
302
+
303
+ @user3 << :super
304
+
305
+ acl do
306
+ allow :admin
307
+ allow :cool
308
+ end.permit(@user).permit(@user2).forbid(nil).forbid(@user3)
309
+ end
310
+
311
+ it "#deny with role" do
312
+ @user << :foo
313
+
314
+ acl { default :allow; deny :foo }.forbid(@user).permit(nil).permit(@user2)
315
+ end
316
+
317
+ it "#deny with plural role name" do
318
+ @user << :mouse
319
+
320
+ acl do
321
+ default :allow
322
+ deny :mice
323
+ end.forbid(@user).permit(nil).permit(@user2)
324
+ end
325
+
326
+ it "#deny with several roles" do
327
+ @user << :admin
328
+ @user << :cool
329
+
330
+ @user2 << :cool
331
+
332
+ @user3 << :super
333
+
334
+ acl do
335
+ default :allow
336
+ deny :admin
337
+ deny :cool
338
+ end.forbid(@user).forbid(@user2).permit(nil).permit(@user3)
339
+ end
340
+ end
341
+
342
+ describe "prepositions" do
343
+ [:of, :for, :in, :on, :at, :by].each do |prep|
344
+ it "#allow with object role (:#{prep}) should check controller's ivar" do
345
+ @user << [:manager, @foo]
346
+
347
+ acl do
348
+ allow :manager, prep => :foo
349
+ end.
350
+ permit(@user, :foo => @foo).
351
+ forbid(@user, :foo => @foo2).
352
+ forbid(@user, :foo => FakeFoo).
353
+ forbid(nil, :foo => @foo).
354
+ forbid(@user2, :foo => @foo)
355
+ end
356
+
357
+ it "#allow with invalid value for preposition should raise an ArgumentError" do
358
+ arg_err do
359
+ allow :hom, :by => 1
360
+ end
361
+ end
362
+ end
363
+
364
+ it "#allow with a class role should verify this role against a class" do
365
+ @user << [:owner, FakeFoo]
366
+
367
+ acl do
368
+ allow :owner, :of => FakeFoo
369
+ end.permit(@user).forbid(nil).forbid(@user2)
370
+ end
371
+
372
+ [:of, :for, :in, :on, :at, :by].each do |prep|
373
+ it "#deny with object role (:#{prep}) should check controller's ivar" do
374
+ @user << [:bastard, @foo]
375
+
376
+ acl do
377
+ default :allow
378
+ deny :bastard, prep => :foo
379
+ end.
380
+ forbid(@user, :foo => @foo).
381
+ permit(@user, :foo => @foo2).
382
+ permit(@user, :foo => FakeFoo).
383
+ permit(nil, :foo => @foo).
384
+ permit(@user2, :foo => @foo)
385
+ end
386
+
387
+ it "#deny with invalid value for preposition should raise an ArgumentError" do
388
+ arg_err do
389
+ deny :her, :for => "him"
390
+ end
391
+ end
392
+ end
393
+
394
+ it "#deny with a class role should verify this role against a class" do
395
+ @user << [:ignorant, FakeFoo]
396
+
397
+ acl do
398
+ default :allow
399
+ deny :ignorant, :of => FakeFoo
400
+ end.forbid(@user).permit(nil).permit(@user2)
401
+ end
402
+
403
+ it "#allow with several prepositions should raise an ArgumentError" do
404
+ arg_err do
405
+ allow :some, :by => :one, :for => :another
406
+ end
407
+ end
408
+
409
+ it "#deny with several prepositions should raise an ArgumentError" do
410
+ arg_err do
411
+ deny :some, :in => :here, :on => :today
412
+ end
413
+ end
414
+ end
415
+
416
+ describe ":to and :except" do
417
+ it "should raise an ArgumentError when both :to and :except are specified" do
418
+ arg_err do
419
+ allow all, :to => :index, :except => ['show', 'edit']
420
+ end
421
+ end
422
+
423
+ describe do
424
+ after do
425
+ %w(index show).each { |act| @list.permit(nil, act) }
426
+ %w(edit update delete destroy).each { |act| @list.forbid(nil, act) }
427
+
428
+ %w(index show edit update).each { |act| @list.permit(@user, act) }
429
+ %w(delete destroy).each { |act| @list.forbid(@user, act) }
430
+
431
+ %w(index show edit update delete destroy).each { |act| @list.permit(@user2, act) }
432
+ end
433
+
434
+ it ":to should limit rule scope to specified actions" do
435
+ @user << :manager
436
+ @user2 << :trusted
437
+
438
+ @list = acl do
439
+ allow all, :to => [:index, :show]
440
+
441
+ allow 'manager', :to => :edit
442
+ allow 'manager', :to => 'update'
443
+ allow 'trusted', :to => %w(edit update delete destroy)
444
+ end
445
+ end
446
+
447
+ it ":except should limit rule scope to all actions except specified" do
448
+ @user << :manager
449
+ @user2 << :trusted
450
+
451
+ @list = acl do
452
+ allow all, :except => %w(edit update delete destroy)
453
+
454
+ allow 'manager', :except => %w(delete destroy)
455
+ allow 'trusted'
456
+ end
457
+ end
458
+ end
459
+ end
460
+
461
+ describe "several roles as arguments" do
462
+ it "#allow should be able to receive a role list (global roles)" do
463
+ @user << :bzz
464
+ @user2 << :whoa
465
+
466
+ acl do
467
+ allow :bzz, :whoa
468
+ end.permit(@user).permit(@user2).forbid(nil).forbid(@user3)
469
+ end
470
+
471
+ it "#allow should be able to receive a role list (object roles)" do
472
+ @user << [:maker, @foo]
473
+ @user2 << [:faker, @foo2]
474
+
475
+ acl do
476
+ allow :maker, :faker, :of => :foo
477
+ end.
478
+ permit(@user, :foo => @foo).
479
+ forbid(@user, :foo => @foo2).
480
+ permit(@user2, :foo => @foo2).
481
+ forbid(@user2, :foo => @foo).
482
+ forbid(@user3, :foo => @foo).
483
+ forbid(@user3, :foo => @foo2).
484
+ forbid(nil)
485
+ end
486
+
487
+ it "#allow should be able to receive a role list (class roles)" do
488
+ @user << [:frooble, FakeFoo]
489
+ @user2 << [:oombigle, FakeFoo]
490
+ @user3 << :frooble
491
+
492
+ acl do
493
+ allow :frooble, :oombigle, :by => FakeFoo
494
+ end.
495
+ permit(@user).
496
+ permit(@user2).
497
+ forbid(@user3).
498
+ forbid(nil)
499
+ end
500
+
501
+ it "#deny should be able to receive a role list (global roles)" do
502
+ @user << :bzz
503
+ @user2 << :whoa
504
+
505
+ acl do
506
+ default :allow
507
+ deny :bzz, :whoa
508
+ end.forbid(@user).forbid(@user2).permit(nil).permit(@user3)
509
+ end
510
+
511
+ it "#deny should be able to receive a role list (object roles)" do
512
+ @user << [:maker, @foo]
513
+ @user2 << [:faker, @foo2]
514
+ @user3 = FakeUser.new
515
+
516
+ acl do
517
+ default :allow
518
+ deny :maker, :faker, :of => :foo
519
+ end.
520
+ forbid(@user, :foo => @foo).
521
+ permit(@user, :foo => @foo2).
522
+ forbid(@user2, :foo => @foo2).
523
+ permit(@user2, :foo => @foo).
524
+ permit(@user3, :foo => @foo).
525
+ permit(@user3, :foo => @foo2).
526
+ permit(nil)
527
+ end
528
+
529
+ it "#deny should be able to receive a role list (class roles)" do
530
+ @user << [:frooble, FakeFoo]
531
+ @user2 << [:oombigle, FakeFoo]
532
+ @user3 << :frooble
533
+
534
+ acl do
535
+ default :allow
536
+ deny :frooble, :oombigle, :by => FakeFoo
537
+ end.
538
+ forbid(@user).
539
+ forbid(@user2).
540
+ permit(@user3).
541
+ permit(nil)
542
+ end
543
+
544
+ it "should also respect :to and :except" do
545
+ class Moo; end
546
+
547
+ @user << :foo
548
+ @user2 << [:joo, @foo]
549
+ @user3 << [:qoo, Moo]
550
+
551
+ acl do
552
+ allow :foo, :boo, :to => [:index, :show]
553
+ allow :zoo, :joo, :by => :foo, :to => [:edit, :update]
554
+ allow :qoo, :woo, :of => Moo
555
+ deny :qoo, :woo, :of => Moo, :except => [:delete, :destroy]
556
+ end.
557
+ permit(@user, 'index').
558
+ permit(@user, 'show').
559
+ forbid(@user, 'edit').
560
+ permit(@user2, 'edit', :foo => @foo).
561
+ permit(@user2, 'update', :foo => @foo).
562
+ forbid(@user2, 'show', :foo => @foo).
563
+ forbid(@user2, 'show').
564
+ permit(@user3, 'delete').
565
+ permit(@user3, 'destroy').
566
+ forbid(@user3, 'edit').
567
+ forbid(@user3, 'show')
568
+ end
569
+ end
570
+
571
+ describe "actions block" do
572
+ it "should raise an ArgumentError when actions has no block" do
573
+ arg_err do
574
+ actions :foo, :bar
575
+ end
576
+ end
577
+
578
+ it "should raise an ArgumentError when actions has no arguments" do
579
+ arg_err do
580
+ actions do end
581
+ end
582
+ end
583
+
584
+ it "should raise an ArgumentError when actions is called inside actions block" do
585
+ arg_err do
586
+ actions :foo, :bar do
587
+ actions :foo, :bar do
588
+ end
589
+ end
590
+ end
591
+ end
592
+
593
+ it "should raise an ArgumentError when default is called inside actions block" do
594
+ arg_err do
595
+ actions :foo, :bar do
596
+ default :allow
597
+ end
598
+ end
599
+ end
600
+
601
+ [:to, :except].each do |opt|
602
+ it "should raise an ArgumentError when allow is called with #{opt} option" do
603
+ arg_err do
604
+ actions :foo do
605
+ allow all, opt => :bar
606
+ end
607
+ end
608
+ end
609
+
610
+ it "should raise an ArgumentError when deny is called with #{opt} option" do
611
+ arg_err do
612
+ actions :foo do
613
+ deny all, opt => :bar
614
+ end
615
+ end
616
+ end
617
+ end
618
+
619
+ it "empty actions block should do nothing" do
620
+ acl do
621
+ actions :foo do
622
+ end
623
+
624
+ allow all
625
+ end.permit(nil).permit(nil, :foo)
626
+ end
627
+
628
+ it "#allow should limit its scope to specified actions" do
629
+ @user << :bee
630
+
631
+ acl do
632
+ actions :edit do
633
+ allow :bee
634
+ end
635
+ end.
636
+ permit(@user, :edit).
637
+ forbid(@user, :update)
638
+ end
639
+
640
+ it "#deny should limit its scope to specified actions" do
641
+ @user << :bee
642
+
643
+ acl do
644
+ default :allow
645
+ actions :edit do
646
+ deny :bee
647
+ end
648
+ end.
649
+ forbid(@user, :edit).
650
+ permit(@user, :update)
651
+ end
652
+
653
+ it "#allow and #deny should work together inside actions block" do
654
+ @foo = FakeFoo.new
655
+ @user << [:owner, @foo]
656
+ @user2 << :hacker
657
+ @user2 << :the_destroyer
658
+ @user3 << [:owner, @foo]
659
+ @user3 << :hacker
660
+
661
+ list = acl do
662
+ actions :show, :index do
663
+ allow all
664
+ end
665
+
666
+ actions :edit, :update do
667
+ allow :owner, :of => :object
668
+ deny :hacker
669
+ end
670
+
671
+ actions :delete, :destroy do
672
+ allow :owner, :of => :object
673
+ allow :the_destroyer
674
+ end
675
+ end
676
+
677
+ @all_actions = %w(show index edit update delete destroy)
678
+
679
+ permit_some(list, @user, @all_actions, :object => @foo)
680
+ permit_some(list, @user2, %w(show index delete destroy))
681
+ permit_some(list, @user3, %w(show index delete destroy), :object => @foo)
682
+ end
683
+ end
684
+
685
+ private
686
+
687
+ def acl(meth = :current_user, &block)
688
+ producer = Acl9::FilterProducer.new(meth)
689
+ producer.acl(&block)
690
+
691
+ producer.extend(PermissionChecks)
692
+
693
+ producer
694
+ end
695
+
696
+ def arg_err(&block)
697
+ lambda do
698
+ acl(&block)
699
+ end.should raise_error(ArgumentError)
700
+ end
701
+
702
+ def permit_some(list, user, actions, vars = {})
703
+ actions.each { |act| list.permit(user, act, vars) }
704
+ (@all_actions - actions).each { |act| list.forbid(user, act, vars) }
705
+ end
706
+ end
707
+ end