raise AccessDenied error when loading child while parent is nil, pass :shallow => true to bypass

This commit is contained in:
Ryan Bates 2010-09-21 11:32:56 -07:00
parent ebef3cc745
commit 264e2d2b68
3 changed files with 25 additions and 5 deletions

View File

@ -71,6 +71,9 @@ module CanCan
# [:+through+] # [:+through+]
# Load this resource through another one. This should match the name of the parent instance variable. # Load this resource through another one. This should match the name of the parent instance variable.
# #
# [:+shallow+]
# Pass +true+ to allow this resource to be loaded directly when parent is +nil+. Defaults to +false+.
#
# [:+singleton+] # [:+singleton+]
# Pass +true+ if this is a singleton resource through a +has_one+ association. # Pass +true+ if this is a singleton resource through a +has_one+ association.
# #

View File

@ -127,10 +127,17 @@ module CanCan
# The object that methods (such as "find", "new" or "build") are called on. # The object that methods (such as "find", "new" or "build") are called on.
# If the :through option is passed it will go through an association on that instance. # If the :through option is passed it will go through an association on that instance.
# If the :shallow option is passed it will use the resource_class if there's no parent
# If the :singleton option is passed it won't use the association because it needs to be handled later. # If the :singleton option is passed it won't use the association because it needs to be handled later.
def resource_base def resource_base
if @options[:through]
if parent_resource if parent_resource
@options[:singleton] ? parent_resource : parent_resource.send(name.to_s.pluralize) @options[:singleton] ? parent_resource : parent_resource.send(name.to_s.pluralize)
elsif @options[:shallow]
resource_class
else
raise AccessDenied # maybe this should be a record not found error instead?
end
else else
resource_class resource_class
end end

View File

@ -174,12 +174,22 @@ describe CanCan::ControllerResource do
@controller.instance_variable_get(:@project).should == :some_project @controller.instance_variable_get(:@project).should == :some_project
end end
it "should not load through parent resource if instance isn't loaded" do it "should not load through parent resource if instance isn't loaded when shallow" do
@params.merge!(:action => "show", :id => 123)
stub(Project).find(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller, :through => :category, :shallow => true)
resource.load_resource
@controller.instance_variable_get(:@project).should == :some_project
end
it "should raise AccessDenied when attempting to load resource through nil" do
@params.merge!(:action => "show", :id => 123) @params.merge!(:action => "show", :id => 123)
stub(Project).find(123) { :some_project } stub(Project).find(123) { :some_project }
resource = CanCan::ControllerResource.new(@controller, :through => :category) resource = CanCan::ControllerResource.new(@controller, :through => :category)
lambda {
resource.load_resource resource.load_resource
@controller.instance_variable_get(:@project).should == :some_project }.should raise_error(CanCan::AccessDenied)
@controller.instance_variable_get(:@project).should be_nil
end end
it "should authorize nested resource through parent association on index action" do it "should authorize nested resource through parent association on index action" do