Customizing CanCan ability.rs

I have successfully created a login system using Devise and CanCan, and I have 3 types of users. Administrators, internal and global users. I created controllers and index actions: Admin, Cpanel, Report, and State, and I want to restrict access to these controllers for some users.

Admin user must have access privileges: reports (all), status (read), Admin (all)

The global user must have access privileges: reports (read only), status (read), cpanel (all)

The internal user must have access privileges: reports (all), status (read)

And I tried to do this with the following code in the .rs capabilities file :

class Ability include CanCan::Ability def initialize(user) user ||= User.new # guest user (not logged in) if user.role? :admin can :manage, [Report, Admin] can :read, State elsif user.role? :global_user can :read, [Report, State] can :manage, Cpanel elsif user.role? :internal_user can :manage, Report can :read, State end end end 

At this time, I only have index actions in these controllers, and when I log in to the application with an internal user, I can connect to / admin, for example, and this is not the behavior I want. I want to restrict access to all controllers, not the controllers listed in the capability.rb class.

Source code here

+4
source share
3 answers

If I am going to deny access to the entire controller, I would make a filter before that redirects the user to the access denied page if he does not have an administrator role. It might look something like this:

 def check_permissions raise CanCan::AccessDenied unless @current_user.role?(:admin) end 

If I just wanted to prevent access to the update and create, for example, I would do:

 def update raise CanCan::AccessDenied unless can?(:update,Thing) ... end def create raise CanCan::AccessDenied unless can?(:create,Thing) ... end 

You can handle the CanCan::AccessDenied in the application controller:

 rescue_from CanCan::AccessDenied do |exception| flash[:error] = exception.message redirect_to no_access_path end 

I have some good posts about CanCan and Devise here and here.

UPDATE I use this method in my application controller to set my current user variable:

 # Make the current user object available to views #---------------------------------------------------------------------------- def get_user @current_user = session[:current_user] end 
+8
source

You need to add cancan authorization checks for your controllers.

It could just be adding a line like

 authorize! :read, @state 

to your state controller index action and similarly for all other index actions.

EDIT: Sorry, you probably won't have @state in the action of the state controller index, so the above is not applicable. Maybe something like

 authorize! :read, State 

There is also a load_and_authorize method that you can use to combine authorization for several actions in the controller and shorten your code. The load_and_authorize version is likely to be similar to

load_and_authorize_resource: state

and this should be before your actions.

You might want to look at railscast for cancan authorization for a complete basic setup (in rails2).

I suspect that I have clarified other issues, perhaps we will need another code. Try publishing your controller code.

I did not use this in rails3, but I assume that most of them remain more or less similar.

+2
source

I solved this problem with

 def check_permissions raise CanCan::AccessDenied unless current_user.role?(:admin) end 

but note that I have to change @current_user to current_user (without @)

Thank you, Tony

0
source

Source: https://habr.com/ru/post/1341909/


All Articles