/* Copyright 2006-2009 the original author or authors. * * 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. */ package org.grails.plugins.springsecurity.service import org.codehaus.groovy.grails.plugins.springsecurity.AuthorizeTools import org.springframework.security.context.SecurityContextHolder as SCH import org.springframework.security.ui.AbstractProcessingFilter as APF import org.springframework.security.userdetails.UserDetails /** * Authentication utility methods. * * @author T.Yamamoto * @author Burt Beckwith */ class AuthenticateService { boolean transactional = false private securityConfig /** dependency injection for {@link GrailsFilterInvocationDefinition} */ def objectDefinitionSource /** dependency injection for the password encoder */ def passwordEncoder /** * @deprecated You can invoke tags from controllers (since grails-0.6) */ boolean ifAllGranted(role) { return AuthorizeTools.ifAllGranted(role) } /** * @deprecated You can invoke tags from controllers (since grails-0.6) */ boolean ifNotGranted(role) { return AuthorizeTools.ifNotGranted(role) } /** * @deprecated You can invoke tags from controllers (since grails-0.6) */ boolean ifAnyGranted(role) { return AuthorizeTools.ifAnyGranted(role) } /** * Get the currently logged in user's principal. * @return the principal or null if not logged in */ def principal() { return SCH?.context?.authentication?.principal } /** * Get the currently logged in user's domain class. * @return the domain object or null if not logged in */ def userDomain() { return isLoggedIn() ? principal().domainClass : null } /** * Load the security configuration. * @return the config */ ConfigObject getSecurityConfig() { if (securityConfig == null) { securityConfig = AuthorizeTools.getSecurityConfig() } return securityConfig } /** * returns a MessageDigest password. * (changes algorithm method dynamically by param of config) * @deprecated use encodePassword instead */ String passwordEncoder(String passwd) { return encodePassword(passwd) } String encodePassword(String passwd) { return passwordEncoder.encodePassword(passwd, null) } /** * Check if the request was triggered by an Ajax call. * @param request the request * @return true if Ajax */ boolean isAjax(request) { // look for an ajax=true parameter if ('true' == request.getParameter('ajax')) { return true } // check the current request's headers String ajaxHeader = getSecurityConfig().security.ajaxHeader if (request.getHeader(ajaxHeader) != null) { return true } // check the SavedRequest's headers def savedRequest = request.session.getAttribute(APF.SPRING_SECURITY_SAVED_REQUEST_KEY) if (savedRequest) { return savedRequest.getHeaderValues(ajaxHeader).hasNext() } return false } /** * Quick check to see if the current user is logged in. * @return true if the principal is a {@link UserDetails} or subclass */ boolean isLoggedIn() { return principal() instanceof UserDetails } /** * Call when editing, creating, or deleting a Requestmap to flush the cached * configuration and rebuild using the most recent data. */ void clearCachedRequestmaps() { objectDefinitionSource.reset() } /** * Delete a role, and if Requestmap class is used to store roles, remove the role * from all Requestmap definitions. If a Requestmap's config attribute is this role, * it will be deleted. * * @param role the role to delete */ void deleteRole(role) { def conf = getSecurityConfig().security String configAttributeName = conf.requestMapConfigAttributeField role.getClass().withTransaction { status -> if (conf.useRequestMapDomainClass) { String roleName = role.authority def requestmaps = findRequestmapsByRole(roleName, role.getClass(), conf) requestmaps.each { rm -> String configAttribute = rm."$configAttributeName" if (configAttribute.equals(roleName)) { rm.delete() } else { List parts = configAttribute.split(',') as List parts.remove roleName rm."$configAttributeName" = parts.join(',') } } clearCachedRequestmaps() } role.delete() } } /** * Update a role, and if Requestmap class is used to store roles, replace the new role * name in all Requestmap definitions that use it if the name was changed. * * @param role the role to update * @param newProperties the new role attributes ('params' from the calling controller) */ boolean updateRole(role, newProperties) { String oldRoleName = role.authority role.properties = newProperties def conf = getSecurityConfig().security String configAttributeName = conf.requestMapConfigAttributeField if (conf.useRequestMapDomainClass) { String newRoleName = role.authority if (newRoleName != oldRoleName) { def requestmaps = findRequestmapsByRole(oldRoleName, role.getClass(), conf) requestmaps.each { rm -> rm."$configAttributeName" = rm."$configAttributeName".replace(oldRoleName, newRoleName) } } clearCachedRequestmaps() } role.save() return !role.hasErrors() } private List findRequestmapsByRole(String roleName, domainClass, conf) { String requestmapClassName = conf.requestMapClass String configAttributeName = conf.requestMapConfigAttributeField return domainClass.executeQuery( "SELECT rm FROM $requestmapClassName rm " + "WHERE rm.$configAttributeName LIKE :roleName", [roleName: "%$roleName%"]) } }