[seam-commits] Seam SVN: r12446 - in modules/security/trunk: api and 15 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Tue Apr 13 05:09:09 EDT 2010


Author: shane.bryzak at jboss.com
Date: 2010-04-13 05:09:07 -0400 (Tue, 13 Apr 2010)
New Revision: 12446

Added:
   modules/security/trunk/api/
   modules/security/trunk/api/pom.xml
   modules/security/trunk/api/src/
   modules/security/trunk/api/src/main/
   modules/security/trunk/api/src/main/java/
   modules/security/trunk/api/src/main/java/org/
   modules/security/trunk/api/src/main/java/org/jboss/
   modules/security/trunk/api/src/main/java/org/jboss/seam/
   modules/security/trunk/api/src/main/java/org/jboss/seam/security/
   modules/security/trunk/impl/
   modules/security/trunk/impl/pom.xml
   modules/security/trunk/impl/src/
   modules/security/trunk/impl/src/main/
   modules/security/trunk/impl/src/main/java/
   modules/security/trunk/impl/src/main/java/org/
   modules/security/trunk/impl/src/main/java/org/jboss/
   modules/security/trunk/impl/src/main/java/org/jboss/seam/
   modules/security/trunk/impl/src/main/java/org/jboss/seam/security/
   modules/security/trunk/impl/src/main/java/org/jboss/seam/security/IdentityImpl.java
   modules/security/trunk/impl/src/main/java/org/jboss/seam/security/callbacks/
   modules/security/trunk/impl/src/main/java/org/jboss/seam/security/crypto/
   modules/security/trunk/impl/src/main/java/org/jboss/seam/security/jaas/
   modules/security/trunk/impl/src/main/java/org/jboss/seam/security/management/
   modules/security/trunk/impl/src/main/java/org/jboss/seam/security/permission/
   modules/security/trunk/impl/src/main/java/org/jboss/seam/security/util/
Removed:
   modules/security/trunk/core/src/main/java/org/jboss/seam/security/Identity.java
Modified:
   modules/security/trunk/pom.xml
Log:
split into api and impl projects


Added: modules/security/trunk/api/pom.xml
===================================================================
--- modules/security/trunk/api/pom.xml	                        (rev 0)
+++ modules/security/trunk/api/pom.xml	2010-04-13 09:09:07 UTC (rev 12446)
@@ -0,0 +1,36 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+   <modelVersion>4.0.0</modelVersion>
+
+   <parent>
+      <groupId>org.jboss.seam.security</groupId>
+      <artifactId>seam-security-parent</artifactId>      
+      <version>3.0.0-SNAPSHOT</version>
+   </parent>
+
+   <groupId>org.jboss.seam.security</groupId>
+   <artifactId>seam-security-api</artifactId>
+   <version>3.0.0-SNAPSHOT</version>
+   <packaging>jar</packaging>   
+   <name>Seam Security API</name>
+  
+   <dependencies>
+
+      <dependency>
+         <groupId>javax.enterprise</groupId>
+         <artifactId>cdi-api</artifactId>
+         <scope>provided</scope>
+      </dependency>
+
+   </dependencies>
+
+   <build>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <version>2.6.1</version>
+         </plugin>
+      </plugins>
+   </build>
+
+</project>

