Skip to content

Instantly share code, notes, and snippets.

@stoffie
Created December 14, 2015 10:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stoffie/32e97c2e1c1b31546f62 to your computer and use it in GitHub Desktop.
Save stoffie/32e97c2e1c1b31546f62 to your computer and use it in GitHub Desktop.

"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."


Installation

Add this to your Gemfile and run the bundle install command

gem 'cancancan', '~> 1.10'

Abilities

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

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

The can Method

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

Authorization

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

Check Abilities

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 %>

Unauthorized Access

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

Lock It Down

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment