cancan 1.6.9 → 1.6.10
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +12 -0
- data/lib/cancan/controller_additions.rb +5 -0
- data/lib/cancan/controller_resource.rb +4 -2
- data/lib/cancan/model_adapters/active_record_adapter.rb +14 -3
- data/lib/cancan/rule.rb +1 -1
- data/spec/cancan/ability_spec.rb +6 -0
- data/spec/cancan/controller_resource_spec.rb +32 -15
- data/spec/cancan/model_adapters/active_record_adapter_spec.rb +10 -0
- data/spec/spec_helper.rb +12 -0
- metadata +4 -4
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
1.6.10 (May 7, 2013)
|
2
|
+
|
3
|
+
* fix matches_conditons_hash for string values on 1.8 (thanks rrosen)
|
4
|
+
|
5
|
+
* work around SQL injection vulnerability in older Rails versions (thanks steerio) - issue #800
|
6
|
+
|
7
|
+
* add support for nested join conditions (thanks yuszuv) - issue #806
|
8
|
+
|
9
|
+
* fix load_resource "find_by" in mongoid resources (thanks albertobajo) - issue #705
|
10
|
+
|
11
|
+
* fix namespace split behavior (thanks xinuc) - issue #668
|
12
|
+
|
1
13
|
1.6.9 (February 4, 2013)
|
2
14
|
|
3
15
|
* fix inserting AND (NULL) to end of SQL queries (thanks jonsgreen) - issue #687
|
@@ -96,6 +96,11 @@ module CanCan
|
|
96
96
|
#
|
97
97
|
# load_resource :find_by => :permalink # will use find_by_permalink!(params[:id])
|
98
98
|
#
|
99
|
+
# [:+id_param+]
|
100
|
+
# Find using a param key other than :id. For example:
|
101
|
+
#
|
102
|
+
# load_resource :id_key => :url # will use find(params[:url])
|
103
|
+
#
|
99
104
|
# [:+collection+]
|
100
105
|
# Specify which actions are resource collection actions in addition to :+index+. This
|
101
106
|
# is usually not necessary because it will try to guess depending on if the id param is present.
|
@@ -107,6 +107,8 @@ module CanCan
|
|
107
107
|
if @options[:find_by]
|
108
108
|
if resource_base.respond_to? "find_by_#{@options[:find_by]}!"
|
109
109
|
resource_base.send("find_by_#{@options[:find_by]}!", id_param)
|
110
|
+
elsif resource_base.respond_to? "find_by"
|
111
|
+
resource_base.send("find_by", { @options[:find_by].to_sym => id_param })
|
110
112
|
else
|
111
113
|
resource_base.send(@options[:find_by], id_param)
|
112
114
|
end
|
@@ -129,7 +131,7 @@ module CanCan
|
|
129
131
|
@params[@options[:id_param]]
|
130
132
|
else
|
131
133
|
@params[parent? ? :"#{name}_id" : :id]
|
132
|
-
end
|
134
|
+
end.to_s
|
133
135
|
end
|
134
136
|
|
135
137
|
def member_action?
|
@@ -225,7 +227,7 @@ module CanCan
|
|
225
227
|
end
|
226
228
|
|
227
229
|
def namespace
|
228
|
-
@params[:controller].split(
|
230
|
+
@params[:controller].split(/::|\//)[0..-2]
|
229
231
|
end
|
230
232
|
|
231
233
|
def namespaced_name
|
@@ -66,11 +66,22 @@ module CanCan
|
|
66
66
|
return conditions unless conditions.kind_of? Hash
|
67
67
|
conditions.inject({}) do |result_hash, (name, value)|
|
68
68
|
if value.kind_of? Hash
|
69
|
+
value = value.dup
|
69
70
|
association_class = model_class.reflect_on_association(name).class_name.constantize
|
70
|
-
|
71
|
-
|
71
|
+
nested = value.inject({}) do |nested,(k,v)|
|
72
|
+
if v.kind_of? Hash
|
73
|
+
value.delete(k)
|
74
|
+
nested[k] = v
|
75
|
+
else
|
76
|
+
name = model_class.reflect_on_association(name).table_name.to_sym
|
77
|
+
result_hash[name] = value
|
78
|
+
end
|
79
|
+
nested
|
80
|
+
end
|
81
|
+
result_hash.merge!(tableized_conditions(nested,association_class))
|
82
|
+
else
|
83
|
+
result_hash[name] = value
|
72
84
|
end
|
73
|
-
result_hash[name] = value
|
74
85
|
result_hash
|
75
86
|
end
|
76
87
|
end
|
data/lib/cancan/rule.rb
CHANGED
@@ -116,7 +116,7 @@ module CanCan
|
|
116
116
|
else
|
117
117
|
!attribute.nil? && matches_conditions_hash?(attribute, value)
|
118
118
|
end
|
119
|
-
elsif value.kind_of?(Enumerable)
|
119
|
+
elsif !value.is_a?(String) && value.kind_of?(Enumerable)
|
120
120
|
value.include? attribute
|
121
121
|
else
|
122
122
|
attribute == value
|
data/spec/cancan/ability_spec.rb
CHANGED
@@ -269,6 +269,12 @@ describe CanCan::Ability do
|
|
269
269
|
@ability.can?(:read, []).should be_false
|
270
270
|
end
|
271
271
|
|
272
|
+
it "should match strings but not substrings specified in a conditions hash" do
|
273
|
+
@ability.can :read, String, :presence => "declassified"
|
274
|
+
@ability.can?(:read, "declassified").should be_true
|
275
|
+
@ability.can?(:read, "classified").should be_false
|
276
|
+
end
|
277
|
+
|
272
278
|
it "should not stop at cannot definition when comparing class" do
|
273
279
|
@ability.can :read, Range
|
274
280
|
@ability.cannot :read, Range, :begin => 1
|
@@ -20,7 +20,7 @@ describe CanCan::ControllerResource do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should not load resource into an instance variable if already set" do
|
23
|
-
@params.merge!(:action => "show", :id => 123)
|
23
|
+
@params.merge!(:action => "show", :id => "123")
|
24
24
|
@controller.instance_variable_set(:@project, :some_project)
|
25
25
|
resource = CanCan::ControllerResource.new(@controller)
|
26
26
|
resource.load_resource
|
@@ -67,6 +67,16 @@ describe CanCan::ControllerResource do
|
|
67
67
|
@controller.instance_variable_get(:@project).should == project
|
68
68
|
end
|
69
69
|
|
70
|
+
it "has the specified nested resource_class when using / for namespace" do
|
71
|
+
module Admin
|
72
|
+
class Dashboard; end
|
73
|
+
end
|
74
|
+
@ability.can(:index, "admin/dashboard")
|
75
|
+
@params.merge!(:controller => "admin/dashboard", :action => "index")
|
76
|
+
resource = CanCan::ControllerResource.new(@controller, :authorize => true)
|
77
|
+
resource.send(:resource_class).should == Admin::Dashboard
|
78
|
+
end
|
79
|
+
|
70
80
|
it "should build a new resource with hash if params[:id] is not specified" do
|
71
81
|
@params.merge!(:action => "create", :project => {:name => "foobar"})
|
72
82
|
resource = CanCan::ControllerResource.new(@controller)
|
@@ -148,7 +158,7 @@ describe CanCan::ControllerResource do
|
|
148
158
|
end
|
149
159
|
|
150
160
|
it "should perform authorization using controller action and loaded model" do
|
151
|
-
@params.merge!(:action => "show", :id => 123)
|
161
|
+
@params.merge!(:action => "show", :id => "123")
|
152
162
|
@controller.instance_variable_set(:@project, :some_project)
|
153
163
|
stub(@controller).authorize!(:show, :some_project) { raise CanCan::AccessDenied }
|
154
164
|
resource = CanCan::ControllerResource.new(@controller)
|
@@ -156,14 +166,14 @@ describe CanCan::ControllerResource do
|
|
156
166
|
end
|
157
167
|
|
158
168
|
it "should perform authorization using controller action and non loaded model" do
|
159
|
-
@params.merge!(:action => "show", :id => 123)
|
169
|
+
@params.merge!(:action => "show", :id => "123")
|
160
170
|
stub(@controller).authorize!(:show, Project) { raise CanCan::AccessDenied }
|
161
171
|
resource = CanCan::ControllerResource.new(@controller)
|
162
172
|
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
|
163
173
|
end
|
164
174
|
|
165
175
|
it "should call load_resource and authorize_resource for load_and_authorize_resource" do
|
166
|
-
@params.merge!(:action => "show", :id => 123)
|
176
|
+
@params.merge!(:action => "show", :id => "123")
|
167
177
|
resource = CanCan::ControllerResource.new(@controller)
|
168
178
|
mock(resource).load_resource
|
169
179
|
mock(resource).authorize_resource
|
@@ -171,7 +181,7 @@ describe CanCan::ControllerResource do
|
|
171
181
|
end
|
172
182
|
|
173
183
|
it "should not build a single resource when on custom collection action even with id" do
|
174
|
-
@params.merge!(:action => "sort", :id => 123)
|
184
|
+
@params.merge!(:action => "sort", :id => "123")
|
175
185
|
resource = CanCan::ControllerResource.new(@controller, :collection => [:sort, :list])
|
176
186
|
resource.load_resource
|
177
187
|
@controller.instance_variable_get(:@project).should be_nil
|
@@ -187,7 +197,7 @@ describe CanCan::ControllerResource do
|
|
187
197
|
end
|
188
198
|
|
189
199
|
it "should build a resource when on custom new action even when params[:id] exists" do
|
190
|
-
@params.merge!(:action => "build", :id => 123)
|
200
|
+
@params.merge!(:action => "build", :id => "123")
|
191
201
|
stub(Project).new { :some_project }
|
192
202
|
resource = CanCan::ControllerResource.new(@controller, :new => :build)
|
193
203
|
resource.load_resource
|
@@ -238,30 +248,30 @@ describe CanCan::ControllerResource do
|
|
238
248
|
end
|
239
249
|
|
240
250
|
it "should load resource through the association of another parent resource using instance variable" do
|
241
|
-
@params.merge!(:action => "show", :id => 123)
|
251
|
+
@params.merge!(:action => "show", :id => "123")
|
242
252
|
category = Object.new
|
243
253
|
@controller.instance_variable_set(:@category, category)
|
244
|
-
stub(category).projects.stub!.find(123) { :some_project }
|
254
|
+
stub(category).projects.stub!.find("123") { :some_project }
|
245
255
|
resource = CanCan::ControllerResource.new(@controller, :through => :category)
|
246
256
|
resource.load_resource
|
247
257
|
@controller.instance_variable_get(:@project).should == :some_project
|
248
258
|
end
|
249
259
|
|
250
260
|
it "should load resource through the custom association name" do
|
251
|
-
@params.merge!(:action => "show", :id => 123)
|
261
|
+
@params.merge!(:action => "show", :id => "123")
|
252
262
|
category = Object.new
|
253
263
|
@controller.instance_variable_set(:@category, category)
|
254
|
-
stub(category).custom_projects.stub!.find(123) { :some_project }
|
264
|
+
stub(category).custom_projects.stub!.find("123") { :some_project }
|
255
265
|
resource = CanCan::ControllerResource.new(@controller, :through => :category, :through_association => :custom_projects)
|
256
266
|
resource.load_resource
|
257
267
|
@controller.instance_variable_get(:@project).should == :some_project
|
258
268
|
end
|
259
269
|
|
260
270
|
it "should load resource through the association of another parent resource using method" do
|
261
|
-
@params.merge!(:action => "show", :id => 123)
|
271
|
+
@params.merge!(:action => "show", :id => "123")
|
262
272
|
category = Object.new
|
263
273
|
stub(@controller).category { category }
|
264
|
-
stub(category).projects.stub!.find(123) { :some_project }
|
274
|
+
stub(category).projects.stub!.find("123") { :some_project }
|
265
275
|
resource = CanCan::ControllerResource.new(@controller, :through => :category)
|
266
276
|
resource.load_resource
|
267
277
|
@controller.instance_variable_get(:@project).should == :some_project
|
@@ -298,10 +308,10 @@ describe CanCan::ControllerResource do
|
|
298
308
|
end
|
299
309
|
|
300
310
|
it "should load through first matching if multiple are given" do
|
301
|
-
@params.merge!(:action => "show", :id => 123)
|
311
|
+
@params.merge!(:action => "show", :id => "123")
|
302
312
|
category = Object.new
|
303
313
|
@controller.instance_variable_set(:@category, category)
|
304
|
-
stub(category).projects.stub!.find(123) { :some_project }
|
314
|
+
stub(category).projects.stub!.find("123") { :some_project }
|
305
315
|
resource = CanCan::ControllerResource.new(@controller, :through => [:category, :user])
|
306
316
|
resource.load_resource
|
307
317
|
@controller.instance_variable_get(:@project).should == :some_project
|
@@ -367,7 +377,7 @@ describe CanCan::ControllerResource do
|
|
367
377
|
end
|
368
378
|
|
369
379
|
it "should authorize based on resource name if class is false" do
|
370
|
-
@params.merge!(:action => "show", :id => 123)
|
380
|
+
@params.merge!(:action => "show", :id => "123")
|
371
381
|
stub(@controller).authorize!(:show, :project) { raise CanCan::AccessDenied }
|
372
382
|
resource = CanCan::ControllerResource.new(@controller, :class => false)
|
373
383
|
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
|
@@ -390,6 +400,13 @@ describe CanCan::ControllerResource do
|
|
390
400
|
@controller.instance_variable_get(:@project).should == project
|
391
401
|
end
|
392
402
|
|
403
|
+
# CVE-2012-5664
|
404
|
+
it "should always convert id param to string" do
|
405
|
+
@params.merge!(:action => "show", :the_project => { :malicious => "I am" })
|
406
|
+
resource = CanCan::ControllerResource.new(@controller, :id_param => :the_project)
|
407
|
+
resource.send(:id_param).class.should == String
|
408
|
+
end
|
409
|
+
|
393
410
|
it "should load resource using custom find_by attribute" do
|
394
411
|
project = Project.create!(:name => "foo")
|
395
412
|
@params.merge!(:action => "show", :id => "foo")
|
@@ -207,6 +207,16 @@ if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
|
|
207
207
|
@ability.model_adapter(Article, :read).conditions.should == "'t'='t'"
|
208
208
|
end
|
209
209
|
|
210
|
+
it "should return appropriate sql conditions in complex case with nested joins" do
|
211
|
+
@ability.can :read, Comment, :article => { :category => { :visible => true } }
|
212
|
+
@ability.model_adapter(Comment, :read).conditions.should == { Category.table_name.to_sym => { :visible => true } }
|
213
|
+
end
|
214
|
+
|
215
|
+
it "should return appropriate sql conditions in complex case with nested joins of different depth" do
|
216
|
+
@ability.can :read, Comment, :article => { :published => true, :category => { :visible => true } }
|
217
|
+
@ability.model_adapter(Comment, :read).conditions.should == { Article.table_name.to_sym => { :published => true }, Category.table_name.to_sym => { :visible => true } }
|
218
|
+
end
|
219
|
+
|
210
220
|
it "should not forget conditions when calling with SQL string" do
|
211
221
|
@ability.can :read, Article, :published => true
|
212
222
|
@ability.can :read, Article, ['secret=?', false]
|
data/spec/spec_helper.rb
CHANGED
@@ -20,6 +20,18 @@ RSpec.configure do |config|
|
|
20
20
|
config.extend WithModel if ENV["MODEL_ADAPTER"].nil? || ENV["MODEL_ADAPTER"] == "active_record"
|
21
21
|
end
|
22
22
|
|
23
|
+
# Working around CVE-2012-5664 requires us to convert all ID params
|
24
|
+
# to strings. Let's switch to using string IDs in tests, otherwise
|
25
|
+
# SuperModel and/or RR will fail (as strings are not fixnums).
|
26
|
+
|
27
|
+
module SuperModel
|
28
|
+
class Base
|
29
|
+
def generate_id
|
30
|
+
object_id.to_s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
23
35
|
class Ability
|
24
36
|
include CanCan::Ability
|
25
37
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cancan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 1.6.
|
9
|
+
- 10
|
10
|
+
version: 1.6.10
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ryan Bates
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2013-
|
18
|
+
date: 2013-05-07 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|