cancancan 1.11.0 → 2.3.0
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.
- checksums.yaml +5 -5
- data/cancancan.gemspec +15 -19
- data/lib/cancan/ability/actions.rb +91 -0
- data/lib/cancan/ability/rules.rb +85 -0
- data/lib/cancan/ability.rb +74 -136
- data/lib/cancan/conditions_matcher.rb +93 -0
- data/lib/cancan/controller_additions.rb +34 -40
- data/lib/cancan/controller_resource.rb +47 -212
- data/lib/cancan/controller_resource_builder.rb +24 -0
- data/lib/cancan/controller_resource_finder.rb +40 -0
- data/lib/cancan/controller_resource_loader.rb +116 -0
- data/lib/cancan/controller_resource_name_finder.rb +21 -0
- data/lib/cancan/controller_resource_sanitizer.rb +30 -0
- data/lib/cancan/exceptions.rb +7 -3
- data/lib/cancan/matchers.rb +12 -3
- data/lib/cancan/model_adapters/abstract_adapter.rb +8 -8
- data/lib/cancan/model_adapters/active_record_4_adapter.rb +33 -10
- data/lib/cancan/model_adapters/active_record_5_adapter.rb +70 -0
- data/lib/cancan/model_adapters/active_record_adapter.rb +41 -81
- data/lib/cancan/model_adapters/can_can/model_adapters/active_record_adapter/joins.rb +39 -0
- data/lib/cancan/model_adapters/conditions_extractor.rb +75 -0
- data/lib/cancan/model_additions.rb +0 -1
- data/lib/cancan/rule.rb +36 -92
- data/lib/cancan/rules_compressor.rb +20 -0
- data/lib/cancan/version.rb +1 -1
- data/lib/cancan.rb +5 -12
- data/lib/generators/cancan/ability/ability_generator.rb +1 -1
- metadata +54 -65
- data/.gitignore +0 -15
- data/.rspec +0 -1
- data/.travis.yml +0 -55
- data/Appraisals +0 -136
- data/CHANGELOG.rdoc +0 -503
- data/CONTRIBUTING.md +0 -23
- data/Gemfile +0 -3
- data/LICENSE +0 -22
- data/README.md +0 -188
- data/Rakefile +0 -9
- data/gemfiles/activerecord_3.0.gemfile +0 -18
- data/gemfiles/activerecord_3.1.gemfile +0 -20
- data/gemfiles/activerecord_3.2.gemfile +0 -20
- data/gemfiles/activerecord_4.0.gemfile +0 -17
- data/gemfiles/activerecord_4.1.gemfile +0 -17
- data/gemfiles/activerecord_4.2.gemfile +0 -18
- data/gemfiles/datamapper_1.x.gemfile +0 -14
- data/gemfiles/mongoid_2.x.gemfile +0 -20
- data/gemfiles/sequel_3.x.gemfile +0 -20
- data/lib/cancan/inherited_resource.rb +0 -20
- data/lib/cancan/model_adapters/active_record_3_adapter.rb +0 -47
- data/lib/cancan/model_adapters/data_mapper_adapter.rb +0 -34
- data/lib/cancan/model_adapters/mongoid_adapter.rb +0 -54
- data/lib/cancan/model_adapters/sequel_adapter.rb +0 -87
- data/spec/README.rdoc +0 -27
- data/spec/cancan/ability_spec.rb +0 -487
- data/spec/cancan/controller_additions_spec.rb +0 -141
- data/spec/cancan/controller_resource_spec.rb +0 -632
- data/spec/cancan/exceptions_spec.rb +0 -58
- data/spec/cancan/inherited_resource_spec.rb +0 -71
- data/spec/cancan/matchers_spec.rb +0 -29
- data/spec/cancan/model_adapters/active_record_4_adapter_spec.rb +0 -85
- data/spec/cancan/model_adapters/active_record_adapter_spec.rb +0 -446
- data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +0 -119
- data/spec/cancan/model_adapters/default_adapter_spec.rb +0 -7
- data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +0 -227
- data/spec/cancan/model_adapters/sequel_adapter_spec.rb +0 -132
- data/spec/cancan/rule_spec.rb +0 -52
- data/spec/matchers.rb +0 -13
- data/spec/spec.opts +0 -2
- data/spec/spec_helper.rb +0 -28
- data/spec/support/ability.rb +0 -7
@@ -1,632 +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 => "my_engine/models", :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/sub_models", '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 "authorizes with :custom_action for parent collection action" do
|
235
|
-
controller.instance_variable_set(:@category, :some_category)
|
236
|
-
allow(controller).to receive(:authorize!).with(:custom_action, :some_category) { raise CanCan::AccessDenied }
|
237
|
-
|
238
|
-
resource = CanCan::ControllerResource.new(controller, :category, :parent => true, :parent_action => :custom_action )
|
239
|
-
expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
|
240
|
-
end
|
241
|
-
|
242
|
-
it "has the specified nested resource_class when using / for namespace" do
|
243
|
-
module Admin
|
244
|
-
class Dashboard; end
|
245
|
-
end
|
246
|
-
ability.can(:index, "admin/dashboard")
|
247
|
-
params.merge!(:controller => "admin/dashboard")
|
248
|
-
resource = CanCan::ControllerResource.new(controller, :authorize => true)
|
249
|
-
expect(resource.send(:resource_class)).to eq(Admin::Dashboard)
|
250
|
-
end
|
251
|
-
|
252
|
-
it "does not build a single resource when on custom collection action even with id" do
|
253
|
-
params.merge!(:action => "sort", :id => "123")
|
254
|
-
|
255
|
-
resource = CanCan::ControllerResource.new(controller, :collection => [:sort, :list])
|
256
|
-
resource.load_resource
|
257
|
-
expect(controller.instance_variable_get(:@model)).to be_nil
|
258
|
-
end
|
259
|
-
|
260
|
-
it "loads a collection resource when on custom action with no id param" do
|
261
|
-
allow(Model).to receive(:accessible_by).with(ability, :sort) { :found_models }
|
262
|
-
params[:action] = "sort"
|
263
|
-
resource = CanCan::ControllerResource.new(controller)
|
264
|
-
resource.load_resource
|
265
|
-
expect(controller.instance_variable_get(:@model)).to be_nil
|
266
|
-
expect(controller.instance_variable_get(:@models)).to eq(:found_models)
|
267
|
-
end
|
268
|
-
|
269
|
-
it "loads parent resource through proper id parameter" do
|
270
|
-
model = Model.new
|
271
|
-
allow(Model).to receive(:find).with("1") { model }
|
272
|
-
|
273
|
-
params.merge!(:controller => "categories", :model_id => 1)
|
274
|
-
resource = CanCan::ControllerResource.new(controller, :model)
|
275
|
-
resource.load_resource
|
276
|
-
expect(controller.instance_variable_get(:@model)).to eq(model)
|
277
|
-
end
|
278
|
-
|
279
|
-
it "authorizes nested resource through parent association on index action" do
|
280
|
-
controller.instance_variable_set(:@category, category = double)
|
281
|
-
allow(controller).to receive(:authorize!).with(:index, category => Model) { raise CanCan::AccessDenied }
|
282
|
-
resource = CanCan::ControllerResource.new(controller, :through => :category)
|
283
|
-
expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
context "on instance read actions" do
|
288
|
-
before :each do
|
289
|
-
params.merge!(:action => "show", :id => "123")
|
290
|
-
end
|
291
|
-
|
292
|
-
it "loads the resource into an instance variable if params[:id] is specified" do
|
293
|
-
model = Model.new
|
294
|
-
allow(Model).to receive(:find).with("123") { model }
|
295
|
-
|
296
|
-
resource = CanCan::ControllerResource.new(controller)
|
297
|
-
resource.load_resource
|
298
|
-
expect(controller.instance_variable_get(:@model)).to eq(model)
|
299
|
-
end
|
300
|
-
|
301
|
-
it "does not load resource into an instance variable if already set" do
|
302
|
-
controller.instance_variable_set(:@model, :some_model)
|
303
|
-
resource = CanCan::ControllerResource.new(controller)
|
304
|
-
resource.load_resource
|
305
|
-
expect(controller.instance_variable_get(:@model)).to eq(:some_model)
|
306
|
-
end
|
307
|
-
|
308
|
-
it "loads resource for namespaced controller" do
|
309
|
-
model = Model.new
|
310
|
-
allow(Model).to receive(:find).with("123") { model }
|
311
|
-
params.merge!(:controller => "admin/models")
|
312
|
-
|
313
|
-
resource = CanCan::ControllerResource.new(controller)
|
314
|
-
resource.load_resource
|
315
|
-
expect(controller.instance_variable_get(:@model)).to eq(model)
|
316
|
-
end
|
317
|
-
|
318
|
-
it "performs authorization using controller action and loaded model" do
|
319
|
-
controller.instance_variable_set(:@model, :some_model)
|
320
|
-
allow(controller).to receive(:authorize!).with(:show, :some_model) { raise CanCan::AccessDenied }
|
321
|
-
|
322
|
-
resource = CanCan::ControllerResource.new(controller)
|
323
|
-
expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
|
324
|
-
end
|
325
|
-
|
326
|
-
it "performs authorization using controller action and non loaded model" do
|
327
|
-
allow(controller).to receive(:authorize!).with(:show, Model) { raise CanCan::AccessDenied }
|
328
|
-
resource = CanCan::ControllerResource.new(controller)
|
329
|
-
expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
|
330
|
-
end
|
331
|
-
|
332
|
-
it "calls load_resource and authorize_resource for load_and_authorize_resource" do
|
333
|
-
resource = CanCan::ControllerResource.new(controller)
|
334
|
-
expect(resource).to receive(:load_resource)
|
335
|
-
expect(resource).to receive(:authorize_resource)
|
336
|
-
resource.load_and_authorize_resource
|
337
|
-
end
|
338
|
-
|
339
|
-
it "loads resource through the association of another parent resource using instance variable" do
|
340
|
-
category = double(:models => {})
|
341
|
-
controller.instance_variable_set(:@category, category)
|
342
|
-
allow(category.models).to receive(:find).with("123") { :some_model }
|
343
|
-
resource = CanCan::ControllerResource.new(controller, :through => :category)
|
344
|
-
resource.load_resource
|
345
|
-
expect(controller.instance_variable_get(:@model)).to eq(:some_model)
|
346
|
-
end
|
347
|
-
|
348
|
-
it "loads resource through the custom association name" do
|
349
|
-
category = double(:custom_models => {})
|
350
|
-
controller.instance_variable_set(:@category, category)
|
351
|
-
allow(category.custom_models).to receive(:find).with("123") { :some_model }
|
352
|
-
resource = CanCan::ControllerResource.new(controller, :through => :category, :through_association => :custom_models)
|
353
|
-
resource.load_resource
|
354
|
-
expect(controller.instance_variable_get(:@model)).to eq(:some_model)
|
355
|
-
end
|
356
|
-
|
357
|
-
it "loads resource through the association of another parent resource using method" do
|
358
|
-
category = double(:models => {})
|
359
|
-
allow(controller).to receive(:category) { category }
|
360
|
-
allow(category.models).to receive(:find).with("123") { :some_model }
|
361
|
-
resource = CanCan::ControllerResource.new(controller, :through => :category)
|
362
|
-
resource.load_resource
|
363
|
-
expect(controller.instance_variable_get(:@model)).to eq(:some_model)
|
364
|
-
end
|
365
|
-
|
366
|
-
it "does not load through parent resource if instance isn't loaded when shallow" do
|
367
|
-
model = Model.new
|
368
|
-
allow(Model).to receive(:find).with("123") { model }
|
369
|
-
|
370
|
-
resource = CanCan::ControllerResource.new(controller, :through => :category, :shallow => true)
|
371
|
-
resource.load_resource
|
372
|
-
expect(controller.instance_variable_get(:@model)).to eq(model)
|
373
|
-
end
|
374
|
-
|
375
|
-
it "raises AccessDenied when attempting to load resource through nil" do
|
376
|
-
resource = CanCan::ControllerResource.new(controller, :through => :category)
|
377
|
-
expect {
|
378
|
-
resource.load_resource
|
379
|
-
}.to raise_error(CanCan::AccessDenied) { |exception|
|
380
|
-
expect(exception.action).to eq(:show)
|
381
|
-
expect(exception.subject).to eq(Model)
|
382
|
-
}
|
383
|
-
expect(controller.instance_variable_get(:@model)).to be_nil
|
384
|
-
end
|
385
|
-
|
386
|
-
it "loads through first matching if multiple are given" do
|
387
|
-
category = double(:models => {})
|
388
|
-
controller.instance_variable_set(:@category, category)
|
389
|
-
allow(category.models).to receive(:find).with("123") { :some_model }
|
390
|
-
|
391
|
-
resource = CanCan::ControllerResource.new(controller, :through => [:category, :user])
|
392
|
-
resource.load_resource
|
393
|
-
expect(controller.instance_variable_get(:@model)).to eq(:some_model)
|
394
|
-
end
|
395
|
-
|
396
|
-
it "finds record through has_one association with :singleton option without id param" do
|
397
|
-
params.merge!(:id => nil)
|
398
|
-
|
399
|
-
category = double(:model => :some_model)
|
400
|
-
controller.instance_variable_set(:@category, category)
|
401
|
-
resource = CanCan::ControllerResource.new(controller, :through => :category, :singleton => true)
|
402
|
-
resource.load_resource
|
403
|
-
expect(controller.instance_variable_get(:@model)).to eq(:some_model)
|
404
|
-
end
|
405
|
-
|
406
|
-
it "does not try to load resource for other action if params[:id] is undefined" do
|
407
|
-
params.merge!(:action => 'list', :id => nil)
|
408
|
-
resource = CanCan::ControllerResource.new(controller)
|
409
|
-
resource.load_resource
|
410
|
-
expect(controller.instance_variable_get(:@model)).to be_nil
|
411
|
-
end
|
412
|
-
|
413
|
-
it "finds record through has_one association with :singleton and :shallow options" do
|
414
|
-
model = Model.new
|
415
|
-
allow(Model).to receive(:find).with("123") { model }
|
416
|
-
|
417
|
-
resource = CanCan::ControllerResource.new(controller, :through => :category, :singleton => true, :shallow => true)
|
418
|
-
resource.load_resource
|
419
|
-
expect(controller.instance_variable_get(:@model)).to eq(model)
|
420
|
-
end
|
421
|
-
|
422
|
-
it "loads the model using a custom class" do
|
423
|
-
model = Model.new
|
424
|
-
allow(Model).to receive(:find).with("123") { model }
|
425
|
-
|
426
|
-
resource = CanCan::ControllerResource.new(controller, :class => Model)
|
427
|
-
resource.load_resource
|
428
|
-
expect(controller.instance_variable_get(:@model)).to eq(model)
|
429
|
-
end
|
430
|
-
|
431
|
-
it "loads the model using a custom namespaced class" do
|
432
|
-
module Sub
|
433
|
-
class Model < ::Model; end
|
434
|
-
end
|
435
|
-
|
436
|
-
model = Sub::Model.new
|
437
|
-
allow(Sub::Model).to receive(:find).with("123") { model }
|
438
|
-
|
439
|
-
resource = CanCan::ControllerResource.new(controller, :class => ::Sub::Model)
|
440
|
-
resource.load_resource
|
441
|
-
expect(controller.instance_variable_get(:@model)).to eq(model)
|
442
|
-
end
|
443
|
-
|
444
|
-
it "authorizes based on resource name if class is false" do
|
445
|
-
allow(controller).to receive(:authorize!).with(:show, :model) { raise CanCan::AccessDenied }
|
446
|
-
resource = CanCan::ControllerResource.new(controller, :class => false)
|
447
|
-
expect { resource.authorize_resource }.to raise_error(CanCan::AccessDenied)
|
448
|
-
end
|
449
|
-
|
450
|
-
it "loads and authorize using custom instance name" do
|
451
|
-
model = Model.new
|
452
|
-
allow(Model).to receive(:find).with("123") { model }
|
453
|
-
|
454
|
-
allow(controller).to receive(:authorize!).with(:show, model) { raise CanCan::AccessDenied }
|
455
|
-
resource = CanCan::ControllerResource.new(controller, :instance_name => :custom_model)
|
456
|
-
expect { resource.load_and_authorize_resource }.to raise_error(CanCan::AccessDenied)
|
457
|
-
expect(controller.instance_variable_get(:@custom_model)).to eq(model)
|
458
|
-
end
|
459
|
-
|
460
|
-
it "loads resource using custom ID param" do
|
461
|
-
model = Model.new
|
462
|
-
allow(Model).to receive(:find).with("123") { model }
|
463
|
-
|
464
|
-
params.merge!(:the_model => 123)
|
465
|
-
resource = CanCan::ControllerResource.new(controller, :id_param => :the_model)
|
466
|
-
resource.load_resource
|
467
|
-
expect(controller.instance_variable_get(:@model)).to eq(model)
|
468
|
-
end
|
469
|
-
|
470
|
-
# CVE-2012-5664
|
471
|
-
it "always converts id param to string" do
|
472
|
-
params.merge!(:the_model => { :malicious => "I am" })
|
473
|
-
resource = CanCan::ControllerResource.new(controller, :id_param => :the_model)
|
474
|
-
expect(resource.send(:id_param).class).to eq(String)
|
475
|
-
end
|
476
|
-
|
477
|
-
it "should id param return nil if param is nil" do
|
478
|
-
params.merge!(:the_model => nil)
|
479
|
-
resource = CanCan::ControllerResource.new(controller, :id_param => :the_model)
|
480
|
-
expect(resource.send(:id_param)).to be_nil
|
481
|
-
end
|
482
|
-
|
483
|
-
it "loads resource using custom find_by attribute" do
|
484
|
-
model = Model.new
|
485
|
-
allow(Model).to receive(:name).with('foo') { model }
|
486
|
-
|
487
|
-
params.merge!(:action => "show", :id => "foo")
|
488
|
-
resource = CanCan::ControllerResource.new(controller, :find_by => :name)
|
489
|
-
resource.load_resource
|
490
|
-
expect(controller.instance_variable_get(:@model)).to eq(model)
|
491
|
-
end
|
492
|
-
|
493
|
-
it "allows full find method to be passed into find_by option" do
|
494
|
-
model = Model.new
|
495
|
-
allow(Model).to receive(:find_by_name).with('foo') { model }
|
496
|
-
|
497
|
-
params.merge!(:action => "show", :id => "foo")
|
498
|
-
resource = CanCan::ControllerResource.new(controller, :find_by => :find_by_name)
|
499
|
-
resource.load_resource
|
500
|
-
expect(controller.instance_variable_get(:@model)).to eq(model)
|
501
|
-
end
|
502
|
-
end
|
503
|
-
|
504
|
-
it "calls the santitizer when the parameter hash matches our object" do
|
505
|
-
params.merge!(:action => 'create', :model => { :name => 'test' })
|
506
|
-
allow(controller).to receive(:create_params).and_return({})
|
507
|
-
|
508
|
-
resource = CanCan::ControllerResource.new(controller)
|
509
|
-
resource.load_resource
|
510
|
-
expect(controller.instance_variable_get(:@model).name).to eq nil
|
511
|
-
end
|
512
|
-
|
513
|
-
it "santitizes correctly when the instance name is overriden" do
|
514
|
-
params.merge!(:action => 'create', :custom_name => {:name => "foobar"})
|
515
|
-
allow(controller).to receive(:create_params).and_return({})
|
516
|
-
|
517
|
-
resource = CanCan::ControllerResource.new(controller, :instance_name => :custom_name)
|
518
|
-
resource.load_resource
|
519
|
-
expect(controller.instance_variable_get(:@custom_name).name).to eq nil
|
520
|
-
end
|
521
|
-
|
522
|
-
it "calls the santitize method on non-save actions when required" do
|
523
|
-
params.merge!(:action => 'new', :model => { :name => 'test' })
|
524
|
-
|
525
|
-
allow(controller).to receive(:resource_params).and_return({})
|
526
|
-
resource = CanCan::ControllerResource.new(controller)
|
527
|
-
resource.load_resource
|
528
|
-
expect(controller.instance_variable_get(:@model).name).to eq nil
|
529
|
-
end
|
530
|
-
|
531
|
-
it "doesn't sanitize parameters on non-save actions when not required" do
|
532
|
-
params.merge!(:action => 'new', :not_our_model => { :name => 'test' })
|
533
|
-
allow(controller).to receive(:resource_params).and_raise
|
534
|
-
|
535
|
-
resource = CanCan::ControllerResource.new(controller)
|
536
|
-
expect {
|
537
|
-
resource.load_resource
|
538
|
-
}.to_not raise_error
|
539
|
-
end
|
540
|
-
|
541
|
-
it "is a parent resource when name is provided which doesn't match controller" do
|
542
|
-
resource = CanCan::ControllerResource.new(controller, :category)
|
543
|
-
expect(resource).to be_parent
|
544
|
-
end
|
545
|
-
|
546
|
-
it "does not be a parent resource when name is provided which matches controller" do
|
547
|
-
resource = CanCan::ControllerResource.new(controller, :model)
|
548
|
-
expect(resource).to_not be_parent
|
549
|
-
end
|
550
|
-
|
551
|
-
it "is parent if specified in options" do
|
552
|
-
resource = CanCan::ControllerResource.new(controller, :model, {:parent => true})
|
553
|
-
expect(resource).to be_parent
|
554
|
-
end
|
555
|
-
|
556
|
-
it "does not be parent if specified in options" do
|
557
|
-
resource = CanCan::ControllerResource.new(controller, :category, {:parent => false})
|
558
|
-
expect(resource).to_not be_parent
|
559
|
-
end
|
560
|
-
|
561
|
-
it "has the specified resource_class if 'name' is passed to load_resource" do
|
562
|
-
class Section; end
|
563
|
-
resource = CanCan::ControllerResource.new(controller, :section)
|
564
|
-
expect(resource.send(:resource_class)).to eq(Section)
|
565
|
-
end
|
566
|
-
|
567
|
-
it "raises ImplementationRemoved when adding :name option" do
|
568
|
-
expect {
|
569
|
-
CanCan::ControllerResource.new(controller, :name => :foo)
|
570
|
-
}.to raise_error(CanCan::ImplementationRemoved)
|
571
|
-
end
|
572
|
-
|
573
|
-
it "raises ImplementationRemoved exception when specifying :resource option since it is no longer used" do
|
574
|
-
expect {
|
575
|
-
CanCan::ControllerResource.new(controller, :resource => Model)
|
576
|
-
}.to raise_error(CanCan::ImplementationRemoved)
|
577
|
-
end
|
578
|
-
|
579
|
-
it "raises ImplementationRemoved exception when passing :nested option" do
|
580
|
-
expect {
|
581
|
-
CanCan::ControllerResource.new(controller, :nested => :model)
|
582
|
-
}.to raise_error(CanCan::ImplementationRemoved)
|
583
|
-
end
|
584
|
-
|
585
|
-
it "skips resource behavior for :only actions in array" do
|
586
|
-
allow(controller_class).to receive(:cancan_skipper) { {:load => {nil => {:only => [:index, :show]}}} }
|
587
|
-
params.merge!(:action => "index")
|
588
|
-
expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be(true)
|
589
|
-
expect(CanCan::ControllerResource.new(controller, :some_resource).skip?(:load)).to be(false)
|
590
|
-
params.merge!(:action => "show")
|
591
|
-
expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be(true)
|
592
|
-
params.merge!(:action => "other_action")
|
593
|
-
expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be_falsey
|
594
|
-
end
|
595
|
-
|
596
|
-
it "skips resource behavior for :only one action on resource" do
|
597
|
-
allow(controller_class).to receive(:cancan_skipper) { {:authorize => {:model => {:only => :index}}} }
|
598
|
-
params.merge!(:action => "index")
|
599
|
-
expect(CanCan::ControllerResource.new(controller).skip?(:authorize)).to be(false)
|
600
|
-
expect(CanCan::ControllerResource.new(controller, :model).skip?(:authorize)).to be(true)
|
601
|
-
params.merge!(:action => "other_action")
|
602
|
-
expect(CanCan::ControllerResource.new(controller, :model).skip?(:authorize)).to be_falsey
|
603
|
-
end
|
604
|
-
|
605
|
-
it "skips resource behavior :except actions in array" do
|
606
|
-
allow(controller_class).to receive(:cancan_skipper) { {:load => {nil => {:except => [:index, :show]}}} }
|
607
|
-
params.merge!(:action => "index")
|
608
|
-
expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be_falsey
|
609
|
-
params.merge!(:action => "show")
|
610
|
-
expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be_falsey
|
611
|
-
params.merge!(:action => "other_action")
|
612
|
-
expect(CanCan::ControllerResource.new(controller).skip?(:load)).to be(true)
|
613
|
-
expect(CanCan::ControllerResource.new(controller, :some_resource).skip?(:load)).to be(false)
|
614
|
-
end
|
615
|
-
|
616
|
-
it "skips resource behavior :except one action on resource" do
|
617
|
-
allow(controller_class).to receive(:cancan_skipper) { {:authorize => {:model => {:except => :index}}} }
|
618
|
-
params.merge!(:action => "index")
|
619
|
-
expect(CanCan::ControllerResource.new(controller, :model).skip?(:authorize)).to be_falsey
|
620
|
-
params.merge!(:action => "other_action")
|
621
|
-
expect(CanCan::ControllerResource.new(controller).skip?(:authorize)).to be(false)
|
622
|
-
expect(CanCan::ControllerResource.new(controller, :model).skip?(:authorize)).to be(true)
|
623
|
-
end
|
624
|
-
|
625
|
-
it "skips loading and authorization" do
|
626
|
-
allow(controller_class).to receive(:cancan_skipper) { {:authorize => {nil => {}}, :load => {nil => {}}} }
|
627
|
-
params.merge!(:action => "new")
|
628
|
-
resource = CanCan::ControllerResource.new(controller)
|
629
|
-
expect { resource.load_and_authorize_resource }.not_to raise_error
|
630
|
-
expect(controller.instance_variable_get(:@model)).to be_nil
|
631
|
-
end
|
632
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe CanCan::AccessDenied do
|
4
|
-
describe "with action and subject" do
|
5
|
-
before(:each) do
|
6
|
-
@exception = CanCan::AccessDenied.new(nil, :some_action, :some_subject)
|
7
|
-
end
|
8
|
-
|
9
|
-
it "has action and subject accessors" do
|
10
|
-
expect(@exception.action).to eq(:some_action)
|
11
|
-
expect(@exception.subject).to eq(:some_subject)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "has a changable default message" do
|
15
|
-
expect(@exception.message).to eq("You are not authorized to access this page.")
|
16
|
-
@exception.default_message = "Unauthorized!"
|
17
|
-
expect(@exception.message).to eq("Unauthorized!")
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe "with only a message" do
|
22
|
-
before(:each) do
|
23
|
-
@exception = CanCan::AccessDenied.new("Access denied!")
|
24
|
-
end
|
25
|
-
|
26
|
-
it "has nil action and subject" do
|
27
|
-
expect(@exception.action).to be_nil
|
28
|
-
expect(@exception.subject).to be_nil
|
29
|
-
end
|
30
|
-
|
31
|
-
it "has passed message" do
|
32
|
-
expect(@exception.message).to eq("Access denied!")
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe "i18n in the default message" do
|
37
|
-
after(:each) do
|
38
|
-
I18n.backend = nil
|
39
|
-
end
|
40
|
-
|
41
|
-
it "uses i18n for the default message" do
|
42
|
-
I18n.backend.store_translations :en, :unauthorized => {:default => "This is a different message"}
|
43
|
-
@exception = CanCan::AccessDenied.new
|
44
|
-
expect(@exception.message).to eq("This is a different message")
|
45
|
-
end
|
46
|
-
|
47
|
-
it "defaults to a nice message" do
|
48
|
-
@exception = CanCan::AccessDenied.new
|
49
|
-
expect(@exception.message).to eq("You are not authorized to access this page.")
|
50
|
-
end
|
51
|
-
|
52
|
-
it "does not use translation if a message is given" do
|
53
|
-
@exception = CanCan::AccessDenied.new("Hey! You're not welcome here")
|
54
|
-
expect(@exception.message).to eq("Hey! You're not welcome here")
|
55
|
-
expect(@exception.message).to_not eq("You are not authorized to access this page.")
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|