I use Grails 2.0.0.RC2 and I have an User class like this:
class User {
String username
String password
// Idea from http://grailsrecipes.wordpress.com/2009/04/19/grails-user-registration-and-login/ .
String formPassword
String formPasswordConfirm
// Constraints and validation ommited
static transients = ['formPassword', 'formPasswordConfirm']
def beforeUpdate() {
println("Inside beforeUpdate")
if (formPassword != null)
encodePassword()
}
protected void encodePassword() {
password = formPassword // Just for this case
}
}
When user asks for his password reset, I send him email with a link to reset password page. Reset password form is simple – it contains only two fields: formPassword and formPasswordConfirm. I do a simple action in controller: user.formPassword = params["formPassword"] and user.formPasswordConfirm = params["formPasswordConfirm"]. Then I do (user.save()) – and problem begins.
My problem is that beforeUpdate() is not called. I thought it was a validation problem (it’s omiited here), but it’s not. As it turns out user.save() didn’t persist user to database! Why? I wanted it to be persisted, password should be changed. But user.isDirty() is false just before user.save(). That’s because none of persistent properties were changed. That’s true. Since user.save() wasn’t called – beforeUpdate() wasn’t called either.
Is this desired behaviour? Maybe it’s a Grails bug and beforeUpdate() should be always called before update and then isDirty() should be checked? What do you think?
I don’t know if
beforeUpdateshould be called when transient fields are updated, but given the choice betweenI would bet a lot of money on 2, and very little on 1.
So leaving that aside, I think you’ve made your domain class a bit more complicated that it needs to be. Specifically, you should be able to achieve your goal with 2 password fields instead of 3.
Your reset password controller action should look like this: