On Feb 25, 2015, at 3:07 AM, Paul Hoadley <[email protected]> wrote:

> Hello,
> 
> I have a User entity with a password attribute that contains a BCrypt-hashed 
> password.  So User has setPassword() and password() methods, and also cover 
> methods setPlaintextPassword() that does the hashing (and then calls 
> setPassword()) and plaintextPassword() that returns null.  It works fine.


Not to get all over your case about it, but how would you ever return a 
plaintextPassword() from a one way hash? That indicates to me you are storing 
the plain password somewhere when you probably shouldn’t.


> There are a couple of things that I would normally do at the application 
> level that I thought might be reasonably moved down to the regular validation 
> system, but it doesn't seem straightforward.  


WOComponent implements NSValidation. It’s okay to do validateKey methods in the 
component when that makes sense :-)


> 1.  Changing the password.  A method User.changePassword(String oldPassword, 
> String newPassword, String confirmPassword) would take those form values and 
> do the obvious: change the password if oldPassword hashes correctly and 
> newPassword == confirmPassword.


To me, this doesn’t seem like model logic. I would implement this in a custom 
component especially for editing passwords.


> 2.  Validate the plaintext password (say, is it long enough).  This could be 
> done in setPlaintextPassword().


Yeah, that makes sense.


> What I'd like is for it all to be part of the validation system, such that 
> when saveChanges() is called, validateForSave() throws appropriate exceptions 
> and messages could be sent to the view layer.  But it's a bit hairy.  
> Consider just setPlaintextPassword().  Say the supplied string is too short 
> and it fails the password length test.  My naive solution was to create the 
> ValidationException, but hang onto it until saveChanges() is called—but, and 
> you can see where this is leading, validateForSave() doesn't get called 
> unless the password is actually changed (assuming nothing else on the User is 
> changed), so I don't get to throw that exception I stashed earlier.  In that 
> case I might be able to make the change to the too-short string, and do what 
> I was planning, but the changePassword() method is another story.

While WOComponents can have validateKey methods, what you want to do here is 
validate two values: newPass1, newPass2. That’s something you’d typically do in 
a validateFor method. But that’s EOValidation interface, and WOComponents don’t 
do that. In this case, what I would do (did) is compare these values in 
takeValuesFromRequest on the component and if they are mismatched/empty then 
create a validation exception and pass it to validationFailedWithException 
there.


> Say changePassword() is called, but oldPassword doesn't hash correctly.  Now 
> what? Do I call setPlaintextPassword(newPassword) anyway to ensure 
> validateForSave() is called?  But then in that method, I throw the exception 
> I stashed, sure, but the password has now _changed_ even though the app 
> reports it _hasn't_.  So a subsequent call to changePassword() with the 
> previous oldPassword value is going to fail.  Again, naively, I considered 
> maybe changing it _back_ to the snapshot value for that attribute in 
> validateForSave() before throwing the exception, but then BAM!  EOF 
> Commandment #4:
> 
>> Don't modify any EO properties in validateFor...(...) methods
> 
> So I'm stumped.  Does this sound possible, or should I give up and continue 
> to handle this kind of thing outside the regular validation system?


If you’d like, have a look at my implementation:

https://github.com/nullterminated/ponder/blob/master/ERAuth/Sources/er/auth/components/ERAEditPassword.java

https://github.com/nullterminated/ponder/blob/master/ERUsers/Sources/er/users/model/ERUser.java


> 
> 
> -- 
> Paul Hoadley
> http://logicsquad.net/
> 


 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list      ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/webobjects-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to