CanCan is a simple authorization strategy for Rails that is decoupled from user roles. All the permissions are stored in one single location. It is a popular authorization library for Ruby on Rails that restricts user access to specific resources.
Abilities are defined in the Ability
class using can
and cannot
methods. Lets look at the following example:
class Ability
include CanCan::Ability
def initialize(user)
// The visitor and user
// A registered user or a new user
user ||= User.new
can :read, Post
// if a user is logged in
if user.present?
if user.admin?
// admins have the privilege to manage everything
can :manage, Post
can :manage, :all
else
// other users are given permission to read and edit their own posts.
can :read, Post
// They cannot read any hidden articles
cannot :read, Post, hidden: true
end
else
// user not signed in should view a sign_up page:
can :read, :sign_up
end
end
end
Permissions are defined in the Ability class and can be used from controllers, views, helpers, or any other place in the code.
To add authorization support, we first add the CanCanCan
gem to our Gemfile:
gem cancancan
Then, we define the ability class:
# app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
end
end
Secondly, in order to check authorization using load_and_authorize_resource
to load authorized models into the controller, write:
class PostsController < ApplicationController
load_and_authorize_resource
def show
// the post is already loaded and authorized
end
end
Use
authorize!
to authorize or raise an exception.
def show
@post= Post.find(params[:post_id])
authorize! :read, @post
end
Use
can?
to check if an object is authorized against a particular action anywhere in the controllers, views, or helpers.
<% if can? :update, @post%>
<%= link_to "Edit", post_path(@post) %>
<% end %>
This assumes the signed user is provided by the current_user method. If a user is provided access to update, then that user is provided with a link to edit the post.
CanCan can handle the entire permission logic inside the Ability class, which results in the efficient unit testing of applications.
The can?
method can be called directly on any Ability so it is easy to test permission logic. Any user can be assigned certain access and any user can be restricted from having certain access. Look at the code below to see how a user can view the post and a restricted user cannot.
test_ability = Ability.new(User.first)
test_ability.can?(:show, Post) #=> true
other_ability = Ability.new(RestrictedUser.first)
other_ability.cannot?(:show, Post) #=> true
Free Resources