codeprimate-cancan 1.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/CHANGELOG.rdoc +291 -0
  2. data/Gemfile +20 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +111 -0
  5. data/Rakefile +18 -0
  6. data/init.rb +1 -0
  7. data/lib/cancan.rb +13 -0
  8. data/lib/cancan/ability.rb +298 -0
  9. data/lib/cancan/controller_additions.rb +389 -0
  10. data/lib/cancan/controller_resource.rb +222 -0
  11. data/lib/cancan/exceptions.rb +50 -0
  12. data/lib/cancan/inherited_resource.rb +19 -0
  13. data/lib/cancan/matchers.rb +14 -0
  14. data/lib/cancan/model_adapters/abstract_adapter.rb +56 -0
  15. data/lib/cancan/model_adapters/active_record_adapter.rb +165 -0
  16. data/lib/cancan/model_adapters/data_mapper_adapter.rb +34 -0
  17. data/lib/cancan/model_adapters/default_adapter.rb +7 -0
  18. data/lib/cancan/model_adapters/mongoid_adapter.rb +53 -0
  19. data/lib/cancan/model_additions.rb +31 -0
  20. data/lib/cancan/rule.rb +142 -0
  21. data/lib/generators/cancan/ability/USAGE +4 -0
  22. data/lib/generators/cancan/ability/ability_generator.rb +11 -0
  23. data/lib/generators/cancan/ability/templates/ability.rb +28 -0
  24. data/spec/README.rdoc +28 -0
  25. data/spec/cancan/ability_spec.rb +419 -0
  26. data/spec/cancan/controller_additions_spec.rb +137 -0
  27. data/spec/cancan/controller_resource_spec.rb +412 -0
  28. data/spec/cancan/exceptions_spec.rb +58 -0
  29. data/spec/cancan/inherited_resource_spec.rb +42 -0
  30. data/spec/cancan/matchers_spec.rb +33 -0
  31. data/spec/cancan/model_adapters/active_record_adapter_spec.rb +278 -0
  32. data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +119 -0
  33. data/spec/cancan/model_adapters/default_adapter_spec.rb +7 -0
  34. data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +216 -0
  35. data/spec/cancan/rule_spec.rb +39 -0
  36. data/spec/matchers.rb +13 -0
  37. data/spec/spec.opts +2 -0
  38. data/spec/spec_helper.rb +41 -0
  39. metadata +167 -0
