Thursday, May 1, 2008

Password validation in Grails on user domain class

If using Grails to create a web site there are many tricks to be learned. This one concerns password validation. In any sane website you ask a user twice for their password. That way you can compare the two to make sure the user entered the password correctly. In Grails domain classes use a nice little DSL for validation. You will probably want to leverage this when validating a user's password. Here is an arbitrary user domain class:


class User {

String userId

String password

String password2

String email

static constraints = {
password(blank: false, nullable: false, size:5..20, validator: {password, obj ->
def password2 = obj.properties['password2']
if(password2 == null) return true // skip matching password validation (only important when setting/resetting pass)
password2 == password ? true : ['invalid.matchingpasswords']
})
}

static transients = ['password2']
}


Notice password2 property is a 'transient' property. This means it will not be included in the database model or object relational mapping of GORM. The other trick here is the custom validator closure in the constraints for the password field. The way this validator works is if password2 property is not null compare it with password, if they do not equal return the error code 'invalid.matchingpasswords'.

In this case you could add the error code user.password.invalid.matchingpasswords in the messages.properties file in 'grails-app/i18n' folder of your project. Do this like normal Java properties:

user.password.invalid.matchingpasswords=uh oh the passwords you entered do not match

Now in cases where password2 is not being used it will be null. This will prevent the validator from doing the test of password vs. password2. This is important if you have forms which update the other fields on your user class while not updating the password field. With out this check for null you would have many troubles saving user instances due to this validation. Note this trick it could be useful to you many times over!

To finish this little exercise off check out this little bit of controller code:


class UsersController {

def create = {
// maybe pass some models into template?
}

def save = {
def user = new User(params) // password, password2 set from form?
if(user.save())
{
flash.message = "user '${user.userId}' added"
redirect(action:create)
}
else
{
flash.message = "error(s) creating user"
render(view:"create",model:[user:user])
}
}
}


When creating the new User object we pass params to the constructor. This will cause the form parameters to bind to the User object's properties. See the data binding section of the Grails reference documentation. If password2 was a form field then it is auto magically set on the new User object. When we call save a few lines later this value will be compared with the 'password' property, voila!