Skipping "authorize_resource" or "load_and_authorize_resource" method on inherited controllers #164

Closed
ghost opened this Issue Sep 30, 2010 · 11 comments

Comments

Projects
None yet
8 participants
@ghost

ghost commented Sep 30, 2010

Currently if your controllers inherit from an AdminController and you wish to put the load_and_authorize_resource in that AdminController, skipping that method on specific controllers is challenging. Any thoughts on clean ways to do this? I am still digging into the code an hope to provide some type of patch.

@ryanb

This comment has been minimized.

Show comment Hide comment
@ryanb

ryanb Oct 4, 2010

Owner

Currently the before_filter is created using a block which means there's no name attached to it so you can't use skip_before_filter. I'll research this a bit and try to come up with the best solution.

Owner

ryanb commented Oct 4, 2010

Currently the before_filter is created using a block which means there's no name attached to it so you can't use skip_before_filter. I'll research this a bit and try to come up with the best solution.

@ryanb

This comment has been minimized.

Show comment Hide comment
@ryanb

ryanb Oct 4, 2010

Owner

I did some testing and it doesn't look like it's possible to attach a name to a before filter when a block is used. One option is to internally use a method call instead of a block so skip_before_filter can be used, but the problem with that is if one uses load_and_authorize_resource I'd like them to have the choice if they want to skip the loading or the authorization.

Another option is to create these class methods: skip_load_resource, skip_authorize_resource and skip_load_and_authorize_resource. This way one can choose to skip just the loading if they want. However this does mean I'd have to implement the :only and :except options from scratch. Hmm.

If anyone has any suggestions please let me know.

Owner

ryanb commented Oct 4, 2010

I did some testing and it doesn't look like it's possible to attach a name to a before filter when a block is used. One option is to internally use a method call instead of a block so skip_before_filter can be used, but the problem with that is if one uses load_and_authorize_resource I'd like them to have the choice if they want to skip the loading or the authorization.

Another option is to create these class methods: skip_load_resource, skip_authorize_resource and skip_load_and_authorize_resource. This way one can choose to skip just the loading if they want. However this does mean I'd have to implement the :only and :except options from scratch. Hmm.

If anyone has any suggestions please let me know.

@sekrett

This comment has been minimized.

Show comment Hide comment
@sekrett

sekrett Oct 5, 2010

You may use double inheritance. You create one class Admin::BaseController, and another:

class Admin::AuthBaseController < Admin::BaseController
  load_and_authorize_resource
end

Later in your application you decide from which on these two classes to inherit.

Even better to put load_resource in first class and authorize_resource in second.

sekrett commented Oct 5, 2010

You may use double inheritance. You create one class Admin::BaseController, and another:

class Admin::AuthBaseController < Admin::BaseController
  load_and_authorize_resource
end

Later in your application you decide from which on these two classes to inherit.

Even better to put load_resource in first class and authorize_resource in second.

@ghost

This comment has been minimized.

Show comment Hide comment
@ghost

ghost Oct 5, 2010

@ryan - You are correct, I realized this after digging more into the code and realized my attempt to use a skip_before_filter was only perceived to be working b/c some other code was preventing the filter from being called. I like the second option you presented - it seems like the most flexible.
@sekrett - Good approach too - I thought of something similar, but I like your naming structure better then what I had ;)

ghost commented Oct 5, 2010

@ryan - You are correct, I realized this after digging more into the code and realized my attempt to use a skip_before_filter was only perceived to be working b/c some other code was preventing the filter from being called. I like the second option you presented - it seems like the most flexible.
@sekrett - Good approach too - I thought of something similar, but I like your naming structure better then what I had ;)

@khoan

This comment has been minimized.

Show comment Hide comment
@khoan

khoan Oct 15, 2010

You can always skip user authentication, and set the ability of nil user to be manage all or something to the effect of disabling authorization.

class MyController
  skip_before_filter :authenticate_user!
end

class Ability
  def initialize(user)
    if user.nil?
      can :manage, :all
    end
  end
end

khoan commented Oct 15, 2010

You can always skip user authentication, and set the ability of nil user to be manage all or something to the effect of disabling authorization.

class MyController
  skip_before_filter :authenticate_user!
end

class Ability
  def initialize(user)
    if user.nil?
      can :manage, :all
    end
  end
end
@voxik

This comment has been minimized.

Show comment Hide comment
@voxik

voxik Nov 4, 2010

This could be the cure:

before_filter do |controller|
  controller.class.cancan_resource_class.new(controller).load_and_authorize_resource unless controller.class == SomeController
end

voxik commented Nov 4, 2010

This could be the cure:

before_filter do |controller|
  controller.class.cancan_resource_class.new(controller).load_and_authorize_resource unless controller.class == SomeController
end
@incognick

This comment has been minimized.

Show comment Hide comment
@incognick

incognick Nov 13, 2010

@voxik - Thanks! This did the trick for me. I only want one location (ApplicationController) where I implement
load_and_authorize_resource
The Devise::SessionsController throws an error otherwise
uninitialized constant Session
Since it's not even getting to the authenticated part, the before_filter in that controller doesn't help. The other options would require changes to all my other controllers as well as new ones.

@voxik - Thanks! This did the trick for me. I only want one location (ApplicationController) where I implement
load_and_authorize_resource
The Devise::SessionsController throws an error otherwise
uninitialized constant Session
Since it's not even getting to the authenticated part, the before_filter in that controller doesn't help. The other options would require changes to all my other controllers as well as new ones.

@ryanb

This comment has been minimized.

Show comment Hide comment
@ryanb

ryanb Jan 8, 2011

Owner

adding skip load and authorize behavior - closed by 5732711

Owner

ryanb commented Jan 8, 2011

adding skip load and authorize behavior - closed by 5732711

@denispeplin

This comment has been minimized.

Show comment Hide comment
@denispeplin

denispeplin Jun 14, 2012

I'm not sure it is documented for cancan+devise.

For devise, I have custom controller, so following code works:

class ApplicationController < ActionController::Base
  authorize_resource
  check_authorization
end

class Users::SessionsController < Devise::SessionsController
  skip_authorize_resource
  skip_authorization_check
end

I'm not sure it is documented for cancan+devise.

For devise, I have custom controller, so following code works:

class ApplicationController < ActionController::Base
  authorize_resource
  check_authorization
end

class Users::SessionsController < Devise::SessionsController
  skip_authorize_resource
  skip_authorization_check
end
@CarlosLCervantes

This comment has been minimized.

Show comment Hide comment
@CarlosLCervantes

CarlosLCervantes Mar 11, 2014

"As of CanCan 1.5 you can use the skip_load_and_authorize_resource, skip_load_resource or skip_authorize_resource methods to skip any of the applied behavior and specify specific actions like in a before filter." - (https://github.com/ryanb/cancan/wiki/authorizing-controller-actions)

"As of CanCan 1.5 you can use the skip_load_and_authorize_resource, skip_load_resource or skip_authorize_resource methods to skip any of the applied behavior and specify specific actions like in a before filter." - (https://github.com/ryanb/cancan/wiki/authorizing-controller-actions)

@sajjadmurtaza

This comment has been minimized.

Show comment Hide comment
@sajjadmurtaza

sajjadmurtaza Oct 13, 2015

@incognick Here is also a way.
load_and_authorize_resource :unless => :devise_controller?

@incognick Here is also a way.
load_and_authorize_resource :unless => :devise_controller?

This issue was closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment