How To: Allow users to edit their password - heartcombo/devise GitHub Wiki

By default, Devise allows users to change their password using the registerable module.

Here we are going to provide a few solutions on how to allow users to change their password.

Solution 1

Make the following link in your view:

<%= link_to "Change your password", edit_user_registration_path %>

Notice: This'll work if you didn't do any modification in your routes.rb file such as

devise_for :users, :skip => [:registrations]

Notice 2: If you use the latest Devise with Strong Parameters, you should add this line to your ApplicationController.rb:

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

  def configure_permitted_parameters
    update_attrs = [:password, :password_confirmation, :current_password]
    devise_parameter_sanitizer.permit :account_update, keys: update_attrs
  end
end

Solution 2

Let's suppose that you don't want to allow users to sign up but you want to allow to change password for registered users. Just paste this code in routes.rb:

devise_for :users, :skip => [:registrations]                                          
as :user do
  get 'users/edit' => 'devise/registrations#edit', :as => 'edit_user_registration'    
  put 'users' => 'devise/registrations#update', :as => 'user_registration'            
end

And then you can make such link in your view:

= link_to "Change your password", edit_user_registration_path

Notice: you will need to update default devise views accordingly, i.e. in app/views/devise/registrations/edit.html.erb change registration_path(resource_name) to user_registration_path(). If you are using shared views for multiple models, you can use send("#{resource_name}_registration_path").

Notice: If you are using rails 4.0+ you should be using patch instead of put for updates. You should change the method in the form_tag residing in app/views/devise/registrations/edit.html.erb and the routes.rb file.

Solution 3

But sometimes, developers want to provide their custom actions that change the password. In such cases, the best option is for you to manually create a controller:

class UsersController < ApplicationController
  
  before_action :authenticate_user!

  def edit
    @user = current_user
  end

  def update_password
    @user = current_user
    if @user.update(user_params)
      # Sign in the user by passing validation in case their password changed
      bypass_sign_in(@user)
      redirect_to root_path
    else
      render "edit"
    end
  end

  private

  def user_params
    # NOTE: Using `strong_parameters` gem
    params.require(:user).permit(:password, :password_confirmation)
  end
end

If you are using several scopes, specify the one you are signing in:

bypass_sign_in @user, scope: :user

The route should be the following:

resource :user, only: [:edit] do
  collection do
    patch 'update_password'
  end
end

And then proceed to implement the view, as below:

<%= form_for(@user, :url => { :action => "update_password" } ) do |f| %>
  <div class="field">
    <%= f.label :password, "Password" %><br />
    <%= f.password_field :password, :autocomplete => "off"  %>
  </div>
  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation %>
  </div>
  <div class="action_container">
    <%= f.submit %>
  </div>
<% end %>

To use "confirm_password" field to force user to enter old password before updating with the new one: Change @user.update(user_params) to @user.update_with_password(user_params) in the controller along with adding :current_password to the permitted parameters, then and add the following to the view code:

  <div class="field">
    <%= f.label :current_password %> <i>(we need your current password to confirm your changes)</i><br />
    <%= f.password_field :current_password %>
  </div>

Remember, Devise models are like any model in your application. If you want to provide custom behavior, just implement new actions and new controllers. Don't try to bend Devise.

⚠️ **GitHub.com Fallback** ⚠️