Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix regression in has_secure_password. #10694

Merged
merged 1 commit into from May 30, 2013

Conversation

steveklabnik
Copy link
Member

If the confirmation was blank, but the password wasn't, it would still save.

Sent via a PR for feedback. Password stuff is tricky.

/cc @josevalim, @senny

@senny
Copy link
Member

senny commented May 20, 2013

thanks Steve!


@user.password = "password"
@user.password_confirmation = ""
refute @user.valid?(:create)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't use refute in the rails code base. You can use assert_not

=> https://github.com/rails/rails/blob/master/activesupport/lib/active_support/test_case.rb#L60-L74

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I get for porting an rspec test over. ;)

@steveklabnik
Copy link
Member Author

@senny you can thank the readers of "Rails 4 in Action" :)

@@ -106,7 +106,8 @@ def password=(unencrypted_password)
end

def password_confirmation=(unencrypted_password)
unless unencrypted_password.blank?
@password ||= nil # prevent warnings about undefined ivar
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should it to nil on initialization? Or we simply should not access the instance variable directly and use self.password instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changing it to self.password fails the test, actually.

@josevalim
Copy link
Contributor

❤️ 💚 💙 💛 💜

@steveklabnik
Copy link
Member Author

Uhhhh, so this isn't actually working right now. Unsure what's up.

@steveklabnik
Copy link
Member Author

Please review again, @josevalim @senny @rafaelfranca <3

@raykrueger
Copy link

I was just going to start working on a fix for that, glad I searched issues first! I'd been banging my head on this for a bit thinking I did something wrong heh. Thanks for all your work Steve.

@rafaelfranca
Copy link
Member

:shipit:

@steveklabnik
Copy link
Member Author

CHANGELOG added.

Ugh, so last minute checks, there is one other test failing:

ConfirmationValidationTest#test_no_title_confirmation [/home/pairing/rails/activemodel/test/cases/validations/confirmation_validation_test.rb:24]:
Failed assertion, no message given.

Unsure what that is right this second.

@@ -3,7 +3,9 @@ module ActiveModel
module Validations
class ConfirmationValidator < EachValidator # :nodoc:
def validate_each(record, attribute, value)
if (confirmed = record.send("#{attribute}_confirmation")) && (value != confirmed)
confirmed = record.send("#{attribute}_confirmation")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't make the changes to the confirmation validator unless we have very good reasons too. I don't feel we should be converting them too strings. What if one value is a float and the other is an integer? I am not sure anybody is relying on this use case but it would be a breaking change.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with this bug is that it's in the validator, not the setter, which is what changed last time.

Converting to strings was a way I saw to get around the case of nil vs "" being acceptable, but I'm not super happy with it either.

@josevalim
Copy link
Contributor

@steveklabnik have you tried fixing this issue by just running the confirmation validation if the password is present? Basically, replacing this line:

https://github.com/rails/rails/blob/master/activemodel/lib/active_model/secure_password.rb#L59

By something like:

validates_confirmation_of :password, if: lambda { |m| m.password.present? }

@steveklabnik
Copy link
Member Author

I have not. Let me try that now, that seems simpler, thanks.

@steveklabnik
Copy link
Member Author

Updated trying that method (but a different conditional, since that one isn't right), but it still fails:

SecurePasswordTest#test_will_not_save_if_confirmation_is_blank_but_password_is_not [/Users/steve/src/rails/activemodel/test/cases/secure_password_test.rb:101]:
Expected true to be nil or false

Still not sure. This bug makes me feel stupid, it should be so easy.

@steveklabnik
Copy link
Member Author

Thanks to help from @pnc, this now works.

:shipit: ?

Also, this should get backported to 4-0-stable and 4-0-0, I think?

@rafaelfranca
Copy link
Member

Yes. It should.

Seems good to me. @josevalim?

If the confirmation was blank, but the password wasn't, it would still save.
steveklabnik added a commit that referenced this pull request May 30, 2013
Fix regression in has_secure_password.
@steveklabnik steveklabnik merged commit 87f3eb6 into rails:master May 30, 2013
@steveklabnik
Copy link
Member Author

:shipit:

@steveklabnik
Copy link
Member Author

In 4-0-0 as b965ce3 and in 4-0-stable as 4e76051.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants