[seam-commits] Seam SVN: r7440 - in trunk/src/main/org/jboss/seam: security and 1 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Tue Feb 19 08:31:28 EST 2008


Author: shane.bryzak at jboss.com
Date: 2008-02-19 08:31:28 -0500 (Tue, 19 Feb 2008)
New Revision: 7440

Added:
   trunk/src/main/org/jboss/seam/security/DynamicPermissionResolver.java
   trunk/src/main/org/jboss/seam/security/PermissionMapper.java
   trunk/src/main/org/jboss/seam/security/ResolverChain.java
   trunk/src/main/org/jboss/seam/security/RuleBasedPermissionResolver.java
   trunk/src/main/org/jboss/seam/security/management/SecurityContext.java
Removed:
   trunk/src/main/org/jboss/seam/security/RuleBasedIdentity.java
Modified:
   trunk/src/main/org/jboss/seam/el/SeamFunctionMapper.java
   trunk/src/main/org/jboss/seam/security/Identity.java
   trunk/src/main/org/jboss/seam/security/PermissionCheck.java
   trunk/src/main/org/jboss/seam/security/SecurityFunctions.java
   trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java
   trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java
Log:
permission resolver implementation

Modified: trunk/src/main/org/jboss/seam/el/SeamFunctionMapper.java
===================================================================
--- trunk/src/main/org/jboss/seam/el/SeamFunctionMapper.java	2008-02-19 13:07:47 UTC (rev 7439)
+++ trunk/src/main/org/jboss/seam/el/SeamFunctionMapper.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -1,11 +1,14 @@
 package org.jboss.seam.el;
 
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import javax.el.FunctionMapper;
 
+import org.jboss.el.lang.ExtendedFunctionMapper;
 import org.jboss.seam.log.LogProvider;
 import org.jboss.seam.log.Logging;
 import org.jboss.seam.security.SecurityFunctions;
@@ -16,12 +19,12 @@
  *  
  * @author Shane Bryzak
  */
