How to configure CanCanCan permissions?

I'm a little confused about how to properly configure CanCanCan.

First, do I need to add load_and_authorize_resource to every controller resource that I want to restrict access to?

This is what I would like to do:

  • An administrator can manage and control all controllers and actions.
  • An editor can read everything, manage: newsroom and can manage all messages
  • The participant can read each post and can create and update messages (do not edit / delete / anything else), cannot access the editorial office. The difference between the update message and the editing in our business rules is that a new message is created in the update, which is a child of the current message. So this is not editing. Just a new report with an ancestral association.
  • The guest can read each post, but cannot create messages and do not contact the editorial office.

This is what my ability.rb looks like:

 class Ability include CanCan::Ability def initialize(user) user ||= User.new # guest user (not logged in) #Admin if user.has_role? :admin can :manage, :all can :manage, :newsroom # Editor elsif user.has_role? :editor can :read, :all can :manage, :newsroom can :manage, Post #Member elsif user.has_role? :member can :read, :all can :create, Post can :status, Post can :update, Post do |post| post.try(:user) == user end #Guest else can :read, :all can :create, Post can :status, Post end end end 

In my routes.rb , I have this:

  authenticate :user, lambda { |u| u.has_role? :admin or :editor } do get 'newsroom', to: 'newsroom#index', as: "newsroom" get 'newsroom/published', to: 'newsroom#published' get 'newsroom/unpublished', to: 'newsroom#unpublished' end 

What happens when I log in with a user who has not been assigned any roles (that is, that I want to be a "guest"), they can access the Newsroom.

When I try to edit a message with the :member role, it gives me the error "It is not allowed to edit the message" (this is correct).

I just can't completely block the Newsroom , and I'm not sure why.

+5
source share
4 answers

For what it was worth, I had to configure my NewsroomController as follows:

 class NewsroomController < ApplicationController authorize_resource :class => false 

Here's what the working version of my ability.rb looks like after I got it to work with the necessary permissions:

 #Roles #Admin if user.has_role? :admin can :manage, :all # Editor elsif user.has_role? :editor can :manage, :newsroom can :manage, Post #Member elsif user.has_role? :member can [:read, :create, :status], Post can :update, Post do |post| post.try(:user) == user end #Guest else can [:read, :status], Post end 
+2
source

You do not need to use load_and_authorize_resource in each controller. This is a handy macro that does two things. First, it assigns an instance variable to the record (s) accepted for the current controller and action. Then it resolves the resource. For some controller actions, the first step may be incorrect, so you want to upload your resource and then authorize it manually. An example from the Railscasts episode about CanCan is as follows:

 def edit @article = Article.find(params[:id]) unauthorized! if cannot? :edit, @article end 

You can also do this as in the CanCan Wiki example for authorizing controllers :

 def show @project = Project.find(params[:project]) authorize! :show, @project end 

Or you can just use authorize_resource and take care of loading it yourself. In the end, you have to make sure that CanCan is used for authorization in some way (controller macro or in every action). As for your abilities, I think you want something like this:

 class Ability include CanCan::Ability def initialize(user) user ||= User.new # guest user (not logged in) #Admin if user.has_role? :admin can :manage, :all # Editor elsif user.has_role? :editor can :read, :all can :manage, :newsroom can :manage, Post #Member elsif user.has_role? :member can :read, :all can :create, Post can :status, Post can :update, Post do |post| post.try(:user) == user end #Guest else can :read, :all cannot [:index, :published, :unpublished], :newsroom end end end 

And here is an example, for example, how you can authorize your edition:

 class ToolsController < ApplicationController authorize_resource :class => false def show # automatically calls authorize!(:show, :tool) end end 

The last personal note about CanCan is that I would not offer it for new projects, as it is not actively supported and that I found it a little contradictory in determining abilities. However, CanCan is one of the most well-documented gems I've worked with, especially the wiki contains many examples and explanations.

+9
source
 can :read, :all 

means that the user has permission to read all the resources of your application. It should be

 can :read, Post 

also add

 cannot :manage, :newsroom 

where you don’t need editorial access. The order in which you specify permissions matters. As already mentioned, "load_and_authorize_resource" is optional. To authorize all controller actions, you only need to "allow the resource". If you skip this, you can "enable" the actions of individual controllers.

Avoid using a block for ability if absolutely necessary. For example, if Post has user_id, then you can do

 can :update, Post, user_id: user.id 

Finally, 'class => false' is used where you do not have a model that supports your controller. those. you do not have a model called "Newsroom", but you have a controller called "NewsroomsController".

+2
source

First I need to add load_and_authorize_resource for each controller resource with which I want to restrict access?

Yes.

What happens when I logged in with a user who has not been assigned any roles (that is, that I want to be a "guest"), they can access the News.

From the guest role above:

 ... #Guest else can :read, :all can :create, Post can :status, Post end 

This gives the reader access to all and the ability to create posts. If you want your guests to be able to read only messages, they should be:

 ... #Guest else can :read, Post # can :status, Post # maybe you want this aswell end 
+1
source

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


All Articles