Rails 5: User accounts with 3 types of roles – Devise, Rails_admin, Cancancan

Article presents how to set up a user accounts for 2 types of end-users’ roles and 1 admin role. Users with admin roles have access to Rails_admin dahsboard. Authentication is done by Devise gem and authorization is set up by Cancancan gem.

Rails: 5.0.0.1
Ruby: 2.3.0

 

Assumptions

Let’s assume that Rails project with basic elements is already initialized and works on MySQL database.

 

Plan

  1. Create User model using Devise gem
  2. Setup authentication by Devise gem
  3. Generate views, links and controllers for Devise’s Users
  4. Create rails_admin dashboard
  5. Set up authorization using Cancancan
  6. Give access to rails_admin only for admin (superadmin) users using Cancancan
  7. Setup mailer for Devise

 

User accounts – Devise

Devise installation

Open Gemfile and add:

Run bundler and then Devise generator:

It prompts few instructions which we have to do manually. First, add to config/environments/development.rb:

Instead of localhost you can put IP of your machine and you can replace port number 3000 if your app uses different.

Next we should set a root_url in config/routes.rb. Probably you have done it already, but if not, let’s do this now: (config/routes.rb):

The third instructions is about flash messages, which notifies about successful and failed login attempts. We will use for this a toastr gem.

Add to Gemfile:

To application.css and application.js add the following:

To display devise notices and alerts via toastr, add the following code to  app/views/layouts/application.rb:

 

Devise generator

In next step, we can generate User model:

Let’s add a new test account before running migration. Open db/migrate/xxx_devise_create_user.rb and add:

Run:

 

Authenticate user

Let’s assume that our application has:

  • landing page – available for anyone – in our example app it can be home#index (index action of home controller),
  • dashboard – this is available only for logged users – user have to sign in to see this area of app.

Let’s add following to app/controllers/application_controller.rb:

authenticate_user placed in application_controller.rb forces an authentication before each action of any controller. You can verify it now by opening any page of your app in web browser. Instead of the desired page, you should see the login form. But we want that landing page should be available without any authentication. So open landing controller, for example app/controllers/home_controller.rb and add following to skip authenticate_user for index action:

Now you should see your landing page without any authentication.

Do you remember that we’ve created a test user account during migration with following params?

  • email: test@test.com
  • password: password

You can now try to open another page and enter this to login form to get access to restricted area of your app.

 

Links and redirections

In this part we will prepare some basic views and links. Let’s start by adding a link to login form to our landing page:

Not signed user will see the Sign in button and would be redirected to login form. Already signed users will see Go to App button which redirects to application dashboard.

You can meet a little problem now. If you are at the landing page, then click on the Sign in button and successfully sign in, you will be redirected back to landing page. But we would like to redirect users directly to dashboard. To do that, we have to overwrite the after_sign_in_path_for method. Open app/controllers/application_controller.rb and add this:

Instead of app_dashboard_index_path you can put path to your page from restricted part of app.

The other links which you should use in your app are presented below. You can use also user_signed_in? method to determine if user is already signed in.

 

Views

To overwrite views, you have to run following devise command:

The set of views is placed under app/views/users/*. In this article we skip the process of customizing forms, but you can make it now.

 

Controllers

Let’s use following command to generate and customize devise controllers:

If you are using custom controllers, you have to set routes in config/routes.rb:

 

Admin Users – rails_admin gem

Add to Gemfile:

And run:

Now you should get access to rails_admin dashboard under /admin in web browser.

Configuration

You can customize rails_admin gem in config/initializers/rails_admin.rb. To use devise for authentication purpose, add following:

 

Authorization – CanCanCan

We use CanCanCan gem to restrict access to some parts of app for users with specific roles. Add to Gemfile:

And run bundler. Next, use following command to genrate ability class:

In file app/models/ability.rb, you can define abilities. But first, we have to set users different roles. It’s up to you how you want to define roles. We will add to user’s model a three boolean columns for three roles: superadmin, supervisor, user. Let’s start by generating migration:

Before we run migration, let’s edit it. Open it (db/migrate/xxx_add_roles_to_users.rb):

We’ve defined default values for superadmin and supervisor as false, and true default value for user_role. Now we can run:

To verify current user role, you can use:

Views

To display some elements only for users with specific role, you can use:

Or you can use CanCanCan abilities:

And in app/model/ability.rb:

 

Controllers

To authorize user access to controller’s actions, let’s add following to specific contoller:

It will use a before action to load the resource into an instance variable and authorize it for every action.

 

Rails_admin and Cancancan

In this part, we set access to our /admin dashboard only for superadmin users. First, we have to configure config/initializers/rails_admin.rb:

Next, let’s modify app/model/ability.rb:

 

Emails

Devise has to send “reset password” and “confirmation” (if unlocked) emails to users. We’ll set also to send welcome email after registration.

First, we have to configure an access to email account. You can use your personal email account, like gmail. Open config/environments/development.rb and add / modify following:

Next, we add mail_username  and mail_password to config/secrets.yml:

Replace test@example.com and Password123 with your data.

In config/initializers/devise.rb you can modify default mailer sender:

Now you can try to reset a password. Open in web browser: /users/password/new . And try to send reset password instructions. If you’ve got an error for gmail account: Net::SMTPAuthenticationError, please follow this solution from stackoverflow.

Last thing is a welcome email, which should be send after creating a new user account. Add to the User model app/models/user.rb:

Generate UserMailer:

Add to app/mailers/application_mailer.rb:

Now we have to create mailer views in html and text formats. Create two files in app/views/user_mailer/ directory: send_welcome_email.html.erb:

… and send_welcome_email.text.erb:

Now you can test it by singing up to application or create new user account manually by your rails_admin dashboard.

 

 

 

 

Tomasz Antas

Ruby on Rails developer and Web designer.
The area of his interest includes Popular Science, Internet of Things, Wearables, AI and Virtual/Augmented Reality.

Latest posts by Tomasz Antas (see all)

Thanks for reading!

  • DavidT

    Hi Tomasz, I just came across this site and am blown away. The topics are relevant and your explanations are clear and concise.
    Thanks so much for pointing out toastr.

    • Tomasz Antas

      Thank you for your kind words!

  • Tyson Buzza

    I’m pretty new to RoR, why toastr? The flash messages seem to work fine without it, what does it do?

    • Tyson Buzza

      I think I’m using bootstrap instead, is there a reason to use toastr still?

      • Tomasz Antas

        Toastr is not required, I’ve used it just for fun in this article 😉 Typical flash messages are fine as well. There is also a lot of similar javascript messaging “tools/libraries”. I cannot recommend any outstanding one, but I believe that it wouldn’t be a problem to find an alternative for toastr.

        • Tyson Buzza

          Just noticed something else, the version of rails_admin you are using has a known security issue. Might be worth adding a comment mentioning this?

  • Suchat Tangjarukij

    How can I edit super_admin_role, because I can only create a normal user.

    • Tomasz Antas

      You want create an user with super_admin_role?

      • Bong Kum Tim

        Hi Tomasz, how do i create super_admin or supervisor ?

        • Bong Kum Tim

          thank Tomasz, i create it using rails console. Your code is simple and nice. Appreciate a lot of your fast reply too! Thanks bro!

          • Tomasz Antas

            NP, Thanks for a kind word!