-public class SeamFunctionMapper extends FunctionMapper
+public class SeamFunctionMapper extends ExtendedFunctionMapper
 {
-   private static Map<String,Method> methodCache = new HashMap<String,Method>();
+   private static Map<String,List<Method>> methodCache = new HashMap<String,List<Method>>();
    
    private static final LogProvider log = Logging.getLogProvider(SeamFunctionMapper.class);
-   
+
    private FunctionMapper functionMapper;
    
    public SeamFunctionMapper(FunctionMapper functionMapper)
@@ -33,6 +36,8 @@
    {
       cacheMethod("hasPermission", SecurityFunctions.class, "hasPermission", 
                new Class[] {String.class, String.class, Object.class});
+      cacheMethod("hasPermission", SecurityFunctions.class, "hasPermission",
+               new Class[] {Object.class, String.class});
       cacheMethod("hasRole", SecurityFunctions.class, "hasRole",
                new Class[] { String.class });      
    }
@@ -42,7 +47,8 @@
    {
       if ( "s".equals(prefix) )
       {
-         return methodCache.get(localName);
+         List<Method> methods = methodCache.get(localName);
+         return methods != null ? methods.get(0) : null;
       }
       else if (functionMapper != null)
       {
@@ -54,12 +60,50 @@
       }
    }  
    
+   @Override 
+   public Method resolveFunction(String prefix, String localName, int paramCount) 
+   {
+      if ( "s".equals(prefix) )
+      {
+         List<Method> methods = methodCache.get(localName);
+         if (methods != null)
+         {
+            for (Method m : methods)
+            {
+               if (m.getParameterTypes().length == paramCount) return m;
+            }
+         }
+         
+         return null;
+      }
+      else if (functionMapper != null)
+      {
+         return functionMapper.resolveFunction(prefix, localName);
+      }
+      else
+      {
+         return null;
+      }
+   }    
+   
    private static void cacheMethod(String localName, Class cls, String name, Class[] params)
    {
       try
       {
          Method m = cls.getMethod(name, params);
-         methodCache.put(localName, m);         
+
+         List<Method> methods;
+         if (methodCache.containsKey(localName))
+         {
+            methods = methodCache.get(localName);
+         }
+         else
+         {
+            methods = new ArrayList<Method>();
+            methodCache.put(localName, methods);
+         }
+         
+         methods.add(m);         
       }
       catch (NoSuchMethodException ex)
       {

Added: trunk/src/main/org/jboss/seam/security/DynamicPermissionResolver.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/DynamicPermissionResolver.java	                        (rev 0)
+++ trunk/src/main/org/jboss/seam/security/DynamicPermissionResolver.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -0,0 +1,15 @@
+package org.jboss.seam.security;
+
+/**
+ * Resolves permissions dynamically assigned in a peristent store, such as a 
+ * database, for example.
+ * 
+ * @author Shane Bryzak
+ */
+public class DynamicPermissionResolver implements PermissionResolver
+{   
+   public boolean hasPermission(Object target, String action)
+   {
+      return true;  
+   }
+}

Modified: trunk/src/main/org/jboss/seam/security/Identity.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/Identity.java	2008-02-19 13:07:47 UTC (rev 7439)
+++ trunk/src/main/org/jboss/seam/security/Identity.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -25,6 +25,7 @@
 import org.jboss.seam.ScopeType;
 import org.jboss.seam.Seam;
 import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.In;
 import org.jboss.seam.annotations.Install;
 import org.jboss.seam.annotations.Name;
 import org.jboss.seam.annotations.Scope;
@@ -90,6 +91,8 @@
    
    private List<String> preAuthenticationRoles = new ArrayList<String>();
    
+   private PermissionMapper permissionMapper;
+   
    /**
     * Flag that indicates we are in the process of authenticating
     */
@@ -99,6 +102,7 @@
    public void create()
    {     
       subject = new Subject();
+      permissionMapper = (PermissionMapper) Component.getInstance(PermissionMapper.class);
    }
    
    public static boolean isSecurityEnabled()
@@ -494,6 +498,25 @@
          }
       }
    }
+   
+   public void checkPermission(Object target, String action)
+   {
+      isLoggedIn(true);
+      
+      if ( !hasPermission(target, action) )
+      {
+         if ( !isLoggedIn() )
+         {
+            if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_LOGGED_IN);
+            throw new NotLoggedInException();            
+         }
+         else
+         {
+            throw new AuthorizationException(String.format(
+                  "Authorization check failed for permission[%s,%s]", target, action));
+         }
+      }
+   }
 
    /**
     * Performs a permission check for the specified name and action
@@ -505,9 +528,31 @@
     */
    public boolean hasPermission(String name, String action, Object...arg)
    {      
-      return !securityEnabled;
+      if (!securityEnabled)
+      {
+         return true;
+      }
+      
+      if (arg != null)
+      {
+         return permissionMapper.resolvePermission(arg[0], action);
+      }
+      else
+      {
+         return permissionMapper.resolvePermission(name, action);
+      }
    }   
    
