Skip to content

Instantly share code, notes, and snippets.

@kickroot
Created November 20, 2012 19:08
Show Gist options
  • Select an option

  • Save kickroot/4120286 to your computer and use it in GitHub Desktop.

Select an option

Save kickroot/4120286 to your computer and use it in GitHub Desktop.
This custom Grails taglib is an easy way to allow for Role and ACL based checks in the view
/* Copyright 2009-2012 SpringSource.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file contains code merged from two SpringSource files, both under
* the Apache 2.0 license with modifications by Jason Nichols (jason@kickroot.com)
*/
import javax.servlet.FilterChain
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
import org.springframework.security.acls.model.Permission
/**
* Custom tags utilizing Spring Role based and ACL based permissions
* @author Burt Beckwith
* @author Jason Nichols (jason@kickroot.com)
*/
class CustomSecurityTagLib {
static namespace = 'customsec'
/** Dependency injection for aclPermissionFactory. */
def aclPermissionFactory
/** Dependency injection for permissionEvaluator. */
def permissionEvaluator
/** Dependency injection for springSecurityService. */
def springSecurityService
/** Dependency injection for webExpressionHandler. */
def webExpressionHandler
/**
* Renders the body if the user has grants for the specified permissions. Permissions are
* specified in the 'permission' attribute and can be a single Permission, an array of
* Permission, an int/Integer (which is assumed to be a mask), a String (which can be a
* single name, or a comma-delimited list of names, or a comma-delimited list of masks),
* or a List of any of these.
*
* Renders the body if the user has grants for the specified permissions of
*/
def permitted = { attrs, body ->
String roles = assertAttribute('roles', attrs, 'permitted')
if (hasPermission(attrs, 'permitted') || SpringSecurityUtils.ifAnyGranted(roles)) {
out << body()
}
}
protected boolean hasPermission(attrs, String tagName) {
if (!springSecurityService.isLoggedIn()) {
return false
}
def auth = springSecurityService.authentication
def perm = assertAttribute('permission', attrs, tagName)
def permissions = resolvePermissions(perm)
def object = attrs.remove('object')
if (object) {
return permissionEvaluator.hasPermission(auth, object, permissions)
}
def id = assertAttribute('id', attrs, tagName)
String className = assertAttribute('className', attrs, tagName)
if (!id || !className) {
throwTagError "Tag [$tagName] requires either an object or a class name and id"
}
return permissionEvaluator.hasPermission(auth, id, className, permissions)
}
/**
* @param permissions can be a single Permission, an array of Permission, an int/Integer (which
* is assumed to be a mask), a String (which can be a single name, or a comma-delimited
* list of names, or a comma-delimited list of masks), or a List of any of these
*/
protected resolvePermissions(permissions) {
Set<Permission> resolvedPermissions = []
if (permissions instanceof String) {
splitStringIntoPermissions permissions, resolvedPermissions
}
else if (permissions instanceof List) {
for (item in permissions) {
if (item instanceof String) {
splitStringIntoPermissions item, resolvedPermissions
}
else if (item instanceof Integer) {
resolvedPermissions << aclPermissionFactory.buildFromMask(item)
}
else if (item instanceof Permission) {
resolvedPermissions << item
}
}
}
else {
// let the permissionEvaluator handle it
return permissions
}
if (resolvedPermissions.any {it instanceof Permission}) {
return resolvedPermissions as Permission[]
}
return permissions
}
protected void splitStringIntoPermissions(String permission, Set permissions) {
for (token in permission.split(',')) {
token = token.trim()
if (token) {
try {
permissions << aclPermissionFactory.buildFromMask(Integer.valueOf(token))
}
catch (NumberFormatException nfe) {
try {
permissions << aclPermissionFactory.buildFromName(token)
}
catch (IllegalArgumentException notfound) {
try {
permissions << aclPermissionFactory.buildFromName(token.toUpperCase())
}
catch (IllegalArgumentException notfoundAgain) {
permissions << token
}
}
}
}
}
}
protected assertAttribute(String name, attrs, String tag) {
if (!attrs.containsKey(name)) {
throwTagError "Tag [$tag] is missing required attribute [$name]"
}
attrs.remove name
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment