"CanCan is an authorization library for Ruby on Rails which restricts what resources a given user is allowed to access. All permissions are defined in a single location (the Ability class) and not duplicated across controllers, views, and database queries."
Add this to your Gemfile and run the bundle install command
gem 'cancancan', '~> 1.10'
User permissions are defined in an Ability
class
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :read, :all
end
end
end
The can
method requires two arguments. The first one is the action you're setting the permission for, the second one is the class of object you're setting it on.
can :update, Article
You can pass :manage
to represent any action and :all
to represent any object.
can :manage, Article
can :read, :all
can :manage, :all
A hash of conditions can be passed to further restrict which records this permission applies to
can :read, Project, active: true, user_id: user.id
If your conditions are too complex to define in a hash you can use a block
can :update, Project do |project|
project.priority < 3
end
The authorize!
method in the controller will raise an exception if the user is not able to perform the given action.
def show
@article = Article.find(params[:id])
authorize! :read, @article
end
The current user's permissions can then be checked using the can?
and cannot?
methods
<% if can? :update, @article %>
<%= link_to "Edit", edit_article_path(@article) %>
<% end %>
If the user authorization fails, a CanCan::AccessDenied
exception will be raised. You can catch this and modify its behavior in the ApplicationController
.
class ApplicationController < ActionController::Base
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_url, :alert => exception.message
end
end
If you want to ensure authorization happens on every action in your application, add check_authorization
to your ApplicationController
.
class ApplicationController < ActionController::Base
check_authorization
end
This will raise an exception if authorization is not performed in an action