diff options
author | Unathi Chonco <choncou@Unathis-MacBook-Pro.local> | 2016-10-12 09:01:57 +0800 |
---|---|---|
committer | Unathi Chonco <choncou@Unathis-MacBook-Pro.local> | 2016-10-12 09:01:57 +0800 |
commit | 9b63bf1dfda36c61802165b2683761d2bb0d2110 (patch) | |
tree | 0744ede2fb6aca01e23af43a7b17c96249ad79b2 | |
parent | 86a48b4da3cbd925d30b0fbe472edbda7171ea9e (diff) | |
download | rails-9b63bf1dfda36c61802165b2683761d2bb0d2110.tar.gz rails-9b63bf1dfda36c61802165b2683761d2bb0d2110.tar.bz2 rails-9b63bf1dfda36c61802165b2683761d2bb0d2110.zip |
Remove method for regenerating a token, and update `#authenticate`.
This change now creates a method `#authenticate_XXX` where XXX is
the configured attribute name on `#has_secure_password`. `#authenticate`
is now an alias to this method when the attribute name is the default
'password'
-rw-r--r-- | activemodel/CHANGELOG.md | 17 | ||||
-rw-r--r-- | activemodel/lib/active_model/secure_password.rb | 56 | ||||
-rw-r--r-- | activemodel/test/cases/secure_password_test.rb | 13 |
3 files changed, 25 insertions, 61 deletions
diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 0721655a9c..21ebe7e9ec 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,21 +1,18 @@ * Allows configurable attribute name for `#has_secure_password`. This still defaults to an attribute named 'password', causing no breaking - change. Also includes a convenience method `#regenerate_XXX` where - +XXX+ is the name of the custom attribute name, eg: + change. There is a new method `#authenticate_XXX` where XXX is the + configured attribute name, making the existing `#authenticate` now an + alias for this when the attribute is the default 'password'. + Example: class User < ActiveRecord::Base has_secure_password :activation_token, validations: false end user = User.new() - user.regenerate_activation_token - user.activation_token # => "ME7abXFGvzZWJRVrD6Et0YqAS6Pg2eDo" - user.activation_token_digest # => "$2a$10$0Budk0Fi/k2CDm2PEwa3Be..." - - The existing `#authenticate` method now allows specifying the attribute - to be authenticated, but defaults to 'password', eg: - - user.authenticate('ME7abXFGvzZWJRVrD6Et0YqAS6Pg2eDo', :activation_token) # => user + user.activation_token = "a_new_token" + user.activation_token_digest # => "$2a$10$0Budk0Fi/k2CDm2PEwa3Be..." + user.authenticate_activation_token('a_new_token') # => user *Unathi Chonco* diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index 5c7322698a..0172ddc97e 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -48,15 +48,14 @@ module ActiveModel # user.save # => false, confirmation doesn't match # user.password_confirmation = 'mUc3m00RsqyRe' # user.save # => true - # user.regenerate_activation_token - # user.activation_token # => "ME7abXFGvzZWJRVrD6Et0YqAS6Pg2eDo" + # user.activation_token = "a_new_token" # user.activation_token_digest # => "$2a$10$0Budk0Fi/k2CDm2PEwa3BeXO5tPOA85b6xazE9rp8nF2MIJlsUik." # user.save # => true # user.authenticate('notright') # => false # user.authenticate('mUc3m00RsqyRe') # => user + # user.authenticate_activation_token('a_new_token') # => user # User.find_by(name: 'david').try(:authenticate, 'notright') # => false # User.find_by(name: 'david').try(:authenticate, 'mUc3m00RsqyRe') # => user - # user.authenticate('ME7abXFGvzZWJRVrD6Et0YqAS6Pg2eDo', :activation_token) # => user def has_secure_password(attribute = :password, validations: true) # Load bcrypt gem only when has_secure_password is used. # This is to avoid ActiveModel (and by extension the entire framework) @@ -70,18 +69,6 @@ module ActiveModel attr_reader attribute - # Encrypts the password into the +password_digest+ attribute, only if the - # new password is not empty. - # - # class User < ActiveRecord::Base - # has_secure_password validations: false - # end - # - # user = User.new - # user.password = nil - # user.password_digest # => nil - # user.password = 'mUc3m00RsqyRe' - # user.password_digest # => "$2a$10$4LEA7r4YmNHtvlAvHhsYAeZmk/xeUVtMTYqwIvYY76EW5GUqDiP4." define_method("#{attribute}=") do |unencrypted_password| if unencrypted_password.nil? self.send("#{attribute}_digest=", nil) @@ -96,11 +83,22 @@ module ActiveModel instance_variable_set("@#{attribute}_confirmation", unencrypted_password) end - define_method("regenerate_#{attribute}") do - self.send("#{attribute}=", self.class.generate_unique_secure_token) + # 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 - include InstanceMethodsOnActivation + alias_method :authenticate, :authenticate_password if attribute == :password if validations include ActiveModel::Validations @@ -117,28 +115,6 @@ module ActiveModel validates_confirmation_of attribute, allow_blank: true end end - - # SecureRandom::base64 is used to generate a 24-character unique token, so collisions are highly unlikely. - def generate_unique_secure_token - SecureRandom.base64(24) - end - end - - module InstanceMethodsOnActivation - # 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('notright') # => false - # user.authenticate('mUc3m00RsqyRe') # => user - def authenticate(unencrypted_password, attribute = :password) - attribute_digest = send("#{attribute}_digest") - BCrypt::Password.new(attribute_digest).is_password?(unencrypted_password) && self - end end end end diff --git a/activemodel/test/cases/secure_password_test.rb b/activemodel/test/cases/secure_password_test.rb index abbd182f66..279a908aeb 100644 --- a/activemodel/test/cases/secure_password_test.rb +++ b/activemodel/test/cases/secure_password_test.rb @@ -189,8 +189,8 @@ class SecurePasswordTest < ActiveModel::TestCase assert !@user.authenticate("wrong") assert @user.authenticate("secret") - assert !@user.authenticate("wrong", :activation_token) - assert @user.authenticate("new_token", :activation_token) + assert !@user.authenticate_activation_token("wrong") + assert @user.authenticate_activation_token("new_token") end test "Password digest cost defaults to bcrypt default cost when min_cost is false" do @@ -219,13 +219,4 @@ class SecurePasswordTest < ActiveModel::TestCase @user.password = "secret" assert_equal BCrypt::Engine::MIN_COST, @user.password_digest.cost end - - test "regenerate attribute method" do - old_digest = @user.activation_token_digest - @user.regenerate_activation_token - - assert_not_nil @user.activation_token - assert_not_nil @user.activation_token_digest - assert_not_equal old_digest, @user.activation_token_digest - end end |