Archive for May, 2012

Make your Spring Security @Secured annotations more DRY

Wednesday, May 30th, 2012

Recently a user on the Grails User mailing list wanted to know how to reduce repetition when defining @Secured annotations. The rules for specifying attributes in Java annotations are pretty restrictive, so I couldn’t see a direct way to do what he was asking.

Using Groovy doesn’t really help here since for the most part annotations in a Groovy class are pretty much the same as in Java (except for the syntax for array values). Of course Groovy now supports closures in annotations, but this would require a code change in the plugin. But then I thought about some work Jeff Brown did recently in the cache plugin.

Spring’s cache abstraction API includes three annotations; @Cacheable, @CacheEvict, and @CachePut. We were thinking ahead about supporting more configuration options than these annotations allow, but since you can’t subclass annotations we decided to use an AST transformation to find our versions of these annotations (currently with the same attributes as the Spring annotations) and convert them to valid Spring annotations. So I looked at Jeff’s code and it ended up being the basis for a fix for this problem.


It’s not possible to use code to externalize the authority lists because you can’t control the compilation order. So I ended up with a solution that isn’t perfect but works – I look for a properties file in the project root (roles.properties). The format is simple – the keys are names for each authority list and the values are the lists of authority names, comma-delimited. Here’s an example:

admins=ROLE_ADMIN, ROLE_SUPERADMIN
switchUser=ROLE_SWITCH_USER
editors=ROLE_EDITOR, ROLE_ADMIN

These keys are the values you use for the new @Authorities annotation:

package grails.plugins.springsecurity.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.codehaus.groovy.transform.GroovyASTTransformationClass;

/**
 * @author Burt Beckwith
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@GroovyASTTransformationClass(
    "grails.plugins.springsecurity.annotation.AuthoritiesTransformation")
public @interface Authorities {
   /**
    * The property file key; the property value will be a
    * comma-delimited list of role names.
    * @return the key
    */
   String value();
}

For example here’s a controller using the new annotation:

@Authorities('admins')
class SecureController {

   @Authorities('editors')
   def someAction() {
      ...
   }
}

This is the equivalent of this controller (and if you decompile the one with @Authorities you’ll see both annotations):

@Secured(['ROLE_ADMIN', 'ROLE_SUPERADMIN'])
class SecureController {

   @Secured(['ROLE_EDITOR', 'ROLE_ADMIN'])
   def someAction() {
      ...
   }
}

The AST transformation class looks for @Authorities annotations, loads the properties file, and adds a new @Secured annotation (the @Authorities annotation isn’t removed) using the role names specified in the properties file:

package grails.plugins.springsecurity.annotation;

import grails.plugins.springsecurity.Secured;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.ListExpression;
import org.codehaus.groovy.control.CompilePhase;
import org.codehaus.groovy.control.SourceUnit;
import org.codehaus.groovy.transform.ASTTransformation;
import org.codehaus.groovy.transform.GroovyASTTransformation;
import org.springframework.util.StringUtils;

/**
 * @author Burt Beckwith
 */
@GroovyASTTransformation(phase=CompilePhase.CANONICALIZATION)
public class AuthoritiesTransformation implements ASTTransformation {

  protected static final ClassNode SECURED =
       new ClassNode(Secured.class);

  public void visit(ASTNode[] astNodes, SourceUnit sourceUnit) {
    try {
      ASTNode firstNode = astNodes[0];
      ASTNode secondNode = astNodes[1];
      if (!(firstNode instanceof AnnotationNode) ||
          !(secondNode instanceof AnnotatedNode)) {
        throw new RuntimeException("Internal error: wrong types: " +
            firstNode.getClass().getName() +
            " / " + secondNode.getClass().getName());
      }

      AnnotationNode rolesAnnotationNode = (AnnotationNode) firstNode;
      AnnotatedNode annotatedNode = (AnnotatedNode) secondNode;

      AnnotationNode secured = createAnnotation(rolesAnnotationNode);
      if (secured != null) {
        annotatedNode.addAnnotation(secured);
      }
    }
    catch (Exception e) {
      // TODO
      e.printStackTrace();
    }
  }

  protected AnnotationNode createAnnotation(AnnotationNode rolesNode)
        throws IOException {
    Expression value = rolesNode.getMembers().get("value");
    if (!(value instanceof ConstantExpression)) {
      // TODO
      System.out.println(
         "annotation @Authorities value isn't a ConstantExpression: " +
         value);
      return null;
    }

    String fieldName = value.getText();
    String[] authorityNames = getAuthorityNames(fieldName);
    if (authorityNames == null) {
      return null;
    }

    return buildAnnotationNode(authorityNames);
  }