Deleted: modules/security/trunk/core/src/main/java/org/jboss/seam/security/Identity.java
===================================================================
--- modules/security/trunk/core/src/main/java/org/jboss/seam/security/Identity.java	2010-04-13 08:51:07 UTC (rev 12445)
+++ modules/security/trunk/core/src/main/java/org/jboss/seam/security/Identity.java	2010-04-13 09:09:07 UTC (rev 12446)
@@ -1,674 +0,0 @@
-package org.jboss.seam.security;
-
-import java.io.IOException;
-import java.io.Serializable;
-import java.security.Principal;
-import java.security.acl.Group;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Set;
-
-import javax.el.ValueExpression;
-import javax.enterprise.context.SessionScoped;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.enterprise.inject.Instance;
-import javax.enterprise.inject.spi.Bean;
-import javax.enterprise.inject.spi.BeanManager;
-import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.Configuration;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import org.jboss.seam.security.callbacks.AuthenticatorCallback;
-import org.jboss.seam.security.callbacks.IdentityCallback;
-import org.jboss.seam.security.callbacks.IdentityManagerCallback;
-import org.jboss.seam.security.events.AlreadyLoggedInEvent;
-import org.jboss.seam.security.events.LoggedInEvent;
-import org.jboss.seam.security.events.LoggedOutEvent;
-import org.jboss.seam.security.events.LoginFailedEvent;
-import org.jboss.seam.security.events.NotAuthorizedEvent;
-import org.jboss.seam.security.events.NotLoggedInEvent;
-import org.jboss.seam.security.events.PostAuthenticateEvent;
-import org.jboss.seam.security.events.PreAuthenticateEvent;
-import org.jboss.seam.security.events.QuietLoginEvent;
-import org.jboss.seam.security.management.IdentityManager;
-import org.jboss.seam.security.permission.PermissionMapper;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * API for authorization and authentication via Seam security.
- * 
- * @author Shane Bryzak
- */
- at Named
- at SessionScoped
-public class Identity implements Serializable
-{
-   private static final long serialVersionUID = 3751659008033189259L;
-   
-   protected static boolean securityEnabled = true;
-   
-   public static final String ROLES_GROUP = "Roles";
-   
-   Logger log = LoggerFactory.getLogger(Identity.class);
-
-   @Inject private BeanManager manager;
-   @Inject private Credentials credentials;
-   @Inject private PermissionMapper permissionMapper;
-   
-   @Inject private IdentityManager identityManager;
-   
-   @Inject Instance<RequestSecurityState> requestSecurityState;
-   
-   private Principal principal;
-   private Subject subject;
-   private String jaasConfigName = null;
-   private List<String> preAuthenticationRoles = new ArrayList<String>();
-   
-   private transient ThreadLocal<Boolean> systemOp;
-   
-   /**
-    * Flag that indicates we are in the process of authenticating
-    */
-   private boolean authenticating = false;
-         
-   @Inject
-   public void create()
-   {
-      subject = new Subject();
-   }
-   
-   public static boolean isSecurityEnabled()
-   {
-      return securityEnabled;
-   }
-   
-   public static void setSecurityEnabled(boolean enabled)
-   {
-      securityEnabled = enabled;
-   }
-   
-   /**
-    * Simple check that returns true if the user is logged in, without attempting to authenticate
-    * 
-    * @return true if the user is logged in
-    */
-   public boolean isLoggedIn()
-   {
-      // If there is a principal set, then the user is logged in.
-      return getPrincipal() != null;
-   }
-   
-   /**
-    * Will attempt to authenticate quietly if the user's credentials are set and they haven't
-    * authenticated already.  A quiet authentication doesn't throw any exceptions if authentication
-    * fails.
-    * 
-    * @return true if the user is logged in, false otherwise
-    */
-   public boolean tryLogin()
-   {      
-      if (!authenticating && getPrincipal() == null && credentials.isSet() && 
-            !requestSecurityState.get().isLoginTried())
-      {
-         requestSecurityState.get().setLoginTried(true);
-         quietLogin();
-      }
-      
-      return isLoggedIn();
-   }
-
-   public Principal getPrincipal()
-   {
-      return principal;
-   }
-   
-   public Subject getSubject()
-   {
-      return subject;
-   }
-   
-   /**
-    * Performs an authorization check, based on the specified security expression.
-    * 
-    * @param expr The security expression to evaluate
-    * @throws NotLoggedInException Thrown if the authorization check fails and
-    * the user is not authenticated
-    * @throws AuthorizationException Thrown if the authorization check fails and
-    * the user is authenticated
-    */
-   // QUESTION should we add the dependency on el-api for the sake of avoiding reinstantiating the VE?
-   
-   // TODO redesign restrictions system to be typesafe
-   /*
-   public void checkRestriction(ValueExpression expression)
-   {
-      if (!securityEnabled)
-      {
-         return;
-      }
-      
-      if (!expressions.getValue(expression, Boolean.class))
-      {
-         if (!isLoggedIn())
-         {
-            manager.fireEvent(new NotLoggedInEvent());
-            
-            log.debug(String.format(
-               "Error evaluating expression [%s] - User not logged in", expression.getExpressionString()));
-            throw new NotLoggedInException();
-         }
-         else
-         {
-            manager.fireEvent(new NotAuthorizedEvent());
-            throw new AuthorizationException(String.format(
-               "Authorization check failed for expression [%s]", expression.getExpressionString()));
-         }
-      }
-   }*/
-   
-   /**
-    * Performs an authorization check, based on the specified security expression string.
-    * 
-    * @param expr The security expression string to evaluate
-    * @throws NotLoggedInException Thrown if the authorization check fails and
-    * the user is not authenticated
-    * @throws AuthorizationException Thrown if the authorization check fails and
-    * the user is authenticated
-    */
-   
-   /*
-   public void checkRestriction(String expr)
-   {
-      if (!securityEnabled)
-      {
-         return;
-      }
-      
-      checkRestriction(expressions.createValueExpression(expr, Boolean.class).toUnifiedValueExpression());
-   }*/
-
-   /**
-    * Attempts to authenticate the user.  This method is distinct to the
-    * authenticate() method in that it raises events in response to whether
-    * authentication is successful or not.  The following events may be raised
-    * by calling login():
-    * 
-    * org.jboss.seam.security.loginSuccessful - raised when authentication is successful
-    * org.jboss.seam.security.loginFailed - raised when authentication fails
-    * org.jboss.seam.security.alreadyLoggedIn - raised if the user is already authenticated
-    * 
-    * @return String returns "loggedIn" if user is authenticated, or null if not.
-    */
-   public String login()
-   {
-      try
-      {
-         if (isLoggedIn())
-         {
-            // If authentication has already occurred during this request via a silent login,
-            // and login() is explicitly called then we still want to raise the LOGIN_SUCCESSFUL event,
-            // and then return.
-            if (requestSecurityState.get().isSilentLogin())
-            {
-               manager.fireEvent(new LoggedInEvent(principal));
-               return "loggedIn";
-            }
-            
-            manager.fireEvent(new AlreadyLoggedInEvent());
-            return "loggedIn";
-         }
-         
-         authenticate();
-         
-         if (!isLoggedIn())
-         {
-            throw new LoginException();
-         }
-         
-         if ( log.isDebugEnabled() )
-         {
-            log.debug("Login successful for: " + credentials);
-         }
-
-         manager.fireEvent(new LoggedInEvent(principal));
-         return "loggedIn";
-      }
-      catch (LoginException ex)
-      {
-         credentials.invalidate();
-         
-         if ( log.isDebugEnabled() )
-         {
-             log.debug("Login failed for: " + credentials, ex);
-         }
-         
-         manager.fireEvent(new LoginFailedEvent(ex));
-      }
-      
-      return null;
-   }
-   
-   /**
-    * Attempts a quiet login, suppressing any login exceptions and not creating
-    * any faces messages. This method is intended to be used primarily as an
-    * internal API call, however has been made public for convenience.
-    */
-   public void quietLogin()
-   {
-      try
-      {
-         manager.fireEvent(new QuietLoginEvent());
-          
-         // Ensure that we haven't been authenticated as a result of the EVENT_QUIET_LOGIN event
-         if (!isLoggedIn())
-         {
-            if (credentials.isSet())
-            {
-               authenticate();
-               
-               if (isLoggedIn())
-               {
-                  requestSecurityState.get().setSilentLogin(true);
-               }
-            }
-         }
-      }
-      catch (LoginException ex)
-      {
-         credentials.invalidate();
-      }
-   }
-
-   /**
-    * 
-    * @throws LoginException
-    */
-   public synchronized void authenticate()
-      throws LoginException
-   {
-      // If we're already authenticated, then don't authenticate again
-      if (!isLoggedIn() && !credentials.isInvalid())
-      {
-         principal = null;
-         subject = new Subject();
-         authenticate( getLoginContext() );
-      }
-   }
-
-    
-   protected void authenticate(LoginContext loginContext)
-      throws LoginException
-   {
-      try
-      {
-         authenticating = true;
-         preAuthenticate();
-         loginContext.login();
-         postAuthenticate();
-      }
-      finally
-      {
-         // Set password to null whether authentication is successful or not
-         credentials.setPassword(null);
-         authenticating = false;
-      }
-   }
-   
-   /**
-    * Clears any roles added by calling addRole() while not authenticated.
-    * This method may be overridden by a subclass if different
-    * pre-authentication logic should occur.
-    */
-   protected void preAuthenticate()
-   {
-      preAuthenticationRoles.clear();
-      manager.fireEvent(new PreAuthenticateEvent());
-   }
-   
-   /**
-    * Extracts the principal from the subject, and populates the roles of the
-    * authenticated user.  This method may be overridden by a subclass if
-    * different post-authentication logic should occur.
-    */
-   protected void postAuthenticate()
-   {
-      // Populate the working memory with the user's principals
-      for ( Principal p : getSubject().getPrincipals() )
-      {
-         if ( !(p instanceof Group))
-         {
-            if (principal == null)
-            {
-               principal = p;
-               break;
-            }
-         }
-      }
-      
-      if (!preAuthenticationRoles.isEmpty() && isLoggedIn())
-      {
-         for (String role : preAuthenticationRoles)
-         {
-            addRole(role);
-         }
-         preAuthenticationRoles.clear();
-      }
-
-      credentials.setPassword(null);
-      
-      manager.fireEvent(new PostAuthenticateEvent());
-   }
-   
-   /**
-    * Resets all security state and credentials
-    */
-   public void unAuthenticate()
-   {
-      principal = null;
-      subject = new Subject();
-      
-      credentials.clear();
-   }
-
-   protected LoginContext getLoginContext() throws LoginException
-   {
-      if (getJaasConfigName() != null)
-      {
-         return new LoginContext(getJaasConfigName(), getSubject(),
-                  createCallbackHandler());
-      }
-      
-      @SuppressWarnings("unchecked")
-      Bean<Configuration> configBean = (Bean<Configuration>) manager.getBeans(Configuration.class).iterator().next();
-      Configuration config = (Configuration) manager.getReference(configBean, Configuration.class, manager.createCreationalContext(configBean));
-      
-      return new LoginContext(JaasConfiguration.DEFAULT_JAAS_CONFIG_NAME, getSubject(),
-            createCallbackHandler(), config);
-   }
-   
-   
-   /**
-    * Creates a callback handler that can handle a standard username/password
-    * callback, using the credentials username and password properties
-    */
-   public CallbackHandler createCallbackHandler()
-   {
-      final Identity identity = this;
-      final Authenticator authenticator;
-      
-      Set<Bean<?>> authenticators = manager.getBeans(Authenticator.class);
-      if (authenticators.size() == 1)
-      {
-         @SuppressWarnings("unchecked")
-         Bean<Authenticator> authenticatorBean = (Bean<Authenticator>) authenticators.iterator().next();
-         authenticator = (Authenticator) manager.getReference(authenticatorBean, Authenticator.class, manager.createCreationalContext(authenticatorBean));
-      }
-      else if (authenticators.size() > 1)
-      {
-         throw new IllegalStateException("More than one Authenticator bean found - please ensure " +
-               "only one Authenticator implementation is provided");
-      }
-      else
-      {
-         authenticator = null;
-      }
-      
-      return new CallbackHandler()
-      {
-         public void handle(Callback[] callbacks)
-            throws IOException, UnsupportedCallbackException
-         {
-            for (int i=0; i < callbacks.length; i++)
-            {
-               if (callbacks[i] instanceof NameCallback)
-               {
-                  ( (NameCallback) callbacks[i] ).setName(credentials.getUsername());
-               }
-               else if (callbacks[i] instanceof PasswordCallback)
-               {
-                  ( (PasswordCallback) callbacks[i] ).setPassword( credentials.getPassword() != null ?
-                           credentials.getPassword().toCharArray() : null );
-               }
-               else if (callbacks[i] instanceof IdentityCallback)
-               {
-                  ((IdentityCallback ) callbacks[i]).setIdentity(identity);
-               }
-               else if (callbacks[i] instanceof AuthenticatorCallback)
-               {
-                  ((AuthenticatorCallback) callbacks[i]).setAuthenticator(authenticator);
-               }
-               else if (callbacks[i] instanceof IdentityManagerCallback)
-               {
-                  ((IdentityManagerCallback) callbacks[i]).setIdentityManager(identityManager);
-               }
-               else
-               {
-                  log.warn("Unsupported callback " + callbacks[i]);
-               }
-            }
-         }
-      };
-   }
-   
-   public void logout()
-   {
-      if (isLoggedIn())
-      {
-         LoggedOutEvent loggedOutEvent = new LoggedOutEvent(principal);
-         unAuthenticate();
-         
-         // TODO - invalidate the session
-         // Session.instance().invalidate();
-         
-         manager.fireEvent(loggedOutEvent);
-      }
-   }
-
-   /**
-    * Checks if the authenticated user is a member of the specified role.
-    * 
-    * @param role String The name of the role to check
-    * @return boolean True if the user is a member of the specified role
-    */
-   public boolean hasRole(String role)
-   {
-      if (!securityEnabled) return true;
-      if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return true;
-      
-      tryLogin();
-      
-      for ( Group sg : getSubject().getPrincipals(Group.class) )
-      {
-         if ( ROLES_GROUP.equals( sg.getName() ) )
-         {
-            return sg.isMember( new Role(role) );
-         }
-      }
-      return false;
-   }
-   
-   /**
-    * Adds a role to the authenticated user.  If the user is not logged in,
-    * the role will be added to a list of roles that will be granted to the
-    * user upon successful authentication, but only during the authentication
-    * process.
-    * 
-    * @param role The name of the role to add
-    */
-   public boolean addRole(String role)
-   {
-      if (role == null || "".equals(role)) return false;
-      
-      if (!isLoggedIn())
-      {
-         preAuthenticationRoles.add(role);
-         return false;
-      }
-      else
-      {
-         for ( Group sg : getSubject().getPrincipals(Group.class) )
-         {
-            if ( ROLES_GROUP.equals( sg.getName() ) )
-            {
-               return sg.addMember(new Role(role));
-            }
-         }
-                  
-         SimpleGroup roleGroup = new SimpleGroup(ROLES_GROUP);
-         roleGroup.addMember(new Role(role));
-         getSubject().getPrincipals().add(roleGroup);
-         return true;
-      }
-   }
-
-   /**
-    * Removes a role from the authenticated user
-    * 
-    * @param role The name of the role to remove
-    */
-   public void removeRole(String role)
-   {
-      for ( Group sg : getSubject().getPrincipals(Group.class) )
-      {
-         if ( ROLES_GROUP.equals( sg.getName() ) )
-         {
-            Enumeration<?> e = sg.members();
-            while (e.hasMoreElements())
-            {
-               Principal member = (Principal) e.nextElement();
-               if (member.getName().equals(role))
-               {
-                  sg.removeMember(member);
-                  break;
-               }
-            }
-
-         }
-      }
-   }
-   
-   /**
-    * Checks that the current authenticated user is a member of
-    * the specified role.
-    * 
-    * @param role String The name of the role to check
-    * @throws AuthorizationException if the authenticated user is not a member of the role
-    */
-   public void checkRole(String role)
-   {
-      tryLogin();
-      
-      if ( !hasRole(role) )
-      {
-         if ( !isLoggedIn() )
-         {
-            manager.fireEvent(new NotLoggedInEvent());
-            throw new NotLoggedInException();
-         }
-         else
-         {
-            manager.fireEvent(new NotAuthorizedEvent());
-            throw new AuthorizationException(String.format(
-                  "Authorization check failed for role [%s]", role));
-         }
-      }
-   }
-   
-   public void checkPermission(Object target, String action)
-   {
-      if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return;
-      
-      tryLogin();
-      
-      if ( !hasPermission(target, action) )
-      {
-         if ( !isLoggedIn() )
-         {
-            manager.fireEvent(new NotLoggedInEvent());
-            throw new NotLoggedInException();
-         }
-         else
-         {
-            manager.fireEvent(new NotAuthorizedEvent());
-            throw new AuthorizationException(String.format(
-                  "Authorization check failed for permission[%s,%s]", target, action));
-         }
-      }
-   }
-   
-   public void filterByPermission(Collection<?> collection, String action)
-   {
-      permissionMapper.filterByPermission(collection, action);
-   }
-   
-   public boolean hasPermission(Object target, String action)
-   {
-      if (!securityEnabled) return true;
-      if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return true;
-      if (permissionMapper == null) return false;
-      if (target == null) return false;
-      
-      return permissionMapper.resolvePermission(target, action);
-   }
-   
-   /**
-    * Evaluates the specified security expression, which must return a boolean
-    * value.
-    * 
-    * @param expr String The expression to evaluate
-    * @return boolean The result of the expression evaluation
-    */
-   /*
-   protected boolean evaluateExpression(String expr)
-   {
-      return expressions.createValueExpression(expr, Boolean.class).getValue();
-   }*/
-   
-   public String getJaasConfigName()
-   {
-      return jaasConfigName;
-   }
-   
-   public void setJaasConfigName(String jaasConfigName)
-   {
-      this.jaasConfigName = jaasConfigName;
-   }
-   
-   public synchronized void runAs(RunAsOperation operation)
-   {
-      Principal savedPrincipal = getPrincipal();
-      Subject savedSubject = getSubject();
-      
-      try
-      {
-         principal = operation.getPrincipal();
-         subject = operation.getSubject();
-         
-         if (systemOp == null)
-         {
-            systemOp = new ThreadLocal<Boolean>();
-         }
-         
-         systemOp.set(operation.isSystemOperation());
-         
-         operation.execute();
-      }
-      finally
-      {
-         systemOp.set(false);
-         principal = savedPrincipal;
-         subject = savedSubject;
-      }
-   }
-}

