11require 'devise/strategies/database_authenticatable'
2+ require 'bcrypt'
23
34module Devise
45 module Models
@@ -50,26 +51,29 @@ def self.required_fields(_klass)
5051 # Generates new password for the new encryptor
5152 # generate password of the old one using super
5253 def password = ( new_password )
53- # everytime we store the new one with the given encryptor
54- self . encrypted_password_migrate_to = generate_digest_for_password ( new_password )
55- # this will set the original password to the database, nothing changed
54+ unless override_existing_password_hash_enabled?
55+ self . encrypted_password_migrate_to = generate_digest_for_password ( new_password )
56+ end
5657 super
5758 end
5859
5960 # Validates the password considering the salt.
6061 def valid_password? ( password )
6162 return false if encrypted_password . blank?
6263
63- # only if feature enabled? then we do the work here
64- if encryptor_validation_enabled? && encrypted_password_migrate_to . present?
64+ if valid_encryptor_hash?
6565 valid_password_using_encryptor? ( password )
6666 else
6767 result = super
68- update_encrypted_password_migrate_to ( password ) if result && encrypted_password_migrate_to . nil?
68+ update_encrypted_password_hash ( password ) if result
6969 result
7070 end
7171 end
7272
73+ def valid_encryptor_hash?
74+ encryptor_class . valid_hash? ( encrypted_password )
75+ end
76+
7377 # redefine serializable_hash to prevent encrypted_password_migrate_to leaking
7478 def serializable_hash ( options = { } )
7579 options [ :except ] ||= [ ]
@@ -79,12 +83,17 @@ def serializable_hash(options = {})
7983
8084 protected
8185
82- def update_encrypted_password_migrate_to ( password )
86+ def password_digest ( password )
87+ override_existing_password_hash_enabled? ? generate_digest_for_password ( password ) : super
88+ end
89+
90+ def update_encrypted_password_hash ( password )
8391 return if new_record?
8492
85- update_column ( :encrypted_password_migrate_to , generate_digest_for_password ( password ) )
93+ column_name = override_existing_password_hash_enabled? ? :encrypted_password : :encrypted_password_migrate_to
94+ update_column ( column_name , generate_digest_for_password ( password ) )
8695 rescue StandardError => e # capture StandardError instead of ActiveRecordError to play safe
87- log_error ( ' Failed to update_column encrypted_password_migrate_to' , e )
96+ log_error ( " Failed to update_column #{ column_name } " , e )
8897 end
8998
9099 def generate_digest_for_password ( password )
@@ -94,13 +103,13 @@ def generate_digest_for_password(password)
94103 self . class . pepper )
95104 end
96105
97- def encryptor_validation_enabled ?
98- self . class . enable_validation &.call ( self )
106+ def override_existing_password_hash_enabled ?
107+ self . class . override_existing_password_hash &.call ( self )
99108 end
100109
101110 def valid_password_using_encryptor? ( password )
102111 encryptor_arguments = [
103- encrypted_password_migrate_to ,
112+ encrypted_password ,
104113 password ,
105114 self . class . stretches ,
106115 self . class . password_salt ,
@@ -119,7 +128,7 @@ def encryptor_class
119128
120129 # class method get injected into Devise module
121130 module ClassMethods
122- Devise ::Models . config ( self , :encryptor , :enable_validation )
131+ Devise ::Models . config ( self , :encryptor , :override_existing_password_hash )
123132
124133 # Returns the class for the configured encryptor.
125134 def encryptor_class
@@ -135,9 +144,9 @@ def password_salt
135144 def compute_encryptor_class ( encryptor )
136145 case encryptor
137146 when :bcrypt
138- raise 'In order to use bcrypt as encryptor, simply remove :encryptable from your devise model'
147+ raise 'In order to use bcrypt as encryptor, simply remove :migratable from your devise model'
139148 when nil
140- raise 'You need to give an :encryptor as option in order to use :encryptable '
149+ raise 'You need to give an :encryptor as option in order to use :migratable '
141150 else
142151 Devise ::Migratable ::Encryptors . const_get ( encryptor . to_s . classify )
143152 end
0 commit comments