Bug in acts_as_authenticated
I found a bug in the acts_as_authenticated plugin. The activate method in User fails to update the user record when using both activate and 2-way reversible encryption. The symptom that I was is that @user.save was false in the controller.
It fails at this line:
update_attributes(:activated_at => Time.now.utc, :activation_code => nil)
This fails because there are a series of validations on saving the model. These on save validations on password_confirmation work (assuming correct values) when the user is created and when the password is changed, but fail on other saves of the user, particularly on activation, but would also fail if acts_as_authenticated had an edit method, or a last_seen method, or any other method that changed the user without also changing the password with a confirmation.
The rails wiki has a proposed fix, which works for activate only if not also using 2-way reversible encryption. The fix causes these validations to be attempted only if password_required, which in turn tests if password.blank? is false.
Two-way reversible encryption populates the model with the value of password, so that password.blank? is always false and password_required is always true.
I resolved the problem in acts_as_authenticated by making the following changes:
validates_presence_of :password_confirmation,
:if => :confirmation_required? # not :password_required
validates_confirmation_of :password,
:if => :confirmation_required? #ditto
And then I added the following:
after_save '@confirm_password = false'
def initialize(attributes = nil)
super
@confirm_password = true
end
def change_password(pass, confirm = nil)
self.password = pass
self.password_confirmation = confirm.nil? ? pass : confirm
@confirm_password = true
end
protected
def confirmation_required?
@confirm_password
end
Hope that helps.
- Posted February 21, 2006 in: Ruby on Rails
- 1 comment | email this | tag this | digg this
Taryn East | May 25, 2007 | Reply
I had a similar issue with that line failing validations. Can’t remember what set it off (I doubt it was two-way encryption).
I resolved it by separating the “update_attributes” call into two update_attribute calls. That bypasses the validations.