Added: modules/security/trunk/impl/pom.xml
===================================================================
--- modules/security/trunk/impl/pom.xml	                        (rev 0)
+++ modules/security/trunk/impl/pom.xml	2010-04-13 09:09:07 UTC (rev 12446)
@@ -0,0 +1,72 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+   <modelVersion>4.0.0</modelVersion>
+
+   <parent>
+      <groupId>org.jboss.seam.security</groupId>
+      <artifactId>seam-security-parent</artifactId>      
+      <version>3.0.0-SNAPSHOT</version>
+   </parent>
+
+   <groupId>org.jboss.seam.security</groupId>
+   <artifactId>seam-security-impl</artifactId>
+   <version>3.0.0-SNAPSHOT</version>
+   <packaging>jar</packaging>   
+   <name>Seam Security Implementation</name>
+  
+   <dependencies>
+      <dependency>
+         <groupId>javax.el</groupId>
+         <artifactId>el-api</artifactId>
+      </dependency>
+
+      <dependency>
+         <groupId>javax.validation</groupId>
+         <artifactId>validation-api</artifactId>
+         <scope>provided</scope>
+      </dependency>
+
+      <dependency>
+         <groupId>javax.enterprise</groupId>
+         <artifactId>cdi-api</artifactId>
+         <scope>provided</scope>
+      </dependency>
+
+      <dependency>
+         <groupId>org.slf4j</groupId>
+         <artifactId>slf4j-api</artifactId>
+         <scope>provided</scope>
+      </dependency>
+
+      <dependency>
+         <groupId>javax.persistence</groupId>
+         <artifactId>persistence-api</artifactId>
+      </dependency>
+
+      <dependency>
+         <groupId>org.jboss.seam.drools</groupId>
+         <artifactId>seam-drools-core</artifactId>
+      </dependency>
+
+      <dependency>
+         <groupId>org.jboss.seam</groupId>
+         <artifactId>seam-persistence</artifactId>
+      </dependency>
+       
+      <dependency>
+         <groupId>org.hibernate</groupId>
+         <artifactId>hibernate-core</artifactId>
+      </dependency>
+
+   </dependencies>
+
+   <build>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <version>2.6.1</version>
+         </plugin>
+      </plugins>
+   </build>
+
+</project>