+   public boolean hasPermission(Object target, String action)
+   {
+      if (!securityEnabled)
+      {
+         return true;
+      }
+      
+      return permissionMapper.resolvePermission(target, action);
+   }
+   
    /**
     * Creates a callback handler that can handle a standard username/password
     * callback, using the username and password properties.
@@ -676,7 +721,7 @@
          {
             if (Strings.isEmpty(restrict.value()))
             {
-               checkPermission(name, action.toString(), entity);
+               checkPermission(entity, action.toString());
             }
             else
             {

Modified: trunk/src/main/org/jboss/seam/security/PermissionCheck.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/PermissionCheck.java	2008-02-19 13:07:47 UTC (rev 7439)
+++ trunk/src/main/org/jboss/seam/security/PermissionCheck.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -9,39 +9,54 @@
  */
 public class PermissionCheck
 {
-  private String name;
-  private String action;
-  private boolean granted;
+   private Object target;
 
-  public PermissionCheck(String name, String action)
-  {
-    this.name = name;
-    this.action = action;
-    this.granted = false;
-  }
+   @Deprecated
+   private String name;
 
-  public String getName()
-  {
-    return name;
-  }
+   private String action;
+   private boolean granted;
+   
+   public PermissionCheck(Object target, String action)
+   {
+      if (target instanceof String)
+      {
+         this.name = (String) target;
+      }
+      
+      this.target = target;
+      this.action = action;
+      granted = false;
+   }
+   
+   public Object getTarget()
+   {
+      return target;
+   }   
 
-  public String getAction()
-  {
-    return action;
-  }
+   @Deprecated
+   public String getName() 
+   {
+      return name;
+   }
 
-  public void grant()
-  {
-    this.granted = true;
-  }
-  
-  public void revoke()
-  {
-     this.granted = false;
-  }
+   public String getAction() 
+   {
+      return action;
+   }
 
-  public boolean isGranted()
-  {
-    return granted;
-  }
+   public void grant() 
+   {
+      this.granted = true;
+   }
+
+   public void revoke() 
+   {
+      this.granted = false;
+   }
+
+   public boolean isGranted() 
+   {
+      return granted;
+   }
 }

Added: trunk/src/main/org/jboss/seam/security/PermissionMapper.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/PermissionMapper.java	                        (rev 0)
+++ trunk/src/main/org/jboss/seam/security/PermissionMapper.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -0,0 +1,118 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.ScopeType.APPLICATION;
+import static org.jboss.seam.annotations.Install.BUILT_IN;
+
+import java.util.HashMap;
+import java.util.Map;
+
+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.Init;
+
+/**
+ * Maps permission checks to resolver chains
+ * 
+ * @author Shane Bryzak
+ */
+ at Scope(APPLICATION)
+ at Name("org.jboss.seam.security.permissionMapper")
+ at Install(precedence = BUILT_IN)
+ at BypassInterceptors
+ at Startup
+public class PermissionMapper
+{
+   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;
+   }   
+   
+   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);
+      }
+      
+      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;
+   }
+}

Added: trunk/src/main/org/jboss/seam/security/ResolverChain.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/ResolverChain.java	                        (rev 0)
+++ trunk/src/main/org/jboss/seam/security/ResolverChain.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -0,0 +1,26 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.ScopeType.SESSION;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+
+ at Scope(SESSION)
+ at BypassInterceptors
+public class ResolverChain
+{
+   private List<PermissionResolver> resolvers = new ArrayList<PermissionResolver>();
+   
+   public List<PermissionResolver> getResolvers()
+   {
+      return resolvers;
+   }
+   
+   public void setResolvers(List<PermissionResolver> resolvers)
+   {
+      this.resolvers = resolvers;
+   }   
+}

