cancan 1.3.4 → 1.4.1
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 +52 -0
- data/Gemfile +2 -0
- data/LICENSE +1 -1
- data/README.rdoc +31 -21
- data/Rakefile +5 -8
- data/lib/cancan/ability.rb +99 -32
- data/lib/cancan/active_record_additions.rb +1 -1
- data/lib/cancan/can_definition.rb +43 -14
- data/lib/cancan/controller_additions.rb +84 -12
- data/lib/cancan/controller_resource.rb +70 -12
- data/lib/cancan/exceptions.rb +5 -1
- data/lib/cancan/inherited_resource.rb +18 -0
- data/lib/cancan.rb +1 -0
- data/spec/cancan/ability_spec.rb +184 -59
- data/spec/cancan/active_record_additions_spec.rb +25 -1
- data/spec/cancan/can_definition_spec.rb +1 -0
- data/spec/cancan/controller_additions_spec.rb +34 -26
- data/spec/cancan/controller_resource_spec.rb +162 -87
- data/spec/cancan/inherited_resource_spec.rb +40 -0
- data/spec/cancan/query_spec.rb +48 -48
- data/spec/matchers.rb +1 -1
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +16 -9
- metadata +79 -6
|
@@ -2,7 +2,7 @@ require "spec_helper"
|
|
|
2
2
|
|
|
3
3
|
describe CanCan::ActiveRecordAdditions do
|
|
4
4
|
before(:each) do
|
|
5
|
-
@model_class = Class.new(
|
|
5
|
+
@model_class = Class.new(Project)
|
|
6
6
|
stub(@model_class).scoped { :scoped_stub }
|
|
7
7
|
@model_class.send(:include, CanCan::ActiveRecordAdditions)
|
|
8
8
|
@ability = Object.new
|
|
@@ -10,12 +10,14 @@ describe CanCan::ActiveRecordAdditions do
|
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
it "should call where('true=false') when no ability is defined so no records are found" do
|
|
13
|
+
stub(@model_class).joins { true } # just so it responds to .joins as well
|
|
13
14
|
stub(@model_class).where('true=false').stub!.joins(nil) { :no_match }
|
|
14
15
|
@model_class.accessible_by(@ability, :read).should == :no_match
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
it "should call where with matching ability conditions" do
|
|
18
19
|
@ability.can :read, @model_class, :foo => {:bar => 1}
|
|
20
|
+
stub(@model_class).joins { true } # just so it responds to .joins as well
|
|
19
21
|
stub(@model_class).where(:foos => { :bar => 1 }).stub!.joins([:foo]) { :found_records }
|
|
20
22
|
@model_class.accessible_by(@ability, :read).should == :found_records
|
|
21
23
|
end
|
|
@@ -48,4 +50,26 @@ describe CanCan::ActiveRecordAdditions do
|
|
|
48
50
|
# @ability.associations_hash(:read, @model_class).should == [{:too => [:far]}, :foo]
|
|
49
51
|
@model_class.accessible_by(@ability).should == :found_records
|
|
50
52
|
end
|
|
53
|
+
|
|
54
|
+
it "should allow to define sql conditions by not hash" do
|
|
55
|
+
@ability.can :read, @model_class, :foo => 1
|
|
56
|
+
@ability.can :read, @model_class, ['bar = ?', 1]
|
|
57
|
+
stub(@model_class).scoped( :conditions => '(bar = 1) OR (foo=1)', :joins => nil ) { :found_records }
|
|
58
|
+
stub(@model_class).scoped{|*args| args.inspect}
|
|
59
|
+
@model_class.accessible_by(@ability).should == :found_records
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should not allow to fetch records when ability with just block present" do
|
|
63
|
+
@ability.can :read, @model_class do false end
|
|
64
|
+
lambda {
|
|
65
|
+
@model_class.accessible_by(@ability)
|
|
66
|
+
}.should raise_error(CanCan::Error)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should not allow to check ability on object when nonhash sql ability definition without block present" do
|
|
70
|
+
@ability.can :read, @model_class, ['bar = ?', 1]
|
|
71
|
+
lambda {
|
|
72
|
+
@ability.can? :read, @model_class.new
|
|
73
|
+
}.should raise_error(CanCan::Error)
|
|
74
|
+
end
|
|
51
75
|
end
|
|
@@ -14,32 +14,10 @@ describe CanCan::ControllerAdditions do
|
|
|
14
14
|
lambda { @controller.unauthorized! }.should raise_error(CanCan::ImplementationRemoved)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
it "should
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
e.message.should == "Access denied!"
|
|
22
|
-
e.action.should == :read
|
|
23
|
-
e.subject.should == :foo
|
|
24
|
-
else
|
|
25
|
-
fail "Expected CanCan::AccessDenied exception to be raised"
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
it "should not raise access denied exception if ability is authorized to perform an action" do
|
|
30
|
-
@controller.current_ability.can :read, :foo
|
|
31
|
-
lambda { @controller.authorize!(:read, :foo) }.should_not raise_error
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
it "should raise access denied exception with default message if not specified" do
|
|
35
|
-
begin
|
|
36
|
-
@controller.authorize! :read, :foo
|
|
37
|
-
rescue CanCan::AccessDenied => e
|
|
38
|
-
e.default_message = "Access denied!"
|
|
39
|
-
e.message.should == "Access denied!"
|
|
40
|
-
else
|
|
41
|
-
fail "Expected CanCan::AccessDenied exception to be raised"
|
|
42
|
-
end
|
|
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
|
|
43
21
|
end
|
|
44
22
|
|
|
45
23
|
it "should have a current_ability method which generates an ability for the current user" do
|
|
@@ -75,4 +53,34 @@ describe CanCan::ControllerAdditions do
|
|
|
75
53
|
mock(@controller_class).before_filter(:only => [:show, :index]) { |options, block| block.call(@controller) }
|
|
76
54
|
@controller_class.load_resource :foo => :bar, :only => [:show, :index]
|
|
77
55
|
end
|
|
56
|
+
|
|
57
|
+
it "skip_authorization_check should set up a before filter which sets @_authorized to true" do
|
|
58
|
+
mock(@controller_class).before_filter(:filter_options) { |options, block| block.call(@controller) }
|
|
59
|
+
@controller_class.skip_authorization_check(:filter_options)
|
|
60
|
+
@controller.instance_variable_get(:@_authorized).should be_true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "check_authorization should trigger AuthorizationNotPerformed in after filter" do
|
|
64
|
+
mock(@controller_class).after_filter(:some_options) { |options, block| block.call(@controller) }
|
|
65
|
+
lambda {
|
|
66
|
+
@controller_class.check_authorization(:some_options)
|
|
67
|
+
}.should raise_error(CanCan::AuthorizationNotPerformed)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "check_authorization should not raise error when @_authorized is set" do
|
|
71
|
+
@controller.instance_variable_set(:@_authorized, true)
|
|
72
|
+
mock(@controller_class).after_filter(:some_options) { |options, block| block.call(@controller) }
|
|
73
|
+
lambda {
|
|
74
|
+
@controller_class.check_authorization(:some_options)
|
|
75
|
+
}.should_not raise_error(CanCan::AuthorizationNotPerformed)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "cancan_resource_class should be ControllerResource by default" do
|
|
79
|
+
@controller.class.cancan_resource_class.should == CanCan::ControllerResource
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "cancan_resource_class should be InheritedResource when class includes InheritedResources::Actions" do
|
|
83
|
+
stub(@controller.class).ancestors { ["InheritedResources::Actions"] }
|
|
84
|
+
@controller.class.cancan_resource_class.should == CanCan::InheritedResource
|
|
85
|
+
end
|
|
78
86
|
end
|
|
@@ -2,77 +2,106 @@ require "spec_helper"
|
|
|
2
2
|
|
|
3
3
|
describe CanCan::ControllerResource do
|
|
4
4
|
before(:each) do
|
|
5
|
-
@params = HashWithIndifferentAccess.new(:controller => "
|
|
5
|
+
@params = HashWithIndifferentAccess.new(:controller => "projects")
|
|
6
6
|
@controller = Object.new # simple stub for now
|
|
7
|
+
@ability = Ability.new(nil)
|
|
7
8
|
stub(@controller).params { @params }
|
|
9
|
+
stub(@controller).current_ability { @ability }
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
it "should load the resource into an instance variable if params[:id] is specified" do
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
project = Project.create!
|
|
14
|
+
@params.merge!(:action => "show", :id => project.id)
|
|
13
15
|
resource = CanCan::ControllerResource.new(@controller)
|
|
14
16
|
resource.load_resource
|
|
15
|
-
@controller.instance_variable_get(:@
|
|
17
|
+
@controller.instance_variable_get(:@project).should == project
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
it "should not load resource into an instance variable if already set" do
|
|
19
21
|
@params.merge!(:action => "show", :id => 123)
|
|
20
|
-
@controller.instance_variable_set(:@
|
|
22
|
+
@controller.instance_variable_set(:@project, :some_project)
|
|
21
23
|
resource = CanCan::ControllerResource.new(@controller)
|
|
22
24
|
resource.load_resource
|
|
23
|
-
@controller.instance_variable_get(:@
|
|
25
|
+
@controller.instance_variable_get(:@project).should == :some_project
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
it "should properly load resource for namespaced controller" do
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
project = Project.create!
|
|
30
|
+
@params.merge!(:controller => "admin/projects", :action => "show", :id => project.id)
|
|
29
31
|
resource = CanCan::ControllerResource.new(@controller)
|
|
30
32
|
resource.load_resource
|
|
31
|
-
@controller.instance_variable_get(:@
|
|
33
|
+
@controller.instance_variable_get(:@project).should == project
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
it "should properly load resource for namespaced controller when using '::' for namespace" do
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
project = Project.create!
|
|
38
|
+
@params.merge!(:controller => "Admin::ProjectsController", :action => "show", :id => project.id)
|
|
37
39
|
resource = CanCan::ControllerResource.new(@controller)
|
|
38
40
|
resource.load_resource
|
|
39
|
-
@controller.instance_variable_get(:@
|
|
41
|
+
@controller.instance_variable_get(:@project).should == project
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
it "should build a new resource with hash if params[:id] is not specified" do
|
|
43
|
-
@params.merge!(:action => "create", :
|
|
44
|
-
|
|
45
|
+
@params.merge!(:action => "create", :project => {:name => "foobar"})
|
|
46
|
+
resource = CanCan::ControllerResource.new(@controller)
|
|
47
|
+
resource.load_resource
|
|
48
|
+
@controller.instance_variable_get(:@project).name.should == "foobar"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should build a new resource with attributes from current ability" do
|
|
52
|
+
@params.merge!(:action => "new")
|
|
53
|
+
@ability.can(:create, Project, :name => "from conditions")
|
|
45
54
|
resource = CanCan::ControllerResource.new(@controller)
|
|
46
55
|
resource.load_resource
|
|
47
|
-
@controller.instance_variable_get(:@
|
|
56
|
+
@controller.instance_variable_get(:@project).name.should == "from conditions"
|
|
48
57
|
end
|
|
49
58
|
|
|
50
|
-
it "should
|
|
51
|
-
@params
|
|
52
|
-
|
|
59
|
+
it "should override initial attributes with params" do
|
|
60
|
+
@params.merge!(:action => "new", :project => {:name => "from params"})
|
|
61
|
+
@ability.can(:create, Project, :name => "from conditions")
|
|
53
62
|
resource = CanCan::ControllerResource.new(@controller)
|
|
54
63
|
resource.load_resource
|
|
55
|
-
@controller.instance_variable_get(:@
|
|
64
|
+
@controller.instance_variable_get(:@project).name.should == "from params"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should build a collection when on index action when class responds to accessible_by" do
|
|
68
|
+
stub(Project).accessible_by(@ability) { :found_projects }
|
|
69
|
+
@params[:action] = "index"
|
|
70
|
+
resource = CanCan::ControllerResource.new(@controller, :project)
|
|
71
|
+
resource.load_resource
|
|
72
|
+
@controller.instance_variable_get(:@project).should be_nil
|
|
73
|
+
@controller.instance_variable_get(:@projects).should == :found_projects
|
|
56
74
|
end
|
|
57
75
|
|
|
58
|
-
it "should not build a
|
|
76
|
+
it "should not build a collection when on index action when class does not respond to accessible_by" do
|
|
59
77
|
@params[:action] = "index"
|
|
60
78
|
resource = CanCan::ControllerResource.new(@controller)
|
|
61
79
|
resource.load_resource
|
|
62
|
-
@controller.instance_variable_get(:@
|
|
80
|
+
@controller.instance_variable_get(:@project).should be_nil
|
|
81
|
+
@controller.instance_variable_defined?(:@projects).should be_false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should not use accessible_by when defining abilities through a block" do
|
|
85
|
+
stub(Project).accessible_by(@ability) { :found_projects }
|
|
86
|
+
@params[:action] = "index"
|
|
87
|
+
@ability.can(:read, Project) { |p| false }
|
|
88
|
+
resource = CanCan::ControllerResource.new(@controller)
|
|
89
|
+
resource.load_resource
|
|
90
|
+
@controller.instance_variable_get(:@project).should be_nil
|
|
91
|
+
@controller.instance_variable_defined?(:@projects).should be_false
|
|
63
92
|
end
|
|
64
93
|
|
|
65
94
|
it "should perform authorization using controller action and loaded model" do
|
|
66
95
|
@params[:action] = "show"
|
|
67
|
-
@controller.instance_variable_set(:@
|
|
68
|
-
stub(@controller).authorize!(:show, :
|
|
96
|
+
@controller.instance_variable_set(:@project, :some_project)
|
|
97
|
+
stub(@controller).authorize!(:show, :some_project) { raise CanCan::AccessDenied }
|
|
69
98
|
resource = CanCan::ControllerResource.new(@controller)
|
|
70
99
|
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
|
|
71
100
|
end
|
|
72
101
|
|
|
73
102
|
it "should perform authorization using controller action and non loaded model" do
|
|
74
103
|
@params[:action] = "show"
|
|
75
|
-
stub(@controller).authorize!(:show,
|
|
104
|
+
stub(@controller).authorize!(:show, Project) { raise CanCan::AccessDenied }
|
|
76
105
|
resource = CanCan::ControllerResource.new(@controller)
|
|
77
106
|
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
|
|
78
107
|
end
|
|
@@ -89,146 +118,192 @@ describe CanCan::ControllerResource do
|
|
|
89
118
|
@params[:action] = "sort"
|
|
90
119
|
resource = CanCan::ControllerResource.new(@controller, :collection => [:sort, :list])
|
|
91
120
|
resource.load_resource
|
|
92
|
-
@controller.instance_variable_get(:@
|
|
121
|
+
@controller.instance_variable_get(:@project).should be_nil
|
|
93
122
|
end
|
|
94
123
|
|
|
95
124
|
it "should build a resource when on custom new action even when params[:id] exists" do
|
|
96
125
|
@params.merge!(:action => "build", :id => 123)
|
|
97
|
-
stub(
|
|
126
|
+
stub(Project).new { :some_project }
|
|
98
127
|
resource = CanCan::ControllerResource.new(@controller, :new => :build)
|
|
99
128
|
resource.load_resource
|
|
100
|
-
@controller.instance_variable_get(:@
|
|
129
|
+
@controller.instance_variable_get(:@project).should == :some_project
|
|
101
130
|
end
|
|
102
131
|
|
|
103
132
|
it "should not try to load resource for other action if params[:id] is undefined" do
|
|
104
133
|
@params[:action] = "list"
|
|
105
134
|
resource = CanCan::ControllerResource.new(@controller)
|
|
106
135
|
resource.load_resource
|
|
107
|
-
@controller.instance_variable_get(:@
|
|
136
|
+
@controller.instance_variable_get(:@project).should be_nil
|
|
108
137
|
end
|
|
109
138
|
|
|
110
139
|
it "should be a parent resource when name is provided which doesn't match controller" do
|
|
111
|
-
resource = CanCan::ControllerResource.new(@controller, :
|
|
140
|
+
resource = CanCan::ControllerResource.new(@controller, :category)
|
|
112
141
|
resource.should be_parent
|
|
113
142
|
end
|
|
114
143
|
|
|
115
144
|
it "should not be a parent resource when name is provided which matches controller" do
|
|
116
|
-
resource = CanCan::ControllerResource.new(@controller, :
|
|
145
|
+
resource = CanCan::ControllerResource.new(@controller, :project)
|
|
117
146
|
resource.should_not be_parent
|
|
118
147
|
end
|
|
119
148
|
|
|
120
149
|
it "should be parent if specified in options" do
|
|
121
|
-
resource = CanCan::ControllerResource.new(@controller, :
|
|
150
|
+
resource = CanCan::ControllerResource.new(@controller, :project, {:parent => true})
|
|
122
151
|
resource.should be_parent
|
|
123
152
|
end
|
|
124
153
|
|
|
125
154
|
it "should not be parent if specified in options" do
|
|
126
|
-
resource = CanCan::ControllerResource.new(@controller, :
|
|
155
|
+
resource = CanCan::ControllerResource.new(@controller, :category, {:parent => false})
|
|
127
156
|
resource.should_not be_parent
|
|
128
157
|
end
|
|
129
158
|
|
|
130
|
-
it "should load parent resource through proper id parameter
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
resource = CanCan::ControllerResource.new(@controller, :
|
|
159
|
+
it "should load parent resource through proper id parameter" do
|
|
160
|
+
project = Project.create!
|
|
161
|
+
@params.merge!(:action => "index", :project_id => project.id)
|
|
162
|
+
resource = CanCan::ControllerResource.new(@controller, :project, :parent => true)
|
|
134
163
|
resource.load_resource
|
|
135
|
-
@controller.instance_variable_get(:@
|
|
164
|
+
@controller.instance_variable_get(:@project).should == project
|
|
136
165
|
end
|
|
137
166
|
|
|
138
|
-
it "should load parent resource
|
|
139
|
-
@params.merge!(:action => "
|
|
140
|
-
|
|
141
|
-
|
|
167
|
+
it "should load resource through the association of another parent resource using instance variable" do
|
|
168
|
+
@params.merge!(:action => "show", :id => 123)
|
|
169
|
+
category = Object.new
|
|
170
|
+
@controller.instance_variable_set(:@category, category)
|
|
171
|
+
stub(category).projects.stub!.find(123) { :some_project }
|
|
172
|
+
resource = CanCan::ControllerResource.new(@controller, :through => :category)
|
|
142
173
|
resource.load_resource
|
|
143
|
-
@controller.instance_variable_get(:@
|
|
174
|
+
@controller.instance_variable_get(:@project).should == :some_project
|
|
144
175
|
end
|
|
145
176
|
|
|
146
|
-
it "should load resource through the association
|
|
177
|
+
it "should load resource through the custom association name" do
|
|
147
178
|
@params.merge!(:action => "show", :id => 123)
|
|
148
|
-
|
|
149
|
-
@controller.instance_variable_set(:@
|
|
150
|
-
stub(
|
|
151
|
-
resource = CanCan::ControllerResource.new(@controller, :through => :
|
|
179
|
+
category = Object.new
|
|
180
|
+
@controller.instance_variable_set(:@category, category)
|
|
181
|
+
stub(category).custom_projects.stub!.find(123) { :some_project }
|
|
182
|
+
resource = CanCan::ControllerResource.new(@controller, :through => :category, :through_association => :custom_projects)
|
|
152
183
|
resource.load_resource
|
|
153
|
-
@controller.instance_variable_get(:@
|
|
184
|
+
@controller.instance_variable_get(:@project).should == :some_project
|
|
154
185
|
end
|
|
155
186
|
|
|
156
|
-
it "should
|
|
187
|
+
it "should load resource through the association of another parent resource using method" do
|
|
157
188
|
@params.merge!(:action => "show", :id => 123)
|
|
158
|
-
|
|
159
|
-
|
|
189
|
+
category = Object.new
|
|
190
|
+
stub(@controller).category { category }
|
|
191
|
+
stub(category).projects.stub!.find(123) { :some_project }
|
|
192
|
+
resource = CanCan::ControllerResource.new(@controller, :through => :category)
|
|
160
193
|
resource.load_resource
|
|
161
|
-
@controller.instance_variable_get(:@
|
|
194
|
+
@controller.instance_variable_get(:@project).should == :some_project
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it "should not load through parent resource if instance isn't loaded when shallow" do
|
|
198
|
+
project = Project.create!
|
|
199
|
+
@params.merge!(:action => "show", :id => project.id)
|
|
200
|
+
resource = CanCan::ControllerResource.new(@controller, :through => :category, :shallow => true)
|
|
201
|
+
resource.load_resource
|
|
202
|
+
@controller.instance_variable_get(:@project).should == project
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
it "should raise AccessDenied when attempting to load resource through nil" do
|
|
206
|
+
project = Project.create!
|
|
207
|
+
@params.merge!(:action => "show", :id => project.id)
|
|
208
|
+
resource = CanCan::ControllerResource.new(@controller, :through => :category)
|
|
209
|
+
lambda {
|
|
210
|
+
resource.load_resource
|
|
211
|
+
}.should raise_error(CanCan::AccessDenied)
|
|
212
|
+
@controller.instance_variable_get(:@project).should be_nil
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it "should authorize nested resource through parent association on index action" do
|
|
216
|
+
@params.merge!(:action => "index")
|
|
217
|
+
category = Object.new
|
|
218
|
+
@controller.instance_variable_set(:@category, category)
|
|
219
|
+
stub(@controller).authorize!(:index, category => Project) { raise CanCan::AccessDenied }
|
|
220
|
+
resource = CanCan::ControllerResource.new(@controller, :through => :category)
|
|
221
|
+
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
|
|
162
222
|
end
|
|
163
223
|
|
|
164
224
|
it "should load through first matching if multiple are given" do
|
|
165
225
|
@params.merge!(:action => "show", :id => 123)
|
|
166
|
-
|
|
167
|
-
@controller.instance_variable_set(:@
|
|
168
|
-
stub(
|
|
169
|
-
resource = CanCan::ControllerResource.new(@controller, :through => [:
|
|
226
|
+
category = Object.new
|
|
227
|
+
@controller.instance_variable_set(:@category, category)
|
|
228
|
+
stub(category).projects.stub!.find(123) { :some_project }
|
|
229
|
+
resource = CanCan::ControllerResource.new(@controller, :through => [:category, :user])
|
|
170
230
|
resource.load_resource
|
|
171
|
-
@controller.instance_variable_get(:@
|
|
231
|
+
@controller.instance_variable_get(:@project).should == :some_project
|
|
172
232
|
end
|
|
173
233
|
|
|
174
234
|
it "should find record through has_one association with :singleton option" do
|
|
175
235
|
@params.merge!(:action => "show")
|
|
176
|
-
|
|
177
|
-
@controller.instance_variable_set(:@
|
|
178
|
-
stub(
|
|
179
|
-
resource = CanCan::ControllerResource.new(@controller, :through => :
|
|
236
|
+
category = Object.new
|
|
237
|
+
@controller.instance_variable_set(:@category, category)
|
|
238
|
+
stub(category).project { :some_project }
|
|
239
|
+
resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true)
|
|
180
240
|
resource.load_resource
|
|
181
|
-
@controller.instance_variable_get(:@
|
|
241
|
+
@controller.instance_variable_get(:@project).should == :some_project
|
|
182
242
|
end
|
|
183
243
|
|
|
184
244
|
it "should build record through has_one association with :singleton option" do
|
|
185
|
-
@params.merge!(:action => "create", :
|
|
186
|
-
|
|
187
|
-
@controller.instance_variable_set(:@
|
|
188
|
-
stub(
|
|
189
|
-
resource = CanCan::ControllerResource.new(@controller, :through => :
|
|
245
|
+
@params.merge!(:action => "create", :project => {:name => "foobar"})
|
|
246
|
+
category = Object.new
|
|
247
|
+
@controller.instance_variable_set(:@category, category)
|
|
248
|
+
stub(category).build_project { Project.new }
|
|
249
|
+
resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true)
|
|
250
|
+
resource.load_resource
|
|
251
|
+
@controller.instance_variable_get(:@project).name.should == "foobar"
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
it "should find record through has_one association with :singleton and :shallow options" do
|
|
255
|
+
project = Project.create!
|
|
256
|
+
@params.merge!(:action => "show", :id => project.id)
|
|
257
|
+
resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true, :shallow => true)
|
|
258
|
+
resource.load_resource
|
|
259
|
+
@controller.instance_variable_get(:@project).should == project
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it "should build record through has_one association with :singleton and :shallow options" do
|
|
263
|
+
@params.merge!(:action => "create", :project => {:name => "foobar"})
|
|
264
|
+
resource = CanCan::ControllerResource.new(@controller, :through => :category, :singleton => true, :shallow => true)
|
|
190
265
|
resource.load_resource
|
|
191
|
-
@controller.instance_variable_get(:@
|
|
266
|
+
@controller.instance_variable_get(:@project).name.should == "foobar"
|
|
192
267
|
end
|
|
193
268
|
|
|
194
269
|
it "should only authorize :read action on parent resource" do
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
stub(@controller).authorize!(:read,
|
|
198
|
-
resource = CanCan::ControllerResource.new(@controller, :
|
|
270
|
+
project = Project.create!
|
|
271
|
+
@params.merge!(:action => "new", :project_id => project.id)
|
|
272
|
+
stub(@controller).authorize!(:read, project) { raise CanCan::AccessDenied }
|
|
273
|
+
resource = CanCan::ControllerResource.new(@controller, :project, :parent => true)
|
|
199
274
|
lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied)
|
|
200
275
|
end
|
|
201
276
|
|
|
202
277
|
it "should load the model using a custom class" do
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
resource = CanCan::ControllerResource.new(@controller, :class =>
|
|
278
|
+
project = Project.create!
|
|
279
|
+
@params.merge!(:action => "show", :id => project.id)
|
|
280
|
+
resource = CanCan::ControllerResource.new(@controller, :class => Project)
|
|
206
281
|
resource.load_resource
|
|
207
|
-
@controller.instance_variable_get(:@
|
|
282
|
+
@controller.instance_variable_get(:@project).should == project
|
|
208
283
|
end
|
|
209
284
|
|
|
210
285
|
it "should authorize based on resource name if class is false" do
|
|
211
286
|
@params.merge!(:action => "show", :id => 123)
|
|
212
|
-
stub(@controller).authorize!(:show, :
|
|
287
|
+
stub(@controller).authorize!(:show, :project) { raise CanCan::AccessDenied }
|
|
213
288
|
resource = CanCan::ControllerResource.new(@controller, :class => false)
|
|
214
289
|
lambda { resource.authorize_resource }.should raise_error(CanCan::AccessDenied)
|
|
215
290
|
end
|
|
216
291
|
|
|
217
292
|
it "should load and authorize using custom instance name" do
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
stub(@controller).authorize!(:show,
|
|
221
|
-
resource = CanCan::ControllerResource.new(@controller, :instance_name => :
|
|
293
|
+
project = Project.create!
|
|
294
|
+
@params.merge!(:action => "show", :id => project.id)
|
|
295
|
+
stub(@controller).authorize!(:show, project) { raise CanCan::AccessDenied }
|
|
296
|
+
resource = CanCan::ControllerResource.new(@controller, :instance_name => :custom_project)
|
|
222
297
|
lambda { resource.load_and_authorize_resource }.should raise_error(CanCan::AccessDenied)
|
|
223
|
-
@controller.instance_variable_get(:@
|
|
298
|
+
@controller.instance_variable_get(:@custom_project).should == project
|
|
224
299
|
end
|
|
225
300
|
|
|
226
301
|
it "should load resource using custom find_by attribute" do
|
|
227
|
-
|
|
228
|
-
|
|
302
|
+
project = Project.create!(:name => "foo")
|
|
303
|
+
@params.merge!(:action => "show", :id => "foo")
|
|
229
304
|
resource = CanCan::ControllerResource.new(@controller, :find_by => :name)
|
|
230
305
|
resource.load_resource
|
|
231
|
-
@controller.instance_variable_get(:@
|
|
306
|
+
@controller.instance_variable_get(:@project).should == project
|
|
232
307
|
end
|
|
233
308
|
|
|
234
309
|
it "should raise ImplementationRemoved when adding :name option" do
|
|
@@ -239,13 +314,13 @@ describe CanCan::ControllerResource do
|
|
|
239
314
|
|
|
240
315
|
it "should raise ImplementationRemoved exception when specifying :resource option since it is no longer used" do
|
|
241
316
|
lambda {
|
|
242
|
-
CanCan::ControllerResource.new(@controller, :resource =>
|
|
317
|
+
CanCan::ControllerResource.new(@controller, :resource => Project)
|
|
243
318
|
}.should raise_error(CanCan::ImplementationRemoved)
|
|
244
319
|
end
|
|
245
320
|
|
|
246
321
|
it "should raise ImplementationRemoved exception when passing :nested option" do
|
|
247
322
|
lambda {
|
|
248
|
-
CanCan::ControllerResource.new(@controller, :nested => :
|
|
323
|
+
CanCan::ControllerResource.new(@controller, :nested => :project)
|
|
249
324
|
}.should raise_error(CanCan::ImplementationRemoved)
|
|
250
325
|
end
|
|
251
326
|
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe CanCan::InheritedResource do
|
|
4
|
+
before(:each) do
|
|
5
|
+
@params = HashWithIndifferentAccess.new(:controller => "projects")
|
|
6
|
+
@controller = Object.new # simple stub for now
|
|
7
|
+
@ability = Ability.new(nil)
|
|
8
|
+
stub(@controller).params { @params }
|
|
9
|
+
stub(@controller).current_ability { @ability }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "show should load resource through @controller.resource" do
|
|
13
|
+
@params[:action] = "show"
|
|
14
|
+
stub(@controller).resource { :project_resource }
|
|
15
|
+
CanCan::InheritedResource.new(@controller).load_resource
|
|
16
|
+
@controller.instance_variable_get(:@project).should == :project_resource
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "new should load through @controller.build_resource" do
|
|
20
|
+
@params[:action] = "new"
|
|
21
|
+
stub(@controller).build_resource { :project_resource }
|
|
22
|
+
CanCan::InheritedResource.new(@controller).load_resource
|
|
23
|
+
@controller.instance_variable_get(:@project).should == :project_resource
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "index should load through @controller.parent when parent" do
|
|
27
|
+
@params[:action] = "index"
|
|
28
|
+
stub(@controller).parent { :project_resource }
|
|
29
|
+
CanCan::InheritedResource.new(@controller, :parent => true).load_resource
|
|
30
|
+
@controller.instance_variable_get(:@project).should == :project_resource
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "index should load through @controller.end_of_association_chain" do
|
|
34
|
+
@params[:action] = "index"
|
|
35
|
+
stub(Project).accessible_by(@ability) { :projects }
|
|
36
|
+
stub(@controller).end_of_association_chain { Project }
|
|
37
|
+
CanCan::InheritedResource.new(@controller).load_resource
|
|
38
|
+
@controller.instance_variable_get(:@projects).should == :projects
|
|
39
|
+
end
|
|
40
|
+
end
|