adding skip load and authorize behavior - closes #164
This commit is contained in:
parent
71ceb83ded
commit
57327119a8
|
@ -166,6 +166,52 @@ module CanCan
|
|||
cancan_resource_class.add_before_filter(self, :authorize_resource, *args)
|
||||
end
|
||||
|
||||
# Skip both the loading and authorization behavior of CanCan for this given controller. This is primarily
|
||||
# useful to skip the behavior of a superclass. You can pass :only and :except options to specify which actions
|
||||
# to skip the effects on. It will apply to all actions by default.
|
||||
#
|
||||
# class ProjectsController < SomeOtherController
|
||||
# skip_load_and_authorize_resource :only => :index
|
||||
# end
|
||||
#
|
||||
# You can also pass the resource name as the first argument to skip that resource.
|
||||
def skip_load_and_authorize_resource(*args)
|
||||
skip_load_resource(*args)
|
||||
skip_authorize_resource(*args)
|
||||
end
|
||||
|
||||
# Skip both the loading behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to
|
||||
# only do authorization on certain actions. You can pass :only and :except options to specify which actions to
|
||||
# skip the effects on. It will apply to all actions by default.
|
||||
#
|
||||
# class ProjectsController < ApplicationController
|
||||
# load_and_authorize_resource
|
||||
# skip_load_resource :only => :index
|
||||
# end
|
||||
#
|
||||
# You can also pass the resource name as the first argument to skip that resource.
|
||||
def skip_load_resource(*args)
|
||||
options = args.extract_options!
|
||||
name = args.first
|
||||
cancan_skipper[:load][name] = options
|
||||
end
|
||||
|
||||
# Skip both the authorization behavior of CanCan. This is useful when using +load_and_authorize_resource+ but want to
|
||||
# only do loading on certain actions. You can pass :only and :except options to specify which actions to
|
||||
# skip the effects on. It will apply to all actions by default.
|
||||
#
|
||||
# class ProjectsController < ApplicationController
|
||||
# load_and_authorize_resource
|
||||
# skip_authorize_resource :only => :index
|
||||
# end
|
||||
#
|
||||
# You can also pass the resource name as the first argument to skip that resource.
|
||||
def skip_authorize_resource(*args)
|
||||
options = args.extract_options!
|
||||
name = args.first
|
||||
cancan_skipper[:authorize][name] = options
|
||||
end
|
||||
|
||||
# Add this to a controller to ensure it performs authorization through +authorized+! or +authorize_resource+ call.
|
||||
# If neither of these authorization methods are called, a CanCan::AuthorizationNotPerformed exception will be raised.
|
||||
# This is normally added to the ApplicationController to ensure all controller actions do authorization.
|
||||
|
@ -209,6 +255,10 @@ module CanCan
|
|||
ControllerResource
|
||||
end
|
||||
end
|
||||
|
||||
def cancan_skipper
|
||||
@_cancan_skipper ||= {:authorize => {}, :load => {}}
|
||||
end
|
||||
end
|
||||
|
||||
def self.included(base)
|
||||
|
|
|
@ -26,21 +26,38 @@ module CanCan
|
|||
end
|
||||
|
||||
def load_resource
|
||||
unless skip?(:load)
|
||||
if load_instance?
|
||||
self.resource_instance ||= load_resource_instance
|
||||
elsif load_collection?
|
||||
self.collection_instance ||= load_collection
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def authorize_resource
|
||||
unless skip?(:authorize)
|
||||
@controller.authorize!(authorization_action, resource_instance || resource_class_with_parent)
|
||||
end
|
||||
end
|
||||
|
||||
def parent?
|
||||
@options.has_key?(:parent) ? @options[:parent] : @name && @name != name_from_controller.to_sym
|
||||
end
|
||||
|
||||
def skip?(behavior) # This could probably use some refactoring
|
||||
options = @controller.class.cancan_skipper[behavior][@name]
|
||||
if options.nil?
|
||||
false
|
||||
elsif options == {}
|
||||
true
|
||||
elsif options[:except] && ![options[:except]].flatten.include?(@params[:action].to_sym)
|
||||
true
|
||||
elsif [options[:only]].flatten.include?(@params[:action].to_sym)
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def load_resource_instance
|
||||
|
|
|
@ -83,4 +83,34 @@ describe CanCan::ControllerAdditions do
|
|||
stub(@controller.class).ancestors { ["InheritedResources::Actions"] }
|
||||
@controller.class.cancan_resource_class.should == CanCan::InheritedResource
|
||||
end
|
||||
|
||||
it "cancan_skipper should be an empty hash with :authorize and :load options and remember changes" do
|
||||
@controller_class.cancan_skipper.should == {:authorize => {}, :load => {}}
|
||||
@controller_class.cancan_skipper[:load] = true
|
||||
@controller_class.cancan_skipper[:load].should == true
|
||||
end
|
||||
|
||||
it "skip_authorize_resource should add itself to the cancan skipper with given model name and options" do
|
||||
@controller_class.skip_authorize_resource(:project, :only => [:index, :show])
|
||||
@controller_class.cancan_skipper[:authorize][:project].should == {:only => [:index, :show]}
|
||||
@controller_class.skip_authorize_resource(:only => [:index, :show])
|
||||
@controller_class.cancan_skipper[:authorize][nil].should == {:only => [:index, :show]}
|
||||
@controller_class.skip_authorize_resource(:article)
|
||||
@controller_class.cancan_skipper[:authorize][:article].should == {}
|
||||
end
|
||||
|
||||
it "skip_load_resource should add itself to the cancan skipper with given model name and options" do
|
||||
@controller_class.skip_load_resource(:project, :only => [:index, :show])
|
||||
@controller_class.cancan_skipper[:load][:project].should == {:only => [:index, :show]}
|
||||
@controller_class.skip_load_resource(:only => [:index, :show])
|
||||
@controller_class.cancan_skipper[:load][nil].should == {:only => [:index, :show]}
|
||||
@controller_class.skip_load_resource(:article)
|
||||
@controller_class.cancan_skipper[:load][:article].should == {}
|
||||
end
|
||||
|
||||
it "skip_load_and_authore_resource should add itself to the cancan skipper with given model name and options" do
|
||||
@controller_class.skip_load_and_authorize_resource(:project, :only => [:index, :show])
|
||||
@controller_class.cancan_skipper[:load][:project].should == {:only => [:index, :show]}
|
||||
@controller_class.cancan_skipper[:authorize][:project].should == {:only => [:index, :show]}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,10 +3,12 @@ require "spec_helper"
|
|||
describe CanCan::ControllerResource do
|
||||
before(:each) do
|
||||
@params = HashWithIndifferentAccess.new(:controller => "projects")
|
||||
@controller = Object.new # simple stub for now
|
||||
@controller_class = Class.new
|
||||
@controller = @controller_class.new
|
||||
@ability = Ability.new(nil)
|
||||
stub(@controller).params { @params }
|
||||
stub(@controller).current_ability { @ability }
|
||||
stub(@controller_class).cancan_skipper { {:authorize => {}, :load => {}} }
|
||||
end
|
||||
|
||||
it "should load the resource into an instance variable if params[:id] is specified" do
|
||||
|
@ -339,4 +341,52 @@ describe CanCan::ControllerResource do
|
|||
CanCan::ControllerResource.new(@controller, :nested => :project)
|
||||
}.should raise_error(CanCan::ImplementationRemoved)
|
||||
end
|
||||
|
||||
it "should skip resource behavior for :only actions in array" do
|
||||
stub(@controller_class).cancan_skipper { {:load => {nil => {:only => [:index, :show]}}} }
|
||||
@params.merge!(:action => "index")
|
||||
CanCan::ControllerResource.new(@controller).skip?(:load).should be_true
|
||||
CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load).should be_false
|
||||
@params.merge!(:action => "show")
|
||||
CanCan::ControllerResource.new(@controller).skip?(:load).should be_true
|
||||
@params.merge!(:action => "other_action")
|
||||
CanCan::ControllerResource.new(@controller).skip?(:load).should be_false
|
||||
end
|
||||
|
||||
it "should skip resource behavior for :only one action on resource" do
|
||||
stub(@controller_class).cancan_skipper { {:authorize => {:project => {:only => :index}}} }
|
||||
@params.merge!(:action => "index")
|
||||
CanCan::ControllerResource.new(@controller).skip?(:authorize).should be_false
|
||||
CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_true
|
||||
@params.merge!(:action => "other_action")
|
||||
CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_false
|
||||
end
|
||||
|
||||
it "should skip resource behavior :except actions in array" do
|
||||
stub(@controller_class).cancan_skipper { {:load => {nil => {:except => [:index, :show]}}} }
|
||||
@params.merge!(:action => "index")
|
||||
CanCan::ControllerResource.new(@controller).skip?(:load).should be_false
|
||||
@params.merge!(:action => "show")
|
||||
CanCan::ControllerResource.new(@controller).skip?(:load).should be_false
|
||||
@params.merge!(:action => "other_action")
|
||||
CanCan::ControllerResource.new(@controller).skip?(:load).should be_true
|
||||
CanCan::ControllerResource.new(@controller, :some_resource).skip?(:load).should be_false
|
||||
end
|
||||
|
||||
it "should skip resource behavior :except one action on resource" do
|
||||
stub(@controller_class).cancan_skipper { {:authorize => {:project => {:except => :index}}} }
|
||||
@params.merge!(:action => "index")
|
||||
CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_false
|
||||
@params.merge!(:action => "other_action")
|
||||
CanCan::ControllerResource.new(@controller).skip?(:authorize).should be_false
|
||||
CanCan::ControllerResource.new(@controller, :project).skip?(:authorize).should be_true
|
||||
end
|
||||
|
||||
it "should skip loading and authorization" do
|
||||
stub(@controller_class).cancan_skipper { {:authorize => {nil => {}}, :load => {nil => {}}} }
|
||||
@params.merge!(:action => "new")
|
||||
resource = CanCan::ControllerResource.new(@controller)
|
||||
lambda { resource.load_and_authorize_resource }.should_not raise_error
|
||||
@controller.instance_variable_get(:@project).should be_nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,10 +3,12 @@ require "spec_helper"
|
|||
describe CanCan::InheritedResource do
|
||||
before(:each) do
|
||||
@params = HashWithIndifferentAccess.new(:controller => "projects")
|
||||
@controller = Object.new # simple stub for now
|
||||
@controller_class = Class.new
|
||||
@controller = @controller_class.new
|
||||
@ability = Ability.new(nil)
|
||||
stub(@controller).params { @params }
|
||||
stub(@controller).current_ability { @ability }
|
||||
stub(@controller_class).cancan_skipper { {:authorize => {}, :load => {}} }
|
||||
end
|
||||
|
||||
it "show should load resource through @controller.resource" do
|
||||
|
|
Loading…
Reference in New Issue
Block a user