Skip to content

Step10: Setting Up Authorization Using CanCan and Rolify

Lev Brie edited this page Jul 30, 2013 · 7 revisions

Inspired by Daniel Kehoe's example application using Devise, CanCan, and Bootstrap. This authorizaiton implementation uses CanCan and Rolify

  1. Generate an ability class for CanCan: rails g cancan:ability

  2. Set up roles with the Rolify gem: $ rails g rolify:role Role User and $ rake db:migrate

  3. Uncomment the line # config.use_dynamic_shortcuts in config/initializers/rolify.rb to enable dynamic shortcuts like user.is_admin?

  4. If you followed the instructions for installing Figaro, place an array of roles in your application.yml file. In this case, we're using ROLES: [admin, developer, user].

  5. Seed the database with the roles and an admin user, whose credentials you can also place in your application.yml file:

YAML.load(ENV['ROLES']).each do |role| Role.create!(:name => role) puts 'role: ' << role end puts 'DEFAULT USERS' admin = User.create!( :name=> ENV['ADMIN_NAME'].dup, :email => ENV['ADMIN_EMAIL'].dup, :username => ENV['ADMIN_USERNAME'].dup, :password => ENV['ADMIN_PASSWORD'].dup, :password_confirmation => ENV['ADMIN_PASSWORD'].dup, :confirmed_at => Time.now) puts 'admin: ' << admin.name admin.add_role :admin developer = User.create!( :name=> 'Developer 1', :email => 'developer1@example.com', :username => 'developer1', :password => 'password55', :password_confirmation => 'password55', :confirmed_at => Time.now) developer.add_role :developer puts 'developer: ' << developer.name

user = User.create!( :name=> 'User 1',:email => 'user1@example.com', :username => 'user1', :password => 'password55', :password_confirmation => 'password55', :confirmed_at => Time.now) user.add_role :user puts 'user: ' << user.name ```

and run rake db:seed

  1. In app/models/ability.rb specify the following basic abilities as follows:

def initialize(user) user ||= User.new # guest user (not logged in) if user.has_role?(:admin) can :manage, :all else can :read, :all if user.has_role? :developer can :read, :users if user.has_role? :user end end ```

  1. Add load_and_authorize_resource to users_controller.rb and run $ rake db:test:prepare again

  2. Add user.add_role :admin to spec/support/controller_macros.rb just before signing in the user.

  3. Add the following to controllers/application_controller.rb:

rescue_from CanCan::AccessDenied do |exception| redirect_to root_url, :alert => exception.message end ```

to catch the CanCan::AccessDenied exception that's raised when user authorization fails. All tests should now be passing.