  protected AnnotationNode buildAnnotationNode(String[] names) {
    AnnotationNode securedAnnotationNode = new AnnotationNode(SECURED);
    List<Expression> nameExpressions = new ArrayList<Expression>();
    for (String authorityName : names) {
      nameExpressions.add(new ConstantExpression(authorityName));
    }
    securedAnnotationNode.addMember("value",
              new ListExpression(nameExpressions));
    return securedAnnotationNode;
  }

  protected String[] getAuthorityNames(String fieldName)
       throws IOException {

    Properties properties = new Properties();
    File propertyFile = new File("roles.properties");
    if (!propertyFile.exists()) {
      // TODO
      System.out.println("Property file roles.properties not found");
      return null;
    }

    properties.load(new FileReader(propertyFile));

    Object value = properties.getProperty(fieldName);
    if (value == null) {
      // TODO
      System.out.println("No value for property '" + fieldName + "'");
      return null;
    }

    List<String> names = new ArrayList<String>();
    String[] nameArray = StringUtils.commaDelimitedListToStringArray(
        value.toString())
    for (String auth : nameArray) {
      auth = auth.trim();
      if (auth.length() > 0) {
        names.add(auth);
      }
    }

    return names.toArray(new String[names.size()]);
  }
}

I’ll probably include this in the plugin at some point – I created a JIRA issue as a reminder – but for now you can just copy these two classes into your application’s src/java folder and create a roles.properties file in the project root. Any time you want to add or remove an entry or add or remove a role name from an entry, update the properties file, run grails clean and grails compile to be sure that the latest values are used.

This Week in Grails (2012-21)

Monday, May 28th, 2012

Grails 2.1 RC2 was released this week and it has several fixes including some addressing issues found in last week’s RC1 release. Grails 2.0.4 was also released, along with 1.3.9 to address a security issue

Ted Naleid did a writeup of an approach to dealing with test pollution, where a test suite can pass in one run but fail in another if the tests run in a different order. This can be very frustrating and hard to fix, so this is a great resource.

GR8Conf is coming up soon (starts next week!) and there was one speaker interview this week:


If you want to keep up with these “This Week in Grails” posts you can access them directly via their category link or in an RSS reader with the feed for just these posts.


Translations of this post:



Plugins

There was one new plugin released:

  • inflector version 0.1. Provides tags to simplify common text inflections, e.g. plural and singular words

and 17 updated plugins:

  • browser-detection version 0.4.1. Provides a service and tag library for browser detection
  • cache version 1.0.0.RC1. Adds request, service method, and taglib caching
  • cloud-foundry version 1.2.2. Integrates Cloud Foundry’s cloud deployment services to manage the running of Grails applications in the cloud from the command line
  • cloud-support version 1.0.11. Support plugin to help cloud plugins update service provider connection information from the cloud environment
  • flash-helper version 0.9.1. Simplifies and standardizes the process of adding/reading messages in the flash scope
  • google-visualization version 0.5.2. Provides a taglib for the interactive charts of the Google Visualization API
  • jslint version 0.5. Run JsLint on javascript files
  • localizations version 1.4.2. Store i18n strings in a database
  • quartz version 1.0-RC2. Schedules jobs to be executed with a specified interval or cron expression using the Quartz Enterprise Job Scheduler
  • quartz-monitor version 0.2. One clear and concise page that enables you to administer all your Quartz jobs
  • quartz2 version 0.2.3. Integration with Quartz 2 framework from quartz-scheduler.org
  • simple-captcha version 0.8.5. Creates simple image CAPTCHAs that protect against automated completion and submission of HTML forms
  • spring-security-facebook version 0.8. Plugin for Facebook Authentication, as extension to Grails Spring Security Core plugin
  • spring-security-ldap version 1.0.6. LDAP authentication support for the Spring Security plugin
  • spring-security-oauth version 2.0.1.1. Adds OAuth-based authentication to the Spring Security plugin using the OAuth plugin
  • stripe version 1.1. Use Stripe to process credit card transactions
  • translate version 1.3.0. Translates text from one language to another using the Microsoft Translator API

Interesting Tweets

User groups and Conferences

This Week in Grails (2012-20)

Tuesday, May 22nd, 2012

Grails 2.1 RC1 was released this week. As always you should look at upgrading to 2.1 now to find issues earlier rather than later.

Please try out the cache plugins. They should be pretty stable, and we’ll have better support and documentation for migrating from the springcache plugin soon.

