package org.jboss.seam.security.permission; import static org.jboss.seam.ScopeType.APPLICATION; import static org.jboss.seam.annotations.Install.BUILT_IN; import java.io.Serializable; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.jboss.seam.Component; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Install; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.Startup; import org.jboss.seam.annotations.intercept.BypassInterceptors; import org.jboss.seam.contexts.Contexts; import org.jboss.seam.core.Events; import org.jboss.seam.core.Init; /** * Maps permission checks to resolver chains * * @author Shane Bryzak */ @Scope(APPLICATION) @Name("org.jboss.seam.security.permissionMapper") @Install(precedence = BUILT_IN) @BypassInterceptors @Startup public class PermissionMapper implements Serializable { public static final String DEFAULT_RESOLVER_CHAIN_CREATED = "org.jboss.seam.security.defaultResolverChainCreated"; private Map<Class,Map<String,String>> resolverChains = new HashMap<Class,Map<String,String>>(); private String defaultResolverChain; private static final String DEFAULT_RESOLVER_CHAIN = "org.jboss.seam.security.defaultResolverChain"; private ResolverChain getResolverChain(Object target, String action) { Class targetClass = null; if (target instanceof Class) { targetClass = (Class) target; } else { // TODO target may be a component name, or an object, or a view name (or arbitrary name) - // we need to deal with all of these possibilities } if (targetClass != null) { Map<String,String> chains = resolverChains.get(target); if (chains != null && chains.containsKey(action)) { return (ResolverChain) Component.getInstance(chains.get(action), true); } } if (defaultResolverChain != null && !"".equals(defaultResolverChain)) { return (ResolverChain) Component.getInstance(defaultResolverChain, true); } return createDefaultResolverChain(); } public boolean resolvePermission(Object target, String action) { ResolverChain chain = getResolverChain(target, action); for (PermissionResolver resolver : chain.getResolvers()) { if (resolver.hasPermission(target, action)) { return true; } } return false; } public void filterByPermission(Collection collection, String action) { boolean homogenous = true; Class targetClass = null; for (Object target : collection) { if (targetClass == null) targetClass = target.getClass(); if (!targetClass.equals(target.getClass())) { homogenous = false; break; } } if (homogenous) { Set<Object> denied = new HashSet<Object>(collection); ResolverChain chain = getResolverChain(targetClass, action); for (PermissionResolver resolver : chain.getResolvers()) { resolver.filterSetByAction(denied, action); } for (Object target : denied) { collection.remove(target); } } else { Map<Class,Set<Object>> deniedByClass = new HashMap<Class,Set<Object>>(); for (Object obj : collection) { if (!deniedByClass.containsKey(obj.getClass())) { Set<Object> denied = new HashSet<Object>(); denied.add(obj); deniedByClass.put(obj.getClass(), denied); } else { deniedByClass.get(obj.getClass()).add(obj); } } for (Class cls : deniedByClass.keySet()) { Set<Object> denied = deniedByClass.get(cls); ResolverChain chain = getResolverChain(cls, action); for (PermissionResolver resolver : chain.getResolvers()) { resolver.filterSetByAction(denied, action); } for (Object target : denied) { collection.remove(target); } } } } private ResolverChain createDefaultResolverChain() { ResolverChain chain = (ResolverChain) Contexts.getSessionContext().get(DEFAULT_RESOLVER_CHAIN); if (chain == null) { chain = new ResolverChain(); for (String resolverName : Init.instance().getPermissionResolvers()) { chain.getResolvers().add((PermissionResolver) Component.getInstance(resolverName, true)); } Contexts.getSessionContext().set(DEFAULT_RESOLVER_CHAIN, chain); if (Events.exists()) Events.instance().raiseEvent(DEFAULT_RESOLVER_CHAIN_CREATED, chain); } return chain; } public static PermissionMapper instance() { if ( !Contexts.isApplicationContextActive() ) { throw new IllegalStateException("No active application context"); } PermissionMapper instance = (PermissionMapper) Component.getInstance( PermissionMapper.class, ScopeType.APPLICATION); if (instance == null) { throw new IllegalStateException("No PermissionMapper could be created"); } return instance; } }