I'm using has_secure_password in a User model. I have implemented a way for users to change their password outside of the model, but to keep things DRY, I'm trying to move the validations needed from the controller to the model.
The User model looks something like this:
class User
include Mongoid::Document
include ActiveModel::SecurePassword
has_secure_password
field: :password_digest, type: String
attr_accessible :password, :password_confirmation, :current_password
end
Users change their passwords by submitting the following:
user[current_password] - Currently stored password
user[password] - New password
user[password_confirmation] - New password confirmation
I'm using update_attributes(params[:user]) on the User model for the current user. My problem is that calling update_attributes updates the password_digest before using validations, so the following code won't work:
def password_validation_required?
password_digest.blank? || !password.blank? || !password_confirmation.blank?
end
validate(on: :update, if: :password_validation_required?) do
unless authenticate(current_password)
add(:current_password, 'invalid password')
end
end
authenticate is authenticating based on the new password_digest generated from user[password]. Is there an elegant way to access the old password_digest value for authentication? One idea I had was to re-query the user to gain access to another authenticate method that will authenticate against the old password_digest value. The problem is that it's not a clean solution.
password=api.rubyonrails.org/classes/ActiveModel/SecurePassword/… - apneadivingpassword=is that I'd have to add a lot of logic inside of it which would prevent future features needing to usepassword=(such asuser.password = ...in some administration feature) - Parazucebefore_save, or ... see answer - apneadiving