GR8Conf EU is in just a few weeks – be sure to get your ticket soon. There was one speaker interview this week:


If you want to keep up with these “This Week in Grails” posts you can access them directly via their category link or in an RSS reader with the feed for just these posts.


Translations of this post:



Plugins

There was one new plugin released:

  • dustjs-resources version 0.2. Supports server-side compilation of .dust template files to their .js counterparts

and 10 updated plugins:

  • bootstrap-file-upload version 2.1.0. Integrates Sebastian Tschan’s Jquery File Upload (https://github.com/blueimp/jQuery-File-Upload)
  • eclipse-scripts version 1.0.6. Downloads and links sources and javadocs for dependencies from public repositories
  • export version 1.3. Export domain objects to a variety of formats (CSV, Excel, ODS, PDF, RTF and XML)
  • fitnesse version 2.0.4. Makes it possible to use the popular Open Source testing framework Fitnesse in combination with Grails.
  • functional-spock version 0.6. Allows you to write and run Spock specs under the functional test scope
  • google-visualization version 0.5.1. Provides a taglib for the interactive charts of the Google Visualization API
  • random version 0.2. Wraps the high-performance, statistically sound Uncommons Maths Pseudorandom Number Generators
  • redis version 1.3.1. Provides integration with a Redis datastore
  • release version 2.0.2. Publishes Grails plugins either to a public or private repository
  • routing version 1.2.2. Send and route messages to a wide variety of destination endpoints directly from your Controllers and Services using Camel

Interesting Tweets

User groups and Conferences


This Week in Grails (2012-19)

Tuesday, May 15th, 2012

We’re getting ready to release Grails 2.1, with a release candidate hopefully this week. The cache plugins I mentioned last week will be released around the same time, and the ‘core’ cache plugin will be a default plugin in BuildConfig.groovy. I released an update of the database-migration plugin to address some bugs that were keeping that from being a default plugin, so that will also be included by default in BuildConfig.groovy.

I’ve been working on a Grails book to be published this fall. The plan is that it will be an advanced book, and presume that you already have experience with Grails or another similar framework in Java or another language and are looking for more detail and best practices. It’s going to be available soon in an early-access digital format so you can follow the progress and help the book by finding mistakes and making suggestions.

A few more GR8Conf EU interviews:


If you want to keep up with these “This Week in Grails” posts you can access them directly via their category link or in an RSS reader with the feed for just these posts.


Translations of this post:



Plugins

There were 6 new plugins released:

  • closure-templates-resources version 0.1. Supports server-side compilation of .soy template files to JavaScript files
  • jquery-mobile-metro version 0.1. Plugin jQuery mobile framework Metro UI theme resource files
  • jrimum-bopepo version 0.2. Allows you to create Boletos Bancarios for Banks of Brazil using the Jrimum Bopepo library
  • plastic-criteria version 0.1. Mock Grails Criteria for Unit Tests
  • split-test version 0.4. An A/B testing framework designed to work with Grails
  • spring-security-oauth version 2.0.1.0. Adds OAuth-based authentication to the Spring Security plugin using the OAuth plugin

and 14 updated plugins:

  • asynchronous-mail version 0.6. Send email asynchronously by storing them in the database and sending with a Quartz job
  • cache version 1.0.0.M2. Adds request, service method, and taglib caching
  • cache-ehcache version 1.0.0.M2. An Ehcache-based implementation of the Cache plugin
  • cache-redis version 1.0.0.M2. A Redis-based implementation of the Cache plugin
  • database-migration version 1.1. Official Grails plugin for database migrations
  • external-config-reload version 1.2.0. Polls for changes to external configuration files (files added to grails.config.locations), reloads the configuration when a change has occurred, and notifies specified plugins by firing the onConfigChange event in each
  • faker version 0.5. A port of Data::Faker from Perl, is used to easily generate fake data: names, addresses, phone numbers, etc.
  • hibernate-search version 0.6.1. Integrates Hibernate Search for domain classes
  • lesscss-resources version 1.3.0.3. Optimises the use of http://www.lesscss.org css files, compiling .less files into their .css counterprt, and place the css into the processing chain to be available to the other resource plugin features
  • pusher version 0.4. Wrapper for pusher.com REST api
  • spring-batch version 0.2.2. Provides the Spring Batch framework and convention based Jobs
  • spring-security-facebook version 0.7.4. Plugin for Facebook Authentication, as extension to Grails Spring Security Core plugin
  • spring-security-twitter version 0.4.3. Twitter authentication as extension to the Spring Security Core plugin
  • zkui version 0.5.1. Seamlessly integrates ZK with Grails’ infrastructures; uses the Grails’ infrastructures such as GSP, controllers rather than zk’s zul as in ZKGrails plugin

Interesting Tweets

Jobs



User groups and Conferences


This Week in Grails (2012-18)

Wednesday, May 09th, 2012

The details for SpringOne 2GX 2012 are now online, it will be in Washington, DC this year, October 15th-18th.

The MongoDB plugin went 1.0 this week.

Jeff and I have been working on the cache plugin, which uses the new Spring cache abstraction and isn’t coupled to a particular implementation. The ‘core’ plugin has an in-memory implementation, but you’ll want to use one of the extension plugins for a more robust version. These currently include the Ehcache and Redis plugins and we’re working on one that uses Gemfire. All three plugins are available now and documentation will be available soon.

STS 3.0.0.M1 was released this week.

A couple more GR8Conf EU speaker interviews:


If you want to keep up with these “This Week in Grails” posts you can access them directly via their category link or in an RSS reader with the feed for just these posts.


Translations of this post:



Plugins

There were 6 new plugins released:

  • bootstrap-crumbs version 1.0.0. Provide simple breadcrumb functionality using the twitter bootstrap library
  • cache version 1.0.0.M1. Adds request, service method, and taglib caching
  • cache-ehcache version 1.0.0.M1. An Ehcache-based implementation of the Cache plugin
  • cache-redis version 1.0.0.M1. A Redis-based implementation of the Cache plugin
  • seofriendly-urls version 1.0.2. Helps to easily convert any string into a SEO-friendly one, eg from ‘The Lord of the Rings’ to ‘the-lord-of-the-rings’
  • github-gist version 0.1. Uploads code snippets from a Grails project to GitHub Gists so you can easily share tested code in blog posts, etc.

and 9 updated plugins:

  • bootstrap-file-upload version 2.0.0. Integrates Sebastian Tschan’s Jquery File Upload (https://github.com/blueimp/jQuery-File-Upload)
  • coffeescript-resources version 0.3.2. Create coffeescript modules that automatically compiles on every file change with jCoffeeScript
  • cucumber version 0.5.0. Test your Grails apps with Cucumber
  • export version 1.2. Export domain objects to a variety of formats (CSV, Excel, ODS, PDF, RTF and XML)
  • hibernate-search version 0.5.1. Integrates Hibernate Search for domain classes
  • horn-jquery version 1.0.57. Provides resources and tags to use the HORN specification for embedding your JS data model in your HTML pages
  • mongodb version 1.0.0.GA. Aims to provide an object-mapping layer on top of MongoDB
  • shiro-oauth version 0.2. Adds OAuth-based authentication to the Shiro plugin using the Scribe OAuth plugin
  • tomcat-bundler version 0.0.3. Simplifies bundling application with Tomcat to create a whole package to be used by hosting

Interesting Tweets

User groups and Conferences


This Week in Grails (2012-17)

Tuesday, May 01st, 2012

Check out this post on using Shiro to secure a Grails application. The Spring Security plugins are much more widely used but Shiro is an excellent security framework and deserves a lot more attention in the Grails community.

Not strictly Grails-related, but an interesting read on using WebSockets in Tomcat 7.

And not even coding-related, but here are two funny Tumbler sites that should be in your RSS reader: Texts From Dog and one tiny hand.


If you want to keep up with these “This Week in Grails” posts you can access them directly via their category link or in an RSS reader with the feed for just these posts.


Translations of this post:



Plugins

There was one new plugin released:

  • yammer-metrics version 2.1.2-1. Packages Coda Hale’s yammer metrics jars

and 9 updated plugins:

  • ckeditor version 3.6.3.0. Implements the integration layer between Grails and the CKEditor web rich text editor.
  • dojo version 1.6.1.10. Integrates the Dojo javascript toolkit
  • fitnesse version 2.0.3. Makes it possible to use the popular Open Source testing framework Fitnesse in combination with Grails.
  • marshallers version 0.2. Easy registration and usage of custom XML and JSON marshallers supporting hierarchical configurations
  • oauth version 2.0.1. Provides easy interaction with OAuth service providers
  • pusher version 0.3. Wrapper for pusher.com REST api
  • redis version 1.3. Provides integration with a Redis datastore
  • spring-batch version 0.2.1. Provides the Spring Batch framework and convention based Jobs
  • spring-security-facebook version 0.7.3. Plugin for Facebook Authentication, as extension to Grails Spring Security Core plugin

Interesting Tweets

User groups and Conferences


Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.