2011
04.11

The Spring-Security plugins for Grails are awesome! They got me 90% of the way there for pretty much everything I needed to do from a security standpoint for Mural Mate. One requirement that I needed to code my own solution for though was the desire to only allow the particular Owner (i.e. person who created it) update that League, Team, Classified, etc.  If it was just Admins it would have been incredibly easy by just using a new Role (ROLE_ADMIN), but obviously I want the Team Owner, League Owner, Classified Owner, etc to be able to update their own stuff, but not anybody else. I couldn’t use a new role (i.e. ROLE_OWNER) for this because a user might be an owner for one League, but obviously not all of them.  Also, Admins need to be able to update anything in the system. So, I dove in and this is what I came up with!

I knew I was going to need two things, a taglib and a service.  The taglib is needed so that I can hide the edit and delete buttons from everybody except the particular owner and admins in GSPs and the service is used to abstract the logic for controllers.  Let’s start with the service first:


/**
* Determines whether the current user
* has the authority to edit the instance
*
* @attr instance the instance to evaluate
**/
boolean hasModifyAuth(instance) {
  if (SpringSecurityUtils.ifAnyGranted("ROLE_ADMIN")
      || instance.owner.id == springSecurityService.getCurrentUser().id) {
    return true
  } else {
    return false
  }
}

This service method is pretty simple, but does the trick! It checks if the current user is an admin or the owner for whatever instance is passed to it (all my domain classes that I want to do this with have an owner property of type User).  Onto the taglib:


static namespace = "mm"
 
/**
* Renders the body if user has authority
*
* @attr value REQUIRED the field value
*/
def ifModifyAuth = { attrs, body ->
  def instance = assertAttribute("value", attrs, "ifModifyAuth")
  if (SpringSecurityUtils.ifAnyGranted("ROLE_ADMIN")
      || instance.owner.id == springSecurityService.getCurrentUser().id) {
    out << body()
  }
}
  
protected assertAttribute(String name, attrs, String tag) {
  if (!attrs.containsKey(name)) {
    throwTagError "Tag [$tag] is missing required attribute [$name]"
  }
  attrs.remove name
}

Once again pretty simple, but works perfectly! I copied the assertAttribute method idea from the Spring-Security-Core plugin and with the REQUIRED in the JavaDocs, SpringSource Tool Suite auto-completes the value attribute for the tags!  Then I just do something like this in my GSPs:


<mm:ifModifyAuth value="${teamInstance}">
  ... edit and delete links ...
</mm:ifModifyAuth>

And this in my controller that I wanted to restrict modify access:


def beforeInterceptor =
  [action:this.&auth,only:['update', 'delete', 'edit']]
 
def auth() {
  def instance = Team.get(params.id)
  if (instance) {
    if (!muralMateSecurityService.hasModifyAuth(instance)) {
      flash.message = "You do not have access to modify this instance"
      redirect(action: "list")
      return false
    }
  } else {
    flash.message = "Instance not found"
    redirect(action: "list")
    return false
  }
}

And there we have it! A reusable taglib for my views and service for my controllers implementing my custom authorization requirements!

2011
04.11

Mural Mate Update

I’ve been working on Mural Mate for just about two weeks now, so I thought it was time to provide an update on my progress! Some basic stats about the app so far: 13 domain classes, roughly 4000 lines of code (Groovy & GSPs) and using 9 Grails plugins.  The initial code-base is focused around five main areas: Users, Leagues, Teams, Games and Classifieds. Every team has a manager and every league has an owner. Each team can belong to a league, but doesn’t have to. All games must belong to a team and all classifieds must belong to a game. Users can belong to or manage as many teams as they want. The whole concept behind classifieds is to allow team managers to post when they need a sub for any particular game.  I might expand on this after the initial release if it becomes popular to allow users to post the opposite type of classified too (availability to play on a particular night for sports they are interested in), but not for the initial release.

I’ve really enjoyed using the Spring-Security plugins (spring-security-core and spring-security-ui). The entire authentication and authorization process (registration, login/logout, forgot password) is all implemented using these plugins. I also have really enjoyed the great Groovy support in SpringSource Tool Suite 2.6.  I’ve finally abandoned TextMate, ha! :) I’m not sure if it will make the initial release, but integrating with Spring-Social is still on my radar!

All along I’ve been planning to use AWS BeanStalk for hosting the application, but there is an interesting announcement being made tomorrow from SpringSource that could potentially change my mind. Whatever they announce, I will certainly weight the pros/cons of it against BeanStalk before I make my decision. I also have all the email accounts setup with Google. I’ll probably have to buy a business account to avoid the 500 emails per day limit of the free ones though.

So, to wrap up, I’ve made lots of progress and hope to have an initial version for beta-users to tryout sometime in May!

Switch to our mobile site