This post covers how to manage User and Admin models in Devise, including apply roles to Admin and restrict registration of Admin from public access.

Quick Setup

Add gem 'devise' to Gemfile and initialize Devise with rails generate devise:install.

Create User and Admin model:

$ rails generate devise user
$ rails generate devise admin

$ rake db:migrate

Generate customizable views for User and Admin.

$ rails generate devise:views users
$ rails generate devise:views admins

Registrations

Now we will customize RegistrationsController to disable public access.

Create admins/registrations_controller.rb under controllers directory:

class Admins::RegistrationsController < Devise::RegistrationsController
  # disable default no_authentication action
  skip_before_action :require_no_authentication, only: [:new, :create, :cancel]
  # now we need admin to register new admin
  prepend_before_action :authenticate_scope!, only: [:new, :create, :cancel]

  protected

  def sign_up(resource_name, resoure)
    # just overwrite the default one
    # to prevent auto sign in as the new sign up
  end
end

Change route to use customized controller:

devise_for :admins, controllers: { registrations: "admins/registrations" }

Roles

Admins or Users could have different roles. Assume we know the set of roles for administrators, we can add a role column to Admins.

$ rails generate migration add_role_to_admins role:integer

Edit the migration just created, set default: 0.

In Admins model, we will add an enum attribute role.

# Default roles available.
# Let the first declared role be the default.
enum role: [:author, :editor, :super_admin]

Now we have a handful of helpers associated, for example:

admin.role      # => author
admin.author?   # => true
admin.editor?   # => false

admin.editor!   # role changed to editor
admin.editor?   # => true

Based on roles, we could restrict Admin registration to super_admins only.

class Admins::RegistrationsController < Devise::RegistrationsController
  # disable default no_authentication action
  skip_before_action :require_no_authentication, only: [:new, :create, :cancel]
  # now we need admin to register new admin
  prepend_before_action :authenticate_super_admin!, only: [:new, :create, :cancel]

  protected

  def sign_up(resource_name, resoure)
    # just overwrite the default one
    # to prevent auto sign in as the new sign up
  end

  def authenticate_super_admin!
    authenticate_scope!

    unless resource.super_admin?
      redirect_to root_path
    end
  end
end

After Sign In

To redirect users to a specific page on successful sign in/out, add this to ApplicationController:

class ApplicationController < ActionController::Base
  protected

  def after_sign_in_path_for(resource)
    # return the path based on resource
  end
end

Comments