Deleted: trunk/src/main/org/jboss/seam/security/RuleBasedIdentity.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/RuleBasedIdentity.java	2008-02-19 13:07:47 UTC (rev 7439)
+++ trunk/src/main/org/jboss/seam/security/RuleBasedIdentity.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -1,226 +0,0 @@
-package org.jboss.seam.security;
-
-import static org.jboss.seam.ScopeType.SESSION;
-import static org.jboss.seam.annotations.Install.FRAMEWORK;
-
-import java.security.Principal;
-import java.security.acl.Group;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.List;
-
-import org.drools.FactHandle;
-import org.drools.RuleBase;
-import org.drools.StatefulSession;
-import org.drools.base.ClassObjectFilter;
-import org.jboss.seam.Component;
-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.log.LogProvider;
-import org.jboss.seam.log.Logging;
-
-/**
- * Identity implementation that supports permission
- * checking via a Drools rulebase.
- * 
- * @author Shane Bryzak
- *
- */
- at Name("org.jboss.seam.security.identity")
- at Scope(SESSION)
- at BypassInterceptors
- at Install(precedence=FRAMEWORK, classDependencies="org.drools.WorkingMemory")
- at Startup
-public class RuleBasedIdentity extends Identity
-{  
-   private static final long serialVersionUID = -2798083003251077858L;
-
-   public static final String RULES_COMPONENT_NAME = "securityRules";   
-   
-   private static final LogProvider log = Logging.getLogProvider(RuleBasedIdentity.class);
-   
-   private StatefulSession securityContext;
-   
-   private RuleBase securityRules;  
-   
-   @Override
-   public void create()
-   {
-      super.create();
-      initSecurityContext();
-   }
-   
-   protected void initSecurityContext()
-   {
-      if (getSecurityRules() == null)
-      {
-         setSecurityRules((RuleBase) Component.getInstance(RULES_COMPONENT_NAME, true));
-      }
-      
-      if (getSecurityRules() != null)
-      {
-         setSecurityContext(getSecurityRules().newStatefulSession(false));
-      }
-      
-      if (getSecurityContext() == null)
-      {
-         log.warn("no security rule base available - please install a RuleBase with the name '" +
-                  RULES_COMPONENT_NAME + "' if permission checks are required.");
-      }
-   }
-
-   @Override
-   protected void postAuthenticate()
-   {
-      super.postAuthenticate();
-
-      if (getSecurityContext() != null)
-      {         
-         getSecurityContext().insert(getPrincipal());
-      }
-   }
-   
-   /**
-    * Performs a permission check for the specified name and action
-    * 
-    * @param name String The permission name
-    * @param action String The permission action
-    * @param arg Object Optional object parameter used to make a permission decision
-    * @return boolean True if the user has the specified permission
-    */
-   @Override
-   public boolean hasPermission(String name, String action, Object...arg)
-   {      
-      if (!securityEnabled) return true;
-      
-      StatefulSession securityContext = getSecurityContext();
-      
-      if (securityContext == null) return false;      
-      
-      List<FactHandle> handles = new ArrayList<FactHandle>();
-
-      PermissionCheck check = new PermissionCheck(name, action);
-      
-      synchronized( securityContext )
-      {
-         synchronizeContext();
-         
-         handles.add( securityContext.insert(check) );
-         
-         for (int i = 0; i < arg.length; i++)
-         {
-            if (i == 0 && arg[0] instanceof Collection)
-            {
-               for (Object value : (Collection) arg[i])
-               {
-                  if ( securityContext.getFactHandle(value) == null )
-                  {
-                     handles.add( securityContext.insert(value) );
-                  }
-               }               
-            }
-            else
-            {
-               handles.add( securityContext.insert(arg[i]) );
-            }
-         }
-   
-         securityContext.fireAllRules();
-   
-         for (FactHandle handle : handles)
-            securityContext.retract(handle);
-      }
-      
-      return check.isGranted();
-   }
-   
-   @SuppressWarnings("unchecked")
-   @Override   
-   public void unAuthenticate()
-   {
-      super.unAuthenticate();
-      if (getSecurityContext() != null)
-      {
-         getSecurityContext().dispose();      
-         setSecurityContext(null);
-      }
-      initSecurityContext();
-   }
-   
-   /**
-    *  Synchronizes the state of the security context with that of the subject
-    */
-   private void synchronizeContext()
-   {
-      if (getSecurityContext() != null)
-      {
-         for ( Group sg : getSubject().getPrincipals(Group.class) )      
-         {
-            if ( ROLES_GROUP.equals( sg.getName() ) )
-            {
-               Enumeration e = sg.members();
-               while (e.hasMoreElements())
-               {
-                  Principal role = (Principal) e.nextElement();
-   
-                  boolean found = false;
-                  Iterator<Role> iter = getSecurityContext().iterateObjects(new ClassObjectFilter(Role.class)); 
-                  while (iter.hasNext()) 
-                  {
-                     Role r = iter.next();
-                     if (r.getName().equals(role.getName()))
-                     {
-                        found = true;
-                        break;
-                     }
-                  }
-                  
-                  if (!found)
-                  {
-                     getSecurityContext().insert(new Role(role.getName()));
-                  }
-                  
-               }
-            }
-         }    
-         
-         Iterator<Role> iter = getSecurityContext().iterateObjects(new ClassObjectFilter(Role.class)); 
-         while (iter.hasNext()) 
-         {
-            Role r = iter.next();
-            if (!super.hasRole(r.getName()))
-            {
-               FactHandle fh = getSecurityContext().getFactHandle(r);
-               getSecurityContext().retract(fh);
-            }
-         }
-      }
-   }
-   
-   
-   public StatefulSession getSecurityContext()
-   {
-      return securityContext;
-   }
-   
-   public void setSecurityContext(StatefulSession securityContext)
-   {
-      this.securityContext = securityContext;
-   }
-   
-
-   public RuleBase getSecurityRules()
-   {
-      return securityRules;
-   }
-
-   public void setSecurityRules(RuleBase securityRules)
-   {
-      this.securityRules = securityRules;
-   }    
-}

