sorcery gemのパスワードリセット機能の修正
sorcery
gemのパスワードリセット機能の修正
sorcery
gemのパスワードリセット機能で、以下の2点の不具合がありこれを修正するのにとても手こずったので、備忘録としてこちらに残します。
・[パスワードの欄]を空欄で[パスワード再確認の欄]のみを入力した場合にバリデーションエラーにならない。
・[パスワードの欄]を空欄で[パスワード再確認の欄]も空欄にした場合にバリデーションエラーにならない。
具体的に以下のような状態です。
コードは、以下のようになっています。
[app/controllers/password_resets_controller.rb] class PasswordResetsController < ApplicationController # In Rails 5 and above, this will raise an error if # before_action :require_login # is not declared in your ApplicationController. # request password reset. # you get here when the user entered their email in the reset password form and submitted it. def new; end def create @user = User.find_by(email: params[:email]) # This line sends an email to the user with instructions on how to reset their password (a url with a random token) @user.deliver_reset_password_instructions! if @user # Tell the user instructions have been sent whether or not email was found. # This is to not leak information to attackers about which emails exist in the system. if logged_in? flash.now[:success] = t '.success_message' render template: 'profiles/show' else flash[:success] = t '.success_message' redirect_to login_path end end # This is the reset password form. def edit @token = params[:id] @user = User.load_from_reset_password_token(@token) if @user.blank? not_authenticated return end end # This action fires when the user has sent the reset password form. def update @token = params[:id] @user = User.load_from_reset_password_token(@token) if @user.blank? not_authenticated return end # the next line makes the password confirmation validation work @user.password_confirmation = params[:user][:password_confirmation] # the next line clears the temporary token and updates the password if @user.change_password(params[:user][:password]) flash[:success] = t '.success_message' redirect_to login_path else render :action => "edit" end end end
[app/models/use.rb] class User < ApplicationRecord authenticates_with_sorcery! validates :password, length: { minimum: 10 }, if: -> { new_record? || changes[:crypted_password] } validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] } validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] } validates :email, uniqueness: { case_sensitive: false }, presence: true validates :name, presence: true has_many :cooking_memories, dependent: :destroy end
なぜ[パスワードの欄]を空欄で[パスワード再確認の欄]のみを入力した場合と、[パスワードの欄]を空欄で[パスワード再確認の欄]も空欄にした場合にパスワートリセットに成功してしまうのかを色々検証してみた。
以下がデバッグした検証結果
[パスワード再確認の欄]のみに入力した場合
40: def update => 41: binding.pry 42: @token = params[:id] 43: @user = User.load_from_reset_password_token(@token) 44: 45: if @user.blank? 46: not_authenticated 47: return 48: end 49: 50: # the next line makes the password confirmation validation work 51: @user.password_confirmation = params[:user][:password_confirmation] 52: # the next line clears the temporary token and updates the password 53: if @user.change_password(params[:user][:password]) 54: flash[:success] = t '.success_message' 55: redirect_to login_path 56: else 57: render :action => "edit" 58: end 59: end [1] pry(#<PasswordResetsController>)> params => <ActionController::Parameters {"_method"=>"patch", "authenticity_token"=>"qmu2f+c2ssTLaQBED4yEI9yWEZn0n02TAVtX0XYm76B1OoNrmOe8DSFKkxBJpsxPdAjWzOetoE4hi9eQE3T9Sg==", "user"=>{"password"=>"", "password_confirmation"=>"11090112sS"}, "commit"=>"更新する", "controller"=>"password_resets", "action"=>"update", "id"=>"JvreH-DiL2Jus4UztTdb"} permitted: false> [2] pry(#<PasswordResetsController>)> @token = params[:id] => "JvreH-DiL2Jus4UztTdb" [3] pry(#<PasswordResetsController>)> @user = User.load_from_reset_password_token(@token) User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`reset_password_token` = 'JvreH-DiL2Jus4UztTdb' ORDER BY `users`.`id` ASC LIMIT 1 ↳ (pry):11:in `update' => #<User:0x00007fdd53356af0 id: 29, name: "テストユーザー", email: "test@gmail.com", crypted_password: "$2a$10$KvVxnw2NXOnK3FT3x9VTCuRwwZ7Eb4V45swlJpCpQWmMRpzHThpTC", salt: "W-pmhgxHUAVBxs717_D9", role: 0, created_at: Tue, 16 Aug 2022 02:17:59 JST +09:00, updated_at: Tue, 16 Aug 2022 02:43:29 JST +09:00, reset_password_token: "JvreH-DiL2Jus4UztTdb", reset_password_token_expires_at: nil, reset_password_email_sent_at: Tue, 16 Aug 2022 02:47:42 JST +09:00, access_count_to_reset_password_page: 0> [4] pry(#<PasswordResetsController>)> @user.password_confirmation => nil [5] pry(#<PasswordResetsController>)> @user.password_confirmation = params[:user][:password_confirmation] => "11090112sS" [6] pry(#<PasswordResetsController>)> @user.password_confirmation => "11090112sS" [7] pry(#<PasswordResetsController>)> @user.valid? User Exists? (0.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):15:in `update' => true [8] pry(#<PasswordResetsController>)> if @user.change_password(params[:user][:password]) [8] pry(#<PasswordResetsController>)* puts true [8] pry(#<PasswordResetsController>)* else [8] pry(#<PasswordResetsController>)* puts false [8] pry(#<PasswordResetsController>)* end CACHE User Exists? (0.0ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):16:in `update' (0.3ms) BEGIN ↳ (pry):16:in `update' User Update (0.6ms) UPDATE `users` SET `users`.`updated_at` = '2022-08-16 02:49:07.255211', `users`.`reset_password_token` = NULL WHERE `users`.`id` = 29 ↳ (pry):16:in `update' (0.9ms) COMMIT ↳ (pry):16:in `update' true => nil
上記の事からバリデーションエラーにならずに、[パスワード再確認の欄]に入力された値のみでパスワードが更新されてしまっている。(UPDATE文が走っているが実際は、パスワードは元のまま)
[パスワードの欄]と[パスワード再確認の欄]の両方を空欄にした場合
40: def update => 41: binding.pry 42: @token = params[:id] 43: @user = User.load_from_reset_password_token(@token) 44: 45: if @user.blank? 46: not_authenticated 47: return 48: end 49: 50: # the next line makes the password confirmation validation work 51: @user.password_confirmation = params[:user][:password_confirmation] 52: # the next line clears the temporary token and updates the password 53: if @user.change_password(params[:user][:password]) 54: flash[:success] = t '.success_message' 55: redirect_to login_path 56: else 57: render :action => "edit" 58: end 59: end [1] pry(#<PasswordResetsController>)> params => <ActionController::Parameters {"_method"=>"patch", "authenticity_token"=>"y7rHggoY87OduOb0RcPwxjdisZUASiaUxD52xebtIvEU6/KWdcn9enebdaAD6biqn/x2wBN4y0nk7vaEg78wGw==", "user"=>{"password"=>"", "password_confirmation"=>""}, "commit"=>"更新する", "controller"=>"password_resets", "action"=>"update", "id"=>"JTAEfrBEaBZk7D_wPVrH"} permitted: false> [2] pry(#<PasswordResetsController>)> @token = params[:id] => "JTAEfrBEaBZk7D_wPVrH" [3] pry(#<PasswordResetsController>)> @user = User.load_from_reset_password_token(@token) User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`reset_password_token` = 'JTAEfrBEaBZk7D_wPVrH' ORDER BY `users`.`id` ASC LIMIT 1 ↳ (pry):23:in `update' => #<User:0x00007fdd53075de0 id: 29, name: "テストユーザー", email: "test@gmail.com", crypted_password: "$2a$10$KvVxnw2NXOnK3FT3x9VTCuRwwZ7Eb4V45swlJpCpQWmMRpzHThpTC", salt: "W-pmhgxHUAVBxs717_D9", role: 0, created_at: Tue, 16 Aug 2022 02:17:59 JST +09:00, updated_at: Tue, 16 Aug 2022 02:49:07 JST +09:00, reset_password_token: "JTAEfrBEaBZk7D_wPVrH", reset_password_token_expires_at: nil, reset_password_email_sent_at: Tue, 16 Aug 2022 02:52:48 JST +09:00, access_count_to_reset_password_page: 0> [4] pry(#<PasswordResetsController>)> @user.password_confirmation => nil [5] pry(#<PasswordResetsController>)> @user.password_confirmation = params[:user][:password_confirmation] => "" [6] pry(#<PasswordResetsController>)> @user.password_confirmation => "" [7] pry(#<PasswordResetsController>)> @user.valid? User Exists? (0.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):27:in `update' => true [8] pry(#<PasswordResetsController>)> if @user.change_password(params[:user][:password]) [8] pry(#<PasswordResetsController>)* puts true [8] pry(#<PasswordResetsController>)* else [8] pry(#<PasswordResetsController>)* puts false [8] pry(#<PasswordResetsController>)* end CACHE User Exists? (0.0ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):28:in `update' (0.2ms) BEGIN ↳ (pry):28:in `update' User Update (0.4ms) UPDATE `users` SET `users`.`updated_at` = '2022-08-16 02:54:31.562467', `users`.`reset_password_token` = NULL WHERE `users`.`id` = 29 ↳ (pry):28:in `update' (0.7ms) COMMIT ↳ (pry):28:in `update' true => nil
上記の事からバリデーションエラーにならずに、パスワードが更新されてしまっている。(UPDATE文が走っているが実際は、パスワードは元のまま)
検証から以下のことが分かった。
・新規でユーザー登録する時は、[パスワードの欄]と[パスワード再確認の欄]の両方に入力しないとバリデーションエラーになるが、パスワード更新時は[パスワードの欄]を空欄で[パスワード再確認の欄]のみを入力した場合も、[パスワードの欄]を空欄で[パスワード再確認の欄]も空欄にした場合もバリデーションエラーにならない。(理由は、不明。。。)
・[パスワードの欄]と[パスワード再確認の欄]でバリデーションがかかるかどうかを場合分すると以下のようになった。
パスワードの欄 | パスワード再確認の欄 | バリデーションがかかるか? |
---|---|---|
入力無し | 入力有り | バリデーションがかからない |
入力無し | 入力無し | バリデーションがかからない |
入力有り | 入力無し | バリデーションがかかる |
入力有り | 入力有り | バリデーションがかかる |
つまり、[パスワードの欄]に入力があれば通常通りバリデーションがかかるようになることが分かりました。
これを実現するためには、[パスワードの欄]にpresence: true
のバリデーションを設定する。
以下のように訂正する。
[app/models/use.rb] class User < ApplicationRecord authenticates_with_sorcery! validates :password, length: { minimum: 10 }, if: -> { new_record? || changes[:crypted_password] } validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] } validates :password, presence: true validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] } validates :email, uniqueness: { case_sensitive: false }, presence: true validates :name, presence: true has_many :cooking_memories, dependent: :destroy end
validates :password, presence: true
を追記後に再度以下のように検証してみた
[パスワード再確認の欄]のみに入力した場合
40: def update => 41: binding.pry 42: @token = params[:id] 43: @user = User.load_from_reset_password_token(@token) 44: 45: if @user.blank? 46: not_authenticated 47: return 48: end 49: 50: # the next line makes the password confirmation validation work 51: @user.password_confirmation = params[:user][:password_confirmation] 52: # the next line clears the temporary token and updates the password 53: if @user.change_password(params[:user][:password]) 54: flash[:success] = t '.success_message' 55: redirect_to login_path 56: else 57: render :action => "edit" 58: end 59: end [1] pry(#<PasswordResetsController>)> params => <ActionController::Parameters {"_method"=>"patch", "authenticity_token"=>"yqv/Oi2zwTL6cD0F6CVFka/ZKJHnMFxTRnmt0d5u+3eax5pG28TzvWIrwZzrHaWwVBUGYCkY5oZhaYHD1AIZLQ==", "user"=>{"password"=>"", "password_confirmation"=>"11090112sS"}, "commit"=>"更新する", "controller"=>"password_resets", "action"=>"update", "id"=>"uqpk5GV1pjYCRv43fA4z"} permitted: false> [2] pry(#<PasswordResetsController>)> @token = params[:id] => "uqpk5GV1pjYCRv43fA4z" [3] pry(#<PasswordResetsController>)> @user = User.load_from_reset_password_token(@token) User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`reset_password_token` = 'uqpk5GV1pjYCRv43fA4z' ORDER BY `users`.`id` ASC LIMIT 1 ↳ (pry):48:in `update' => #<User:0x00007fdd52026160 id: 29, name: "テストユーザー", email: "test@gmail.com", crypted_password: "$2a$10$KvVxnw2NXOnK3FT3x9VTCuRwwZ7Eb4V45swlJpCpQWmMRpzHThpTC", salt: "W-pmhgxHUAVBxs717_D9", role: 0, created_at: Tue, 16 Aug 2022 02:17:59 JST +09:00, updated_at: Tue, 16 Aug 2022 02:58:18 JST +09:00, reset_password_token: "uqpk5GV1pjYCRv43fA4z", reset_password_token_expires_at: nil, reset_password_email_sent_at: Tue, 16 Aug 2022 03:16:47 JST +09:00, access_count_to_reset_password_page: 0> [4] pry(#<PasswordResetsController>)> @user.password_confirmation => nil [5] pry(#<PasswordResetsController>)> @user.password_confirmation = params[:user][:password_confirmation] => "11090112sS" [6] pry(#<PasswordResetsController>)> @user.password_confirmation => "11090112sS" [7] pry(#<PasswordResetsController>)> @user.valid? User Exists? (0.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):52:in `update' => false [8] pry(#<PasswordResetsController>)> if @user.change_password(params[:user][:password]) [8] pry(#<PasswordResetsController>)* puts true [8] pry(#<PasswordResetsController>)* puts "#{@user.errors.full_messages}" [8] pry(#<PasswordResetsController>)* else [8] pry(#<PasswordResetsController>)* puts false [8] pry(#<PasswordResetsController>)* puts "#{@user.errors.full_messages}" [8] pry(#<PasswordResetsController>)* end CACHE User Exists? (0.0ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):53:in `update' false ["パスワードを入力してください"] => nil
上記の事からバリデーションエラーになっていることが分かった。
[パスワードの欄]と[パスワード再確認の欄]の両方を空欄にした場合
40: def update => 41: binding.pry 42: @token = params[:id] 43: @user = User.load_from_reset_password_token(@token) 44: 45: if @user.blank? 46: not_authenticated 47: return 48: end 49: 50: # the next line makes the password confirmation validation work 51: @user.password_confirmation = params[:user][:password_confirmation] 52: # the next line clears the temporary token and updates the password 53: if @user.change_password(params[:user][:password]) 54: flash[:success] = t '.success_message' 55: redirect_to login_path 56: else 57: render :action => "edit" 58: end 59: end [1] pry(#<PasswordResetsController>)> params => <ActionController::Parameters {"_method"=>"patch", "authenticity_token"=>"nL+Dzuf1GvCWF+pdl5KrLIQONZSsk0z7JMxUTMQEBivM0+ayEYIofw5MFsSUqksNf8IbZWK79i4D3HhezmjkcQ==", "user"=>{"password"=>"", "password_confirmation"=>""}, "commit"=>"更新する", "controller"=>"password_resets", "action"=>"update", "id"=>"pZ6xzpWxkDNxZxKo2-u9"} permitted: false> [2] pry(#<PasswordResetsController>)> @token = params[:id] => "pZ6xzpWxkDNxZxKo2-u9" [3] pry(#<PasswordResetsController>)> @user = User.load_from_reset_password_token(@token) User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`reset_password_token` = 'pZ6xzpWxkDNxZxKo2-u9' ORDER BY `users`.`id` ASC LIMIT 1 ↳ (pry):62:in `update' => #<User:0x00007fdd4da3cc08 id: 29, name: "テストユーザー", email: "test@gmail.com", crypted_password: "$2a$10$KvVxnw2NXOnK3FT3x9VTCuRwwZ7Eb4V45swlJpCpQWmMRpzHThpTC", salt: "W-pmhgxHUAVBxs717_D9", role: 0, created_at: Tue, 16 Aug 2022 02:17:59 JST +09:00, updated_at: Tue, 16 Aug 2022 02:58:18 JST +09:00, reset_password_token: "pZ6xzpWxkDNxZxKo2-u9", reset_password_token_expires_at: nil, reset_password_email_sent_at: Tue, 16 Aug 2022 03:22:00 JST +09:00, access_count_to_reset_password_page: 0> [4] pry(#<PasswordResetsController>)> @user.password_confirmation => nil [5] pry(#<PasswordResetsController>)> @user.password_confirmation = params[:user][:password_confirmation] => "" [6] pry(#<PasswordResetsController>)> @user.password_confirmation => "" [7] pry(#<PasswordResetsController>)> @user.valid? User Exists? (0.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):66:in `update' => false [8] pry(#<PasswordResetsController>)> if @user.change_password(params[:user][:password]) [8] pry(#<PasswordResetsController>)* puts true [8] pry(#<PasswordResetsController>)* puts "#{@user.errors.full_messages}" [8] pry(#<PasswordResetsController>)* else [8] pry(#<PasswordResetsController>)* puts false [8] pry(#<PasswordResetsController>)* puts "#{@user.errors.full_messages}" [8] pry(#<PasswordResetsController>)* end CACHE User Exists? (0.0ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):69:in `update' false ["パスワードを入力してください"] => nil
上記の事からバリデーションエラーになっていることが分かった。
上記の事から以下のようにコードを修正した。
def update @token = params[:id] @user = User.load_from_reset_password_token(@token) if @user.blank? not_authenticated return end # the next line makes the password confirmation validation work @user.password = params[:user][:password] @user.password_confirmation = params[:user][:password_confirmation] # the next line clears the temporary token and updates the password if @user.valid? && @user.change_password(params[:user][:password]) flash[:success] = t '.success_message' redirect_to login_path else render :edit end end
結果は、以下のようになった。
[パスワード再確認の欄]のみに入力した場合
40: def update => 41: binding.pry 42: @token = params[:id] 43: @user = User.load_from_reset_password_token(@token) 44: 45: if @user.blank? 46: not_authenticated 47: return 48: end 49: 50: # the next line makes the password confirmation validation work 51: @user.password_confirmation = params[:user][:password_confirmation] 52: # the next line clears the temporary token and updates the password 53: if @user.change_password(params[:user][:password]) && @user.valid? 54: flash[:success] = t '.success_message' 55: redirect_to login_path 56: else 57: render :action => "edit" 58: end 59: end [1] pry(#<PasswordResetsController>)> params => <ActionController::Parameters {"_method"=>"patch", "authenticity_token"=>"Z0Eb44G1z9MS2HT3aLuCsR5PIpAHs9t2JUd+rd4V/Hw3LX6fd8L9XIqDiG5rg2KQ5YMMYcmbYaMCV1K/1HkeJg==", "user"=>{"password"=>"", "password_confirmation"=>"11090112sS"}, "commit"=>"更新する", "controller"=>"password_resets", "action"=>"update", "id"=>"3b6jkuLC1X11wzriynL4"} permitted: false> [2] pry(#<PasswordResetsController>)> @token = params[:id] => "3b6jkuLC1X11wzriynL4" [3] pry(#<PasswordResetsController>)> @user = User.load_from_reset_password_token(@token) User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`reset_password_token` = '3b6jkuLC1X11wzriynL4' ORDER BY `users`.`id` ASC LIMIT 1 ↳ (pry):3:in `update' => #<User:0x00007fe568f2aff8 id: 29, name: "テストユーザー", email: "test@gmail.com", crypted_password: "$2a$10$KvVxnw2NXOnK3FT3x9VTCuRwwZ7Eb4V45swlJpCpQWmMRpzHThpTC", salt: "W-pmhgxHUAVBxs717_D9", role: 0, created_at: Tue, 16 Aug 2022 02:17:59 JST +09:00, updated_at: Tue, 16 Aug 2022 02:58:18 JST +09:00, reset_password_token: "3b6jkuLC1X11wzriynL4", reset_password_token_expires_at: nil, reset_password_email_sent_at: Tue, 16 Aug 2022 03:33:52 JST +09:00, access_count_to_reset_password_page: 0> [4] pry(#<PasswordResetsController>)> @user.password_confirmation => nil [5] pry(#<PasswordResetsController>)> @user.password_confirmation = params[:user][:password_confirmation] => "11090112sS" [6] pry(#<PasswordResetsController>)> @user.password_confirmation => "11090112sS" [7] pry(#<PasswordResetsController>)> @user.valid? User Exists? (0.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):7:in `update' => false [8] pry(#<PasswordResetsController>)> if @user.change_password(params[:user][:password]) && @user.valid? [8] pry(#<PasswordResetsController>)* puts true [8] pry(#<PasswordResetsController>)* puts "#{@user.errors.full_messages}" [8] pry(#<PasswordResetsController>)* else [8] pry(#<PasswordResetsController>)* puts false [8] pry(#<PasswordResetsController>)* puts "#{@user.errors.full_messages}" [8] pry(#<PasswordResetsController>)* end CACHE User Exists? (0.0ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):8:in `update' false ["パスワードを入力してください"] => nil
[パスワードの欄]と[パスワード再確認の欄]の両方を空欄にした場合
40: def update => 41: binding.pry 42: @token = params[:id] 43: @user = User.load_from_reset_password_token(@token) 44: 45: if @user.blank? 46: not_authenticated 47: return 48: end 49: 50: # the next line makes the password confirmation validation work 51: @user.password_confirmation = params[:user][:password_confirmation] 52: # the next line clears the temporary token and updates the password 53: if @user.change_password(params[:user][:password]) && @user.valid? 54: flash[:success] = t '.success_message' 55: redirect_to login_path 56: else 57: render :action => "edit" 58: end 59: end [1] pry(#<PasswordResetsController>)> params => <ActionController::Parameters {"_method"=>"patch", "authenticity_token"=>"yoojFbl6kEu+IyyXNEa+CcvAUnl0A5W8yhXEhulNQj+a5kZpTw2ixCZ40A43fl4oMAx8iLorL2ntBeiU4yGgZQ==", "user"=>{"password"=>"", "password_confirmation"=>""}, "commit"=>"更新する", "controller"=>"password_resets", "action"=>"update", "id"=>"3b6jkuLC1X11wzriynL4"} permitted: false> [2] pry(#<PasswordResetsController>)> @token = params[:id] => "3b6jkuLC1X11wzriynL4" [3] pry(#<PasswordResetsController>)> @user = User.load_from_reset_password_token(@token) User Load (0.4ms) SELECT `users`.* FROM `users` WHERE `users`.`reset_password_token` = '3b6jkuLC1X11wzriynL4' ORDER BY `users`.`id` ASC LIMIT 1 ↳ (pry):17:in `update' => #<User:0x00007fe569c32a70 id: 29, name: "テストユーザー", email: "test@gmail.com", crypted_password: "$2a$10$KvVxnw2NXOnK3FT3x9VTCuRwwZ7Eb4V45swlJpCpQWmMRpzHThpTC", salt: "W-pmhgxHUAVBxs717_D9", role: 0, created_at: Tue, 16 Aug 2022 02:17:59 JST +09:00, updated_at: Tue, 16 Aug 2022 02:58:18 JST +09:00, reset_password_token: "3b6jkuLC1X11wzriynL4", reset_password_token_expires_at: nil, reset_password_email_sent_at: Tue, 16 Aug 2022 03:33:52 JST +09:00, access_count_to_reset_password_page: 0> [4] pry(#<PasswordResetsController>)> @user.password_confirmation => nil [5] pry(#<PasswordResetsController>)> @user.password_confirmation = params[:user][:password_confirmation] => "" [6] pry(#<PasswordResetsController>)> @user.password_confirmation => "" [7] pry(#<PasswordResetsController>)> @user.valid? User Exists? (0.3ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):21:in `update' => false [8] pry(#<PasswordResetsController>)> if @user.change_password(params[:user][:password]) && @user.valid? [8] pry(#<PasswordResetsController>)* puts true [8] pry(#<PasswordResetsController>)* puts "#{@user.errors.full_messages}" [8] pry(#<PasswordResetsController>)* puts false [8] pry(#<PasswordResetsController>)* puts "#{@user.errors.full_messages}" [8] pry(#<PasswordResetsController>)* end CACHE User Exists? (0.0ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'test@gmail.com' AND `users`.`id` != 29 LIMIT 1 ↳ (pry):22:in `update' => nil
ブラウザの画面でも以下のようにちゃんとエラーになった。