Setting Up Role-Based Access Control with CanCan in Rails

In this article, we will explore how to implement role-based access control (RBAC) in a Rails application using the CanCan authorization library. This setup is particularly useful for applications like social networks where users can manage projects and collaborate with others.

Prerequisites

Before we begin, ensure you have the following:

  • A Rails application set up with Devise for user authentication.
  • A Role model to manage user roles.

Step 1: Define Your Models

First, let's define the Role and User models. The Role model will have a simple string attribute to represent the role name.

# app/models/role.rb
class Role < ApplicationRecord
  has_many :users
  # Example: roles could be 'admin', 'moderator', 'member'
  validates :name, presence: true, uniqueness: true
end

# app/models/user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  belongs_to :role
end

Step 2: Setting Up CanCan

Next, we need to configure CanCan to handle authorization based on user roles. Create an Ability class where we will define permissions.

# app/models/ability.rb
class Ability
  include CanCan::Ability

  def initialize(user)
    user ||= User.new # guest user (not logged in)

    if user.role.name == 'admin'
      can :manage, :all
    elsif user.role.name == 'moderator'
      can :manage, Project
      can :read, User
    else
      can :read, Project
    end
  end
end

Step 3: Assigning Roles to Users

When creating users, you can assign them roles based on your application's logic. For instance, you might have a user creation form that allows you to select a role.

# Example of assigning a role during user creation
user = User.new(email: 'example@example.com', password: 'password')
user.role = Role.find_by(name: 'member')
user.save

Step 4: Using CanCan in Controllers

In your controllers, you can now use CanCan to restrict access based on the user's role. For example:

# app/controllers/projects_controller.rb
class ProjectsController < ApplicationController
  load_and_authorize_resource

  def index
    @projects = Project.all
  end

  def show
    @project = Project.find(params[:id])
  end

  def create
    @project = Project.new(project_params)
    if @project.save
      redirect_to @project
    else
      render :new
    end
  end
end

Conclusion

By following these steps, you can effectively manage user roles and permissions in your Rails application using CanCan. This setup allows users to collaborate on projects while ensuring that access is appropriately controlled based on their roles.

For further reading, you can explore the CanCanCan documentation for more advanced configurations and features.