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…

4 comments Posted on 15 August, 2010, in ColdFusion, ORM, ValidateThis

ORM gotcha: Hibernate reserved words

Typically, the very first time I tried to use CF9’s ORM, I ran into a bizarre problem which had me scratching my head for hours…

The setup was this: a table in my SQL database called “member”. A member.cfc object with the following code:

component  output="false" persistent="true"
{
	property name="memberid" fieldtype="id"; 
	property name="firstname";
	property name="lastname";  
}

And a test page which called it:

<cfscript>
members = EntityLoad("member");
writedump(members);
</cfscript>

Running this page always gave the following error:

unexpected token: member near line 1, column 6 [from member]

However, if I gave the EntityLoad() function more arguments, for instance:

members = EntityLoad("member", {});

…it worked perfectly.

After a lot of head-scratching and seeking of help on Twitter (thanks @aliaspooryorik) and Stack Overflow (thanks Henry), I had the idea that “member” might be some sort of reserved word in Hibernate. So I changed the table and component names to “user” – and everything worked exactly as it should.

My guess is that it works fine if in the generated HQL query there’s a WHERE clause following the “SELECT FROM member”; but if you just have the basic EntityLoad(”member”) then it doesn’t have this WHERE clause, and so the reserved word “member” gets seen as an HQL keyword.

I guess I was just unlucky that my very first attempt at ORM ran into this problem; does anyone know of any other table/object names I should steer clear of?

3 comments Posted on 13 August, 2010, in ColdFusion, ORM

Mura plugin: Impersonate User

One feature that is missing from Mura’s site member tools is the ability for an administrator to log in to the site as a particular user.

So I hacked together a very quick tool which will allow you to do just that.

Once installed, go to the plugins page for your site, and click on the name of the Impersonate User plugin.

You’ll then get a form in which you can enter either a UserID (a UUID) or a username. Click the button, and you’ll be immediately logged out of the admin, logged in as the requested user, and directed to the site’s home page.

You can now see the site exactly as that user would, even though you don’t know what their password is…

You can find the source code on the plugin’s github repository, and you can download the plugin here.

No comments Posted on 15 April, 2010, in ColdFusion, Mura CMS

Using GitHub Gists to render source code

I’m curently toying with the idea of using GitHub Gists for all my code snippet rendering here on my site (and perhaps elsewhere).

However, I’m struggling to weigh up the pros and cons, so I’m throwing it open to people for comments.

Pros

  1. The syntax is nicely coloured, in a multitude of languages
  2. GitHub does all the heavy lifting of the colouring and provision of downloadable source
  3. The code doesn’t get mangled by the blog’s HTML editor (in this case, TinyMCE)

Cons

  1. It’s JavaScript-based, so Google won’t index the code
  2. It’s JavaScript-based, so you won’t see the code without JS enabled
  3. Until I find a workaround, page rendering is held up while the browser fetches the script to perform document.writes. And GitHub is not always the fastest at serving the gists

What are people’s thoughts? Are Gists the future, or is there a better solution?

1 comment Posted on 14 April, 2010, in JavaScript

Serving web fonts from IIS

I’ve just started playing with web fonts for a site redesign. I came across the following gotcha (thanks, Firebug, for alerting me to it!).

If you are running IIS 6 or higher on your web server, some of the fonts will be disabled by default.

Your typical @font-face declaration might look like this:

This will deliver one of four different font formats, depending on your browser’s capabilities. (The font is Vegur, a really nice-looking free font I found over at Font Squirrel).

By default, the MIME types in IIS 6 are configured to deliver EOT (as used by IE) and TTF files. But WOFF (Firefox) and SVG (iPhone, iPad & others) will not be served.

Simply add the following MIME type declarations via IIS Manager (HTTP Headers tab of website properties):

.woff  application/x-woff
.svg   image/svg+xml

…and everything should work fine.

No comments Posted on 10 April, 2010, in CSS, Quick Tips