We recently needed to implement a fairly standard user authentication / permission system on a Rails 3 project, with the ability to define these permissions using roles so that it could easily be centralized and expanded on (ie with new roles and permissions down the line). While rolling your own custom code is always an option, there is already a robust collection of gems to do exactly this. This blog post quickly presents how to combine three of these to implement this system.

Devise

Devise is a modular user authentication system thcgem ‘cancan’

  • Generate the Ability class which will contain your user permissions:
  • Open up this file and add the user line so that you can tie your abilities to the currently logged-in user:

Your application controller will need to know what to do if a CanCan exception is thrown:

Now you can decide which actions require CanCan authorization:

Adding this manually to every action in every controller is obviously a dumb idea, so you can just use load_and_authorize_resource at the top of your controller to authorize all actions in a RESTful fashion.

At this point you’ll want to actually make this more granular and allow abilities to be based on roles, which brings us to Role Model.

Role Model

The CanCan documentation provides a very nice explanation of the basic concept of using a bitmask to represent many roles per user, and Role Model is a ready-to-go solution if this approach fits your needs.

  • Add the role_model gem to your gemfile and run bundle install.
  • Edit your user.rb to make it aware of Role Model. With the existing Devise stuff, it should look more or less similar to this:

We effectively defined 3 roles now, now we need to update our ability.rb model to tie our permissions to them.

This is a really simple demonstration of what can be done fairly quickly with this stack, and in our application it was extended to leverage user-level custom permissions for specific assets and very fine-tuned abilities with conditional displays of specific view segments.

  • http://www.facebook.com/sean.doig Sean Doig

    I would have loved to read this but you need to sort out the HTML that’s growing in your code blocks.

    • Danielle Miller

      Hey Sean!

      We went back in and fixed the code. For some reason there was some issues when we migrated this post over from our old blog site. Sorry for the confusion. Enjoy the article!

  • http://www.gearcrm.com/ Brad

    Do you have any tips on how one could integrate omniauth into the stack for off-site login and registration?

  • baburaj

    we can have 2 admin account for the site?If possible how to implement this using rails_admin gem..

  • Jenny @ Abundant.Life

    Thanks for this! Looks like just what I need. :)

  • Jon Denly

    Thanks for posting this, it helped get me up and running quickly.

  • Honza Vosmik

    Thanks for the article. Just one quick question, how can you let the new user to select his role/s. I am not sure how to implement it in a view(form). Thank you!

  • developer

    How to write validation only for registrable of devise?

  • puja

    how to tie this in the view? For example, how can i manage/set user x is tied to role admin, user y is set to role moderator, etc. Explanation on this will be greatly appreciated.