cancan 1.6.7 → 1.6.8.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +67 -0
- data/Gemfile +1 -1
- data/README.rdoc +10 -1
- data/lib/cancan/ability.rb +7 -0
- data/lib/cancan/controller_additions.rb +5 -2
- data/lib/cancan/controller_resource.rb +21 -5
- data/lib/cancan/inherited_resource.rb +2 -1
- data/lib/cancan/model_adapters/active_record_adapter.rb +6 -1
- data/lib/cancan/model_adapters/mongoid_adapter.rb +2 -1
- data/lib/cancan/rule.rb +7 -3
- data/spec/cancan/ability_spec.rb +31 -2
- data/spec/cancan/controller_additions_spec.rb +4 -4
- data/spec/cancan/controller_resource_spec.rb +38 -2
- data/spec/cancan/exceptions_spec.rb +4 -4
- data/spec/cancan/inherited_resource_spec.rb +18 -0
- data/spec/cancan/model_adapters/active_record_adapter_spec.rb +11 -1
- data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +13 -2
- data/spec/cancan/rule_spec.rb +8 -0
- data/spec/spec_helper.rb +16 -1
- metadata +10 -6
data/CHANGELOG.rdoc
CHANGED
@@ -1,7 +1,26 @@
|
|
1
|
+
1.6.8 (unreleased)
|
2
|
+
|
3
|
+
* improved support for namespaced controllers and models
|
4
|
+
|
5
|
+
* pass :if and :unless options for load and authorize resource (thanks mauriciozaffari)
|
6
|
+
|
7
|
+
* Travis CI badge (thanks plentz)
|
8
|
+
|
9
|
+
* adding Ability#merge for combining multiple abilities (thanks rogercampos)
|
10
|
+
|
11
|
+
* support for multiple MetaWhere rules (thanks andhapp)
|
12
|
+
|
13
|
+
* various fixes for DataMapper, Mongoid, and Inherited Resource integration
|
14
|
+
|
15
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.7...master]
|
16
|
+
|
17
|
+
|
1
18
|
1.6.7 (October 4, 2011)
|
2
19
|
|
3
20
|
* fixing nested resource problem caused by namespace addition - issue #482
|
4
21
|
|
22
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.6...1.6.7]
|
23
|
+
|
5
24
|
|
6
25
|
1.6.6 (September 28, 2011)
|
7
26
|
|
@@ -21,6 +40,8 @@
|
|
21
40
|
|
22
41
|
* allow :find_by option to be full find method name - issue #335
|
23
42
|
|
43
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.5...1.6.6]
|
44
|
+
|
24
45
|
|
25
46
|
1.6.5 (May 18, 2011)
|
26
47
|
|
@@ -38,11 +59,15 @@
|
|
38
59
|
|
39
60
|
* improve scope merging - issue #328
|
40
61
|
|
62
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.4...1.6.5]
|
63
|
+
|
41
64
|
|
42
65
|
1.6.4 (March 29, 2011)
|
43
66
|
|
44
67
|
* Fixed mongoid 'or' error - see issue #322
|
45
68
|
|
69
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.3...1.6.4]
|
70
|
+
|
46
71
|
|
47
72
|
1.6.3 (March 25, 2011)
|
48
73
|
|
@@ -50,11 +75,15 @@
|
|
50
75
|
|
51
76
|
* Return subject passed to authorize! - see issue #314
|
52
77
|
|
78
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.2...1.6.3]
|
79
|
+
|
53
80
|
|
54
81
|
1.6.2 (March 18, 2011)
|
55
82
|
|
56
83
|
* Fixed instance loading when :singleton option is used - see issue #310
|
57
84
|
|
85
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.1...1.6.2]
|
86
|
+
|
58
87
|
|
59
88
|
1.6.1 (March 15, 2011)
|
60
89
|
|
@@ -64,6 +93,8 @@
|
|
64
93
|
|
65
94
|
* Reverted Inherited Resources "collection" override since it doesn't seem to be working - see issue #305
|
66
95
|
|
96
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.6.0...1.6.1]
|
97
|
+
|
67
98
|
|
68
99
|
1.6.0 (March 11, 2011)
|
69
100
|
|
@@ -85,6 +116,8 @@
|
|
85
116
|
|
86
117
|
* Raise an exception when trying to make a Ability condition with both a hash of conditions and a block - see issue #269
|
87
118
|
|
119
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.5.1...1.6.0]
|
120
|
+
|
88
121
|
|
89
122
|
1.5.1 (January 20, 2011)
|
90
123
|
|
@@ -92,6 +125,8 @@
|
|
92
125
|
|
93
126
|
* Improving Mongoid support for multiple can and cannot definitions (thanks stellard) - see issue #239
|
94
127
|
|
128
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.5.0...1.5.1]
|
129
|
+
|
95
130
|
|
96
131
|
1.5.0 (January 11, 2011)
|
97
132
|
|
@@ -113,6 +148,8 @@
|
|
113
148
|
|
114
149
|
* Internal: added .rvmrc to auto-switch to 1.8.7 with gemset - see issue #231
|
115
150
|
|
151
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.4.1...1.5.0]
|
152
|
+
|
116
153
|
|
117
154
|
1.4.1 (November 12, 2010)
|
118
155
|
|
@@ -126,6 +163,8 @@
|
|
126
163
|
|
127
164
|
* Fix odd behavior when "cache_classes = false" (thanks mphalliday) - see issue #174
|
128
165
|
|
166
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.4.0...1.4.1]
|
167
|
+
|
129
168
|
|
130
169
|
1.4.0 (October 5, 2010)
|
131
170
|
|
@@ -165,11 +204,15 @@
|
|
165
204
|
|
166
205
|
* No longer calling block in +can+ definition when checking on class - see issue #116
|
167
206
|
|
207
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.3.4...1.4.0]
|
208
|
+
|
168
209
|
|
169
210
|
1.3.4 (August 31, 2010)
|
170
211
|
|
171
212
|
* Don't stop at +cannot+ with hash conditions when checking class (thanks tamoya) - see issue #131
|
172
213
|
|
214
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.3.3...1.3.4]
|
215
|
+
|
173
216
|
|
174
217
|
1.3.3 (August 20, 2010)
|
175
218
|
|
@@ -177,16 +220,22 @@
|
|
177
220
|
|
178
221
|
* Pluralize nested associations for conditions in accessible_by (thanks mlooney) - see issue #123
|
179
222
|
|
223
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.3.2...1.3.3]
|
224
|
+
|
180
225
|
|
181
226
|
1.3.2 (August 7, 2010)
|
182
227
|
|
183
228
|
* Fixing slice error when passing in custom resource name - see issue #112
|
184
229
|
|
230
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.3.1...1.3.2]
|
231
|
+
|
185
232
|
|
186
233
|
1.3.1 (August 6, 2010)
|
187
234
|
|
188
235
|
* Fixing protected sanitize_sql error - see issue #111
|
189
236
|
|
237
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.3.0...1.3.1]
|
238
|
+
|
190
239
|
|
191
240
|
1.3.0 (August 6, 2010)
|
192
241
|
|
@@ -214,6 +263,8 @@
|
|
214
263
|
|
215
264
|
* Supporting deeply nested aliases - see issue #98
|
216
265
|
|
266
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.2.0...1.3.0]
|
267
|
+
|
217
268
|
|
218
269
|
1.2.0 (July 16, 2010)
|
219
270
|
|
@@ -229,11 +280,15 @@
|
|
229
280
|
|
230
281
|
* Adding joins clause to accessible_by when conditions are across associations
|
231
282
|
|
283
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.1.1...1.2.0]
|
284
|
+
|
232
285
|
|
233
286
|
1.1.1 (April 17, 2010)
|
234
287
|
|
235
288
|
* Fixing behavior in Rails 3 by properly initializing ResourceAuthorization
|
236
289
|
|
290
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.1...1.1.1]
|
291
|
+
|
237
292
|
|
238
293
|
1.1.0 (April 17, 2010)
|
239
294
|
|
@@ -257,6 +312,8 @@
|
|
257
312
|
|
258
313
|
* Support additional arguments to can? which get passed to the block - see issue #48
|
259
314
|
|
315
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.0.2...1.1]
|
316
|
+
|
260
317
|
|
261
318
|
1.0.2 (Dec 30, 2009)
|
262
319
|
|
@@ -266,6 +323,8 @@
|
|
266
323
|
|
267
324
|
* Adding custom message argument to unauthorized! method (thanks tjwallace) - see issue #18
|
268
325
|
|
326
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.0.1...1.0.2]
|
327
|
+
|
269
328
|
|
270
329
|
1.0.1 (Dec 14, 2009)
|
271
330
|
|
@@ -273,6 +332,8 @@
|
|
273
332
|
|
274
333
|
* Don't fetch parent of nested resource if *_id parameter is missing so it works with shallow nested routes - see issue #14
|
275
334
|
|
335
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/1.0.0...1.0.1]
|
336
|
+
|
276
337
|
|
277
338
|
1.0.0 (Dec 13, 2009)
|
278
339
|
|
@@ -288,6 +349,8 @@
|
|
288
349
|
|
289
350
|
* BACKWARDS INCOMPATIBLE: turning load and authorize resource methods into class methods which set up the before filter so they can accept additional arguments.
|
290
351
|
|
352
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/0.2.1...1.0.0]
|
353
|
+
|
291
354
|
|
292
355
|
0.2.1 (Nov 26, 2009)
|
293
356
|
|
@@ -297,6 +360,8 @@
|
|
297
360
|
|
298
361
|
* support custom objects (usually symbols) in can definition - see issue #8
|
299
362
|
|
363
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/0.2.0...0.2.1]
|
364
|
+
|
300
365
|
|
301
366
|
0.2.0 (Nov 17, 2009)
|
302
367
|
|
@@ -308,6 +373,8 @@
|
|
308
373
|
|
309
374
|
* BACKWARDS INCOMPATIBLE: use Ability#initialize instead of 'prepare' to set up abilities - see issue #4
|
310
375
|
|
376
|
+
* {see the full list of changes}[https://github.com/ryanb/cancan/compare/0.1.0...0.2.0]
|
377
|
+
|
311
378
|
|
312
379
|
0.1.0 (Nov 16, 2009)
|
313
380
|
|
data/Gemfile
CHANGED
data/README.rdoc
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
= CanCan
|
1
|
+
= CanCan {<img src="https://secure.travis-ci.org/ryanb/cancan.png" />}[http://travis-ci.org/ryanb/cancan]
|
2
2
|
|
3
3
|
Wiki[https://github.com/ryanb/cancan/wiki] | RDocs[http://rdoc.info/projects/ryanb/cancan] | Screencast[http://railscasts.com/episodes/192-authorization-with-cancan]
|
4
4
|
|
@@ -31,6 +31,15 @@ User permissions are defined in an +Ability+ class. CanCan 1.5 includes a Rails
|
|
31
31
|
|
32
32
|
rails g cancan:ability
|
33
33
|
|
34
|
+
In Rails 2.3, just add a new class in `app/models/ability.rb` with the folowing contents:
|
35
|
+
|
36
|
+
class Ability
|
37
|
+
include CanCan::Ability
|
38
|
+
|
39
|
+
def initialize(user)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
34
43
|
See {Defining Abilities}[https://github.com/ryanb/cancan/wiki/defining-abilities] for details.
|
35
44
|
|
36
45
|
|
data/lib/cancan/ability.rb
CHANGED
@@ -228,6 +228,13 @@ module CanCan
|
|
228
228
|
relevant_rules(action, subject).any?(&:only_raw_sql?)
|
229
229
|
end
|
230
230
|
|
231
|
+
def merge(ability)
|
232
|
+
ability.send(:rules).each do |rule|
|
233
|
+
rules << rule.dup
|
234
|
+
end
|
235
|
+
self
|
236
|
+
end
|
237
|
+
|
231
238
|
private
|
232
239
|
|
233
240
|
def unauthorized_message_keys(action, subject)
|
@@ -94,7 +94,7 @@ module CanCan
|
|
94
94
|
# [:+find_by+]
|
95
95
|
# Find using a different attribute other than id. For example.
|
96
96
|
#
|
97
|
-
# load_resource :find_by => :permalink # will use
|
97
|
+
# load_resource :find_by => :permalink # will use find_by_permalink!(params[:id])
|
98
98
|
#
|
99
99
|
# [:+collection+]
|
100
100
|
# Specify which actions are resource collection actions in addition to :+index+. This
|
@@ -151,6 +151,9 @@ module CanCan
|
|
151
151
|
# [:+except+]
|
152
152
|
# Does not apply before filter to given actions.
|
153
153
|
#
|
154
|
+
# [:+singleton+]
|
155
|
+
# Pass +true+ if this is a singleton resource through a +has_one+ association.
|
156
|
+
#
|
154
157
|
# [:+parent+]
|
155
158
|
# True or false depending on if the resource is considered a parent resource. This defaults to +true+ if a resource
|
156
159
|
# name is given which does not match the controller.
|
@@ -382,7 +385,7 @@ module CanCan
|
|
382
385
|
end
|
383
386
|
end
|
384
387
|
|
385
|
-
if defined? ActionController
|
388
|
+
if defined? ActionController::Base
|
386
389
|
ActionController::Base.class_eval do
|
387
390
|
include CanCan::ControllerAdditions
|
388
391
|
end
|
@@ -6,8 +6,8 @@ module CanCan
|
|
6
6
|
options = args.extract_options!
|
7
7
|
resource_name = args.first
|
8
8
|
before_filter_method = options.delete(:prepend) ? :prepend_before_filter : :before_filter
|
9
|
-
controller_class.send(before_filter_method, options.slice(:only, :except)) do |controller|
|
10
|
-
controller.class.cancan_resource_class.new(controller, resource_name, options.except(:only, :except)).send(method)
|
9
|
+
controller_class.send(before_filter_method, options.slice(:only, :except, :if, :unless)) do |controller|
|
10
|
+
controller.class.cancan_resource_class.new(controller, resource_name, options.except(:only, :except, :if, :unless)).send(method)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
@@ -82,7 +82,11 @@ module CanCan
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def build_resource
|
85
|
-
resource = resource_base.new(
|
85
|
+
resource = resource_base.new(resource_params || {})
|
86
|
+
assign_attributes(resource)
|
87
|
+
end
|
88
|
+
|
89
|
+
def assign_attributes(resource)
|
86
90
|
resource.send("#{parent_name}=", parent_resource) if @options[:singleton] && parent_resource
|
87
91
|
initial_attributes.each do |attr_name, value|
|
88
92
|
resource.send("#{attr_name}=", value)
|
@@ -92,7 +96,7 @@ module CanCan
|
|
92
96
|
|
93
97
|
def initial_attributes
|
94
98
|
current_ability.attributes_for(@params[:action].to_sym, resource_class).delete_if do |key, value|
|
95
|
-
|
99
|
+
resource_params && resource_params.include?(key)
|
96
100
|
end
|
97
101
|
end
|
98
102
|
|
@@ -207,8 +211,20 @@ module CanCan
|
|
207
211
|
@name || name_from_controller
|
208
212
|
end
|
209
213
|
|
214
|
+
def resource_params
|
215
|
+
if @options[:class]
|
216
|
+
@params[@options[:class].to_s.underscore.gsub('/', '_')]
|
217
|
+
else
|
218
|
+
@params[namespaced_name.to_s.underscore.gsub("/", "_")]
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def namespace
|
223
|
+
@params[:controller].split("::")[0..-2]
|
224
|
+
end
|
225
|
+
|
210
226
|
def namespaced_name
|
211
|
-
|
227
|
+
[namespace, name.camelize].join('::').singularize.camelize.constantize
|
212
228
|
rescue NameError
|
213
229
|
name
|
214
230
|
end
|
@@ -6,7 +6,8 @@ module CanCan
|
|
6
6
|
@controller.send :association_chain
|
7
7
|
@controller.instance_variable_get("@#{instance_name}")
|
8
8
|
elsif new_actions.include? @params[:action].to_sym
|
9
|
-
@controller.send :build_resource
|
9
|
+
resource = @controller.send :build_resource
|
10
|
+
assign_attributes(resource)
|
10
11
|
else
|
11
12
|
@controller.send :resource
|
12
13
|
end
|
@@ -89,7 +89,12 @@ module CanCan
|
|
89
89
|
if override_scope
|
90
90
|
@model_class.scoped.merge(override_scope)
|
91
91
|
elsif @model_class.respond_to?(:where) && @model_class.respond_to?(:joins)
|
92
|
-
@
|
92
|
+
mergeable_conditions = @rules.select {|rule| rule.unmergeable? }.blank?
|
93
|
+
if mergeable_conditions
|
94
|
+
@model_class.where(conditions).joins(joins)
|
95
|
+
else
|
96
|
+
@model_class.where(*(@rules.map(&:conditions))).joins(joins)
|
97
|
+
end
|
93
98
|
else
|
94
99
|
@model_class.scoped(:conditions => conditions, :joins => joins)
|
95
100
|
end
|
@@ -30,8 +30,9 @@ module CanCan
|
|
30
30
|
else
|
31
31
|
# we only need to process can rules if
|
32
32
|
# there are no rules with empty conditions
|
33
|
-
rules = @rules.reject { |rule| rule.conditions.empty? }
|
33
|
+
rules = @rules.reject { |rule| rule.conditions.empty? && rule.base_behavior }
|
34
34
|
process_can_rules = @rules.count == rules.count
|
35
|
+
|
35
36
|
rules.inject(@model_class.all) do |records, rule|
|
36
37
|
if process_can_rules && rule.base_behavior
|
37
38
|
records.or rule.conditions
|
data/lib/cancan/rule.rb
CHANGED
@@ -54,6 +54,10 @@ module CanCan
|
|
54
54
|
@conditions == {} || @conditions.nil?
|
55
55
|
end
|
56
56
|
|
57
|
+
def unmergeable?
|
58
|
+
@conditions.respond_to?(:keys) && (! @conditions.keys.first.kind_of? Symbol)
|
59
|
+
end
|
60
|
+
|
57
61
|
def associations_hash(conditions = @conditions)
|
58
62
|
hash = {}
|
59
63
|
conditions.map do |name, value|
|
@@ -111,7 +115,7 @@ module CanCan
|
|
111
115
|
else
|
112
116
|
!attribute.nil? && matches_conditions_hash?(attribute, value)
|
113
117
|
end
|
114
|
-
elsif value.kind_of?(
|
118
|
+
elsif value.kind_of?(Enumerable)
|
115
119
|
value.include? attribute
|
116
120
|
else
|
117
121
|
attribute == value
|
@@ -123,7 +127,7 @@ module CanCan
|
|
123
127
|
end
|
124
128
|
|
125
129
|
def nested_subject_matches_conditions?(subject_hash)
|
126
|
-
parent, child = subject_hash.
|
130
|
+
parent, child = subject_hash.first
|
127
131
|
matches_conditions_hash?(parent, @conditions[parent.class.name.downcase.to_sym] || {})
|
128
132
|
end
|
129
133
|
|
@@ -136,7 +140,7 @@ module CanCan
|
|
136
140
|
end
|
137
141
|
|
138
142
|
def model_adapter(subject)
|
139
|
-
ModelAdapters::AbstractAdapter.adapter_class(subject_class?(subject) ? subject : subject.class)
|
143
|
+
CanCan::ModelAdapters::AbstractAdapter.adapter_class(subject_class?(subject) ? subject : subject.class)
|
140
144
|
end
|
141
145
|
end
|
142
146
|
end
|
data/spec/cancan/ability_spec.rb
CHANGED
@@ -249,7 +249,15 @@ describe CanCan::Ability do
|
|
249
249
|
@ability.can?(:read, 1..5).should be_true
|
250
250
|
@ability.can?(:read, 4..6).should be_false
|
251
251
|
end
|
252
|
-
|
252
|
+
|
253
|
+
it "should accept a set as a condition value" do
|
254
|
+
mock(object_with_foo_2 = Object.new).foo { 2 }
|
255
|
+
mock(object_with_foo_3 = Object.new).foo { 3 }
|
256
|
+
@ability.can :read, Object, :foo => [1, 2, 5].to_set
|
257
|
+
@ability.can?(:read, object_with_foo_2).should be_true
|
258
|
+
@ability.can?(:read, object_with_foo_3).should be_false
|
259
|
+
end
|
260
|
+
|
253
261
|
it "should not match subjects return nil for methods that must match nested a nested conditions hash" do
|
254
262
|
mock(object_with_foo = Object.new).foo { :bar }
|
255
263
|
@ability.can :read, Array, :first => { :foo => :bar }
|
@@ -297,7 +305,15 @@ describe CanCan::Ability do
|
|
297
305
|
@ability.can?(:read, "foobar" => Range).should be_false
|
298
306
|
@ability.can?(:read, 123 => Range).should be_true
|
299
307
|
end
|
300
|
-
|
308
|
+
|
309
|
+
it "passing a hash of subjects with multiple definitions should check permissions correctly" do
|
310
|
+
@ability.can :read, Range, :string => {:length => 4}
|
311
|
+
@ability.can [:create, :read], Range, :string => {:upcase => 'FOO'}
|
312
|
+
@ability.can?(:read, "foo" => Range).should be_true
|
313
|
+
@ability.can?(:read, "foobar" => Range).should be_false
|
314
|
+
@ability.can?(:read, 1234 => Range).should be_true
|
315
|
+
end
|
316
|
+
|
301
317
|
it "should allow to check ability on Hash-like object" do
|
302
318
|
class Container < Hash; end
|
303
319
|
@ability.can :read, Container
|
@@ -416,4 +432,17 @@ describe CanCan::Ability do
|
|
416
432
|
@ability.unauthorized_message(:edit, 1..3).should == "edit range"
|
417
433
|
end
|
418
434
|
end
|
435
|
+
|
436
|
+
describe "#merge" do
|
437
|
+
it "should add the rules from the given ability" do
|
438
|
+
@ability.can :use, :tools
|
439
|
+
another_ability = Object.new
|
440
|
+
another_ability.extend(CanCan::Ability)
|
441
|
+
another_ability.can :use, :search
|
442
|
+
|
443
|
+
@ability.merge(another_ability)
|
444
|
+
@ability.can?(:use, :search).should be_true
|
445
|
+
@ability.send(:rules).size.should == 2
|
446
|
+
end
|
447
|
+
end
|
419
448
|
end
|
@@ -49,14 +49,14 @@ describe CanCan::ControllerAdditions do
|
|
49
49
|
|
50
50
|
it "authorize_resource should setup a before filter which passes call to ControllerResource" do
|
51
51
|
stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.authorize_resource
|
52
|
-
mock(@controller_class).before_filter(:except => :show) { |options, block| block.call(@controller) }
|
53
|
-
@controller_class.authorize_resource :foo => :bar, :except => :show
|
52
|
+
mock(@controller_class).before_filter(:except => :show, :if => true) { |options, block| block.call(@controller) }
|
53
|
+
@controller_class.authorize_resource :foo => :bar, :except => :show, :if => true
|
54
54
|
end
|
55
55
|
|
56
56
|
it "load_resource should setup a before filter which passes call to ControllerResource" do
|
57
57
|
stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.load_resource
|
58
|
-
mock(@controller_class).before_filter(:only => [:show, :index]) { |options, block| block.call(@controller) }
|
59
|
-
@controller_class.load_resource :foo => :bar, :only => [:show, :index]
|
58
|
+
mock(@controller_class).before_filter(:only => [:show, :index], :unless => false) { |options, block| block.call(@controller) }
|
59
|
+
@controller_class.load_resource :foo => :bar, :only => [:show, :index], :unless => false
|
60
60
|
end
|
61
61
|
|
62
62
|
it "skip_authorization_check should set up a before filter which sets @_authorized to true" do
|
@@ -47,6 +47,18 @@ describe CanCan::ControllerResource do
|
|
47
47
|
@controller.instance_variable_get(:@project).should == project
|
48
48
|
end
|
49
49
|
|
50
|
+
# Rails includes namespace in params, see issue #349
|
51
|
+
it "should create through the namespaced params" do
|
52
|
+
module MyEngine
|
53
|
+
class Project < ::Project; end
|
54
|
+
end
|
55
|
+
|
56
|
+
@params.merge!(:controller => "MyEngine::ProjectsController", :action => "create", :my_engine_project => {:name => "foobar"})
|
57
|
+
resource = CanCan::ControllerResource.new(@controller)
|
58
|
+
resource.load_resource
|
59
|
+
@controller.instance_variable_get(:@project).name.should == "foobar"
|
60
|
+
end
|
61
|
+
|
50
62
|
it "should properly load resource for namespaced controller when using '::' for namespace" do
|
51
63
|
project = Project.create!
|
52
64
|
@params.merge!(:controller => "Admin::ProjectsController", :action => "show", :id => project.id)
|
@@ -62,6 +74,14 @@ describe CanCan::ControllerResource do
|
|
62
74
|
@controller.instance_variable_get(:@project).name.should == "foobar"
|
63
75
|
end
|
64
76
|
|
77
|
+
it "should build a new resource for namespaced model with hash if params[:id] is not specified" do
|
78
|
+
project = Sub::Project.create!
|
79
|
+
@params.merge!(:action => "create", 'sub_project' => {:name => "foobar"})
|
80
|
+
resource = CanCan::ControllerResource.new(@controller, :class => ::Sub::Project)
|
81
|
+
resource.load_resource
|
82
|
+
@controller.instance_variable_get(:@project).name.should == "foobar"
|
83
|
+
end
|
84
|
+
|
65
85
|
it "should build a new resource with attributes from current ability" do
|
66
86
|
@params.merge!(:action => "new")
|
67
87
|
@ability.can(:create, Project, :name => "from conditions")
|
@@ -195,6 +215,14 @@ describe CanCan::ControllerResource do
|
|
195
215
|
resource.should_not be_parent
|
196
216
|
end
|
197
217
|
|
218
|
+
it "should have the specified resource_class if 'name' is passed to load_resource" do
|
219
|
+
class Section
|
220
|
+
end
|
221
|
+
|
222
|
+
resource = CanCan::ControllerResource.new(@controller, :section)
|
223
|
+
resource.send(:resource_class).should == Section
|
224
|
+
end
|
225
|
+
|
198
226
|
it "should load parent resource through proper id parameter" do
|
199
227
|
project = Project.create!
|
200
228
|
@params.merge!(:controller => "categories", :action => "index", :project_id => project.id)
|
@@ -324,6 +352,14 @@ describe CanCan::ControllerResource do
|
|
324
352
|
@controller.instance_variable_get(:@project).should == project
|
325
353
|
end
|
326
354
|
|
355
|
+
it "should load the model using a custom namespaced class" do
|
356
|
+
project = Sub::Project.create!
|
357
|
+
@params.merge!(:action => "show", :id => project.id)
|
358
|
+
resource = CanCan::ControllerResource.new(@controller, :class => ::Sub::Project)
|
359
|
+
resource.load_resource
|
360
|
+
@controller.instance_variable_get(:@project).should == project
|
361
|
+
end
|
362
|
+
|
327
363
|
it "should authorize based on resource name if class is false" do
|
328
364
|
@params.merge!(:action => "show", :id => 123)
|
329
365
|
stub(@controller).authorize!(:show, :project) { raise CanCan::AccessDenied }
|
@@ -339,7 +375,7 @@ describe CanCan::ControllerResource do
|
|
339
375
|
lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied)
|
340
376
|
@controller.instance_variable_get(:@custom_project).should == project
|
341
377
|
end
|
342
|
-
|
378
|
+
|
343
379
|
it "should load resource using custom ID param" do
|
344
380
|
project = Project.create!
|
345
381
|
@params.merge!(:action => "show", :the_project => project.id)
|
@@ -347,7 +383,7 @@ describe CanCan::ControllerResource do
|
|
347
383
|
resource.load_resource
|
348
384
|
@controller.instance_variable_get(:@project).should == project
|
349
385
|
end
|
350
|
-
|
386
|
+
|
351
387
|
it "should load resource using custom find_by attribute" do
|
352
388
|
project = Project.create!(:name => "foo")
|
353
389
|
@params.merge!(:action => "show", :id => "foo")
|
@@ -32,23 +32,23 @@ describe CanCan::AccessDenied do
|
|
32
32
|
@exception.message.should == "Access denied!"
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
describe "i18n in the default message" do
|
37
37
|
after(:each) do
|
38
38
|
I18n.backend = nil
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
it "uses i18n for the default message" do
|
42
42
|
I18n.backend.store_translations :en, :unauthorized => {:default => "This is a different message"}
|
43
43
|
@exception = CanCan::AccessDenied.new
|
44
44
|
@exception.message.should == "This is a different message"
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
it "defaults to a nice message" do
|
48
48
|
@exception = CanCan::AccessDenied.new
|
49
49
|
@exception.message.should == "You are not authorized to access this page."
|
50
50
|
end
|
51
|
-
|
51
|
+
|
52
52
|
it "does not use translation if a message is given" do
|
53
53
|
@exception = CanCan::AccessDenied.new("Hey! You're not welcome here")
|
54
54
|
@exception.message.should == "Hey! You're not welcome here"
|
@@ -39,4 +39,22 @@ describe CanCan::InheritedResource do
|
|
39
39
|
CanCan::InheritedResource.new(@controller).load_resource
|
40
40
|
@controller.instance_variable_get(:@projects).should == :projects
|
41
41
|
end
|
42
|
+
|
43
|
+
it "should build a new resource with attributes from current ability" do
|
44
|
+
@params[:action] = "new"
|
45
|
+
@ability.can(:create, Project, :name => "from conditions")
|
46
|
+
stub(@controller).build_resource { Struct.new(:name).new }
|
47
|
+
resource = CanCan::InheritedResource.new(@controller)
|
48
|
+
resource.load_resource
|
49
|
+
@controller.instance_variable_get(:@project).name.should == "from conditions"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should override initial attributes with params" do
|
53
|
+
@params.merge!(:action => "new", :project => {:name => "from params"})
|
54
|
+
@ability.can(:create, Project, :name => "from conditions")
|
55
|
+
stub(@controller).build_resource { Struct.new(:name).new }
|
56
|
+
resource = CanCan::ControllerResource.new(@controller)
|
57
|
+
resource.load_resource
|
58
|
+
@controller.instance_variable_get(:@project).name.should == "from params"
|
59
|
+
end
|
42
60
|
end
|
@@ -133,7 +133,7 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
|
|
133
133
|
article1 = Article.create!(:secret => true, :category => category1)
|
134
134
|
article2 = Article.create!(:secret => true, :category => category2)
|
135
135
|
category1.articles.accessible_by(@ability).should == [article1]
|
136
|
-
end
|
136
|
+
end
|
137
137
|
|
138
138
|
it "should raise an exception when trying to merge scope with other conditions" do
|
139
139
|
@ability.can :read, Article, :published => true
|
@@ -236,6 +236,16 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
|
|
236
236
|
@ability.should_not be_able_to(:read, article2)
|
237
237
|
end
|
238
238
|
|
239
|
+
it "should merge MetaWhere and non-MetaWhere conditions" do
|
240
|
+
@ability.can :read, Article, :priority.lt => 2
|
241
|
+
@ability.can :read, Article, :priority => 1
|
242
|
+
article1 = Article.create!(:priority => 1)
|
243
|
+
article2 = Article.create!(:priority => 3)
|
244
|
+
Article.accessible_by(@ability).should == [article1]
|
245
|
+
@ability.should be_able_to(:read, article1)
|
246
|
+
@ability.should_not be_able_to(:read, article2)
|
247
|
+
end
|
248
|
+
|
239
249
|
it "should match any MetaWhere condition" do
|
240
250
|
adapter = CanCan::ModelAdapters::ActiveRecordAdapter
|
241
251
|
article1 = Article.new(:priority => 1, :name => "Hello World")
|
@@ -73,6 +73,17 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
|
|
73
73
|
MongoidProject.accessible_by(@ability, :read).entries.should == [sir]
|
74
74
|
end
|
75
75
|
|
76
|
+
it "should return the correct records when a mix of can and cannot rules in defined ability" do
|
77
|
+
@ability.can :manage, MongoidProject, :title => 'Sir'
|
78
|
+
@ability.cannot :destroy, MongoidProject
|
79
|
+
|
80
|
+
sir = MongoidProject.create(:title => 'Sir')
|
81
|
+
lord = MongoidProject.create(:title => 'Lord')
|
82
|
+
dude = MongoidProject.create(:title => 'Dude')
|
83
|
+
|
84
|
+
MongoidProject.accessible_by(@ability, :destroy).entries.should == [sir]
|
85
|
+
end
|
86
|
+
|
76
87
|
it "should be able to mix empty conditions and hashes" do
|
77
88
|
@ability.can :read, MongoidProject
|
78
89
|
@ability.can :read, MongoidProject, :title => 'Sir'
|
@@ -185,7 +196,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
|
|
185
196
|
@ability.can :read, MongoidProject, :foo => {:bar => 1}
|
186
197
|
MongoidProject.accessible_by(@ability, :read).entries.first.should == obj
|
187
198
|
end
|
188
|
-
|
199
|
+
|
189
200
|
it "should exclude from the result if set to cannot" do
|
190
201
|
obj = MongoidProject.create(:bar => 1)
|
191
202
|
obj2 = MongoidProject.create(:bar => 2)
|
@@ -202,7 +213,7 @@ if ENV["MODEL_ADAPTER"] == "mongoid"
|
|
202
213
|
@ability.can :read, MongoidProject, :bar => 2
|
203
214
|
MongoidProject.accessible_by(@ability, :read).entries.should =~ [obj, obj2]
|
204
215
|
end
|
205
|
-
|
216
|
+
|
206
217
|
it "should not allow to fetch records when ability with just block present" do
|
207
218
|
@ability.can :read, MongoidProject do
|
208
219
|
false
|
data/spec/cancan/rule_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "spec_helper"
|
2
|
+
require "ostruct" # for OpenStruct below
|
2
3
|
|
3
4
|
# Most of Rule functionality is tested in Ability specs
|
4
5
|
describe CanCan::Rule do
|
@@ -36,4 +37,11 @@ describe CanCan::Rule do
|
|
36
37
|
rule = CanCan::Rule.new(true, :read, Integer, nil, nil)
|
37
38
|
rule.associations_hash.should == {}
|
38
39
|
end
|
40
|
+
|
41
|
+
it "should not be mergeable if conditions are not simple hashes" do
|
42
|
+
meta_where = OpenStruct.new(:name => 'metawhere', :column => 'test')
|
43
|
+
@conditions[meta_where] = :bar
|
44
|
+
|
45
|
+
@rule.should be_unmergeable
|
46
|
+
end
|
39
47
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -17,7 +17,7 @@ RSpec.configure do |config|
|
|
17
17
|
Project.delete_all
|
18
18
|
Category.delete_all
|
19
19
|
end
|
20
|
-
config.extend WithModel
|
20
|
+
config.extend WithModel if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
|
21
21
|
end
|
22
22
|
|
23
23
|
class Ability
|
@@ -31,6 +31,21 @@ class Category < SuperModel::Base
|
|
31
31
|
has_many :projects
|
32
32
|
end
|
33
33
|
|
34
|
+
module Sub
|
35
|
+
class Project < SuperModel::Base
|
36
|
+
belongs_to :category
|
37
|
+
attr_accessor :category # why doesn't SuperModel do this automatically?
|
38
|
+
|
39
|
+
def self.respond_to?(method, include_private = false)
|
40
|
+
if method.to_s == "find_by_name!" # hack to simulate ActiveRecord
|
41
|
+
true
|
42
|
+
else
|
43
|
+
super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
34
49
|
class Project < SuperModel::Base
|
35
50
|
belongs_to :category
|
36
51
|
attr_accessor :category # why doesn't SuperModel do this automatically?
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cancan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: -2317773892
|
5
|
+
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
|
9
|
+
- 8
|
10
|
+
- rc
|
11
|
+
- 1
|
12
|
+
version: 1.6.8.rc1
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- Ryan Bates
|
@@ -15,7 +17,8 @@ autorequire:
|
|
15
17
|
bindir: bin
|
16
18
|
cert_chain: []
|
17
19
|
|
18
|
-
date:
|
20
|
+
date: 2012-06-19 00:00:00 -07:00
|
21
|
+
default_executable:
|
19
22
|
dependencies:
|
20
23
|
- !ruby/object:Gem::Dependency
|
21
24
|
name: rspec
|
@@ -128,6 +131,7 @@ files:
|
|
128
131
|
- Rakefile
|
129
132
|
- README.rdoc
|
130
133
|
- init.rb
|
134
|
+
has_rdoc: true
|
131
135
|
homepage: http://github.com/ryanb/cancan
|
132
136
|
licenses: []
|
133
137
|
|
@@ -159,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
163
|
requirements: []
|
160
164
|
|
161
165
|
rubyforge_project: cancan
|
162
|
-
rubygems_version: 1.
|
166
|
+
rubygems_version: 1.6.2
|
163
167
|
signing_key:
|
164
168
|
specification_version: 3
|
165
169
|
summary: Simple authorization solution for Rails.
|