Separating and securing Grails controllers

Ever wanted to have several Grails controllers automatically secured – just by name?

I had to make a subset of my Grails 1.2.2 application controllers only available to a certain group of people. A few controllers made actions on the application possible which only Administrators were allowed to do.

Acegi what?

So, I think everybody recognizes the ever so popular Acegi way (using Spring Security) of securing things with a single com.app.controller.HelloController in SecurityConfig.groovy:

security {
	active = true

	useRequestMapDomainClass = false
	requestMapString = """
		CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
		PATTERN_TYPE_APACHE_ANT

		/hello/**=ROLE_USER
		/**=IS_AUTHENTICATED_ANONYMOUSLY
	"""
}

This way a login-screen will appear when a user tries to open the HelloController on /hello since ROLE_USER is required. Well, not really high-tech yet – a basic example you could find in the Acegi plugin’s documentation as well.

More…more controllers!

Let’s introduce several other controllers next to the com.app.controller.HelloController. Notice I myself made up the package name com.app.controller – just a habit to seperate Domain classes, Controllers and Services into com.app.domain, com.app.controller and com.app.services.

Continue reading “Separating and securing Grails controllers”

Grails remote jQuery form validation

I recently had to validate a form in my Grails application using jQuery. jQuery has an excellent mechanism to validate a form with certain validation rules. It allows you to prevent form submission if the user input doesn’t pass the validation attached to the form.

Below a simple example HTML snippet to validate a postal code field:

<script type="text/javascript">
$(function (){
	$("#form").validate({
		rules: {
			'address.postalCode': {
				required: true
			},
		},
		messages: {
			'address.postalCode': {
				required: "Please enter a postal code."
			}
		}
	});
});
</script>
<g:form method="post" action="register" name="form">
	<input type="text" name="address.postalCode" id="postalCode" />
	<input type="submit" value="Proceed" />
</g:form>

As you can see: a simple ‘required’ rule is specified for field with name address.postalCode and errormessage to go with it. Notice that special field names e.g. with a dot requires a notation with quotes around it.

Now, let’s say we need to validate the postal code on the server side for validity and still need to have the form validation performed by jQuery – and not inside the controller and returing some kind of error- or flash message. Use the remote rule!

As the documentation states:

The serverside resource is called via $.ajax (XMLHttpRequest) and gets a key/value pair, corresponding to the name of the validated element and its value as a GET parameter. The response is evaluated as JSON and must be true for valid elements, and can be any false, undefined or null for invalid elements, using the default message; or a string, eg. “That name is already taken, try peter123 instead” to display as the error message.

We create a controller which does such a thing: check the submitted postal code, verify it against some kind of backend service or database table and return the expected JSON return values.

E.g. let’s expand our form HTML with the following:

<script type="text/javascript">
	$(function (){
		$("#form").validate({
			rules: {
				'address.postalCode': {
					required: true,
					remote: {
						url: "${createLink(controller:'postalCode', action:'validate')}",
						type: "post",
						data: {
							postalCode: function() {
								return $("#postalCode").val();
						  }
						}
					  }
				},
			},
			messages: {
				'address.postalCode': {
					required: "Please enter a postal code.",
					remote: "Please enter a valid postal code."
				}
			}
		});
	});
</script>
<g:form method="post" action="register" name="form">
	<input type="text" name="address.postalCode" id="postalCode" />
	<input type="submit" value="Proceed" />
</g:form>

As you can see, the remote rule specifies a resource which is one of our controllers and a specified action. As data for our Grails action we pass along the current value of the post code field – using the ‘data’ block with a function.

Our PostalCodeController may have the following validate action:

class PostalCodeController {

	def postalCodeService
	
	def validate = {		
		String pc = params.postalCode
		
		String result = "false"
		if (postalCodeService.checkPostalCode(pc)) {
			result = "true"
		}
				
		response.setContentType("text/json;charset=UTF-8");
		render result
	}
}

Voila! We validate our data (which we simply read from the params) en return a string “true” if it’s valid else “false”.

Upon form submission our action is called and the outcome is used by jQuery to validate the user data! I couldn’t get my response rendered via the usual Grails JSON builder which seems to have trouble with single values (such as “true” or “false”), but set the content type directly. You might want to send additional caching headers along with the JSON response to prevent browser caching, but that’s all left as an excercise for the reader.