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