Added: trunk/src/main/org/jboss/seam/security/RuleBasedPermissionResolver.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/RuleBasedPermissionResolver.java	                        (rev 0)
+++ trunk/src/main/org/jboss/seam/security/RuleBasedPermissionResolver.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -0,0 +1,248 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.ScopeType.SESSION;
+import static org.jboss.seam.annotations.Install.FRAMEWORK;
+
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+
+import org.drools.FactHandle;
+import org.drools.RuleBase;
+import org.drools.StatefulSession;
+import org.drools.base.ClassObjectFilter;
+import org.jboss.seam.Component;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.Seam;
+import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.Install;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Observer;
+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.log.LogProvider;
+import org.jboss.seam.log.Logging;
+import org.jboss.seam.security.management.JpaIdentityStore;
+import org.jboss.seam.security.management.SecurityContext;
+import org.jboss.seam.security.management.UserAccount;
+
+ at Name("org.jboss.seam.security.ruleBasedPermissionResolver")
+ at Scope(SESSION)
+ at BypassInterceptors
+ at Install(precedence=FRAMEWORK, classDependencies="org.drools.WorkingMemory")
+ at Startup
+public class RuleBasedPermissionResolver implements PermissionResolver
+{      
+   public static final String RULES_COMPONENT_NAME = "securityRules";   
+   
+   private static final LogProvider log = Logging.getLogProvider(RuleBasedPermissionResolver.class);
+   
+   private StatefulSession securityContext;
+   
+   private RuleBase securityRules;  
+   
+   @Create
+   public boolean create()
+   {
+      initSecurityContext();
+      return getSecurityContext() != null;
+   }
+   
+   protected void initSecurityContext()
+   {
+      if (getSecurityRules() == null)
+      {
+         setSecurityRules((RuleBase) Component.getInstance(RULES_COMPONENT_NAME, true));
+      }
+      
+      if (getSecurityRules() != null)
+      {
+         setSecurityContext(getSecurityRules().newStatefulSession(false));
+      }
+      
+      if (getSecurityContext() == null)
+      {
+         log.warn("no security rule base available - please install a RuleBase with the name '" +
+                  RULES_COMPONENT_NAME + "' if permission checks are required.");
+      }
+   }
+
+   @Observer(Identity.EVENT_POST_AUTHENTICATE)
+   public void postAuthenticate()
+   {
+      if (getSecurityContext() != null)
+      {         
+         getSecurityContext().insert(Identity.instance().getPrincipal());
+      }
+   }
+   
+   /**
+    * Performs a permission check for the specified name and action
+    * 
+    * @param target Object The target of the permission check
+    * @param action String The action to be performed on the target
+    * @return boolean True if the user has the specified permission
+    */
+   public boolean hasPermission(Object target, String action)
+   {           
+      StatefulSession securityContext = getSecurityContext();
+      
+      if (securityContext == null) return false;      
+      
+      List<FactHandle> handles = new ArrayList<FactHandle>();
+                  
+      if (!(target instanceof String) && !(target instanceof Class))
+      {
+         handles.add( securityContext.insert(target) );
+      }
+      
+      if (target instanceof Class)
+      {
+         String componentName = Seam.getComponentName((Class) target);
+         target = componentName != null ? componentName : ((Class) target).getName(); 
+      }
+      
+      PermissionCheck check = new PermissionCheck(target, action);      
+      
+      synchronized( securityContext )
+      {
+         synchronizeContext();
+         
+         handles.add( securityContext.insert(check) );
+
+         securityContext.fireAllRules();
+   
+         for (FactHandle handle : handles)
+            securityContext.retract(handle);
+      }
+      
+      return check.isGranted();
+   }
+   
+   @SuppressWarnings("unchecked")  
+   @Observer(Identity.EVENT_LOGGED_OUT)
+   public void unAuthenticate()
+   {
+      if (getSecurityContext() != null)
+      {
+         getSecurityContext().dispose();      
+         setSecurityContext(null);
+      }
+      initSecurityContext();
+   }
+   
+   /**
+    *  Synchronises the state of the security context with that of the subject
+    */
+   private void synchronizeContext()
+   {
+      Identity identity = Identity.instance();
+      
+      getSecurityContext().insert(identity.getPrincipal());
+      
+      if (getSecurityContext() != null)
+      {
+         for ( Group sg : identity.getSubject().getPrincipals(Group.class) )      
+         {
+            if ( Identity.ROLES_GROUP.equals( sg.getName() ) )
+            {
+               Enumeration e = sg.members();
+               while (e.hasMoreElements())
+               {
+                  Principal role = (Principal) e.nextElement();
+   
+                  boolean found = false;
+                  Iterator<Role> iter = getSecurityContext().iterateObjects(new ClassObjectFilter(Role.class)); 
+                  while (iter.hasNext()) 
+                  {
+                     Role r = iter.next();
+                     if (r.getName().equals(role.getName()))
+                     {
+                        found = true;
+                        break;
+                     }
+                  }
+                  
+                  if (!found)
+                  {
+                     getSecurityContext().insert(new Role(role.getName()));
+                  }
+                  
+               }
+            }
+         }    
+         
+         Iterator<Role> iter = getSecurityContext().iterateObjects(new ClassObjectFilter(Role.class)); 
+         while (iter.hasNext()) 
+         {
+            Role r = iter.next();
+            if (!identity.hasRole(r.getName()))
+            {
+               FactHandle fh = getSecurityContext().getFactHandle(r);
+               getSecurityContext().retract(fh);
+            }
+         }
+      }
+   }
+   
+   
+   public StatefulSession getSecurityContext()
+   {
+      return securityContext;
+   }
+   
+   public void setSecurityContext(StatefulSession securityContext)
+   {
+      this.securityContext = securityContext;
+   }
+   
+
+   public RuleBase getSecurityRules()
+   {
+      return securityRules;
+   }
+
+   public void setSecurityRules(RuleBase securityRules)
+   {
+      this.securityRules = securityRules;
+   }       
+   
+   public static RuleBasedPermissionResolver instance()
+   {
+      if ( !Contexts.isSessionContextActive() )
+      {
+         throw new IllegalStateException("No active session context");
+      }
+
+      RuleBasedPermissionResolver instance = (RuleBasedPermissionResolver) Component.getInstance(
+            RuleBasedPermissionResolver.class, ScopeType.SESSION);
+
+      if (instance == null)
+      {
+         throw new IllegalStateException("No RuleBasedPermissionResolver could be created");
+      }
+
+      return instance;
+   }
+   
+   /**
+    * If we were authenticated with the JpaIdentityStore, then insert the authenticated
+    * UserAccount into the security context.
+    */
+   @Observer(Identity.EVENT_POST_AUTHENTICATE)
+   public void setUserAccountInSecurityContext()
+   {
+      if (Contexts.isEventContextActive() && Contexts.isSessionContextActive() &&
+            Contexts.getEventContext().isSet(JpaIdentityStore.AUTHENTICATED_USER))
+      {
+         SecurityContext context = new SecurityContext();
+         context.setUserAccount((UserAccount) Contexts.getEventContext().get(JpaIdentityStore.AUTHENTICATED_USER));
+         getSecurityContext().insert(context);
+      }
+   }
+}

