cancancan 1.10.0 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +5 -5
  2. data/cancancan.gemspec +19 -21
  3. data/init.rb +2 -0
  4. data/lib/cancan/ability/actions.rb +93 -0
  5. data/lib/cancan/ability/rules.rb +96 -0
  6. data/lib/cancan/ability/strong_parameter_support.rb +41 -0
  7. data/lib/cancan/ability.rb +114 -146
  8. data/lib/cancan/class_matcher.rb +30 -0
  9. data/lib/cancan/conditions_matcher.rb +147 -0
  10. data/lib/cancan/config.rb +101 -0
  11. data/lib/cancan/controller_additions.rb +38 -41
  12. data/lib/cancan/controller_resource.rb +59 -215
  13. data/lib/cancan/controller_resource_builder.rb +26 -0
  14. data/lib/cancan/controller_resource_finder.rb +42 -0
  15. data/lib/cancan/controller_resource_loader.rb +120 -0
  16. data/lib/cancan/controller_resource_name_finder.rb +23 -0
  17. data/lib/cancan/controller_resource_sanitizer.rb +32 -0
  18. data/lib/cancan/exceptions.rb +25 -5
  19. data/lib/cancan/matchers.rb +17 -3
  20. data/lib/cancan/model_adapters/abstract_adapter.rb +30 -9
  21. data/lib/cancan/model_adapters/active_record_4_adapter.rb +43 -15
  22. data/lib/cancan/model_adapters/active_record_5_adapter.rb +61 -0
  23. data/lib/cancan/model_adapters/active_record_adapter.rb +157 -82
  24. data/lib/cancan/model_adapters/conditions_extractor.rb +75 -0
  25. data/lib/cancan/model_adapters/conditions_normalizer.rb +49 -0
  26. data/lib/cancan/model_adapters/default_adapter.rb +2 -0
  27. data/lib/cancan/model_adapters/sti_normalizer.rb +47 -0
  28. data/lib/cancan/model_adapters/strategies/base.rb +40 -0
  29. data/lib/cancan/model_adapters/strategies/joined_alias_each_rule_as_exists_subquery.rb +93 -0
  30. data/lib/cancan/model_adapters/strategies/joined_alias_exists_subquery.rb +31 -0
  31. data/lib/cancan/model_adapters/strategies/left_join.rb +11 -0
  32. data/lib/cancan/model_adapters/strategies/subquery.rb +18 -0
  33. data/lib/cancan/model_additions.rb +6 -3
  34. data/lib/cancan/parameter_validators.rb +9 -0
  35. data/lib/cancan/relevant.rb +29 -0
  36. data/lib/cancan/rule.rb +79 -91
  37. data/lib/cancan/rules_compressor.rb +23 -0
  38. data/lib/cancan/sti_detector.rb +12 -0
  39. data/lib/cancan/unauthorized_message_resolver.rb +24 -0
  40. data/lib/cancan/version.rb +3 -1
  41. data/lib/cancan.rb +16 -12
  42. data/lib/cancancan.rb +2 -0
  43. data/lib/generators/cancan/ability/ability_generator.rb +4 -2
  44. data/lib/generators/cancan/ability/templates/ability.rb +9 -9
  45. metadata +82 -93
  46. data/.gitignore +0 -15
  47. data/.rspec +0 -1
  48. data/.travis.yml +0 -48
  49. data/Appraisals +0 -135
  50. data/CHANGELOG.rdoc +0 -495
  51. data/CONTRIBUTING.md +0 -23
  52. data/Gemfile +0 -3
  53. data/LICENSE +0 -22
  54. data/README.md +0 -197
  55. data/Rakefile +0 -9
  56. data/gemfiles/activerecord_3.0.gemfile +0 -18
  57. data/gemfiles/activerecord_3.1.gemfile +0 -20
  58. data/gemfiles/activerecord_3.2.gemfile +0 -20
  59. data/gemfiles/activerecord_4.0.gemfile +0 -17
  60. data/gemfiles/activerecord_4.1.gemfile +0 -17
  61. data/gemfiles/activerecord_4.2.gemfile +0 -17
  62. data/gemfiles/datamapper_1.x.gemfile +0 -14
  63. data/gemfiles/mongoid_2.x.gemfile +0 -20
  64. data/gemfiles/sequel_3.x.gemfile +0 -20
  65. data/lib/cancan/inherited_resource.rb +0 -20
  66. data/lib/cancan/model_adapters/active_record_3_adapter.rb +0 -47
  67. data/lib/cancan/model_adapters/data_mapper_adapter.rb +0 -34
  68. data/lib/cancan/model_adapters/mongoid_adapter.rb +0 -54
  69. data/lib/cancan/model_adapters/sequel_adapter.rb +0 -87
  70. data/spec/README.rdoc +0 -27
  71. data/spec/cancan/ability_spec.rb +0 -487
  72. data/spec/cancan/controller_additions_spec.rb +0 -141
  73. data/spec/cancan/controller_resource_spec.rb +0 -648
  74. data/spec/cancan/exceptions_spec.rb +0 -58
  75. data/spec/cancan/inherited_resource_spec.rb +0 -71
  76. data/spec/cancan/matchers_spec.rb +0 -29
  77. data/spec/cancan/model_adapters/active_record_4_adapter_spec.rb +0 -40
  78. data/spec/cancan/model_adapters/active_record_adapter_spec.rb +0 -446
  79. data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +0 -119
  80. data/spec/cancan/model_adapters/default_adapter_spec.rb +0 -7
  81. data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +0 -227
  82. data/spec/cancan/model_adapters/sequel_adapter_spec.rb +0 -132
  83. data/spec/cancan/rule_spec.rb +0 -52
  84. data/spec/matchers.rb +0 -13
  85. data/spec/spec.opts +0 -2
  86. data/spec/spec_helper.rb +0 -27
  87. data/spec/support/ability.rb +0 -7
