cancan 1.6.9 → 1.6.10
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.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
|