Validate new passwords with ORM and ValidateThis
My new project is using CF9’s ORM, FW/1 and ValidateThis, all for the first time – so naturally I’m having to work a few things out. There will probably be a few posts like this one over the next few weeks…
I have a user edit page, on which you can edit your personal details and change your password. It’s set up something like this:
user.cfc
component output="false" persistent="true"
{
// identifier
property name="userid" fieldtype="id";
// properties
property name="firstname";
property name="lastname";
property name="uuid";
property name="password";
}
user.xml (ValidateThis rules)
<?xml version="1.0" encoding="UTF-8"?>
<validateThis xsi:noNamespaceSchemaLocation="http://www.validatethis.org/validateThis.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<objectProperties>
<property name="firstname" desc="First name">
<rule type="required" />
</property>
<property name="lastname" desc="Last name">
<rule type="required" />
</property>
</objectProperties>
</validateThis>
…and the (simplified) code to run the validation:
user = variables.userService.get( rc.userID );
user.setFirstName( rc.firstname );
user.setLastName( rc.lastname );
result = application.ValidateThis.validate( user );
if ( result.hasErrors() ) {
// show error messages
} else {
// save user
}
Which is all well and good, but the problem comes with the password. My user object has a password field which stores a hash of the user’s password and uuid. The update form has two fields, newpassword1 and newpassword2, which have to match in order to set the password. But these are not persisted values; they are only used to set the actual persisted password value. So how to make them part of the user object so it can be validated in one easy command using ValidateThis?
The answer is simple, and will apply to other situations as well. All the persisted values in the user object are set up using properties, and so also get the auto-generated getters and setters. But if we add a couple of explicit getters and setters for our non-persisted values, ValidateThis will be able to access the values from the object, but they will not be a part of the persisted data. So our new user.cfc object will look like this:
component output="false" persistent="true"
{
// identifier
property name="userid" fieldtype="id";
// properties
property name="firstname";
property name="lastname";
property name="uuid";
property name="password";
variables.newpassword1 = "";
variables.newpassword2 = "";
function getVariables() {
return variables;
}
function setNewPassword1(string newpassword1) {
variables.newpassword1 = newpassword1;
}
function getNewPassword1() {
return variables.newpassword1;
}
function setNewPassword2(string newpassword2) {
variables.newpassword2 = newpassword2;
}
function getNewPassword2() {
return variables.newpassword2;
}
function updatePassword() {
setPassword( hash( getNewPassword1() & getUUID() ) );
}
}
And we can add the following rules to our user.xml (in the real code we would probably make newpassword1 required only under certain contexts, such as the initial user creation):
<property name="newpassword1" desc="New password">
<rule type="required" />
</property>
<property name="newpassword2" desc="New password confirmation">
<rule type="equalTo" failureMessage="Please make sure your passwords match">
<param DependentPropertyName="newpassword1" />
<param ComparePropertyName="newpassword1" />
</rule>
</property>
And then, when the user validates successfully, we simply call the updatePassword() method before persisting the object, and it will be updated with the new hashed password:
user = variables.userService.get( rc.userID );
user.setFirstName( rc.firstname );
user.setLastName( rc.lastname );
user.setNewPassword1( rc.newpassword1 );
user.setNewPassword2( rc.newpassword2 );
result = application.ValidateThis.validate( user );
if ( result.hasErrors() ) {
// show error messages
} else {
user.updatePassword();
// save user
}
I hope this is useful to others who are just starting to use these technologies…