Skip to content

How To: Require admin to activate account before sign_in

Clay Shentrup edited this page Mar 4, 2022 · 29 revisions

Instead of using the confirmable module (to allow users to activate their own accounts), you may want to require an admin or moderator to activate new accounts.

Model changes

Create a migration as follows (assuming the model is called User):

rails g migration add_approved_to_user approved:boolean
class AddApprovedToUser < ActiveRecord::Migration
  def self.up
    add_column :users, :approved, :boolean, :default => false, :null => false
    add_index  :users, :approved
  end

  def self.down
    remove_index  :users, :approved
    remove_column :users, :approved
  end
end

WARNING: Adding 'approved' as whitelisted parameter in strong params could allow any user to approve itself by adding an input tag in the registrations form. Take actions to manage.

Override the following methods in your model (often user.rb):

def active_for_authentication? 
  super && approved?
end 
  
def inactive_message 
  approved? ? super : :not_approved
end

You will need to create an entry for :not_approved and :signed_up_but_not_approved in the i18n file, located at config/locales/devise.##.yml:

devise:
  registrations:
    user:
      signed_up_but_not_approved: 'You have signed up successfully but your account has not been approved by your administrator yet'
  errors:
    messages:
      not_approved: 'Your account has not been approved by your administrator yet.'

Controllers and Views

You'll want to create a controller method that is admin-accessible only, that lists the unapproved users and provides a simple way to approve them.

I added a simple link in my index.html.erb page to filter the results to show 'Users awaiting approval'

<table>
  <% @users.each do |user| %>
    <tr>
      <td><%= user.email %>
      <td><%= user.approved %>
      <td><%= link_to "Edit", edit_user_path(user) %>
    </tr>
  <% end %>
</table>

Then in my users controller I have this:

def index
  if params[:approved] == "false"
    @users = User.where(approved: false)
  else
    @users = User.all
  end
end

Email Notifications

Create a new mailer (using AdminMailer for this example):

rails g mailer AdminMailer

Modify the mailer configuration file (app/mailers/admin_mailer.rb):

class AdminMailer < Devise::Mailer
  default from: 'from@example.com'
  layout 'mailer'

  def new_user_waiting_for_approval(email)
    @email = email
    mail(to: 'admin@email.com', subject: 'New user awaiting admin approval')
  end
end

Add to app/models/user.rb

after_create :send_admin_mail

def send_admin_mail
  AdminMailer.new_user_waiting_for_approval(email).deliver
end

You will also need to create a new mailer template under 'views/admin_mailer/new_user_waiting_for_approval.erb'

<p><%= @email %> has registered to join your site!</p>
<p>An admin can approve this registration by visiting the website and editing the user</p>

For more details how to send email, see ActionMailer

Reset password instructions

In the model (app/model/user.rb):

def self.send_reset_password_instructions(attributes={})
  recoverable = find_or_initialize_with_errors(reset_password_keys, attributes, :not_found)
  if recoverable.persisted?
    if recoverable.approved?
      recoverable.send_reset_password_instructions
    else
      recoverable.errors.add(:base, :not_approved)
    end
  end
  recoverable
end
Clone this wiki locally