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
data/spec/roles_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: be9-acl9
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Dashevskii
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-01-
|
12
|
+
date: 2009-01-14 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -37,36 +37,40 @@ executables: []
|
|
37
37
|
extensions: []
|
38
38
|
|
39
39
|
extra_rdoc_files:
|
40
|
-
- lib/acl9/
|
40
|
+
- lib/acl9/model_extensions.rb
|
41
|
+
- lib/acl9/version.rb
|
41
42
|
- lib/acl9/model_extensions/subject.rb
|
42
43
|
- lib/acl9/model_extensions/object.rb
|
44
|
+
- lib/acl9/controller_extensions/generators.rb
|
45
|
+
- lib/acl9/controller_extensions/dsl_base.rb
|
46
|
+
- lib/acl9/config.rb
|
43
47
|
- lib/acl9/controller_extensions.rb
|
44
|
-
- lib/acl9/controller_extensions/filter_producer.rb
|
45
|
-
- lib/acl9/version.rb
|
46
|
-
- lib/acl9/model_extensions.rb
|
47
48
|
- lib/acl9.rb
|
48
49
|
- README.textile
|
50
|
+
- CHANGELOG.textile
|
49
51
|
files:
|
50
|
-
-
|
52
|
+
- init.rb
|
53
|
+
- Manifest
|
54
|
+
- lib/acl9/model_extensions.rb
|
55
|
+
- lib/acl9/version.rb
|
51
56
|
- lib/acl9/model_extensions/subject.rb
|
52
57
|
- lib/acl9/model_extensions/object.rb
|
58
|
+
- lib/acl9/controller_extensions/generators.rb
|
59
|
+
- lib/acl9/controller_extensions/dsl_base.rb
|
60
|
+
- lib/acl9/config.rb
|
53
61
|
- lib/acl9/controller_extensions.rb
|
54
|
-
- lib/acl9/controller_extensions/filter_producer.rb
|
55
|
-
- lib/acl9/version.rb
|
56
|
-
- lib/acl9/model_extensions.rb
|
57
62
|
- lib/acl9.rb
|
63
|
+
- README.textile
|
64
|
+
- acl9.gemspec
|
65
|
+
- CHANGELOG.textile
|
66
|
+
- MIT-LICENSE
|
67
|
+
- Rakefile
|
58
68
|
- spec/db/schema.rb
|
59
|
-
- spec/
|
69
|
+
- spec/dsl_base_spec.rb
|
60
70
|
- spec/spec_helper.rb
|
61
|
-
- spec/models.rb
|
62
71
|
- spec/access_control_spec.rb
|
63
72
|
- spec/roles_spec.rb
|
64
|
-
-
|
65
|
-
- MIT-LICENSE
|
66
|
-
- Rakefile
|
67
|
-
- README.textile
|
68
|
-
- init.rb
|
69
|
-
- acl9.gemspec
|
73
|
+
- spec/models.rb
|
70
74
|
has_rdoc: true
|
71
75
|
homepage: http://github.com/be9/acl9
|
72
76
|
post_install_message:
|
@@ -1,244 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
module Acl9
|
4
|
-
class AccessDenied < Exception; end
|
5
|
-
class FilterSyntaxError < Exception; end
|
6
|
-
|
7
|
-
class FilterProducer
|
8
|
-
attr_reader :allows, :denys
|
9
|
-
|
10
|
-
def initialize(subject_method)
|
11
|
-
@subject_method = subject_method
|
12
|
-
@default_action = nil
|
13
|
-
@allows = []
|
14
|
-
@denys = []
|
15
|
-
|
16
|
-
@subject = "controller.send(:#{subject_method})"
|
17
|
-
end
|
18
|
-
|
19
|
-
def acl(&acl_block)
|
20
|
-
self.instance_eval(&acl_block)
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_s
|
24
|
-
_allowance_check_expression
|
25
|
-
end
|
26
|
-
|
27
|
-
def to_proc
|
28
|
-
code = <<-RUBY
|
29
|
-
lambda do |controller|
|
30
|
-
unless #{self.to_s}
|
31
|
-
raise Acl9::AccessDenied
|
32
|
-
end
|
33
|
-
end
|
34
|
-
RUBY
|
35
|
-
|
36
|
-
self.instance_eval(code, __FILE__, __LINE__)
|
37
|
-
rescue SyntaxError
|
38
|
-
raise FilterSyntaxError, code
|
39
|
-
end
|
40
|
-
|
41
|
-
def to_method_code(method_name, filter = true)
|
42
|
-
body = if filter
|
43
|
-
"unless #{self.to_s}; raise Acl9::AccessDenied; end"
|
44
|
-
else
|
45
|
-
self.to_s
|
46
|
-
end
|
47
|
-
|
48
|
-
<<-RUBY
|
49
|
-
def #{method_name}
|
50
|
-
controller = self
|
51
|
-
#{body}
|
52
|
-
end
|
53
|
-
RUBY
|
54
|
-
end
|
55
|
-
|
56
|
-
def default_action
|
57
|
-
@default_action.nil? ? :deny : @default_action
|
58
|
-
end
|
59
|
-
|
60
|
-
protected
|
61
|
-
|
62
|
-
def default(default_action)
|
63
|
-
raise ArgumentError, "default can only be called once in access_control block" if @default_action
|
64
|
-
|
65
|
-
unless [:allow, :deny].include? default_action
|
66
|
-
raise ArgumentError, "invalid value for default (can be :allow or :deny)"
|
67
|
-
end
|
68
|
-
|
69
|
-
@default_action = default_action
|
70
|
-
end
|
71
|
-
|
72
|
-
def allow(*args)
|
73
|
-
@current_rule = :allow
|
74
|
-
_parse_and_add_rule(*args)
|
75
|
-
end
|
76
|
-
|
77
|
-
def deny(*args)
|
78
|
-
@current_rule = :deny
|
79
|
-
_parse_and_add_rule(*args)
|
80
|
-
end
|
81
|
-
|
82
|
-
def actions(*args, &block)
|
83
|
-
raise ArgumentError, "actions should receive at least 1 action as argument" if args.size < 1
|
84
|
-
|
85
|
-
subsidiary = FilterProducer.new(@subject_method)
|
86
|
-
|
87
|
-
class <<subsidiary
|
88
|
-
def actions(*args)
|
89
|
-
raise ArgumentError, "You cannot use actions inside another actions block"
|
90
|
-
end
|
91
|
-
|
92
|
-
def default(*args)
|
93
|
-
raise ArgumentError, "You cannot use default inside an actions block"
|
94
|
-
end
|
95
|
-
|
96
|
-
def _set_action_clause(to, except)
|
97
|
-
raise ArgumentError, "You cannot use :to/:except inside actions block" if to || except
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
subsidiary.acl(&block)
|
102
|
-
|
103
|
-
action_check = _action_check_expression(args)
|
104
|
-
|
105
|
-
squash = lambda do |rules|
|
106
|
-
_either_of(rules) + ' && ' + action_check
|
107
|
-
end
|
108
|
-
|
109
|
-
@allows << squash.call(subsidiary.allows) if subsidiary.allows.size > 0
|
110
|
-
@denys << squash.call(subsidiary.denys) if subsidiary.denys.size > 0
|
111
|
-
end
|
112
|
-
|
113
|
-
alias action actions
|
114
|
-
|
115
|
-
def anonymous
|
116
|
-
nil
|
117
|
-
end
|
118
|
-
|
119
|
-
def all
|
120
|
-
true
|
121
|
-
end
|
122
|
-
|
123
|
-
def logged_in
|
124
|
-
false
|
125
|
-
end
|
126
|
-
|
127
|
-
private
|
128
|
-
|
129
|
-
def _parse_and_add_rule(*args)
|
130
|
-
options = if args.last.is_a? Hash
|
131
|
-
args.pop
|
132
|
-
else
|
133
|
-
{}
|
134
|
-
end
|
135
|
-
|
136
|
-
_set_action_clause(options.delete(:to), options.delete(:except))
|
137
|
-
|
138
|
-
object = _role_object(options)
|
139
|
-
|
140
|
-
role_checks = args.map do |who|
|
141
|
-
case who
|
142
|
-
when nil then "#{@subject}.nil?" # anonymous
|
143
|
-
when false then "!#{@subject}.nil?" # logged_in
|
144
|
-
when true then "true" # all
|
145
|
-
else
|
146
|
-
"!#{@subject}.nil? && #{@subject}.has_role?('#{who.to_s.singularize}', #{object})"
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
_add_rule case role_checks.size
|
151
|
-
when 0
|
152
|
-
raise ArgumentError, "allow/deny should have at least 1 argument"
|
153
|
-
when 1 then role_checks.first
|
154
|
-
else
|
155
|
-
_either_of(role_checks)
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def _either_of(exprs)
|
160
|
-
exprs.map { |expr| "(#{expr})" }.join(' || ')
|
161
|
-
end
|
162
|
-
|
163
|
-
def _add_rule(what)
|
164
|
-
what = "(#{what}) && #{@action_clause}" if @action_clause
|
165
|
-
|
166
|
-
(@current_rule == :allow ? @allows : @denys) << what
|
167
|
-
end
|
168
|
-
|
169
|
-
def _set_action_clause(to, except)
|
170
|
-
raise ArgumentError, "both :to and :except cannot be specified in the rule" if to && except
|
171
|
-
|
172
|
-
@action_clause = nil
|
173
|
-
|
174
|
-
action_list = to || except
|
175
|
-
return unless action_list
|
176
|
-
|
177
|
-
expr = _action_check_expression(action_list)
|
178
|
-
|
179
|
-
@action_clause = if to
|
180
|
-
"#{expr}"
|
181
|
-
else
|
182
|
-
"!#{expr}"
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
def _action_check_expression(action_list)
|
187
|
-
unless action_list.is_a?(Array)
|
188
|
-
action_list = [ action_list.to_s ]
|
189
|
-
end
|
190
|
-
|
191
|
-
case action_list.size
|
192
|
-
when 0 then "true"
|
193
|
-
when 1 then "(controller.action_name == '#{action_list.first}')"
|
194
|
-
else
|
195
|
-
set_of_actions = "Set.new([" + action_list.map { |act| "'#{act}'"}.join(',') + "])"
|
196
|
-
|
197
|
-
"#{set_of_actions}.include?(controller.action_name)"
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
VALID_PREPOSITIONS = %w(of for in on at by).freeze unless defined? VALID_PREPOSITIONS
|
202
|
-
|
203
|
-
def _role_object(options)
|
204
|
-
object = nil
|
205
|
-
|
206
|
-
VALID_PREPOSITIONS.each do |prep|
|
207
|
-
if options[prep.to_sym]
|
208
|
-
raise ArgumentError, "You may only use one preposition to specify object" if object
|
209
|
-
|
210
|
-
object = options[prep.to_sym]
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
case object
|
215
|
-
when Class
|
216
|
-
object.to_s
|
217
|
-
when Symbol
|
218
|
-
"controller.instance_variable_get('@#{object}')"
|
219
|
-
when nil
|
220
|
-
"nil"
|
221
|
-
else
|
222
|
-
raise ArgumentError, "object specified by preposition can only be a Class or a Symbol"
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def _allowance_check_expression
|
227
|
-
allowed_expr = if @allows.size > 0
|
228
|
-
@allows.map { |clause| "(#{clause})" }.join(' || ')
|
229
|
-
else
|
230
|
-
"false"
|
231
|
-
end
|
232
|
-
|
233
|
-
not_denied_expr = if @denys.size > 0
|
234
|
-
@denys.map { |clause| "!(#{clause})" }.join(' && ')
|
235
|
-
else
|
236
|
-
"true"
|
237
|
-
end
|
238
|
-
|
239
|
-
[allowed_expr, not_denied_expr].
|
240
|
-
map { |expr| "(#{expr})" }.
|
241
|
-
join(default_action == :deny ? ' && ' : ' || ')
|
242
|
-
end
|
243
|
-
end
|
244
|
-
end
|
@@ -1,707 +0,0 @@
|
|
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
|