Archive | Devise RSS for this section

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

Adding a Username to the User & Admin Model

In this tutorial I will be using the following gems

  • Rails 4.0
  • Devise 3.2

If you haven’t already you should check out my previous post Creating User and Admin Model using Devise Rails 4.0. This post will build off the previous post.

We can begin by adding a username as a string into the database.

$ rails generate migration add_username_to_users username:string:uniq

Next  you have to migrate the database.

$ rake db:migrate

This will add the username into the database.

==  AddUsernameToUsers: migrating =============================================
-- add_column(:users, :username, :string)
-> 0.0012s
==  AddUsernameToUsers: migrated (0.0018s) ====================================

In order to get the username to work you need to add strong parameters to the application controller. You can find this in “app/controllers/application_controller.rb”

class ApplicationController < ActionController::Base
  before_filter :configure_permitted_parameters, if: :devise_controller?

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :email, :password, :password_confirmation, :remember_me) }
    devise_parameter_sanitizer.for(:sign_in) { |u| u.permit(:username, :email, :password, :remember_me) }
  end
end

This will whitelist all of the parameters that you list. This is a very good feature to use because we only want to allow the user to sign up and sign in using these parameters.

You can optionally add this line to whitelist the account settings.

devise_parameter_sanitizer.for(:account_update) {|u| u.permit(:username, :email, :password, :password_confirmation, :current_password)}

Next we will generate the username for the admin model.

$ rails generate migration add_username_to_admin username:string:uniq

Then we have to migrate the username to the database.

$ rake db:migrate
==  AddUsernameToAdmin: migrating =============================================
-- add_column(:admins, :username, :string)
-> 0.0015s
==  AddUsernameToAdmin: migrated (0.0019s) ====================================

The devise views must be edited in order for the username field to appear in the sign_in and sign_up forms. Add this line of code to the following files.
“app/views/devise/sessions/new.html.erb”
“app/views/devise/registrations/new.html.erb”
“app/views/devise/registrations/edit.html.erb”

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

Thats it! You have successfully created a User and Admin model with a username.

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

Look for my next post showing you how to sign in with the username or email.

Creating User and Admin Model using Devise Rails 4.0

In this tutorial I will show you how to install Devise. I decided to make this tutorial because it is hard to find a good resource for installing Devise on Rails 4.0. This tutorial will NOT teach you the basics of Ruby on Rails. It is intended to help those who have a basic understanding of Ruby on Rails.https://rubyonrailshelp.wordpress.com/wp-admin/post.php?post=12&action=edit&message=10

If you would like a good place to start learning Ruby on Rails, read and complete http://ruby.railstutorial.org/ruby-on-rails-tutorial-book by Michael Hartl

Other good resources are:
Devise Github page https://github.com/plataformatec/devise
Railscasts http://railscasts.com/

In this tutorial I will be using the following gems

  • Rails 4.0
  • Devise 3.2
  • PostgresSQL 9.1

Using PostgreSQL is optional. If you would like to use it then you can follow the railscast to learn how to set it up. http://railscasts.com/episodes/342-migrating-to-postgresql

This tutorial will show you how to create two models within devise. We will create a User and Admin model. I will also show you how set up a username for the sign in page.

Installing Devise

First we will install Devise.

$ gem install devise

This will install devise. After that we need to add devise into your Gemfile. This can be done by typing

$ gem 'devise'

within your Gemfile. Your Gemfile is within your application’s root folder. Next run the generator by using the command

$ rails generate devise:install

Generating a User Model

Next you should create a model called user.

$ rails generate devise user

Rails will create a user model and configure it with Devise modules. It will also create a migration file located in “db/migrate/devise_create_users.rb”. Run the command

$ rake db:migrate

When you run db:migrate, rails will create a table called users. It will display

==  DeviseCreateUsers: migrating ==============================================
-- create_table(:users)
-> 0.0071s
-- add_index(:users, :email, {:unique=>true})
-> 0.0009s
-- add_index(:users, :reset_password_token, {:unique=>true})
-> 0.0012s
==  DeviseCreateUsers: migrated (0.0101s) =====================================

Now the the model has been successfully generated. You can start the rails server by typing

$ rails server

or

$ rails s

To see what the site looks like you can go to http://localhost:3000/ or http://0.0.0.0:3000/ in your browser. You should see the rails home page when you open your browser.

You can see the devise generated sign-up and sign-in forms through these addresses.
http://localhost:3000/users/sign_up
http://localhost:3000/users/sign_in

You can add

<% if user_signed_in? %>

to the template. This will help to let us know whether devise is working or not. We can also add the link paths. This will allow us to get working links within our page.

new_user_session_path

will allow you to login and it will create a new session until you logout.

edit_user_registration_path

will allow us to change our password and delete our account.

destroy_user_session_path

will allow you to logout and it will destroy your current session.

Here is part of my header file which can be found in “app/views/layouts/_header.html.erb”

<ul class="nav pull-right">
  <li><%= link_to "Home",       root_path %></li>
  <li><%= link_to "Help",         help_path %></li>
  <% if user_signed_in? %>
    <li id="fat-menu" class="dropdown">
      <a href="#" class="dropdown-toggle" data-toggle="dropdown">
        Account <b class="caret"></b>
      </a>
      <ul class="dropdown-menu">
        <li><%= link_to "Profile", edit_user_registration_path %></li>
        <li><%= link_to "Settings", '#' %></li>
        <li class="divider"></li>
        <li>
          <%= link_to "Logout", destroy_user_session_path, :method => :delete %>
        </li>
      </ul>
    </li>
    <li> <%= link_to "Logout", destroy_user_session_path, :method => :delete %></li>
  <% else %>
    <li><%= link_to "Sign in", new_user_session_path %></li>
  <% end %>
