aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2019-04-05 01:43:41 +0900
committerRyuta Kamizono <kamipo@gmail.com>2019-04-05 01:55:00 +0900
commit50fba828d533ff75671ca8b83337dd99aa613ff7 (patch)
treeae63103d3a690fe63f34271851d9b23dadf9c5aa /activemodel
parentdc45130c44ebe0d8b621eba29332b35ea2840738 (diff)
downloadrails-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.rb74
-rw-r--r--activemodel/test/cases/secure_password_test.rb14
-rw-r--r--activemodel/test/models/user.rb7
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