見出し画像

Rails sorcery パスワードリセット機能の実装.

sourceryのreset_passwordモジュールの導入.

以下のコマンドをターミナルで実行します.

$ rails g sorcery:install reset_password --only-submodules
class SorceryResetPassword < ActiveRecord::Migration
 def change
   add_column :users, :reset_password_token, :string, default: nil
   add_column :users, :reset_password_token_expires_at, :datetime, default: nil
   add_column :users, :reset_password_email_sent_at, :datetime, default: nil
 end
end

上記のように自動で追加される.

$ rails db:migrate #実行する.

バリデーションの設定をする.

user.rb

validates :reset_password_token, uniqueness: true, allow_nil: true

ユニーク制約と加えて :allow_nilオプションも付与する.

これはパスワード変更の際にreset_password_tokenがnilになる.

なので uniqueness: true に引っかかってしまう.

ユニーク制約に引っかかんないように allow_nilオプションを追加する.

:allow_nilオプションとは.
対象の値がnilの場合にバリデーションをスキップする.

パスワードリセット用のMailerを作成

$ rails g mailer UserMailer reset_password_email

sorceryはパラメータとして新しいユーザーを送信する.

メイラーを編集して、アクションにuserパラメータを追加する必要がある.

config/initializers/sorcery.rb

Rails.application.config.sorcery.submodules = [:reset_password]
Rails.application.config.sorcery.configure do |config|
 config.user_config do |user|
   user.reset_password_mailer = UserMailer # ここで作成したUserMailerを設定する.
 end
end

パスワードリセット用のメソッドを追加する.

app/mailers/user_mailer.rb

def reset_password_email(user)
 @user = User.find user.id
 @url  = edit_password_reset_url(@user.reset_password_token)
 mail(:to => user.email,
      :subject => "Your password has been reset")
end

メイラーのビューの設定.

app/views/user_mailer/reset_password_email.text.erb

<%= @user.name %>様

<p>以下のリンクからパスワードの再発行を行ってください。</p>
<p><%= @url %></p>

ここのファイル名は,user_mailer.rbで設定したメソッド名と同じ名前にする.

ルーティングの設定.

config/routes.rb

resources :password_resets, only: [:create, :edit, :update]

コントローラの設定.

class PasswordResetsController < ApplicationController
 def new; end
 def create
   @user = User.find_by(email: params[:email])
   @user&.deliver_reset_password_instructions!
   redirect_to root_path
   flash[:success] = 'パスワードリセット手順を送信しました'
 end
 def edit
   @token = params[:id]
   @user = User.load_from_reset_password_token(params[:id])
   return not_authenticated if @user.blank?
 end
 def update
   @token = params[:id]
   @user = User.load_from_reset_password_token(params[:id])
   return not_authenticated if @user.blank?
   @user.password_confirmation = params[:user][:password_confirmation]
   if @user.change_password(params[:user][:password])
     redirect_to login_path
     flash[:success] = 'パスワードを変更しました'
   else
     flash.now[:danger] = ‘パスワード変更に失敗しました’
     render :edit
   end
 end
end
deliver_reset_password_instructions!とは.
有効期限付きのリセットコードを生成し、ユーザーにメールを送信する.
User.load_from_reset_password_tokenとは.
トークンが見つかり、有効であればユーザーを返す.
change_passwordとは.
トークンをクリアして、ユーザーの新しいパスワードを更新しようとする.

パスワードリセット申請画面作成.

app/views/password_resets/new.html.erb

<h1>パスワードリセット申請</h1>
  <%= form_with url: password_resets_path, local: true, method: :post do |f| %>
    <div class="form-group">
      <%= f.label :email %>
      <%= f.text_field :email, class:"form-control" %>
    </div>
    <%= f.submit '送信', class: 'btn btn-primary' %>
  <% end %>


パスワードリセット画面.

app/views/password_resets/edit.html.erb

<%= form_with model: @user, url: password_reset_path(@token), local: true do |f| %>
  <div class="form-group">
    <%= f.label :email %>
    <%= @user.email %>
    <%= f.label :password %>
    <%= f.password_field :password, class: 'form-control' %>
    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation, class: 'form-control' %>
  </div>
  <%= f.submit '更新する', class: 'btn btn-primary' %>
<% end %>


リンクの追加.

app/views/user_sessions/new.html.erb

<%= link_to ‘パスワードを忘れた方はこちら’, new_password_reset_path %>

参考.



この記事が参加している募集

スキしてみて

この記事が気に入ったらサポートをしてみませんか?