开发者

Setting CanCan ability.rs model

I successfully made login system with Devise and CanCan, and I have 3 types of users. Admin, internal and global users. I created Controllers and index actions: Admin, Cpanel, Report and State, and I want to restrict access to this controllers for some users.

Admin user should have privilegies to access: Reports(all), State (read), Admin (all)

Global user should have privilegies to access: Reports(only read), State(read), Cpanel(all)

Internal user should have privilegies to access: Reports(all), State (read)

And I tried to do this with following code in ability.rs:

class Abil开发者_运维知识库ity
  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 have only index actions in this controllers, and when I login to app with internal user I CAN access to /admin for example, and that is not behavior that I want. I want to restrict access to all controllers instead of controllers listed in ability.rb class.

Source code is here


If I were going to prevent access to an entire controller, I would make a before filter that redirects the user to an access denied page if he does not have the admin role. Might look something like:

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

If I just wanted to prevent access to 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 exception in your application controller:

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

I have some pretty 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


You need to add checks for the cancan authorization to your controllers.

This might be just adding a line like

authorize! :read, @state

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

EDIT: Sorry, in a state controller index action, you likely don't have @state, so the above wouldn't apply. Possibly something like

authorize! :read, State

There is also a load_and_authorize method that you can use to combine authorization for multiple actions in a controller and reduce your code. The load_and_authorize version is likely to look similar to

load_and_authorize_resource :state

and it should be before your actions.

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

I suspect to clear up other problems, we might need to see some more code. Try posting some of your controller code.

I haven't used this in rails3, but I assume most of it remains more or less similar.


I solved this problem with

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

but, note that I must to change @current_user to current_user (without @)

Thanks Tony

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