I bring to your attention one of the best, in my opinion, gems for authentication in rails-applications. Unfortunately, there is very little Russian-language information on this gem, including on the habr, so I want to highlight this topic. The article, first of all, is designed for beginners and is a detailed tutorial on setting up authentication based on the mentioned heme. In the first part, I will highlight the basic setup steps. Further more about gem.
Devise is a ruby ​​gem that provides authentication capabilities in rails applications. Devise works in conjunction with the Warden gem, which in turn provides the mechanism for authentication in rack-based ruby ​​applications. The main features of Devise are described below:
- based on Rack;
- is a complete Rails based MVC solution;
- Allows logging in on several models simultaneously;
- based on modularity: uses only what you really need.
So let's proceed to installing and configuring Devise for your rails application. Further process for readability will be divided into separate steps.
Note : I did all the installation and configuration for rails version 4.0.1.
Step 1. Add a gem to the gemfile
gem 'devise'
Or with the indication of the exact version (the next version works stably with rails 4.0.1)
gem 'devise', '3.2.2'
Run the bundle to install new gems
bundle install
The following gems will be additionally installed as dependencies:
warden - middleware software that provides authentication for Rack applications;
orm_adapter - provides a single point of entry for using the basic functions of Ruby ORMs;
bcrypt-ruby - provides a simple password wrapper. It is based on the cryptographic hash function bcrypt ();
thread_safe — Provides thread-safe collections and utilities for Ruby
railties are internal components of Rails, such as application loaders, plugins, generators, and rake tasks.
')
Step 2. So, the heme was downloaded, but still does not interact with our application. Devise has in its arsenal convenient generators, one of which we now use. Perform a Devise installation by running the following generator:
rails generate devise:install
This generator will install the initializer, which describes all the configuration settings Devise, necessary for work, as well as a file with the base locale (English). Also, the installer will offer us a basic setup.
Step 3. Make the basic setting of the heme after installation
3.1. Now we need to set the mailer (mail sender) settings for each of the execution environments. For the development environment, add the following line to the
config / environments / development.rb file:
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
For the production environment it is necessary to replace the key value
: host with the current one.
3.2. After the user logs in, confirms the account, or updates the password, Devise will look for a path for subsequent redirection. By default, it will redirect to
user_root_path , if it exists. Otherwise, Devise will redirect to
root_path . Therefore, this path must be defined in the application. Check your
config / routes.rb routes
file for a line like this:
root 'home#index'
I think you will agree with me that it is not very logical to redirect the user to the main page of the application after entering. In this regard, let's set up redirection after successfully logging in to the user profile page. To do this, add the following route in the
config / routes.rb :
get 'persons/profile', as: 'user_root'
Note :
1) You must first create a controller and action. This can be done through the console using a convenient generator:
rails generate controller persons profile
2) As a result, the generator will create a
persons_controller controller with one method (action)
profile , as well as a view for this action.
The list of routes can be obtained through the console. Just enter the command:
bundle exec rake routes
In our case, the next router should be available.
user_root GET /persons/profile(.:format) persons
for which the user_root_path
helper will be available
There is also another way by which you can define your own redirections both after entering and after exiting. To do this, you must override the existing devise-methods
after_sign_in_path_for and
after_sign_out_path_for in
ApplicationController (
app / controllers / application_controller.rb ). Personally, I liked this redirection option more:
def after_sign_in_path_for(resource) current_user_path end
After logging in, the user will be redirected to the page described by the
current_user_path helper
def after_sign_out_path_for(resource_or_scope) request.referrer end
After logging out, the user will remain on the same page.
3.3. It is necessary to add notifications and warnings to the template.
<p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p>
3.4. If you are deploying an application on
Heroku using Rails version 3.2, then you need to add the following line in
config / application.rb config.assets.initialize_on_precompile = false
3.5. We can customize view files to fit our needs. To do this, you need to copy them from gem to your application by running the following command:
rails generate devise:views
In the
app / views / devise directory you will find all the
view files used by the
gem . You can customize them as you wish, to the overall style of your application.
Step 4. Now it's time to create a user model that will perform the authentication. We will generate a user model, so let's call it
User . The model may also be called
admin :
rails generate devise User
This generator will create a new model if it did not exist before and configure it with the default modules used. Most likely, you will receive the following code in
app / models / user.rb (the code is somewhat formatted):
class User < ActiveRecord::Base
Devise has in its arsenal 10 modules. By default, you will have 6 modules connected. You can edit this list. The description of all available modules is given below:
1.
Database Authenticatable : provides the ability to log on to the system based on the password encrypted and stored in the database. Login can be done by sending a POST request or using HTTP Basic Authentication.
2.
Omniauthable : adds support for Omniauth (
https://github.com/intridea/omniauth ).
3.
Confirmable : allows you to send an email with instructions to verify the account created during registration.
4.
Recoverable : allows you to recover your forgotten password. Sends recovery instructions to email.
5.
Registerable : manages the registration of users, allows you to edit and delete accounts.
6.
Rememberable : allows you to remember users based on cookies. Manages the creation and deletion of tokens.
7.
Trackable : keeps statistics of the number of entries, takes into account time and IT-addresses.
8.
Timeoutable : responsible for the duration of the user activity session in the system;
9.
Validatable : provides validation tools for e-mail and password. The module can be easily configured, you can define your own validators.
10.
Lockable : locks the account after the number of failed authorization attempts specified in the settings. Account can be unlocked via email or after a certain period of time.
Also, the command that we executed above will create a database migration file and a route. The migration file looks like this:
class DeviseCreateUsers < ActiveRecord::Migration def change create_table(:users) do |t|
Here we see that a user table is being created (3rd line of code). Since we called our model
User , the table has the same name, but in the plural (according to the
ActiveRecord naming convention). The following describes the fields that will be added to the table during creation. As we see from the code, only 6 Devise modules for work may require fields in the table.
If you do not use any of the modules, do not forget to comment out the corresponding fields in the migration. And, on the contrary, when you make some of the modules active, then also do not forget to uncomment the corresponding lines.
The following route will be created in the
config / routes.rb file :
devise_for :users
Let me remind you that the list of existing routes can be viewed by command:
bundle exec rake routes
Step 5. So, we figured out the modules, we connected them, we looked at the migration file. Now you need to perform a migration that will create a user table with the required set of fields. Run the following command:
bundle exec rake db:migrate
Step 6. Next, be sure to restart the application for all changes to take effect. If this is not done, then you can encounter various kinds of errors.
Since my application is running on the
Unicorn server, I restart it. If you are testing your application under the
Webrick server, then it is enough to stop it using the
CTRL + C key combination and then restart it:
rails server
Step 7. Our module and our application are ready to work. The next step is to add links to the template to enter and register. This can be done as follows:
<% if user_signed_in? %> <span>, <%= current_user.email %></span> <%= link_to '', destroy_user_session_path, :method => :delete %> <% else %> <%= link_to '', new_user_session_path %> <%= link_to '', new_user_registration_path %> <% end %>
If the user entered the site, then write him “Hello, [user mail]” and next place the link to exit. If the user has not yet logged into the site, then we have two “Login” and “Register” links nearby. We use existing helpers as reference paths. Let me remind you that the routes were established in the fourth step and they can see the list by the following command. The helper consists of a prefix (the leftmost column + '_path')
bundle exec rake routes
Step 8. It's time to start using Devise for its intended purpose - to restrict access to an unauthorized user to certain sections of the site. Suppose we want to allow only an authorized user to execute an order. To do this, we must add a filter to the appropriate controller:
class OrdersController < ApplicationController before_filter :authenticate_user!, except => [:show, :index] def index
Here, in the code, the second parameter to the
before_filter method is
that we pass a list of controller methods that should not be filtered. Thus, authorization is needed only to fulfill the order (access to the work of the
order method). If it is necessary to filter all controller methods, then the second parameter is not required. Just write:
before_filter :authenticate_user!
List of useful helper methods
Devise contains useful helpers that can be used inside controllers and views. Some of them cite below.
You can verify that a user is logged in with the following helper: user_signed_in?
With the help of the following helper, we will get the object of the user currently authorized on the site current_user
You can display the user's email as follows. current_user.email
Access to the current session can be obtained as follows: user_session
At this end, the first part, and in the next part I plan to write about other equally important and no less interesting settings of this wonderful gem for authentication.
Bibliography:
The main source of material used was official gem documentation -
github.com/plataformatec/devise , supplemented with its own customization experience.