@@ -1,648 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe CanCan::ControllerResource do
4
- let(:ability) { Ability.new(nil) }
5
- let(:params) { HashWithIndifferentAccess.new(:controller => "models") }
6
- let(:controller_class) { Class.new }
7
- let(:controller) { controller_class.new }
8
-
9
- before(:each) do
10
- class Model
11
- attr_accessor :name
12
-
13
- def initialize(attributes={})
14
- attributes.each do |attribute, value|
15
- send("#{attribute}=", value)
16
- end
17
- end
18
- end
19
-
20
- allow(controller).to receive(:params) { params }
21
- allow(controller).to receive(:current_ability) { ability }
22
- allow(controller_class).to receive(:cancan_skipper) { {:authorize => {}, :load => {}} }
23
- end
24
-
25
- context "on build actions" do
26
- before :each do
27
- params.merge!(:action => "new")
28
- end
29
-
30
- it "builds a new resource with attributes from current ability" do
31
- ability.can(:create, Model, :name => "from conditions")
32
- resource = CanCan::ControllerResource.new(controller)
33
- resource.load_resource
34
- expect(controller.instance_variable_get(:@model).name).to eq("from conditions")
35
- end
36
-
37
- it "overrides initial attributes with params" do
38
- params.merge!(:model => {:name => "from params"})
39
- ability.can(:create, Model, :name => "from conditions")
40
- resource = CanCan::ControllerResource.new(controller)
41
- resource.load_resource
42
- expect(controller.instance_variable_get(:@model).name).to eq("from params")
43
- end
44
-
45
- it "builds a resource when on custom new action even when params[:id] exists" do
46
- params.merge!(:action => "build", :id => "123")
47
- allow(Model).to receive(:new) { :some_model }
48
- resource = CanCan::ControllerResource.new(controller, :new => :build)
49
- resource.load_resource
50
- expect(controller.instance_variable_get(:@model)).to eq(:some_model)
51
- end
52
-
53
- it "only authorizes :show action on parent resource" do
54
- model = Model.new
55
- allow(Model).to receive(:find).with("123") { model }
56
-
57
- params.merge!(:model_id => 123)
58
- allow(controller).to receive(:authorize!).with(:show, model) { raise CanCan::AccessDenied }
59
- resource = CanCan::ControllerResource.new(controller, :model, :parent => true)
60
- expect { resource.load_and_authorize_resource }.to raise_error(CanCan::AccessDenied)
61
- end
62
- end
63
-
64
- context "on create actions" do
65
- before :each do
66
- params.merge!(:action => 'create')
67
- end
68
-
69
- # Rails includes namespace in params, see issue #349
70
- it "creates through the namespaced params" do
71
- module MyEngine
72
- class Model < ::Model; end
73
- end
74
-
75
- params.merge!(:controller => "MyEngine::ModelsController", :my_engine_model => {:name => "foobar"})
76
- resource = CanCan::ControllerResource.new(controller)
77
- resource.load_resource
78
- expect(controller.instance_variable_get(:@model).name).to eq("foobar")
79
- end
80
-
81
- it "builds a new resource with hash if params[:id] is not specified" do
82
- params.merge!(:model => {:name => "foobar"})
83
- resource = CanCan::ControllerResource.new(controller)
84
- resource.load_resource
85
- expect(controller.instance_variable_get(:@model).name).to eq("foobar")
86
- end
87
-
88
- it "builds a new resource for namespaced model with hash if params[:id] is not specified" do
89
- module Sub
90
- class Model < ::Model; end
91
- end
92
-
93
- params.merge!('sub_model' => {:name => "foobar"})
94
- resource = CanCan::ControllerResource.new(controller, :class => ::Sub::Model)
95
- resource.load_resource
96
- expect(controller.instance_variable_get(:@model).name).to eq("foobar")
97
- end
98
-
99
- it "builds a new resource for namespaced controller and namespaced model with hash if params[:id] is not specified" do
100
- params.merge!(:controller => "Admin::SubModelsController", 'sub_model' => {:name => "foobar"})
101
- resource = CanCan::ControllerResource.new(controller, :class => Model)
102
- resource.load_resource
103
- expect(controller.instance_variable_get(:@sub_model).name).to eq("foobar")
104
- end
105
-
106
- it "builds a new resource for namespaced controller given through folder format" do
107
- module Admin
108
- module SubModule
109
- class HiddenModel < ::Model; end
110
- end
111
- end
112
- params.merge!(:controller => "admin/sub_module/hidden_models")
113
- resource = CanCan::ControllerResource.new(controller)
114
- expect { resource.load_resource }.not_to raise_error
115
- end
116
-
117
- it "does not build record through has_one association with :singleton option because it can cause it to delete it in the database" do
118
- category = Class.new
119
- allow_any_instance_of(Model).to receive('category=').with(category)
120
- allow_any_instance_of(Model).to receive('category') { category }
121
-
122
- params.merge!(:model => {:name => "foobar"})
123
-
124
- controller.instance_variable_set(:@category, category)
125
- resource = CanCan::ControllerResource.new(controller, :through => :category, :singleton => true)
126
- resource.load_resource
127
- expect(controller.instance_variable_get(:@model).name).to eq("foobar")
128
- expect(controller.instance_variable_get(:@model).category).to eq(category)
129
- end
130
-
131
- it "builds record through has_one association with :singleton and :shallow options" do
132
- params.merge!(:model => {:name => "foobar"})
133
- resource = CanCan::ControllerResource.new(controller, :through => :category, :singleton => true, :shallow => true)
134
- resource.load_resource
135
- expect(controller.instance_variable_get(:@model).name).to eq("foobar")
136
- end
137
-
138
- context "with a strong parameters method" do
139
- before :each do
140
- params.merge!(:controller => "model", :model => { :name => 'test'})
141
- end
142
-
143
- it "accepts and uses the specified symbol for santitizing input" do
144
- allow(controller).to receive(:resource_params).and_return(:resource => 'params')
145
- allow(controller).to receive(:model_params).and_return(:model => 'params')
146
- allow(controller).to receive(:create_params).and_return(:create => 'params')
147
- allow(controller).to receive(:custom_params).and_return(:custom => 'params')
148
- resource = CanCan::ControllerResource.new(controller, {:param_method => :custom_params})
149
- expect(resource.send("resource_params")).to eq(:custom => 'params')
150
- end
151
-
152
- it "accepts the specified string for sanitizing input" do
153
- resource = CanCan::ControllerResource.new(controller, {:param_method => "{:custom => 'params'}"})
154
- expect(resource.send("resource_params")).to eq(:custom => 'params')
155
- end
156
-
157
- it "accepts the specified proc for sanitizing input" do
158
- resource = CanCan::ControllerResource.new(controller, {:param_method => Proc.new { |c| {:custom => 'params'}}})
159
- expect(resource.send("resource_params")).to eq(:custom => 'params')
160
- end
161
-
162
- it "prefers to use the create_params method for santitizing input" do
163
- allow(controller).to receive(:resource_params).and_return(:resource => 'params')
164
- allow(controller).to receive(:model_params).and_return(:model => 'params')
165
- allow(controller).to receive(:create_params).and_return(:create => 'params')
166
- allow(controller).to receive(:custom_params).and_return(:custom => 'params')
167
- resource = CanCan::ControllerResource.new(controller)
168
- expect(resource.send("resource_params")).to eq(:create => 'params')
169
- end
170
-
171
- it "prefers to use the <model_name>_params method for santitizing input if create is not found" do
172
- allow(controller).to receive(:resource_params).and_return(:resource => 'params')
173
- allow(controller).to receive(:model_params).and_return(:model => 'params')
174
- allow(controller).to receive(:custom_params).and_return(:custom => 'params')
175
- resource = CanCan::ControllerResource.new(controller)
176
- expect(resource.send("resource_params")).to eq(:model => 'params')
177
- end
178
-
179
- it "prefers to use the resource_params method for santitizing input if create or model is not found" do
180
- allow(controller).to receive(:resource_params).and_return(:resource => 'params')
181
- allow(controller).to receive(:custom_params).and_return(:custom => 'params')
182
- resource = CanCan::ControllerResource.new(controller)
183
- expect(resource.send("resource_params")).to eq(:resource => 'params')
184
- end
185
- end
186
- end
187
-
188
- context "on collection actions" do
189
- before :each do
190
- params[:action] = 'index'
191
- end
192
-
193
- it "builds a collection when on index action when class responds to accessible_by" do
194
- allow(Model).to receive(:accessible_by).with(ability, :index) { :found_models }
195
-
196
- resource = CanCan::ControllerResource.new(controller, :model)
197
- resource.load_resource
198
- expect(controller.instance_variable_get(:@model)).to be_nil
199
- expect(controller.instance_variable_get(:@models)).to eq(:found_models)
200
- end
201
-
202
- it "does not build a collection when on index action when class does not respond to accessible_by" do
203
- resource = CanCan::ControllerResource.new(controller)
204
- resource.load_resource
205
- expect(controller.instance_variable_get(:@model)).to be_nil
206
- expect(controller.instance_variable_defined?(:@models)).to be(false)
207
- end
208
-
209
- it "does not use accessible_by when defining abilities through a block" do
210
- allow(Model).to receive(:accessible_by).with(ability) { :found_models }
211
-
212
- ability.can(:read, Model) { |p| false }
213
- resource = CanCan::ControllerResource.new(controller)
214
- resource.load_resource
215
- expect(controller.instance_variable_get(:@model)).to be_nil
216
- expect(controller.instance_variable_defined?(:@models)).to be(false)
217
- end
218
-
219
- it "does not authorize single resource in collection action" do
220
- allow(controller).to receive(:authorize!).with(:index, Model) { raise CanCan::AccessDenied }
221
- resource = CanCan::ControllerResource.new(controller)
222
-
223
- expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
224
- end
225
-
226
- it "authorizes parent resource in collection action" do
227
- controller.instance_variable_set(:@category, :some_category)
228
- allow(controller).to receive(:authorize!).with(:show, :some_category) { raise CanCan::AccessDenied }
229
-
230
- resource = CanCan::ControllerResource.new(controller, :category, :parent => true)
231
- expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
232
- end
233
-
234
- it "has the specified nested resource_class when using / for namespace" do
235
- module Admin
236
- class Dashboard; end
237
- end
238
- ability.can(:index, "admin/dashboard")
239
- params.merge!(:controller => "admin/dashboard")
240
- resource = CanCan::ControllerResource.new(controller, :authorize => true)
241
- expect(resource.send(:resource_class)).to eq(Admin::Dashboard)
242
- end
243
-
244
- it "does not build a single resource when on custom collection action even with id" do
245
- params.merge!(:action => "sort", :id => "123")
246
-
247
- resource = CanCan::ControllerResource.new(controller, :collection => [:sort, :list])
248
- resource.load_resource
249
- expect(controller.instance_variable_get(:@model)).to be_nil
250
- end
251
-
252
- it "loads a collection resource when on custom action with no id param" do
253
- allow(Model).to receive(:accessible_by).with(ability, :sort) { :found_models }
254
- params[:action] = "sort"
255
- resource = CanCan::ControllerResource.new(controller)
256
- resource.load_resource
257
- expect(controller.instance_variable_get(:@model)).to be_nil
258
- expect(controller.instance_variable_get(:@models)).to eq(:found_models)
259
- end
260
-
261
- it "loads parent resource through proper id parameter" do
262
- model = Model.new
263
- allow(Model).to receive(:find).with("1") { model }
264
-
265
- params.merge!(:controller => "categories", :model_id => 1)
266
- resource = CanCan::ControllerResource.new(controller, :model)
267
- resource.load_resource
268
- expect(controller.instance_variable_get(:@model)).to eq(model)
269
- end
270
-
271
- it "authorizes nested resource through parent association on index action" do
272
- controller.instance_variable_set(:@category, category = double)
273
- allow(controller).to receive(:authorize!).with(:index, category => Model) { raise CanCan::AccessDenied }
274
- resource = CanCan::ControllerResource.new(controller, :through => :category)
275
- expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
276
- end
277
- end
278
-
279
- context "on instance read actions" do
280
- before :each do
281
- params.merge!(:action => "show", :id => "123")
282
- end
283
-
284
- it "loads the resource into an instance variable if params[:id] is specified" do
285
- model = Model.new
286
- allow(Model).to receive(:find).with("123") { model }
287
-
288
- resource = CanCan::ControllerResource.new(controller)
289
- resource.load_resource
290
- expect(controller.instance_variable_get(:@model)).to eq(model)
291
- end
292
-
293
- it "does not load resource into an instance variable if already set" do
294
- controller.instance_variable_set(:@model, :some_model)
295
- resource = CanCan::ControllerResource.new(controller)
296
- resource.load_resource
297
- expect(controller.instance_variable_get(:@model)).to eq(:some_model)
298
- end
299
-
300
- it "loads resource for namespaced controller" do
301
- model = Model.new
302
- allow(Model).to receive(:find).with("123") { model }
303
- params.merge!(:controller => "admin/models")
304
-
305
- resource = CanCan::ControllerResource.new(controller)
306
- resource.load_resource
307
- expect(controller.instance_variable_get(:@model)).to eq(model)
308
- end
309
-
310
- it "attempts to load a resource with the same namespace as the controller when using :: for namespace" do
311
- module MyEngine
312
- class Model < ::Model; end
313
- end
314
-
315
- model = MyEngine::Model.new
316
- allow(MyEngine::Model).to receive(:find).with("123") { model }
317
-
318
- params.merge!(:controller => "MyEngine::ModelsController")
319
- resource = CanCan::ControllerResource.new(controller)
320
- resource.load_resource
321
- expect(controller.instance_variable_get(:@model)).to eq(model)
322
- end
323
-
324
- it "loads resource for namespaced controller when using '::' for namespace" do
325
- model = Model.new
326
- allow(Model).to receive(:find).with("123") { model }
327
-
328
- params.merge!(:controller => "Admin::ModelsController")
329
- resource = CanCan::ControllerResource.new(controller)
330
- resource.load_resource
331
- expect(controller.instance_variable_get(:@model)).to eq(model)
332
- end
333
-
334
- it "performs authorization using controller action and loaded model" do
335
- controller.instance_variable_set(:@model, :some_model)
336
- allow(controller).to receive(:authorize!).with(:show, :some_model) { raise CanCan::AccessDenied }
337
-
338
- resource = CanCan::ControllerResource.new(controller)
339
- expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
340
- end
341
-
342
- it "performs authorization using controller action and non loaded model" do
343
- allow(controller).to receive(:authorize!).with(:show, Model) { raise CanCan::AccessDenied }
344
- resource = CanCan::ControllerResource.new(controller)
345
- expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
346
- end
347
-
348
- it "calls load_resource and authorize_resource for load_and_authorize_resource" do
349
- resource = CanCan::ControllerResource.new(controller)
350
- expect(resource).to receive(:load_resource)
351
- expect(resource).to receive(:authorize_resource)
352
- resource.load_and_authorize_resource
353
- end
354
-
355
- it "loads resource through the association of another parent resource using instance variable" do
356
- category = double(:models => {})
357
- controller.instance_variable_set(:@category, category)
358
- allow(category.models).to receive(:find).with("123") { :some_model }
359
- resource = CanCan::ControllerResource.new(controller, :through => :category)
360
- resource.load_resource
361
- expect(controller.instance_variable_get(:@model)).to eq(:some_model)
362
- end
363
-
364
- it "loads resource through the custom association name" do
365
- category = double(:custom_models => {})
366
- controller.instance_variable_set(:@category, category)
367
- allow(category.custom_models).to receive(:find).with("123") { :some_model }
368
- resource = CanCan::ControllerResource.new(controller, :through => :category, :through_association => :custom_models)
369
- resource.load_resource
370
- expect(controller.instance_variable_get(:@model)).to eq(:some_model)
371
- end
372
-
373
- it "loads resource through the association of another parent resource using method" do
374
- category = double(:models => {})
375
- allow(controller).to receive(:category) { category }
376
- allow(category.models).to receive(:find).with("123") { :some_model }
377
- resource = CanCan::ControllerResource.new(controller, :through => :category)
378
- resource.load_resource
379
- expect(controller.instance_variable_get(:@model)).to eq(:some_model)
380
- end
381
-
382
- it "does not load through parent resource if instance isn't loaded when shallow" do
383
- model = Model.new
384
- allow(Model).to receive(:find).with("123") { model }
385
-
386
- resource = CanCan::ControllerResource.new(controller, :through => :category, :shallow => true)
387
- resource.load_resource
388
- expect(controller.instance_variable_get(:@model)).to eq(model)
389
- end
390
-
391
- it "raises AccessDenied when attempting to load resource through nil" do
392
- resource = CanCan::ControllerResource.new(controller, :through => :category)
393
- expect {
394
- resource.load_resource
395
- }.to raise_error(CanCan::AccessDenied) { |exception|
396
- expect(exception.action).to eq(:show)
397
- expect(exception.subject).to eq(Model)
398
- }
399
- expect(controller.instance_variable_get(:@model)).to be_nil
400
- end
401
-
402
- it "loads through first matching if multiple are given" do
403
- category = double(:models => {})
404
- controller.instance_variable_set(:@category, category)
405
- allow(category.models).to receive(:find).with("123") { :some_model }
406
-
407
- resource = CanCan::ControllerResource.new(controller, :through => [:category, :user])
408
- resource.load_resource
409
- expect(controller.instance_variable_get(:@model)).to eq(:some_model)
410
- end
411
-
412
- it "finds record through has_one association with :singleton option without id param" do
413
- params.merge!(:id => nil)
414
-
415
- category = double(:model => :some_model)
416
- controller.instance_variable_set(:@category, category)
417
- resource = CanCan::ControllerResource.new(controller, :through => :category, :singleton => true)
418
- resource.load_resource
419
- expect(controller.instance_variable_get(:@model)).to eq(:some_model)
420
- end
421
-
422
- it "does not try to load resource for other action if params[:id] is undefined" do
423
- params.merge!(:action => 'list', :id => nil)
424
- resource = CanCan::ControllerResource.new(controller)
425
- resource.load_resource
426
- expect(controller.instance_variable_get(:@model)).to be_nil
427
- end
428
-
429
- it "finds record through has_one association with :singleton and :shallow options" do
430
- model = Model.new
431
- allow(Model).to receive(:find).with("123") { model }
432
-
433
- resource = CanCan::ControllerResource.new(controller, :through => :category, :singleton => true, :shallow => true)
434
- resource.load_resource
435
- expect(controller.instance_variable_get(:@model)).to eq(model)
436
- end
437
-
438
- it "loads the model using a custom class" do
439
- model = Model.new
440
- allow(Model).to receive(:find).with("123") { model }
441
-
442
- resource = CanCan::ControllerResource.new(controller, :class => Model)
443
- resource.load_resource
444
- expect(controller.instance_variable_get(:@model)).to eq(model)
445
- end
446
-
447
- it "loads the model using a custom namespaced class" do
448
- module Sub
449
- class Model < ::Model; end
450
- end
451
-
452
- model = Sub::Model.new
453
- allow(Sub::Model).to receive(:find).with("123") { model }
454
-
455
- resource = CanCan::ControllerResource.new(controller, :class => ::Sub::Model)
456
- resource.load_resource
457
- expect(controller.instance_variable_get(:@model)).to eq(model)
458
- end
459
-
460
- it "authorizes based on resource name if class is false" do
461
- allow(controller).to receive(:authorize!).with(:show, :model) { raise CanCan::AccessDenied }
462
- resource = CanCan::ControllerResource.new(controller, :class => false)
463
- expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
464
- end
465
-
466
- it "loads and authorize using custom instance name" do
467
- model = Model.new
468
- allow(Model).to receive(:find).with("123") { model }
469
-
470
- allow(controller).to receive(:authorize!).with(:show, model) { raise CanCan::AccessDenied }
471
- resource = CanCan::ControllerResource.new(controller, :instance_name => :custom_model)
472
- expect { resource.load_and_authorize_resource }.to raise_error(CanCan::AccessDenied)
473
- expect(controller.instance_variable_get(:@custom_model)).to eq(model)
474
- end
475
-
476
- it "loads resource using custom ID param" do
477
- model = Model.new
478
- allow(Model).to receive(:find).with("123") { model }
479
-
480
- params.merge!(:the_model => 123)
481
- resource = CanCan::ControllerResource.new(controller, :id_param => :the_model)
482
- resource.load_resource
483
- expect(controller.instance_variable_get(:@model)).to eq(model)
484
- end
485
-
486
- # CVE-2012-5664
487
- it "always converts id param to string" do
488
- params.merge!(:the_model => { :malicious => "I am" })
489
- resource = CanCan::ControllerResource.new(controller, :id_param => :the_model)
490
- expect(resource.send(:id_param).class).to eq(String)
491
- end
492
-
493
- it "should id param return nil if param is nil" do
494
- params.merge!(:the_model => nil)
495
- resource = CanCan::ControllerResource.new(controller, :id_param => :the_model)
496
- expect(resource.send(:id_param)).to be_nil
497
- end
498
-
499
- it "loads resource using custom find_by attribute" do
500
- model = Model.new
501
- allow(Model).to receive(:name).with('foo') { model }
502
-
503
- params.merge!(:action => "show", :id => "foo")
504
- resource = CanCan::ControllerResource.new(controller, :find_by => :name)
505
- resource.load_resource
506
- expect(controller.instance_variable_get(:@model)).to eq(model)
507
- end
508
-
509
- it "allows full find method to be passed into find_by option" do
510
- model = Model.new
511
- allow(Model).to receive(:find_by_name).with('foo') { model }
512
-
513
- params.merge!(:action => "show", :id => "foo")
514
- resource = CanCan::ControllerResource.new(controller, :find_by => :find_by_name)
515
- resource.load_resource
516
- expect(controller.instance_variable_get(:@model)).to eq(model)
517
- end
518
- end
519
-
520
- it "calls the santitizer when the parameter hash matches our object" do
521
- params.merge!(:action => 'create', :model => { :name => 'test' })
522
- allow(controller).to receive(:create_params).and_return({})
523
-
524
- resource = CanCan::ControllerResource.new(controller)
525
- resource.load_resource
526
- expect(controller.instance_variable_get(:@model).name).to eq nil
527
- end
528
-
529
- it "santitizes correctly when the instance name is overriden" do
530
- params.merge!(:action => 'create', :custom_name => {:name => "foobar"})
531
- allow(controller).to receive(:create_params).and_return({})
532
-
533
- resource = CanCan::ControllerResource.new(controller, :instance_name => :custom_name)
534
- resource.load_resource
535
- expect(controller.instance_variable_get(:@custom_name).name).to eq nil
536
- end
537
-
538
- it "calls the santitize method on non-save actions when required" do
539
- params.merge!(:action => 'new', :model => { :name => 'test' })
540
-
541
- allow(controller).to receive(:resource_params).and_return({})
542
- resource = CanCan::ControllerResource.new(controller)
543
- resource.load_resource
544
- expect(controller.instance_variable_get(:@model).name).to eq nil
545
- end
546
-
547
- it "doesn't sanitize parameters on non-save actions when not required" do
548
- params.merge!(:action => 'new', :not_our_model => { :name => 'test' })
549
- allow(controller).to receive(:resource_params).and_raise
550
-
551
- resource = CanCan::ControllerResource.new(controller)
552
- expect {
553
- resource.load_resource
554
- }.to_not raise_error
555
- end
556
-
557
- it "is a parent resource when name is provided which doesn't match controller" do
558
- resource = CanCan::ControllerResource.new(controller, :category)
559
- expect(resource).to be_parent
560
- end
561
-
562
- it "does not be a parent resource when name is provided which matches controller" do
563
- resource = CanCan::ControllerResource.new(controller, :model)
564
- expect(resource).to_not be_parent
565
- end
566
-
567
- it "is parent if specified in options" do
568
- resource = CanCan::ControllerResource.new(controller, :model, {:parent => true})
569
- expect(resource).to be_parent
570
- end
571
-
572
- it "does not be parent if specified in options" do
573
- resource = CanCan::ControllerResource.new(controller, :category, {:parent => false})
574
- expect(resource).to_not be_parent
575
- end
576
-
577
- it "has the specified resource_class if 'name' is passed to load_resource" do
578
- class Section; end
579
- resource = CanCan::ControllerResource.new(controller, :section)
580
- expect(resource.send(:resource_class)).to eq(Section)
581
- end
582
-
583
- it "raises ImplementationRemoved when adding :name option" do
584
- expect {
585
- CanCan::ControllerResource.new(controller, :name => :foo)
586
- }.to raise_error(CanCan::ImplementationRemoved)
587
- end
588
-
589
- it "raises ImplementationRemoved exception when specifying :resource option since it is no longer used" do
590
- expect {
591
- CanCan::ControllerResource.new(controller, :resource => Model)
592
- }.to raise_error(CanCan::ImplementationRemoved)
593
- end
594
-
595
- it "raises ImplementationRemoved exception when passing :nested option" do
596
- expect {
597
- CanCan::ControllerResource.new(controller, :nested => :model)
598
- }.to raise_error(CanCan::ImplementationRemoved)
599
- end
600
-
601
- it "skips resource behavior for :only actions in array" do
602
- allow(controller_class).to receive(:cancan_skipper) { {:load => {nil => {:only => [:index, :show]}}} }
603
- params.merge!(:action => "index")
604
- expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be(true)
605
- expect(CanCan::ControllerResource.new(controller, :some_resource).skip?(:load)).to be(false)
606
- params.merge!(:action => "show")
607
- expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be(true)
608
- params.merge!(:action => "other_action")
609
- expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be_falsey
610
- end
611
-
612
- it "skips resource behavior for :only one action on resource" do
613
- allow(controller_class).to receive(:cancan_skipper) { {:authorize => {:model => {:only => :index}}} }
614
- params.merge!(:action => "index")
615
- expect(CanCan::ControllerResource.new(controller).skip?(:authorize)).to be(false)
616
- expect(CanCan::ControllerResource.new(controller, :model).skip?(:authorize)).to be(true)
617
- params.merge!(:action => "other_action")
618
- expect(CanCan::ControllerResource.new(controller, :model).skip?(:authorize)).to be_falsey
619
- end
620
-
621
- it "skips resource behavior :except actions in array" do
622
- allow(controller_class).to receive(:cancan_skipper) { {:load => {nil => {:except => [:index, :show]}}} }
623
- params.merge!(:action => "index")
624
- expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be_falsey
625
- params.merge!(:action => "show")
626
- expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be_falsey
627
- params.merge!(:action => "other_action")
628
- expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be(true)
629
- expect(CanCan::ControllerResource.new(controller, :some_resource).skip?(:load)).to be(false)
630
- end
631
-
632
- it "skips resource behavior :except one action on resource" do
633
- allow(controller_class).to receive(:cancan_skipper) { {:authorize => {:model => {:except => :index}}} }
634
- params.merge!(:action => "index")
635
- expect(CanCan::ControllerResource.new(controller, :model).skip?(:authorize)).to be_falsey
636
- params.merge!(:action => "other_action")
637
- expect(CanCan::ControllerResource.new(controller).skip?(:authorize)).to be(false)
638
- expect(CanCan::ControllerResource.new(controller, :model).skip?(:authorize)).to be(true)
639
- end
640
-
641
- it "skips loading and authorization" do
642
- allow(controller_class).to receive(:cancan_skipper) { {:authorize => {nil => {}}, :load => {nil => {}}} }
643
- params.merge!(:action => "new")
644
- resource = CanCan::ControllerResource.new(controller)
645
- expect { resource.load_and_authorize_resource }.not_to raise_error
646
- expect(controller.instance_variable_get(:@model)).to be_nil
647
- end
648
- end