Allow Users and Admin to Sign In with Username or Email

In this tutorial I will be using the following gems

  • Rails 4.0
  • Devise 3.2

This tutorial will show you how the user can login with their username or email. If you have not read my tutorial on Adding a Username to the User & Admin Model then please do so.

Login to user model with username or email

First we can create a virtual login attribute. In the “app/models/user.rb” file you should add

attr_accessor :login

This looks similar to the Rails 3 attr_accessible. However they are not the same. Here is a good explanation to understand them.

Next you have to tell devise to use the login attribute. Modify the “config/initializers/devise.rb” to have

config.authentication_keys = [ :login ]

Next you want to overwrite devise’s find_for_database_authentication method. In “app/models/user.rb” you need to insert

def self.find_first_by_auth_conditions(warden_conditions)
  conditions = warden_conditions.dup
  if login = conditions.delete(:login)
    where(conditions).where(["username = :value OR lower(email) = lower(:value)", { :value => login }]).first
  else
    where(conditions).first
  end
end

You will also want to create validations for the username. In “app/models/user.rb” you should add something like this:

validates :username, presence: true, length: {maximum: 255}, uniqueness: { case_sensitive: false }, format: { with: /\A[a-zA-Z0-9]*\z/, message: "may only contain letters and numbers." }

Adding presence: true means that the user must submit a username. The length must be less than 255 characters. Uniqueness: { case_sensitive: false } will accept the username with lower or uppercase. The format: { with: /\A[a-zA-Z0-9]*\z/, message: “may only contain letters and numbers.”} command checks that your username only contains letters and numbers.

At this point you should already have devise views. If you do not then you can get them by running

rails generate devise:views

Next we have to modify the views to show the login attribute. In “app/views/devise/sessions/new.html.erb”

You can delete

<p><%= f.label :email %><br />
<%= f.email_field :email %></p>

Add

<p><%= f.label :login %><br />
<%= f.text_field :login %></p>

In “app/views/devise/registrations/new.html.erb”

Add

<p><%= f.label :username %><br />
<%= f.text_field :username %></p>

In “app/views/devise/registrations/edit.html.erb”

Add

<p><%= f.label :username %><br />
<%= f.text_field :username %></p>

Now you should change the login label from “invalid: email or password to invalid: login or password This can be found in “config/locales/devise.en.yml”

Use login with reset password and confirmation keys

You need to edit “config/initializers/devise.rb”

config.reset_password_keys = [ :login ]
config.confirmation_keys = [ :login ]

Next we have to modify the views for the login attribute. In “app/views/devise/passwords/new.html.erb”

Delete

<p><%= f.label :email %><br />
<%= f.email_field :email %></p>

Add

<p><%= f.label :login %><br />
<%= f.text_field :login %></p>

In “app/views/devise/confirmations/new.html.erb”

Delete

<p><%= f.label :email %><br />
<%= f.email_field :email %></p>

Add

<p><%= f.label :login %><br />
<%= f.text_field :login %></p>

Login to admin model with username or email

To start we should add a virtual login attribute. In the “app/models/admin.rb” file you should add

attr_accessor :login

Next you want to overwrite devise’s find_for_database_authentication method. In “app/models/admin.rb” you need to insert

def self.find_first_by_auth_conditions(warden_conditions)
  conditions = warden_conditions.dup
  if login = conditions.delete(:login)
    where(conditions).where(["username = :value OR lower(email) = lower(:value)", { :value => login }]).first
  else
    where(conditions).first
  end
end

You can add validations for the username. In “app/models/admin.rb” you should add something like this:

validates :username, presence: true, length: {maximum: 255}, uniqueness: { case_sensitive: false }, format: { with: /\A[a-zA-Z0-9]*\z/, message: "may only contain letters and numbers." }

The views should already be configured when we configured them in the earlier section of this tutorial.

I used this page as a guide to help write this: How To: Allow users to sign in using their username or email address

Advertisements

Tags: ,

One response to “Allow Users and Admin to Sign In with Username or Email”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: