From b1a5252a36d1c657d8eda69b1aa22f7a45f6e572 Mon Sep 17 00:00:00 2001 From: Matthew Daubert Date: Mon, 25 Apr 2011 08:59:37 -0400 Subject: [PATCH 1/2] Added support for required configuration parameter --- activemodel/lib/active_model/secure_password.rb | 19 ++++++++++++++----- activemodel/test/cases/secure_password_test.rb | 13 +++++++++++++ activemodel/test/models/user.rb | 2 +- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb index ee94ad6..8b202ef 100644 --- a/activemodel/lib/active_model/secure_password.rb +++ b/activemodel/lib/active_model/secure_password.rb @@ -29,11 +29,18 @@ module ActiveModel # user.authenticate("mUc3m00RsqyRe") # => user # User.find_by_name("david").try(:authenticate, "notright") # => nil # User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user - def has_secure_password + # + # Configuration options: + # * :required - Validates presence of password otherwise allow blank or nil (default is true). + def has_secure_password(options={}) + options.reverse_merge! :required => true + attr_reader :password validates_confirmation_of :password - validates_presence_of :password_digest + if options[:required] + validates_presence_of :password_digest + end include InstanceMethodsOnActivation @@ -46,9 +53,9 @@ module ActiveModel end module InstanceMethodsOnActivation - # Returns self if the password is correct, otherwise false. + # Returns self if a password is set and the password is correct, otherwise false. def authenticate(unencrypted_password) - if BCrypt::Password.new(password_digest) == unencrypted_password + if password_digest && BCrypt::Password.new(password_digest) == unencrypted_password self else false @@ -58,7 +65,9 @@ module ActiveModel # Encrypts the password into the password_digest attribute. def password=(unencrypted_password) @password = unencrypted_password - unless unencrypted_password.blank? + if unencrypted_password.blank? + self.password_digest = nil + else self.password_digest = BCrypt::Password.create(unencrypted_password) end end diff --git a/activemodel/test/cases/secure_password_test.rb b/activemodel/test/cases/secure_password_test.rb index 6950c3b..f286bd2 100644 --- a/activemodel/test/cases/secure_password_test.rb +++ b/activemodel/test/cases/secure_password_test.rb @@ -1,5 +1,6 @@ require 'cases/helper' require 'models/user' +require 'models/user_with_optional_password' require 'models/visitor' require 'models/administrator' @@ -7,18 +8,26 @@ class SecurePasswordTest < ActiveModel::TestCase setup do @user = User.new + @user_no_password = UserWithOptionalPassword.new end test "blank password" do user = User.new user.password = '' assert !user.valid?, 'user should be invalid' + user = UserWithOptionalPassword.new + user.password = '' + assert user.valid?, 'user should be valid' end test "nil password" do user = User.new user.password = nil assert !user.valid?, 'user should be invalid' + user = UserWithOptionalPassword.new + user.password = nil + assert user.valid?, 'user should be valid' + assert user.password_digest.nil?, 'password_digest should be nil' end test "password must be present" do @@ -42,6 +51,10 @@ class SecurePasswordTest < ActiveModel::TestCase assert !@user.authenticate("wrong") assert @user.authenticate("secret") + + @user_no_password.password = "" + + assert !@user_no_password.authenticate("") end test "visitor#password_digest should be protected against mass assignment" do diff --git a/activemodel/test/models/user.rb b/activemodel/test/models/user.rb index e221bb8..0736fe0 100644 --- a/activemodel/test/models/user.rb +++ b/activemodel/test/models/user.rb @@ -4,5 +4,5 @@ class User has_secure_password - attr_accessor :password_digest, :password_salt + attr_accessor :password_digest end -- 1.7.2.3 From e8504addf569ae8b27adaf72ffdb1a885156df26 Mon Sep 17 00:00:00 2001 From: Matthew Daubert Date: Mon, 25 Apr 2011 08:59:52 -0400 Subject: [PATCH 2/2] Added support for required configuration parameter --- .../test/models/user_with_optional_password.rb | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) create mode 100644 activemodel/test/models/user_with_optional_password.rb diff --git a/activemodel/test/models/user_with_optional_password.rb b/activemodel/test/models/user_with_optional_password.rb new file mode 100644 index 0000000..d4a3b66 --- /dev/null +++ b/activemodel/test/models/user_with_optional_password.rb @@ -0,0 +1,8 @@ +class UserWithOptionalPassword + include ActiveModel::Validations + include ActiveModel::SecurePassword + + has_secure_password :required => false + + attr_accessor :password_digest +end -- 1.7.2.3