package com.globant.katari.core.security;
import java.util.Iterator;
import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.intercept.web.AbstractFilterInvocationDefinitionSource;
import org.acegisecurity.SecurityConfig;
import org.acegisecurity.ConfigAttribute;
import org.apache.commons.lang.Validate;
import com.globant.katari.core.web.ModuleContext;
import com.globant.katari.core.web.ModuleContextRegistrar;
import com.globant.katari.core.web.ModuleUtils;
/**
* This class extends {@link AbstractFilterInvocationDefinitionSource} in order
* to have a different way to look for attributes, since we do not have just
* one definition source (url's matching roles), but each module has its own
* source.
* @author maximiliano.roman
* @author ulises.bocchio
*/
public class ModuleFilterInvocationDefinitionSource extends
AbstractFilterInvocationDefinitionSource {
/**This is the module context registrar.
*
* It cannot be null.
*/
private ModuleContextRegistrar moduleContextRegistrar;
/**
* The default UrlToRoleMapper. It is use in case no module name is found
* in the url given to the lookupAttributes() method.
* It cannot be null.
*/
private UrlToRoleMapper defaultMapper;
/**Constructor.
*
* @param theModuleContextRegistrar
* the ModuleContextRegistrar.
* It is used to get the differents Module Context to get the
* <code>UrlToRoleMapper</code> of each module to perform security.
* It cannot be null.
* @param theDefaultMapper The default UrlToRoleMapper used in case no module
* name is found in the url given to the lookupAttributes() method.
*/
public ModuleFilterInvocationDefinitionSource(
final ModuleContextRegistrar theModuleContextRegistrar,
final UrlToRoleMapper theDefaultMapper) {
Validate.notNull(theModuleContextRegistrar, "The "
+ "ModuleContextRegistrar cannot be null");
Validate.notNull(theDefaultMapper, "The default UrlToRoleMapper cannot"
+ "be null");
moduleContextRegistrar = theModuleContextRegistrar;
defaultMapper = theDefaultMapper;
}
/** It returns the ConfigAttributeDefinition for the specified url.
*
* If the request corresponds to a module (mapped to [ctx]/module), it asks
* the module for ConfigAttributeDefinition. Otherwise, it uses a global
* mapper. If no ConfigAttributeDefinition is found, it throws an exception.
*
* @param url the url to look for the <code>ConfigAttributeDefinition</code>.
* It cannot be null.
*
* @return the config attribute definition for the given url. It returns null
* if the url is public.
*/
@Override
public ConfigAttributeDefinition lookupAttributes(final String url) {
Validate.notNull(url, "The url cannot be null");
String moduleName = ModuleUtils.getModuleNameFromUrl(url);
if (moduleName != null) {
UrlToRoleMapper moduleMapper;
ModuleContext moduleContext;
moduleContext = moduleContextRegistrar.getModuleContext(moduleName);
if (moduleContext == null) {
throw new IllegalArgumentException("The module name: " + moduleName
+ " extracted from the url doesn't match any module");
}
moduleMapper = moduleContext.getUrlToRoleMapper();
String strippedUrl = ModuleUtils.stripModuleNameFromUrl(url);
String[] roles = moduleMapper.getRolesForUrl(strippedUrl);
return buildConfigAttributeDefinition(roles);
}
String[] roles = defaultMapper.getRolesForUrl(url);
return buildConfigAttributeDefinition(roles);
}
/** It returns null, there's no need to implement this method it is optional.
* @return it returns null
*/
@SuppressWarnings("unchecked")
public Iterator getConfigAttributeDefinitions() {
return null;
}
/** Builds a <code>ConfigAttributeDefinition</code> from the array of
* roles.
*
* The config attribute definition is built from different
* <code>ConfigAttribute</code>.
*
* @param roles The roles to build the ConfigAttributeDefinition for. It
* cannot be null.
*
* @return ConfigAttributeDefinition. It returns null if an empty array is
* given.
*/
private static ConfigAttributeDefinition buildConfigAttributeDefinition(
final String[] roles) {
Validate.notNull(roles, "The roles array cannot be null");
if (roles.length == 0) {
return null;
}
ConfigAttributeDefinition configAttributeDefinition
= new ConfigAttributeDefinition();
for (String currentRole : roles) {
if (currentRole == null || "".equals(currentRole.trim())) {
throw new IllegalArgumentException("The Roles array contains an empty"
+ " role value");
}
ConfigAttribute configAttribute = new SecurityConfig(currentRole.trim());
configAttributeDefinition.addConfigAttribute(configAttribute);
}
return configAttributeDefinition;
}
}