06 March 2010

User Verification Using Rails AuthLogic Gem

So here comes the month of march. You must be thinking what's so special about March and if you have started thinking about the same, well, please do let me know if there is anything special about March. For now, let me get the things straight for this post.

Few months ago(I assume in January 2010), I had written a post on Rails gem called "AuthLogic" for the purpose of user authentication.

Here is the link for that post if you do not know, what is AuthLogic all about.

With the help of AuthLogic, we created a beautiful user registration and login/logout features for a web application. Here, when a user registers, on successful registration he will instantly get logged in. But in most web application, that is not the case, We need the registered user to verify his account before his account is activated, and for that, we need to send a verification email with verification related info to the user. So in this post I will be giving you all the necessary information with codes, on how this feature can be achieved.

Add the following codes to your Model "user_session.rb"

class UserSession < Authlogic::Session::Base

validate :check_if_verified

  private

  def check_if_verified
    errors.add(:base, "You have not yet verified your account") unless attempted_record && attempted_record.verified
  end

end 


What this does is, when user tries to login, it will check if the user is a verified user or not. Well, so how do we know if the registered user has verified his account or not? Yes, we have to create a new field in our User Table. Here is the migration file for doing that:

class AddVerifiedToUser < ActiveRecord::Migration

  def self.up
    add_column :users, :verified, :boolean, :default => false
  end

  def self.down
    remove_column :users, :verified
  end
end 

On migration, new field called "verified" of type "boolean" will be added to the User Table in our database. Next, we will look into our controller which is responsible for creating a new user while user registers through our registration form. Well, while registration, the "create" method of "UserController" comes into the action, so we need to edit this file for sending verification information to the user's email:

def create
    @user = User.new(params[:user])
    if @user.save
      @user.deliver_user_verification_instructions!
      flash[:notice] = "Registration verification email sent.Please verify your account."
      redirect_to root_url
    else
      render :action => "new"
    end
  end 

what does line number 4 does? it call deliver_user_verifications! method on the user object. So we need to create a new method in our "User" model:

def deliver_user_verification_instructions!
    reset_perishable_token!
    Notifier.deliver_user_verification_instructions(self)
  end 

Here in this method we see that "user_verification_instructions" method of class Notifier is being called. So we create that method in models/notifier.rb file

def user_verification_instructions(user)
    subject    'User verification instructions'
    recipients user.email
    from       'XYZ Notifications'
    sent_on    Time.now
    
    @body[:url]  = "http://test.domain.com/user_verifications/show/#{user.perishable_token}"
  end 

Ok, so you now know, what "user_verification_instructions" method of "Notifier" class does. It sends the email to the user. This method will look for a file called app/views/notifier/user_verification_instructions.erb so let us create it

You have created an account for http://domain.com
Please follow the link below to verify your account and get started with XYZ

<%= @url %>

If the above URL does not work try copying and pasting it into your browser.
If you continue to have problem please feel free to contact us. 

here the variable "@url" will have the link which we have given as subject previously. This is how your mail will look:



So from the link, we know, it looks into "show" method of "user_verifications" controller. We will have to create this controller with following codes:

class UserVerificationsController < ApplicationController

  before_filter :load_user_using_perishable_token

  def show
    if @user
      @user.verify!
      flash[:notice] = "Thank you for verifying your account. You may now login."
    end
    redirect_to root_url
  end

  private

  def load_user_using_perishable_token
    @user = User.find_using_perishable_token(params[:id])
    flash[:notice] = "Unable to find your account." unless @user
  end

end 

here there is a "before_filter" which will check if the link is valid. if valid it will read show method. The show method needs to verify the user. It is done by the "verfiy!" method which needs to be created in "User Model"

def verify!
    self.verified = true
    self.save
  end 
 
That is it. On successful verification, the verified field gets a value of one and thus, user will be able to log in. So have you guys tried any other ways of doing this. Please share your ideas with me.
Thanks

6 comments:

  1. Thanks so much for the excellent post - it saved me a good deal of time! The only other thing I had to do was add before_filter :require_user, :except => [:show] in the user_verifications_controller.rb.

    ReplyDelete
  2. how can i send mail(verification) from localhost?

    ReplyDelete
  3. @arka from localhost you cannot send verification mails.

    ReplyDelete
  4. @TechSlam :thanks for quick reply. Now I have to think what can i do...

    ReplyDelete
  5. @arka you could actualy deploy the app and test email verification part live. That is what i did for one of my rails projects.

    ReplyDelete
  6. Loved this post. Thanks for sharing your day!

    ReplyDelete

Share your thoughts, Lets have a discussion :)