Copied: modules/security/trunk/impl/src/main/java/org/jboss/seam/security/IdentityImpl.java (from rev 12256, modules/security/trunk/core/src/main/java/org/jboss/seam/security/Identity.java)
===================================================================
--- modules/security/trunk/impl/src/main/java/org/jboss/seam/security/IdentityImpl.java	                        (rev 0)
+++ modules/security/trunk/impl/src/main/java/org/jboss/seam/security/IdentityImpl.java	2010-04-13 09:09:07 UTC (rev 12446)
@@ -0,0 +1,674 @@
+package org.jboss.seam.security;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+
+import javax.el.ValueExpression;
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.jboss.seam.security.callbacks.AuthenticatorCallback;
+import org.jboss.seam.security.callbacks.IdentityCallback;
+import org.jboss.seam.security.callbacks.IdentityManagerCallback;
+import org.jboss.seam.security.events.AlreadyLoggedInEvent;
+import org.jboss.seam.security.events.LoggedInEvent;
+import org.jboss.seam.security.events.LoggedOutEvent;
+import org.jboss.seam.security.events.LoginFailedEvent;
+import org.jboss.seam.security.events.NotAuthorizedEvent;
+import org.jboss.seam.security.events.NotLoggedInEvent;
+import org.jboss.seam.security.events.PostAuthenticateEvent;
+import org.jboss.seam.security.events.PreAuthenticateEvent;
+import org.jboss.seam.security.events.QuietLoginEvent;
+import org.jboss.seam.security.management.IdentityManager;
+import org.jboss.seam.security.permission.PermissionMapper;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * API for authorization and authentication via Seam security.
+ * 
+ * @author Shane Bryzak
+ */
+ at Named
+ at SessionScoped
+public class Identity implements Serializable
+{
+   private static final long serialVersionUID = 3751659008033189259L;
+   
+   protected static boolean securityEnabled = true;
+   
+   public static final String ROLES_GROUP = "Roles";
+   
+   Logger log = LoggerFactory.getLogger(Identity.class);
+
+   @Inject private BeanManager manager;
+   @Inject private Credentials credentials;
+   @Inject private PermissionMapper permissionMapper;
+   
+   @Inject private IdentityManager identityManager;
+   
+   @Inject Instance<RequestSecurityState> requestSecurityState;
+   
+   private Principal principal;
+   private Subject subject;
+   private String jaasConfigName = null;
+   private List<String> preAuthenticationRoles = new ArrayList<String>();
+   
+   private transient ThreadLocal<Boolean> systemOp;
+   
+   /**
+    * Flag that indicates we are in the process of authenticating
+    */
+   private boolean authenticating = false;
+         
+   @Inject
+   public void create()
+   {
+      subject = new Subject();
+   }
+   
+   public static boolean isSecurityEnabled()
+   {
+      return securityEnabled;
+   }
+   
+   public static void setSecurityEnabled(boolean enabled)
+   {
+      securityEnabled = enabled;
+   }
+   
+   /**
+    * Simple check that returns true if the user is logged in, without attempting to authenticate
+    * 
+    * @return true if the user is logged in
+    */
+   public boolean isLoggedIn()
+   {
+      // If there is a principal set, then the user is logged in.
+      return getPrincipal() != null;
+   }
+   
+   /**
+    * Will attempt to authenticate quietly if the user's credentials are set and they haven't
+    * authenticated already.  A quiet authentication doesn't throw any exceptions if authentication
+    * fails.
+    * 
+    * @return true if the user is logged in, false otherwise
+    */
+   public boolean tryLogin()
+   {      
+      if (!authenticating && getPrincipal() == null && credentials.isSet() && 
+            !requestSecurityState.get().isLoginTried())
+      {
+         requestSecurityState.get().setLoginTried(true);
+         quietLogin();
+      }
+      
+      return isLoggedIn();
+   }
+
+   public Principal getPrincipal()
+   {
+      return principal;
+   }
+   
+   public Subject getSubject()
+   {
+      return subject;
+   }
+   
+   /**
+    * Performs an authorization check, based on the specified security expression.
+    * 
+    * @param expr The security expression to evaluate
+    * @throws NotLoggedInException Thrown if the authorization check fails and
+    * the user is not authenticated
+    * @throws AuthorizationException Thrown if the authorization check fails and
+    * the user is authenticated
+    */
+   // QUESTION should we add the dependency on el-api for the sake of avoiding reinstantiating the VE?
+   
+   // TODO redesign restrictions system to be typesafe
+   /*
+   public void checkRestriction(ValueExpression expression)
+   {
+      if (!securityEnabled)
+      {
+         return;
+      }
+      
+      if (!expressions.getValue(expression, Boolean.class))
+      {
+         if (!isLoggedIn())
+         {
+            manager.fireEvent(new NotLoggedInEvent());
+            
+            log.debug(String.format(
+               "Error evaluating expression [%s] - User not logged in", expression.getExpressionString()));
+            throw new NotLoggedInException();
+         }
+         else
+         {
+            manager.fireEvent(new NotAuthorizedEvent());
+            throw new AuthorizationException(String.format(
+               "Authorization check failed for expression [%s]", expression.getExpressionString()));
+         }
+      }
+   }*/
+   
+   /**
+    * Performs an authorization check, based on the specified security expression string.
+    * 
+    * @param expr The security expression string to evaluate
+    * @throws NotLoggedInException Thrown if the authorization check fails and
+    * the user is not authenticated
+    * @throws AuthorizationException Thrown if the authorization check fails and
+    * the user is authenticated
+    */
+   
+   /*
+   public void checkRestriction(String expr)
+   {
+      if (!securityEnabled)
+      {
+         return;
+      }
+      
+      checkRestriction(expressions.createValueExpression(expr, Boolean.class).toUnifiedValueExpression());
+   }*/
+
+   /**
+    * Attempts to authenticate the user.  This method is distinct to the
+    * authenticate() method in that it raises events in response to whether
+    * authentication is successful or not.  The following events may be raised
+    * by calling login():
+    * 
+    * org.jboss.seam.security.loginSuccessful - raised when authentication is successful
+    * org.jboss.seam.security.loginFailed - raised when authentication fails
+    * org.jboss.seam.security.alreadyLoggedIn - raised if the user is already authenticated
+    * 
+    * @return String returns "loggedIn" if user is authenticated, or null if not.
+    */
+   public String login()
+   {
+      try
+      {
+         if (isLoggedIn())
+         {
+            // If authentication has already occurred during this request via a silent login,
+            // and login() is explicitly called then we still want to raise the LOGIN_SUCCESSFUL event,
+            // and then return.
+            if (requestSecurityState.get().isSilentLogin())
+            {
+               manager.fireEvent(new LoggedInEvent(principal));
+               return "loggedIn";
+            }
+            
+            manager.fireEvent(new AlreadyLoggedInEvent());
+            return "loggedIn";
+         }
+         
+         authenticate();
+         
+         if (!isLoggedIn())
+         {
+            throw new LoginException();
+         }
+         
+         if ( log.isDebugEnabled() )
+         {
+            log.debug("Login successful for: " + credentials);
+         }
+
+         manager.fireEvent(new LoggedInEvent(principal));
+         return "loggedIn";
+      }
+      catch (LoginException ex)
+      {
+         credentials.invalidate();
+         
+         if ( log.isDebugEnabled() )
+         {
+             log.debug("Login failed for: " + credentials, ex);
+         }
+         
+         manager.fireEvent(new LoginFailedEvent(ex));
+      }
+      
+      return null;
+   }
+   
+   /**
+    * Attempts a quiet login, suppressing any login exceptions and not creating
+    * any faces messages. This method is intended to be used primarily as an
+    * internal API call, however has been made public for convenience.
+    */
+   public void quietLogin()
+   {
+      try
+      {
+         manager.fireEvent(new QuietLoginEvent());
+          
+         // Ensure that we haven't been authenticated as a result of the EVENT_QUIET_LOGIN event
+         if (!isLoggedIn())
+         {
+            if (credentials.isSet())
+            {
+               authenticate();
+               
+               if (isLoggedIn())
+               {
+                  requestSecurityState.get().setSilentLogin(true);
+               }
+            }
+         }
+      }
+      catch (LoginException ex)
+      {
+         credentials.invalidate();
+      }
+   }
+
+   /**
+    * 
+    * @throws LoginException
+    */
+   public synchronized void authenticate()
+      throws LoginException
+   {
+      // If we're already authenticated, then don't authenticate again
+      if (!isLoggedIn() && !credentials.isInvalid())
+      {
+         principal = null;
+         subject = new Subject();
+         authenticate( getLoginContext() );
+      }
+   }
+
+    
+   protected void authenticate(LoginContext loginContext)
+      throws LoginException
+   {
+      try
+      {
+         authenticating = true;
+         preAuthenticate();
+         loginContext.login();
+         postAuthenticate();
+      }
+      finally
+      {
+         // Set password to null whether authentication is successful or not
+         credentials.setPassword(null);
+         authenticating = false;
+      }
+   }
+   
+   /**
+    * Clears any roles added by calling addRole() while not authenticated.
+    * This method may be overridden by a subclass if different
+    * pre-authentication logic should occur.
+    */
+   protected void preAuthenticate()
+   {
+      preAuthenticationRoles.clear();
+      manager.fireEvent(new PreAuthenticateEvent());
+   }
+   
+   /**
+    * Extracts the principal from the subject, and populates the roles of the
+    * authenticated user.  This method may be overridden by a subclass if
+    * different post-authentication logic should occur.
+    */
+   protected void postAuthenticate()
+   {
+      // Populate the working memory with the user's principals
+      for ( Principal p : getSubject().getPrincipals() )
+      {
+         if ( !(p instanceof Group))
+         {
+            if (principal == null)
+            {
+               principal = p;
+               break;
+            }
+         }
+      }
+      
+      if (!preAuthenticationRoles.isEmpty() && isLoggedIn())
+      {
+         for (String role : preAuthenticationRoles)
+         {
+            addRole(role);
+         }
+         preAuthenticationRoles.clear();
+      }
+
+      credentials.setPassword(null);
+      
+      manager.fireEvent(new PostAuthenticateEvent());
+   }
+   
+   /**
+    * Resets all security state and credentials
+    */
+   public void unAuthenticate()
+   {
+      principal = null;
+      subject = new Subject();
+      
+      credentials.clear();
+   }
+
+   protected LoginContext getLoginContext() throws LoginException
+   {
+      if (getJaasConfigName() != null)
+      {
+         return new LoginContext(getJaasConfigName(), getSubject(),
+                  createCallbackHandler());
+      }
+      
+      @SuppressWarnings("unchecked")
+      Bean<Configuration> configBean = (Bean<Configuration>) manager.getBeans(Configuration.class).iterator().next();
+      Configuration config = (Configuration) manager.getReference(configBean, Configuration.class, manager.createCreationalContext(configBean));
+      
+      return new LoginContext(JaasConfiguration.DEFAULT_JAAS_CONFIG_NAME, getSubject(),
+            createCallbackHandler(), config);
+   }
+   
+   
+   /**
+    * Creates a callback handler that can handle a standard username/password
+    * callback, using the credentials username and password properties
+    */
+   public CallbackHandler createCallbackHandler()
+   {
+      final Identity identity = this;
+      final Authenticator authenticator;
+      
+      Set<Bean<?>> authenticators = manager.getBeans(Authenticator.class);
+      if (authenticators.size() == 1)
+      {
+         @SuppressWarnings("unchecked")
+         Bean<Authenticator> authenticatorBean = (Bean<Authenticator>) authenticators.iterator().next();
+         authenticator = (Authenticator) manager.getReference(authenticatorBean, Authenticator.class, manager.createCreationalContext(authenticatorBean));
+      }
+      else if (authenticators.size() > 1)
+      {
+         throw new IllegalStateException("More than one Authenticator bean found - please ensure " +
+               "only one Authenticator implementation is provided");
+      }
+      else
+      {
+         authenticator = null;
+      }
+      
+      return new CallbackHandler()
+      {
+         public void handle(Callback[] callbacks)
+            throws IOException, UnsupportedCallbackException
+         {
+            for (int i=0; i < callbacks.length; i++)
+            {
+               if (callbacks[i] instanceof NameCallback)
+               {
+                  ( (NameCallback) callbacks[i] ).setName(credentials.getUsername());
+               }
+               else if (callbacks[i] instanceof PasswordCallback)
+               {
+                  ( (PasswordCallback) callbacks[i] ).setPassword( credentials.getPassword() != null ?
+                           credentials.getPassword().toCharArray() : null );
+               }
+               else if (callbacks[i] instanceof IdentityCallback)
+               {
+                  ((IdentityCallback ) callbacks[i]).setIdentity(identity);
+               }
+               else if (callbacks[i] instanceof AuthenticatorCallback)
+               {
+                  ((AuthenticatorCallback) callbacks[i]).setAuthenticator(authenticator);
+               }
+               else if (callbacks[i] instanceof IdentityManagerCallback)
+               {
+                  ((IdentityManagerCallback) callbacks[i]).setIdentityManager(identityManager);
+               }
+               else
+               {
+                  log.warn("Unsupported callback " + callbacks[i]);
+               }
+            }
+         }
+      };
+   }
+   
+   public void logout()
+   {
+      if (isLoggedIn())
+      {
+         LoggedOutEvent loggedOutEvent = new LoggedOutEvent(principal);
+         unAuthenticate();
+         
+         // TODO - invalidate the session
+         // Session.instance().invalidate();
+         
+         manager.fireEvent(loggedOutEvent);
+      }
+   }
+
+   /**
+    * Checks if the authenticated user is a member of the specified role.
+    * 
+    * @param role String The name of the role to check
+    * @return boolean True if the user is a member of the specified role
+    */
+   public boolean hasRole(String role)
+   {
+      if (!securityEnabled) return true;
+      if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return true;
+      
+      tryLogin();
+      
+      for ( Group sg : getSubject().getPrincipals(Group.class) )
+      {
+         if ( ROLES_GROUP.equals( sg.getName() ) )
+         {
+            return sg.isMember( new Role(role) );
+         }
+      }
+      return false;
+   }
+   
+   /**
+    * Adds a role to the authenticated user.  If the user is not logged in,
+    * the role will be added to a list of roles that will be granted to the
+    * user upon successful authentication, but only during the authentication
+    * process.
+    * 
+    * @param role The name of the role to add
+    */
+   public boolean addRole(String role)
+   {
+      if (role == null || "".equals(role)) return false;
+      
+      if (!isLoggedIn())
+      {
+         preAuthenticationRoles.add(role);
+         return false;
+      }
+      else
+      {
+         for ( Group sg : getSubject().getPrincipals(Group.class) )
+         {
+            if ( ROLES_GROUP.equals( sg.getName() ) )
+            {
+               return sg.addMember(new Role(role));
+            }
+         }
+                  
+         SimpleGroup roleGroup = new SimpleGroup(ROLES_GROUP);
+         roleGroup.addMember(new Role(role));
+         getSubject().getPrincipals().add(roleGroup);
+         return true;
+      }
+   }
+
+   /**
+    * Removes a role from the authenticated user
+    * 
+    * @param role The name of the role to remove
+    */
+   public void removeRole(String role)
+   {
+      for ( Group sg : getSubject().getPrincipals(Group.class) )
+      {
+         if ( ROLES_GROUP.equals( sg.getName() ) )
+         {
+            Enumeration<?> e = sg.members();
+            while (e.hasMoreElements())
+            {
+               Principal member = (Principal) e.nextElement();
+               if (member.getName().equals(role))
+               {
+                  sg.removeMember(member);
+                  break;
+               }
+            }
+
+         }
+      }
+   }
+   
+   /**
+    * Checks that the current authenticated user is a member of
+    * the specified role.
+    * 
+    * @param role String The name of the role to check
+    * @throws AuthorizationException if the authenticated user is not a member of the role
+    */
+   public void checkRole(String role)
+   {
+      tryLogin();
+      
+      if ( !hasRole(role) )
+      {
+         if ( !isLoggedIn() )
+         {
+            manager.fireEvent(new NotLoggedInEvent());
+            throw new NotLoggedInException();
+         }
+         else
+         {
+            manager.fireEvent(new NotAuthorizedEvent());
+            throw new AuthorizationException(String.format(
+                  "Authorization check failed for role [%s]", role));
+         }
+      }
+   }
+   
+   public void checkPermission(Object target, String action)
+   {
+      if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return;
+      
+      tryLogin();
+      
+      if ( !hasPermission(target, action) )
+      {
+         if ( !isLoggedIn() )
+         {
+            manager.fireEvent(new NotLoggedInEvent());
+            throw new NotLoggedInException();
+         }
+         else
+         {
+            manager.fireEvent(new NotAuthorizedEvent());
+            throw new AuthorizationException(String.format(
+                  "Authorization check failed for permission[%s,%s]", target, action));
+         }
+      }
+   }
+   
+   public void filterByPermission(Collection<?> collection, String action)
+   {
+      permissionMapper.filterByPermission(collection, action);
+   }
+   
+   public boolean hasPermission(Object target, String action)
+   {
+      if (!securityEnabled) return true;
+      if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return true;
+      if (permissionMapper == null) return false;
+      if (target == null) return false;
+      
+      return permissionMapper.resolvePermission(target, action);
+   }
+   
+   /**
+    * Evaluates the specified security expression, which must return a boolean
+    * value.
+    * 
+    * @param expr String The expression to evaluate
+    * @return boolean The result of the expression evaluation
+    */
+   /*
+   protected boolean evaluateExpression(String expr)
+   {
+      return expressions.createValueExpression(expr, Boolean.class).getValue();
+   }*/
+   
+   public String getJaasConfigName()
+   {
+      return jaasConfigName;
+   }
+   
+   public void setJaasConfigName(String jaasConfigName)
+   {
+      this.jaasConfigName = jaasConfigName;
+   }
+   
+   public synchronized void runAs(RunAsOperation operation)
+   {
+      Principal savedPrincipal = getPrincipal();
+      Subject savedSubject = getSubject();
+      
+      try
+      {
+         principal = operation.getPrincipal();
+         subject = operation.getSubject();
+         
+         if (systemOp == null)
+         {
+            systemOp = new ThreadLocal<Boolean>();
+         }
+         
+         systemOp.set(operation.isSystemOperation());
+         
+         operation.execute();
+      }
+      finally
+      {
+         systemOp.set(false);
+         principal = savedPrincipal;
+         subject = savedSubject;
+      }
+   }
+}

Modified: modules/security/trunk/pom.xml
===================================================================
--- modules/security/trunk/pom.xml	2010-04-13 08:51:07 UTC (rev 12445)
+++ modules/security/trunk/pom.xml	2010-04-13 09:09:07 UTC (rev 12446)
@@ -16,7 +16,8 @@
    <name>Seam Security Parent</name>
 
    <modules>
-      <module>core</module>
+      <module>api</module>
+      <module>impl</module>
       <!--module>docs</module-->
       <module>examples/seamspace</module>
    </modules>
@@ -59,10 +60,16 @@
          </dependency>
   
          <dependency>
-            <groupId>org.drools</groupId>
-            <artifactId>drools-core</artifactId>
-            <version>5.1.0.M1</version>
+            <groupId>org.jboss.seam.drools</groupId>
+            <artifactId>seam-drools-core</artifactId>
+            <version>3.0.0-SNAPSHOT</version>
          </dependency>
+
+         <dependency>
+            <groupId>org.jboss.seam</groupId>
+            <artifactId>seam-persistence</artifactId>
+            <version>3.0.0-SNAPSHOT</version>
+         </dependency>
   
          <dependency>
             <groupId>org.hibernate</groupId>



More information about the seam-commits mailing list