</ul>

If a user is signed in; show a link to users, profile, settings, and logout. Otherwise show the link to sign in.

For the home page of my app I include the link to sign up. The link path to sign up is

new_user_registration_path

My example can be found in “app/views/static_pages/home.html.erb”

<%= link_to "Sign up now!", new_user_registration_path, class: "btn btn-large btn-primary" %>

Generating an Admin Model

Next we will generate the admin model.

$ rails generate devise Admin

Then you should migrate the database by running

$ rake db:migrate

You should see something like this:

==  DeviseCreateAdmins: migrating =============================================
-- create_table(:admins)
-> 0.1063s
-- add_index(:admins, :email, {:unique=>true})
-> 0.0666s
-- add_index(:admins, :reset_password_token, {:unique=>true})
-> 0.0446s
==  DeviseCreateAdmins: migrated (0.2180s) ====================================

The generated admin model can be found here:

http://localhost:3000/admins/sign_in
http://localhost:3000/admins/sign_up

We also will generate the views for both of the models.

$ rails generate devise:views

You can see the views are generated for devise in the devise folder. “app/views/devise”

I have made a couple other tutorials which will be posted on this blog, or they can be found here: https://github.com/danweller18/devise/wiki

Setting Up Mailer Using Devise For Forgot Password

In this tutorial I will show you how to set up the mailer for the forgot password feature in Devise. In the tutorial I will be setting up a Gmail account and I will show you how its done using local environment variables. I will also be using Heroku and Foreman to set up environment variables.

I am using Rails 4 and Devise 3 for this tutorial.

Seting Up Development Environment

First we will set up the development mailer for use on your local machine. In “config/environments/development.rb” you should already have included

config.action_mailer.default_url_options = { :host => 'localhost:3000' }

when you installed devise.

Next you should turn on the option to raise an exception if there is an error when sending an email. You can do this by including

config.action_mailer.raise_delivery_errors = true

in the same file. Next we will add the email delivery method. You should leave the values as they are because I will show you how to set your email information later using local environment variables. Using local environment variables will allow you to hide your email information on open source software sites like Github. In the same file add

config.action_mailer.delivery_method = :smtp

config.action_mailer.smtp_settings = {
address: “smtp.gmail.com”,
port: 587,
domain: ENV[“GMAIL_DOMAIN”],
authentication: “plain”,
enable_starttls_auto: true,
user_name: ENV[“GMAIL_USERNAME”],
password: ENV[“GMAIL_PASSWORD”]
}

Make sure that you leave the values as they are in order to allow you to set the local variables later on.

Setting Up Production Environment

Now you will need to edit the file “config/environments/production.rb”. We will be adding very similar things to this file. First you can add:

config.action_mailer.default_url_options = { :host => 'yoursite.herokuapp.com' }

NOTE: You may also need to add this line. When I was setting up the mailer, I did not find this line in any other tutorials. I had the development mailer working, however I could not get heroku to work. I received this error in the heroku logs:

ActionView::Template::Error: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true

I found the answer here: ActionView::Template::Error: Missing host to link to on stackoverflow. If you come across this, then add:

Rails.application.routes.default_url_options[:host] = 'yoursite.herokuapp.com'

to your production.rb file.

Next you will have to add in these lines. Once again make sure that you leave the variables as they are.

config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false
config.action_mailer.default :charset => "utf-8"

config.action_mailer.smtp_settings = {
address: "smtp.gmail.com",
port: 587,
domain: ENV["GMAIL_DOMAIN"],
authentication: "plain",
enable_starttls_auto: true,
user_name: ENV["GMAIL_USERNAME"],
password: ENV["GMAIL_PASSWORD"]
}

Devise includes its own emails for the mailer. These can be found at “app/views/devise/mailer/”

Adding Local Environment Variables

In this section you will set local variables to your local host and your production site (Heroku).

First create a file in the root directory called “.env”. This is the file we will use to hold our environment variables so that the whole world does not have access to them. Within “.env” you should type:

GMAIL_DOMAIN=yoururl.com
GMAIL_USERNAME=support@yoururl.com
GMAIL_PASSWORD=password12345

this time filling in your information for your gmail. The GMAIL_DOMAIN is gmail.com and you will use your own information for the rest of it. In this case we set the variables inside the file and within the development and production files, it will look for these variables.

Heroku recommends using a gem called Foreman. This will allow us to use our .env file by accessing the local variables before starting the application. We are already using Heroku for production so we should only install Foreman for testing and development. Open the Gemfile and add:

group :development, :test do
gem 'foreman'
end

Then run bundle install and you will have added the file. Next we will create a file in the root directory called “Procfile”. This file will tell the application which files should be run. Inside the Procfile you should add:

web: bundle exec rails s

Next it is very IMPORTANT that you update your .gitignore file. Failure to update your .gitignore may result in your information becoming public to the world. It is a good idea to add in the Procfile to ensure that Heroku does not receive a R11 – Bad Bind Error.

.env
Procfile

Now you will need to add the local environment variables to Heroku. This link to Heroku can give you a better idea of how it works. To add the variables to Heroku, make sure you are in the root directory and type:

heroku config:add GMAIL_PASSWORD=password12345 GMAIL_USERNAME=support@yoururl.com GMAIL_DOMAIN=yoururl.com

replacing the values with your real information. With Foreman installed, you can now start your application and test out the mailer for the local machine. You can use

foreman start

to start your web application.

This tutorial was made using the following resources: