ruby-on-rails

Devise, CanCanCan and ActiveAdmin

Follow me
Follow me

Latest posts by Tomasz Antas (see all)

Feb 1, 2015

Article shows how to integrate Devise, CanCanCan and ActiveAdmin gems in Rails app. Devise allows to authenticate, CanCanCan allows to authorizate the users and ActiveAdmin gives an access to data in our app.

 

1. Installation

Add to Gemfile:

Run bundler:

 

2. Generators

ActiveAdmin

Run generator in command shell:

After all, we need to do few things manually.

– Open config/environments/development.rb and add:

– We need to place the notices and alerts somewhere in our app. Probably, the most convenient place is application.html.erb, because it’s present in each view of our app. Open app/views/layouts/application.html.erb and add these two lines:

 

Devise

Run:

ActiveAdmin invoked the Devise generator, so Devise asks if we want overwrite devise.rb file. We can simply type “Y” and file should be overwritten.

 

 User

Now, we can generate User (or it can take any other name than User) model for devise:

If our app requires to define different user roles, we can add role attribute to User model:

Open migration file from previous command: db/migrate/XXX_add_role_to_users.rb and change this file like below:

It will generate a first admin user when we will set up database.

If you want add more attributes, you can create another migrations or add more attributes in one migration. For example, if you want add role and nickname attributes, you can use followinf command:

 

3. Integrate ActiveAdmin and Devise

Firstly, we need to change configurations in config/initializers/active_admin.rb:

In config/initializers/devise.rb change following line:

to:

Now, we need to define  authenticate_active_admin_user!, which we use in active_admin.rb as authentication method. Add to app/controllers/application_controller.rb file following method:

In application_controller.rb we use User.role? method, so we have to define it in app/models/user.rb:

ActiveAdmin generates its own model – AdminUser, but it’s unnecessary while Devise User model is in use. We can remove AdminUser model from ActiveAdmin:

We have to remove manually also another two files:

Remove from config/routes.rb:

Finally, we have to register Devise User model to ActiveAdmin:

This generates the app/admin/user.rb. Modify this file like below:

 

4. Customizing Devise views and controllers

If we want customize devise controllers and views, we have to execute following commands:

In config/routes.rb we have to point which controllers’ actions should be used:

It’s possible to modify the routes also. For example, if you want to get access to sing_in under login:

Now, you can use localhost:3000/users/login. If you want to get access to login under localhost:3000/login, add this:

The “first” line gives possibilites to change /users/login path to /login path. Another part gives a redirtection. If user is already logged, will be redirected to ActiveAdmin dashboard. In the other hand, user will be redirected to login site.

 

 5. Running

Let’s migrate, run server…

… and visit localhost:3000/admin. Enter email: admin@admin.com and password: adminadmin.

If you get any errors, try also make:

 

 6. Login toolbar as partial

Create partial: app/views/layouts/_navbar.html.erb and add following content:

The login toolbar is embedded inside of Bootstrap navbar. Navbar containing the login toolbar will be added as partial to app/views/layouts/application.html.erb:

 

7. CanCanCan

At the beginning, we added CanCanCan gem to Gemfile, so it should be already installed with bundler. Now, we can generate ability.rb  model:

Open ability.rb in app/models and modify like following:

Add following line to the controller of your model:

 

 

 

Tomasz AntasDevise, CanCanCan and ActiveAdmin
  • Pinu Jain

    Hi Tomasz Antas, Thanks for sharing this wonderful post. I was struggling to hard to achieve this, and your tutorial is just perfect example of it. I could use my application autorization and authentication done with devise and cancan for Models in Active_Admin. Now one single table Users is suffice for everything. And I implemented Authorization using a separate model ‘Role’ through User_Roles and integrated with canCan Ability.rb. It worked like a charm. Just loved your Post. Thanks a ton.

  • james_ward

    What file does the last snippet for point 4 go in? devise_scope :user do…

    • Tomasz Antas

      It’s config/routes.rb

  • james_ward

    These two lines:

    config.logout_link_method = :delete

    and

    config.sign_out_via = :get

    Cause the ActiveAdmin logout button to stop working. I know you add your own navbar with the fixed logout link manually but it seems unnecessary to break the ActiveAdmin logout and likely unintentional. Leaving config.sign_out_via = :delete works fine for me.

    • Tomasz Antas

      Thanks for that note! I think you might be right

  • standingwave

    It’s crazy that you don’t indicate anywhere when this post was written. It looks like decent information but without knowing how long ago it worked it’s a lot less useful.

    • mattygabe

      I think content providers first reaction is to not show content dates so that it’s used more as it ages, but like you, if I don’t see any date information for technical articles, I almost immediately stop using it. When it was posted is just as important as what it is. Sorry Tomasz, not going to even read this.

      • Tomasz Antas

        You are right both. I also dislike a technical articles/resources without publication date. I’ve added it right now. Thanks for your comments!

  • robaldred

    This is a great walkthrough for devise, cancancan and active admin. I have one issue. I cannot change user’s role without entering their password in the admin. Active admin complains the password cannot be blank.

  • Michal

    Sth is not working here. I’ve been using Rails 4.2. I followed all the
    steps from this tutorial and there are two significant issues that I am
    facing:

    1. I get redirection loop error when I am trying to log in as
    registered user with value ‘none’ as role. I think the solution is to
    modify authenticate_active_admin_user method to:

    def authenticate_active_admin_user!

    authenticate_user!
    unless current_user.role?(:admin) || current_user.role?(:none)
    flash[:alert] = “You are not authorized to access this resource!”
    redirect_to root_path
    end

    end

    In my opinion it is ok to allow all registered users to reach admin dashboard
    because cancan later is to limit available admin resources based on given
    user role. And here is second problem:

    2. I log in as user that
    has ‘none’ value set as role. Nevertheless I have full access to all
    CRUD operations. It seems to me that no information from ability.rb is
    loaded.

    Can sb help me with that?

    • Subramanya Chakravarthy

      I too have the same problem

  • Subramanya Chakravarthy

    where should I add this line ‘load_and_authorize_resource’