diff options
author | Ryuta Kamizono <kamipo@gmail.com> | 2019-04-05 01:43:41 +0900 |
---|---|---|
committer | Ryuta Kamizono <kamipo@gmail.com> | 2019-04-05 01:55:00 +0900 |
commit | 50fba828d533ff75671ca8b83337dd99aa613ff7 (patch) | |
tree | ae63103d3a690fe63f34271851d9b23dadf9c5aa /activemodel | |
parent | dc45130c44ebe0d8b621eba29332b35ea2840738 (diff) | |
download | rails-50fba828d533ff75671ca8b83337dd99aa613ff7.tar.gz rails-50fba828d533ff75671ca8b83337dd99aa613ff7.tar.bz2 rails-50fba828d533ff75671ca8b83337dd99aa613ff7.zip |
Refactor `has_secure_password` to extract dedicated attribute module
Follow up of #26764 and #35700.
And add test case for #35700.
Diffstat (limited to 'activemodel')
-rw-r--r-- | activemodel/lib/active_model/secure_password.rb | 74 | ||||
-rw-r--r-- | activemodel/test/cases/secure_password_test.rb | 14 | ||||
-rw-r--r-- | activemodel/test/models/user.rb | 7 |
3 files changed, 59 insertions, 36 deletions
diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index cc1368d3a0..5f409326bd 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -69,42 +69,7 @@ module ActiveModel raise end - mod = Module.new do - attr_reader attribute - - define_method("#{attribute}=") do |unencrypted_password| - if unencrypted_password.nil? - self.send("#{attribute}_digest=", nil) - elsif !unencrypted_password.empty? - instance_variable_set("@#{attribute}", unencrypted_password) - cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost - self.send("#{attribute}_digest=", BCrypt::Password.create(unencrypted_password, cost: cost)) - end - end - - define_method("#{attribute}_confirmation=") do |unencrypted_password| - instance_variable_set("@#{attribute}_confirmation", unencrypted_password) - end - - # Returns +self+ if the password is correct, otherwise +false+. - # - # class User < ActiveRecord::Base - # has_secure_password validations: false - # end - # - # user = User.new(name: 'david', password: 'mUc3m00RsqyRe') - # user.save - # user.authenticate_password('notright') # => false - # user.authenticate_password('mUc3m00RsqyRe') # => user - define_method("authenticate_#{attribute}") do |unencrypted_password| - attribute_digest = send("#{attribute}_digest") - BCrypt::Password.new(attribute_digest).is_password?(unencrypted_password) && self - end - - alias_method :authenticate, :authenticate_password if attribute == :password - end - - include mod + include InstanceMethodsOnActivation.new(attribute) if validations include ActiveModel::Validations @@ -122,5 +87,42 @@ module ActiveModel end end end + + class InstanceMethodsOnActivation < Module + def initialize(attribute) + attr_reader attribute + + define_method("#{attribute}=") do |unencrypted_password| + if unencrypted_password.nil? + self.send("#{attribute}_digest=", nil) + elsif !unencrypted_password.empty? + instance_variable_set("@#{attribute}", unencrypted_password) + cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost + self.send("#{attribute}_digest=", BCrypt::Password.create(unencrypted_password, cost: cost)) + end + end + + define_method("#{attribute}_confirmation=") do |unencrypted_password| + instance_variable_set("@#{attribute}_confirmation", unencrypted_password) + end + + # Returns +self+ if the password is correct, otherwise +false+. + # + # class User < ActiveRecord::Base + # has_secure_password validations: false + # end + # + # user = User.new(name: 'david', password: 'mUc3m00RsqyRe') + # user.save + # user.authenticate_password('notright') # => false + # user.authenticate_password('mUc3m00RsqyRe') # => user + define_method("authenticate_#{attribute}") do |unencrypted_password| + attribute_digest = send("#{attribute}_digest") + BCrypt::Password.new(attribute_digest).is_password?(unencrypted_password) && self + end + + alias_method :authenticate, :authenticate_password if attribute == :password + end + end end end diff --git a/activemodel/test/cases/secure_password_test.rb b/activemodel/test/cases/secure_password_test.rb index bbf443290b..0aca714bd2 100644 --- a/activemodel/test/cases/secure_password_test.rb +++ b/activemodel/test/cases/secure_password_test.rb @@ -184,6 +184,20 @@ class SecurePasswordTest < ActiveModel::TestCase assert_nil @existing_user.password_digest end + test "override secure password attribute" do + assert_nil @user.password_called + + @user.password = "secret" + + assert_equal "secret", @user.password + assert_equal 1, @user.password_called + + @user.password = "terces" + + assert_equal "terces", @user.password + assert_equal 2, @user.password_called + end + test "authenticate" do @user.password = "secret" @user.recovery_password = "42password" diff --git a/activemodel/test/models/user.rb b/activemodel/test/models/user.rb index bb1b187694..fc4a9e4334 100644 --- a/activemodel/test/models/user.rb +++ b/activemodel/test/models/user.rb @@ -10,4 +10,11 @@ class User has_secure_password :recovery_password, validations: false attr_accessor :password_digest, :recovery_password_digest + attr_accessor :password_called + + def password=(unencrypted_password) + self.password_called ||= 0 + self.password_called += 1 + super + end end |