codeprimate-cancan 1.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +291 -0
- data/Gemfile +20 -0
- data/LICENSE +20 -0
- data/README.rdoc +111 -0
- data/Rakefile +18 -0
- data/init.rb +1 -0
- data/lib/cancan.rb +13 -0
- data/lib/cancan/ability.rb +298 -0
- data/lib/cancan/controller_additions.rb +389 -0
- data/lib/cancan/controller_resource.rb +222 -0
- data/lib/cancan/exceptions.rb +50 -0
- data/lib/cancan/inherited_resource.rb +19 -0
- data/lib/cancan/matchers.rb +14 -0
- data/lib/cancan/model_adapters/abstract_adapter.rb +56 -0
- data/lib/cancan/model_adapters/active_record_adapter.rb +165 -0
- data/lib/cancan/model_adapters/data_mapper_adapter.rb +34 -0
- data/lib/cancan/model_adapters/default_adapter.rb +7 -0
- data/lib/cancan/model_adapters/mongoid_adapter.rb +53 -0
- data/lib/cancan/model_additions.rb +31 -0
- data/lib/cancan/rule.rb +142 -0
- data/lib/generators/cancan/ability/USAGE +4 -0
- data/lib/generators/cancan/ability/ability_generator.rb +11 -0
- data/lib/generators/cancan/ability/templates/ability.rb +28 -0
- data/spec/README.rdoc +28 -0
- data/spec/cancan/ability_spec.rb +419 -0
- data/spec/cancan/controller_additions_spec.rb +137 -0
- data/spec/cancan/controller_resource_spec.rb +412 -0
- data/spec/cancan/exceptions_spec.rb +58 -0
- data/spec/cancan/inherited_resource_spec.rb +42 -0
- data/spec/cancan/matchers_spec.rb +33 -0
- data/spec/cancan/model_adapters/active_record_adapter_spec.rb +278 -0
- data/spec/cancan/model_adapters/data_mapper_adapter_spec.rb +119 -0
- data/spec/cancan/model_adapters/default_adapter_spec.rb +7 -0
- data/spec/cancan/model_adapters/mongoid_adapter_spec.rb +216 -0
- data/spec/cancan/rule_spec.rb +39 -0
- data/spec/matchers.rb +13 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +41 -0
- 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
|