Modified: trunk/src/main/org/jboss/seam/security/SecurityFunctions.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/SecurityFunctions.java	2008-02-19 13:07:47 UTC (rev 7439)
+++ trunk/src/main/org/jboss/seam/security/SecurityFunctions.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -23,4 +23,9 @@
          return Identity.instance().hasPermission(name, action);
       }
    }
+   
+   public static boolean hasPermission(Object target, String action)
+   {
+      return Identity.instance().hasPermission(target, action);
+   }
 }

Modified: trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java	2008-02-19 13:07:47 UTC (rev 7439)
+++ trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -60,7 +60,7 @@
             }
             else if (target != null && action != null)
             {
-               // TODO implement the security check
+               Identity.instance().checkPermission(target, action);
             }
          }
       }
@@ -162,7 +162,7 @@
     */
    private String createDefaultExpr(Method method)
    {
-      return String.format( "#{s:hasPermission('%s','%s', null)}", 
+      return String.format( "#{s:hasPermission('%s','%s')}", 
             getComponent().getName(), method.getName() );
    }
 }

Modified: trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java	2008-02-19 13:07:47 UTC (rev 7439)
+++ trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -15,9 +15,12 @@
 
 import org.jboss.seam.Component;
 import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.Observer;
 import org.jboss.seam.annotations.Scope;
 import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.contexts.Contexts;
 import org.jboss.seam.core.Events;