@@ -0,0 +1,137 @@
1
+ require "spec_helper"
2
+
3
+ describe CanCan::ControllerAdditions do
4
+ before(:each) do
5
+ @controller_class = Class.new
6
+ @controller = @controller_class.new
7
+ stub(@controller).params { {} }
8
+ stub(@controller).current_user { :current_user }
9
+ mock(@controller_class).helper_method(:can?, :cannot?, :current_ability)
10
+ @controller_class.send(:include, CanCan::ControllerAdditions)
11
+ end
12
+
13
+ it "should raise ImplementationRemoved when attempting to call 'unauthorized!' on a controller" do
14
+ lambda { @controller.unauthorized! }.should raise_error(CanCan::ImplementationRemoved)
15
+ end
16
+
17
+ it "authorize! should assign @_authorized instance variable and pass args to current ability" do
18
+ mock(@controller.current_ability).authorize!(:foo, :bar)
19
+ @controller.authorize!(:foo, :bar)
20
+ @controller.instance_variable_get(:@_authorized).should be_true
21
+ end
22
+
23
+ it "should have a current_ability method which generates an ability for the current user" do
24
+ @controller.current_ability.should be_kind_of(Ability)
25
+ end
26
+
27
+ it "should provide a can? and cannot? methods which go through the current ability" do
28
+ @controller.current_ability.should be_kind_of(Ability)
29
+ @controller.can?(:foo, :bar).should be_false
30
+ @controller.cannot?(:foo, :bar).should be_true
31
+ end
32
+
33
+ it "load_and_authorize_resource should setup a before filter which passes call to ControllerResource" do
34
+ stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.load_and_authorize_resource
35
+ mock(@controller_class).before_filter({}) { |options, block| block.call(@controller) }
36
+ @controller_class.load_and_authorize_resource :foo => :bar
37
+ end
38
+
39
+ it "load_and_authorize_resource should properly pass first argument as the resource name" do
40
+ stub(CanCan::ControllerResource).new(@controller, :project, :foo => :bar).mock!.load_and_authorize_resource
41
+ mock(@controller_class).before_filter({}) { |options, block| block.call(@controller) }
42
+ @controller_class.load_and_authorize_resource :project, :foo => :bar
43
+ end
44
+
45
+ it "load_and_authorize_resource with :prepend should prepend the before filter" do
46
+ mock(@controller_class).prepend_before_filter({})
47
+ @controller_class.load_and_authorize_resource :foo => :bar, :prepend => true
48
+ end
49
+
50
+ it "authorize_resource should setup a before filter which passes call to ControllerResource" do
51
+ stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.authorize_resource
52
+ mock(@controller_class).before_filter(:except => :show) { |options, block| block.call(@controller) }
53
+ @controller_class.authorize_resource :foo => :bar, :except => :show
54
+ end
55
+
56
+ it "load_resource should setup a before filter which passes call to ControllerResource" do
57
+ stub(CanCan::ControllerResource).new(@controller, nil, :foo => :bar).mock!.load_resource
58
+ mock(@controller_class).before_filter(:only => [:show, :index]) { |options, block| block.call(@controller) }
59
+ @controller_class.load_resource :foo => :bar, :only => [:show, :index]
60
+ end
61
+
62
+ it "skip_authorization_check should set up a before filter which sets @_authorized to true" do
63
+ mock(@controller_class).before_filter(:filter_options) { |options, block| block.call(@controller) }
64
+ @controller_class.skip_authorization_check(:filter_options)
65
+ @controller.instance_variable_get(:@_authorized).should be_true
66
+ end
67
+
68
+ it "check_authorization should trigger AuthorizationNotPerformed in after filter" do
69
+ mock(@controller_class).after_filter(:only => [:test]) { |options, block| block.call(@controller) }
70
+ lambda {
71
+ @controller_class.check_authorization(:only => [:test])
72
+ }.should raise_error(CanCan::AuthorizationNotPerformed)
73
+ end
74
+
75
+ it "check_authorization should not trigger AuthorizationNotPerformed when :if is false" do
76
+ stub(@controller).check_auth? { false }
77
+ mock(@controller_class).after_filter({}) { |options, block| block.call(@controller) }
78
+ lambda {
79
+ @controller_class.check_authorization(:if => :check_auth?)
80
+ }.should_not raise_error(CanCan::AuthorizationNotPerformed)
81
+ end
82
+
83
+ it "check_authorization should not trigger AuthorizationNotPerformed when :unless is true" do
84
+ stub(@controller).engine_controller? { true }
85
+ mock(@controller_class).after_filter({}) { |options, block| block.call(@controller) }
86
+ lambda {
87
+ @controller_class.check_authorization(:unless => :engine_controller?)
88
+ }.should_not raise_error(CanCan::AuthorizationNotPerformed)
89
+ end
90
+
91
+ it "check_authorization should not raise error when @_authorized is set" do
92
+ @controller.instance_variable_set(:@_authorized, true)
93
+ mock(@controller_class).after_filter(:only => [:test]) { |options, block| block.call(@controller) }
94
+ lambda {
95
+ @controller_class.check_authorization(:only => [:test])
96
+ }.should_not raise_error(CanCan::AuthorizationNotPerformed)
97
+ end
98
+
99
+ it "cancan_resource_class should be ControllerResource by default" do
100
+ @controller.class.cancan_resource_class.should == CanCan::ControllerResource
101
+ end
102
+
103
+ it "cancan_resource_class should be InheritedResource when class includes InheritedResources::Actions" do
104
+ stub(@controller.class).ancestors { ["InheritedResources::Actions"] }
105
+ @controller.class.cancan_resource_class.should == CanCan::InheritedResource
106
+ end
107
+
108
+ it "cancan_skipper should be an empty hash with :authorize and :load options and remember changes" do
109
+ @controller_class.cancan_skipper.should == {:authorize => {}, :load => {}}
110
+ @controller_class.cancan_skipper[:load] = true
111
+ @controller_class.cancan_skipper[:load].should == true
112
+ end
113
+
114
+ it "skip_authorize_resource should add itself to the cancan skipper with given model name and options" do
115
+ @controller_class.skip_authorize_resource(:project, :only => [:index, :show])
116
+ @controller_class.cancan_skipper[:authorize][:project].should == {:only => [:index, :show]}
117
+ @controller_class.skip_authorize_resource(:only => [:index, :show])
118
+ @controller_class.cancan_skipper[:authorize][nil].should == {:only => [:index, :show]}
119
+ @controller_class.skip_authorize_resource(:article)
120
+ @controller_class.cancan_skipper[:authorize][:article].should == {}
121
+ end
122
+
123
+ it "skip_load_resource should add itself to the cancan skipper with given model name and options" do
124
+ @controller_class.skip_load_resource(:project, :only => [:index, :show])
125
+ @controller_class.cancan_skipper[:load][:project].should == {:only => [:index, :show]}
126
+ @controller_class.skip_load_resource(:only => [:index, :show])
127
+ @controller_class.cancan_skipper[:load][nil].should == {:only => [:index, :show]}
128
+ @controller_class.skip_load_resource(:article)
129
+ @controller_class.cancan_skipper[:load][:article].should == {}
130
+ end
131
+
132
+ it "skip_load_and_authore_resource should add itself to the cancan skipper with given model name and options" do
133
+ @controller_class.skip_load_and_authorize_resource(:project, :only => [:index, :show])
134
+ @controller_class.cancan_skipper[:load][:project].should == {:only => [:index, :show]}
135
+ @controller_class.cancan_skipper[:authorize][:project].should == {:only => [:index, :show]}
136
+ end
137
+ end
@@ -0,0 +1,412 @@
1
+ require "spec_helper"
2
+
3
+ describe CanCan::ControllerResource do
4
+ before(:each) do
5
+ @params = HashWithIndifferentAccess.new(:controller => "projects")
6
+ @controller_class = Class.new
7
+ @controller = @controller_class.new
8
+ @ability = Ability.new(nil)
9
+ stub(@controller).params { @params }
10
+ stub(@controller).current_ability { @ability }
11
+ stub(@controller_class).cancan_skipper { {:authorize => {}, :load => {}} }
12
+ end
13
+
14
+ it "should load the resource into an instance variable if params[:id] is specified" do
15
+ project = Project.create!
16
+ @params.merge!(:action => "show", :id => project.id)
17
+ resource = CanCan::ControllerResource.new(@controller)
18
+ resource.load_resource
19
+ @controller.instance_variable_get(:@project).should == project
20
+ end
21
+
22
+ it "should not load resource into an instance variable if already set" do
23
+ @params.merge!(:action => "show", :id => 123)
24
+ @controller.instance_variable_set(:@project, :some_project)
25
+ resource = CanCan::ControllerResource.new(@controller)
26
+ resource.load_resource
27
+ @controller.instance_variable_get(:@project).should == :some_project
28
+ end
29
+
30
+ it "should properly load resource for namespaced controller" do
31
+ project = Project.create!
32
+ @params.merge!(:controller => "admin/projects", :action => "show", :id => project.id)
33
+ resource = CanCan::ControllerResource.new(@controller)
34
+ resource.load_resource
35
+ @controller.instance_variable_get(:@project).should == project
36
+ end
37
+
38
+ it "should properly load resource for namespaced controller when using '::' for namespace" do
39
+ project = Project.create!
40
+ @params.merge!(:controller => "Admin::ProjectsController", :action => "show", :id => project.id)
41
+ resource = CanCan::ControllerResource.new(@controller)
42
+ resource.load_resource
43
+ @controller.instance_variable_get(:@project).should == project
44
+ end
45
+
46
+ it "should build a new resource with hash if params[:id] is not specified" do
47
+ @params.merge!(:action => "create", :project => {:name => "foobar"})
48
+ resource = CanCan::ControllerResource.new(@controller)
49
+ resource.load_resource
50
+ @controller.instance_variable_get(:@project).name.should == "foobar"
51
+ end
52
+
53
+ it "should build a new resource with attributes from current ability" do
54
+ @params.merge!(:action => "new")
55
+ @ability.can(:create, Project, :name => "from conditions")
56
+ resource = CanCan::ControllerResource.new(@controller)
57
+ resource.load_resource
58
+ @controller.instance_variable_get(:@project).name.should == "from conditions"
59
+ end
60
+
61
+ it "should override initial attributes with params" do
62
+ @params.merge!(:action => "new", :project => {:name => "from params"})
63
+ @ability.can(:create, Project, :name => "from conditions")
64
+ resource = CanCan::ControllerResource.new(@controller)
65
+ resource.load_resource
66
+ @controller.instance_variable_get(:@project).name.should == "from params"
67
+ end
68
+
69
+ it "should build a collection when on index action when class responds to accessible_by" do
70
+ stub(Project).accessible_by(@ability, :index) { :found_projects }
71
+ @params[:action] = "index"
72
+ resource = CanCan::ControllerResource.new(@controller, :project)
73
+ resource.load_resource
74
+ @controller.instance_variable_get(:@project).should be_nil
75
+ @controller.instance_variable_get(:@projects).should == :found_projects
76
+ end
77
+
78
+ it "should not build a collection when on index action when class does not respond to accessible_by" do
79
+ @params[:action] = "index"
80
+ resource = CanCan::ControllerResource.new(@controller)
81
+ resource.load_resource
82
+ @controller.instance_variable_get(:@project).should be_nil
83
+ @controller.instance_variable_defined?(:@projects).should be_false
84
+ end
85
+
86
+ it "should not use accessible_by when defining abilities through a block" do
87
+ stub(Project).accessible_by(@ability) { :found_projects }
88
+ @params[:action] = "index"
89
+ @ability.can(:read, Project) { |p| false }
90
+ resource = CanCan::ControllerResource.new(@controller)
91
+ resource.load_resource
92
+ @controller.instance_variable_get(:@project).should be_nil
93
+ @controller.instance_variable_defined?(:@projects).should be_false
94
+ end
95
+
96
+ it "should not authorize single resource in collection action" do
97
+ @params[:action] = "index"
98
+ @controller.instance_variable_set(:@project, :some_project)
99
+ stub(@controller).authorize!(:index, Project) { raise CanCan::AccessDenied }
100
+ resource = CanCan::ControllerResource.new(@controller)
101
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
102
+ end
103
+
104
+ it "should authorize parent resource in collection action" do
105
+ @params[:action] = "index"
106
+ @controller.instance_variable_set(:@category, :some_category)
107
+ stub(@controller).authorize!(:show, :some_category) { raise CanCan::AccessDenied }
108
+ resource = CanCan::ControllerResource.new(@controller, :category, :parent => true)
109
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
110
+ end
111
+
112
+ it "should perform authorization using controller action and loaded model" do
113
+ @params.merge!(:action => "show", :id => 123)
114
+ @controller.instance_variable_set(:@project, :some_project)
115
+ stub(@controller).authorize!(:show, :some_project) { raise CanCan::AccessDenied }
116
+ resource = CanCan::ControllerResource.new(@controller)
117
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
118
+ end
119
+
120
+ it "should perform authorization using controller action and non loaded model" do
121
+ @params.merge!(:action => "show", :id => 123)
122
+ stub(@controller).authorize!(:show, Project) { raise CanCan::AccessDenied }
123
+ resource = CanCan::ControllerResource.new(@controller)
124
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
125
+ end
126
+
127
+ it "should call load_resource and authorize_resource for load_and_authorize_resource" do
128
+ @params.merge!(:action => "show", :id => 123)
129
+ resource = CanCan::ControllerResource.new(@controller)
130
+ mock(resource).load_resource
131
+ mock(resource).authorize_resource
132
+ resource.load_and_authorize_resource
133
+ end
134
+
135
+ it "should not build a single resource when on custom collection action even with id" do
136
+ @params.merge!(:action => "sort", :id => 123)
137
+ resource = CanCan::ControllerResource.new(@controller, :collection => [:sort, :list])
138
+ resource.load_resource
139
+ @controller.instance_variable_get(:@project).should be_nil
140
+ end
141
+
142
+ it "should load a collection resource when on custom action with no id param" do
143
+ stub(Project).accessible_by(@ability, :sort) { :found_projects }
144
+ @params[:action] = "sort"
145
+ resource = CanCan::ControllerResource.new(@controller)
146
+ resource.load_resource
147
+ @controller.instance_variable_get(:@project).should be_nil
148
+ @controller.instance_variable_get(:@projects).should == :found_projects
149
+ end
150
+
151
+ it "should build a resource when on custom new action even when params[:id] exists" do
152
+ @params.merge!(:action => "build", :id => 123)
153
+ stub(Project).new { :some_project }
154
+ resource = CanCan::ControllerResource.new(@controller, :new => :build)
155
+ resource.load_resource
156
+ @controller.instance_variable_get(:@project).should == :some_project
157
+ end
158
+
159
+ it "should not try to load resource for other action if params[:id] is undefined" do
160
+ @params[:action] = "list"
161
+ resource = CanCan::ControllerResource.new(@controller)
162
+ resource.load_resource
163
+ @controller.instance_variable_get(:@project).should be_nil
164
+ end
165
+
166
+ it "should be a parent resource when name is provided which doesn't match controller" do
167
+ resource = CanCan::ControllerResource.new(@controller, :category)
168
+ resource.should be_parent
169
+ end
170
+
171
+ it "should not be a parent resource when name is provided which matches controller" do
172
+ resource = CanCan::ControllerResource.new(@controller, :project)
173
+ resource.should_not be_parent
174
+ end
175
+
176
+ it "should be parent if specified in options" do
177
+ resource = CanCan::ControllerResource.new(@controller, :project, {:parent => true})
178
+ resource.should be_parent
179
+ end
180
+
181
+ it "should not be parent if specified in options" do
182
+ resource = CanCan::ControllerResource.new(@controller, :category, {:parent => false})
183
+ resource.should_not be_parent
184
+ end
185
+
186
+ it "should load parent resource through proper id parameter" do
187
+ project = Project.create!
188
+ @params.merge!(:action => "index", :project_id => project.id)
189
+ resource = CanCan::ControllerResource.new(@controller, :project, :parent => true)
190
+ resource.load_resource
191
+ @controller.instance_variable_get(:@project).should == project
192
+ end
193
+
194
+ it "should load resource through the association of another parent resource using instance variable" do
195
+ @params.merge!(:action => "show", :id => 123)
196
+ category = Object.new
197
+ @controller.instance_variable_set(:@category, category)
198
+ stub(category).projects.stub!.find(123) { :some_project }
199
+ resource = CanCan::ControllerResource.new(@controller, :through => :category)
200
+ resource.load_resource
201
+ @controller.instance_variable_get(:@project).should == :some_project
202
+ end
203
+
204
+ it "should load resource through the custom association name" do
205
+ @params.merge!(:action => "show", :id => 123)
206
+ category = Object.new
207
+ @controller.instance_variable_set(:@category, category)
208
+ stub(category).custom_projects.stub!.find(123) { :some_project }
209
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :through_association => :custom_projects)
210
+ resource.load_resource
211
+ @controller.instance_variable_get(:@project).should == :some_project
212
+ end
213
+
214
+ it "should load resource through the association of another parent resource using method" do
215
+ @params.merge!(:action => "show", :id => 123)
216
+ category = Object.new
217
+ stub(@controller).category { category }
218
+ stub(category).projects.stub!.find(123) { :some_project }
219
+ resource = CanCan::ControllerResource.new(@controller, :through => :category)
220
+ resource.load_resource
221
+ @controller.instance_variable_get(:@project).should == :some_project
222
+ end
223
+
224
+ it "should not load through parent resource if instance isn't loaded when shallow" do
225
+ project = Project.create!
226
+ @params.merge!(:action => "show", :id => project.id)
227
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :shallow => true)
228
+ resource.load_resource
229
+ @controller.instance_variable_get(:@project).should == project
230
+ end
231
+
232
+ it "should raise AccessDenied when attempting to load resource through nil" do
233
+ project = Project.create!
234
+ @params.merge!(:action => "show", :id => project.id)
235
+ resource = CanCan::ControllerResource.new(@controller, :through => :category)
236
+ lambda {
237
+ resource.load_resource
238
+ }.should raise_error(CanCan::AccessDenied) { |exception|
239
+ exception.action.should == :show
240
+ exception.subject.should == Project
241
+ }
242
+ @controller.instance_variable_get(:@project).should be_nil
243
+ end
244
+
245
+ it "should authorize nested resource through parent association on index action" do
246
+ @params.merge!(:action => "index")
247
+ category = Object.new
248
+ @controller.instance_variable_set(:@category, category)
249
+ stub(@controller).authorize!(:index, category => Project) { raise CanCan::AccessDenied }
250
+ resource = CanCan::ControllerResource.new(@controller, :through => :category)
251
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
252
+ end
253
+
254
+ it "should load through first matching if multiple are given" do
255
+ @params.merge!(:action => "show", :id => 123)
256
+ category = Object.new
257
+ @controller.instance_variable_set(:@category, category)
258
+ stub(category).projects.stub!.find(123) { :some_project }
259
+ resource = CanCan::ControllerResource.new(@controller, :through => [:category, :user])
260
+ resource.load_resource
261
+ @controller.instance_variable_get(:@project).should == :some_project
262
+ end
263
+
264
+ it "should find record through has_one association with :singleton option without id param" do
265
+ @params.merge!(:action => "show", :id => nil)
266
+ category = Object.new
267
+ @controller.instance_variable_set(:@category, category)
268
+ stub(category).project { :some_project }
269
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true)
270
+ resource.load_resource
271
+ @controller.instance_variable_get(:@project).should == :some_project
272
+ end
273
+
274
+ it "should not build record through has_one association with :singleton option because it can cause it to delete it in the database" do
275
+ @params.merge!(:action => "create", :project => {:name => "foobar"})
276
+ category = Category.new
277
+ @controller.instance_variable_set(:@category, category)
278
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true)
279
+ resource.load_resource
280
+ @controller.instance_variable_get(:@project).name.should == "foobar"
281
+ @controller.instance_variable_get(:@project).category.should == category
282
+ end
283
+
284
+ it "should find record through has_one association with :singleton and :shallow options" do
285
+ project = Project.create!
286
+ @params.merge!(:action => "show", :id => project.id)
287
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true, :shallow => true)
288
+ resource.load_resource
289
+ @controller.instance_variable_get(:@project).should == project
290
+ end
291
+
292
+ it "should build record through has_one association with :singleton and :shallow options" do
293
+ @params.merge!(:action => "create", :project => {:name => "foobar"})
294
+ resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true, :shallow => true)
295
+ resource.load_resource
296
+ @controller.instance_variable_get(:@project).name.should == "foobar"
297
+ end
298
+
299
+ it "should only authorize :show action on parent resource" do
300
+ project = Project.create!
301
+ @params.merge!(:action => "new", :project_id => project.id)
302
+ stub(@controller).authorize!(:show, project) { raise CanCan::AccessDenied }
303
+ resource = CanCan::ControllerResource.new(@controller, :project, :parent => true)
304
+ lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied)
305
+ end
306
+
307
+ it "should load the model using a custom class" do
308
+ project = Project.create!
309
+ @params.merge!(:action => "show", :id => project.id)
310
+ resource = CanCan::ControllerResource.new(@controller, :class => Project)
311
+ resource.load_resource
312
+ @controller.instance_variable_get(:@project).should == project
313
+ end
314
+
315
+ it "should authorize based on resource name if class is false" do
316
+ @params.merge!(:action => "show", :id => 123)
317
+ stub(@controller).authorize!(:show, :project) { raise CanCan::AccessDenied }
318
+ resource = CanCan::ControllerResource.new(@controller, :class => false)
319
+ lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
320
+ end
321
+
322
+ it "should load and authorize using custom instance name" do
323
+ project = Project.create!
324
+ @params.merge!(:action => "show", :id => project.id)
325
+ stub(@controller).authorize!(:show, project) { raise CanCan::AccessDenied }
326
+ resource = CanCan::ControllerResource.new(@controller, :instance_name => :custom_project)
327
+ lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied)
328
+ @controller.instance_variable_get(:@custom_project).should == project
329
+ end
330
+
331
+ it "should load resource using custom find_by attribute" do
332
+ project = Project.create!(:name => "foo")
333
+ @params.merge!(:action => "show", :id => "foo")
334
+ resource = CanCan::ControllerResource.new(@controller, :find_by => :name)
335
+ resource.load_resource
336
+ @controller.instance_variable_get(:@project).should == project
337
+ end
338
+
339
+ it "should allow full find method to be passed into find_by option" do
340
+ project = Project.create!(:name => "foo")
341
+ @params.merge!(:action => "show", :id => "foo")
342
+ resource = CanCan::ControllerResource.new(@controller, :find_by => :find_by_name)
343
+ resource.load_resource
344
+ @controller.instance_variable_get(:@project).should == project
345
+ end
346
+
347
+ it "should raise ImplementationRemoved when adding :name option" do
348
+ lambda {
349
+ CanCan::ControllerResource.new(@controller, :name => :foo)
350
+ }.should raise_error(CanCan::ImplementationRemoved)
351
+ end
352
+
353
+ it "should raise ImplementationRemoved exception when specifying :resource option since it is no longer used" do
354
+ lambda {
355
+ CanCan::ControllerResource.new(@controller, :resource => Project)
356
+ }.should raise_error(CanCan::ImplementationRemoved)
357
+ end
358
+
359
+ it "should raise ImplementationRemoved exception when passing :nested option" do
360
+ lambda {
361
+ CanCan::ControllerResource.new(@controller, :nested => :project)
362
+ }.should raise_error(CanCan::ImplementationRemoved)
363
+ end
364
+
365
+ it "should skip resource behavior for :only actions in array" do
366
+ stub(@controller_class).cancan_skipper { {:load => {nil => {:only => [:index, :show]}}} }
367
+ @params.merge!(:action => "index")
368
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_true
369
+ CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load).should be_false
370
+ @params.merge!(:action => "show")
371
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_true
372
+ @params.merge!(:action => "other_action")
373
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_false
374
+ end
375
+
376
+ it "should skip resource behavior for :only one action on resource" do
377
+ stub(@controller_class).cancan_skipper { {:authorize => {:project => {:only => :index}}} }
378
+ @params.merge!(:action => "index")
379
+ CanCan::ControllerResource.new(@controller).skip?(:authorize).should be_false
380
+ CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_true
381
+ @params.merge!(:action => "other_action")
382
+ CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_false
383
+ end
384
+
385
+ it "should skip resource behavior :except actions in array" do
386
+ stub(@controller_class).cancan_skipper { {:load => {nil => {:except => [:index, :show]}}} }
387
+ @params.merge!(:action => "index")
388
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_false
389
+ @params.merge!(:action => "show")
390
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_false
391
+ @params.merge!(:action => "other_action")
392
+ CanCan::ControllerResource.new(@controller).skip?(:load).should be_true
393
+ CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load).should be_false
394
+ end
395
+
396
+ it "should skip resource behavior :except one action on resource" do
397
+ stub(@controller_class).cancan_skipper { {:authorize => {:project => {:except => :index}}} }
398
+ @params.merge!(:action => "index")
399
+ CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_false
400
+ @params.merge!(:action => "other_action")
401
+ CanCan::ControllerResource.new(@controller).skip?(:authorize).should be_false
402
+ CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_true
403
+ end
404
+
405
+ it "should skip loading and authorization" do
406
+ stub(@controller_class).cancan_skipper { {:authorize => {nil => {}}, :load => {nil => {}}} }
407
+ @params.merge!(:action => "new")
408
+ resource = CanCan::ControllerResource.new(@controller)
409
+ lambda { resource.load_and_authorize_resource }.should_not raise_error
410
+ @controller.instance_variable_get(:@project).should be_nil
411
+ end
412
+ end