From b1508e93e188596e42e4b889552854c9a24c891e Mon Sep 17 00:00:00 2001 From: Lucas Mazza Date: Fri, 1 Jul 2016 14:08:38 -0300 Subject: [PATCH] Properly check for `authentication_keys` or `encrypted_password` changes when clearing the reset password token This change is required to better support scenarios where records don't have an `encrypted_password` column and the password is managed elsewhere (LDAP, for instance). The move from `email_changed?` to loop through the `authentication_keys` is also useful to support edge cases where users can authenticate with different attributes besides their email. Closes #3624. --- lib/devise/models/recoverable.rb | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/lib/devise/models/recoverable.rb b/lib/devise/models/recoverable.rb index c2cbd0f2..e1e8ed8f 100644 --- a/lib/devise/models/recoverable.rb +++ b/lib/devise/models/recoverable.rb @@ -27,11 +27,7 @@ module Devise end included do - before_update do - if (respond_to?(:email_changed?) && email_changed?) || encrypted_password_changed? - clear_reset_password_token - end - end + before_update :clear_reset_password_token, if: :clear_reset_password_token? end # Update password saving the record and clearing token. Returns true if @@ -97,6 +93,15 @@ module Devise send_devise_notification(:reset_password_instructions, token, {}) end + def clear_reset_password_token? + encrypted_password_changed = respond_to?(:encrypted_password_changed?) && encrypted_password_changed? + authentication_keys_changed = self.class.authentication_keys.any? do |attribute| + respond_to?("#{attribute}_changed?") && send("#{attribute}_changed?") + end + + authentication_keys_changed || encrypted_password_changed + end + module ClassMethods # Attempt to find a user by password reset token. If a user is found, return it # If a user is not found, return nil