Skip to content

How To: Require admin to activate account before sign_in

Louis DeScioli edited this page Dec 4, 2013 · 12 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 (in this case, I'm 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

Note: You may want to add approved to your 'attr_accessible' in your user model so that you can do bulk assignment when creating new users. This is deprecated, and incorrect for Rails 4. Use Strong Parameters instead.

Then, override the following methods in your model (User.rb):

  def active_for_authentication? 
    super && approved? 
  end 
  
  def inactive_message 
    if !approved? 
      :not_approved 
    else 
      super # Use whatever other message 
    end 
  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'
    failure:
      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.haml page to filter the results to show 'Users awaiting approval'

%h1 Users

= link_to "All Users", :action => "index"
|
= link_to "Users awaiting approval", :action => "index", :approved => "false"

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

Then in my users controller I have this:

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

Email Notifications

Add to app/models/user.rb

  after_create :send_admin_mail
  def send_admin_mail
    AdminMailer.new_user_waiting_for_approval(self).deliver
  end

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.approved?
      recoverable.errors[:base] << I18n.t("devise.failure.not_approved")
    elsif recoverable.persisted?
      recoverable.send_reset_password_instructions
    end
    recoverable
  end
Clone this wiki locally