+import org.jboss.seam.security.Identity;
 import org.jboss.seam.security.management.UserAccount.AccountType;
 import org.jboss.seam.util.Hex;
 
@@ -30,6 +33,8 @@
 @BypassInterceptors
 public class JpaIdentityStore implements IdentityStore
 {  
+   public static final String AUTHENTICATED_USER = "org.jboss.seam.security.management.authenticatedUser";
+   
    public static final String EVENT_ACCOUNT_CREATED = "org.jboss.seam.security.management.accountCreated"; 
    public static final String EVENT_ACCOUNT_AUTHENTICATED = "org.jboss.seam.security.management.accountAuthenticated";
    
@@ -355,15 +360,30 @@
       }
       
       boolean success = hashPassword(password, username).equals(account.getPasswordHash());
-      
+            
       if (success && Events.exists())
       {
+         if (Contexts.isEventContextActive())
+         {
+            Contexts.getEventContext().set(AUTHENTICATED_USER, account);
+         }
+         
          Events.instance().raiseEvent(EVENT_ACCOUNT_AUTHENTICATED, account);
       }
       
       return success;
    }
    
+   @Observer(Identity.EVENT_POST_AUTHENTICATE)
+   public void setUserAccountForSession()
+   {
+      if (Contexts.isEventContextActive() && Contexts.isSessionContextActive())
+      {
+         Contexts.getSessionContext().set(AUTHENTICATED_USER, 
+               Contexts.getEventContext().get(AUTHENTICATED_USER));
+      }
+   }
+   
    protected UserAccount validateAccount(String name)       
    {
       try

Added: trunk/src/main/org/jboss/seam/security/management/SecurityContext.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/management/SecurityContext.java	                        (rev 0)
+++ trunk/src/main/org/jboss/seam/security/management/SecurityContext.java	2008-02-19 13:31:28 UTC (rev 7440)
@@ -0,0 +1,21 @@
+package org.jboss.seam.security.management;
+
+/**
+ * A wrapper that is inserted into the working memory for rule-based permissions. 
+ * 
+ * @author Shane Bryzak
+ */
+public class SecurityContext
+{  
+   private UserAccount userAccount;
+   
+   public UserAccount getUserAccount()
+   {
+      return userAccount;
+   }
+   
+   public void setUserAccount(UserAccount userAccount)
+   {
+      this.userAccount = userAccount;
+   }
+}




More information about the seam-commits mailing list