[seam-commits] Seam SVN: r7808 - trunk/src/main/org/jboss/seam/security/management.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Thu Apr 3 07:41:20 EDT 2008


Author: shane.bryzak at jboss.com
Date: 2008-04-03 07:41:20 -0400 (Thu, 03 Apr 2008)
New Revision: 7808

Removed:
   trunk/src/main/org/jboss/seam/security/management/UserAccount.java
Modified:
   trunk/src/main/org/jboss/seam/security/management/IdentityManager.java
   trunk/src/main/org/jboss/seam/security/management/IdentityStore.java
   trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java
   trunk/src/main/org/jboss/seam/security/management/LdapIdentityStore.java
Log:
first pass of identity management changes

Modified: trunk/src/main/org/jboss/seam/security/management/IdentityManager.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/management/IdentityManager.java	2008-04-03 11:34:45 UTC (rev 7807)
+++ trunk/src/main/org/jboss/seam/security/management/IdentityManager.java	2008-04-03 11:41:20 UTC (rev 7808)
@@ -1,6 +1,6 @@
 package org.jboss.seam.security.management;
 
-import static org.jboss.seam.ScopeType.APPLICATION;
+import static org.jboss.seam.ScopeType.EVENT;
 import static org.jboss.seam.annotations.Install.BUILT_IN;
 
 import java.io.Serializable;
@@ -9,11 +9,11 @@
 import java.util.List;
 
 import org.jboss.seam.Component;
-import org.jboss.seam.ScopeType;
 import org.jboss.seam.annotations.Create;
 import org.jboss.seam.annotations.Install;
 import org.jboss.seam.annotations.Name;
 import org.jboss.seam.annotations.Scope;
+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;
@@ -24,9 +24,10 @@
  * 
  * @author Shane Bryzak
  */
- at Scope(APPLICATION)
+ at Scope(EVENT)
 @Name("org.jboss.seam.security.management.identityManager")
 @Install(precedence = BUILT_IN)
+ at BypassInterceptors
 public class IdentityManager implements Serializable
 {
    public static final String ACCOUNT_PERMISSION_NAME = "seam.account";
@@ -49,6 +50,12 @@
    
    protected void initIdentityStore()
    {    
+      // Default to JpaIdentityStore
+      if (identityStore == null)
+      {
+         identityStore = (IdentityStore) Component.getInstance(JpaIdentityStore.class, true);
+      }
+      
       if (roleIdentityStore == null && identityStore != null)
       {
          roleIdentityStore = identityStore;
@@ -63,13 +70,13 @@
    
    public static IdentityManager instance()
    {
-      if ( !Contexts.isApplicationContextActive() )
+      if ( !Contexts.isEventContextActive() )
       {
-         throw new IllegalStateException("No active application context");
+         throw new IllegalStateException("No active event context");
       }
 
       IdentityManager instance = (IdentityManager) Component.getInstance(
-            IdentityManager.class, ScopeType.APPLICATION);
+            IdentityManager.class, EVENT);
 
       if (instance == null)
       {

Modified: trunk/src/main/org/jboss/seam/security/management/IdentityStore.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/management/IdentityStore.java	2008-04-03 11:34:45 UTC (rev 7807)
+++ trunk/src/main/org/jboss/seam/security/management/IdentityStore.java	2008-04-03 11:41:20 UTC (rev 7808)
@@ -1,6 +1,10 @@
 package org.jboss.seam.security.management;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * The identity store does the actual work of persisting user accounts in a
@@ -10,51 +14,57 @@
  */
 public interface IdentityStore
 {     
+   public enum Feature { createUser, deleteUser, enableUser, disableUser, changePassword, 
+      createRole, deleteRole, grantRole, revokeRole }
+   
    public class FeatureSet 
-   {
-      public static final int FEATURE_CREATE_USER = 1;
-      public static final int FEATURE_DELETE_USER = 2;
-      public static final int FEATURE_ENABLE_USER = 4;
-      public static final int FEATURE_DISABLE_USER = 8;      
-      public static final int FEATURE_CHANGE_PASSWORD = 16;
+   {                             
+      private Set<Feature> features;
+
+      public FeatureSet()
+      {
+         this(null);
+      }
       
-      public static final int FEATURE_CREATE_ROLE = 32;
-      public static final int FEATURE_DELETE_ROLE = 64;
-      public static final int FEATURE_GRANT_ROLE = 128;
-      public static final int FEATURE_REVOKE_ROLE = 256;
+      public FeatureSet(Set<Feature> features)
+      {
+         if (features != null)
+         {
+            this.features = features;
+         }
+         else
+         {
+            this.features = new HashSet<Feature>();
+         }
+      }
       
-      public static final int FEATURE_ALL_USER = FEATURE_CREATE_USER | 
-          FEATURE_DELETE_USER | 
-          FEATURE_ENABLE_USER |
-          FEATURE_DISABLE_USER |
-          FEATURE_CHANGE_PASSWORD;
+      public Set<Feature> getFeatures()
+      {
+         return features;
+      }
       
-      public static final int FEATURE_ALL_ROLE = FEATURE_CREATE_ROLE |
-          FEATURE_DELETE_ROLE |
-          FEATURE_GRANT_ROLE |
-          FEATURE_REVOKE_ROLE;
-          
-      public static final int FEATURE_ALL = FEATURE_ALL_USER | FEATURE_ALL_ROLE;
+      public boolean supports(Feature feature)
+      {
+         return features.contains(feature);
+      }
       
-      private int features;
-      
-      public FeatureSet(int features)
+      public void addFeature(Feature feature)
       {
-         this.features = features;
+         features.add(feature);
       }
       
-      public int getFeatures()
+      public void removeFeature(Feature feature)
       {
-         return features;
+         features.remove(feature);
       }
       
-      public boolean supports(int feature)
+      public void enableAll()
       {
-         return (features & feature) == feature;
+         for (Feature f : Feature.values()) addFeature(f);
       }
    }
    
-   boolean supportsFeature(int feature);
+   boolean supportsFeature(Feature feature);
    
    boolean createUser(String username, String password);
    boolean createUser(String username, String password, String firstname, String lastname);

Modified: trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java	2008-04-03 11:34:45 UTC (rev 7807)
+++ trunk/src/main/org/jboss/seam/security/management/JpaIdentityStore.java	2008-04-03 11:41:20 UTC (rev 7808)
@@ -4,12 +4,13 @@
 import static org.jboss.seam.annotations.Install.BUILT_IN;
 
 import java.io.Serializable;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import javax.persistence.EntityManager;
@@ -21,12 +22,21 @@
 import org.jboss.seam.annotations.Observer;
 import org.jboss.seam.annotations.Scope;
 import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.annotations.security.management.RoleGroups;
+import org.jboss.seam.annotations.security.management.RoleName;
+import org.jboss.seam.annotations.security.management.UserEnabled;
+import org.jboss.seam.annotations.security.management.UserFirstName;
+import org.jboss.seam.annotations.security.management.UserLastName;
+import org.jboss.seam.annotations.security.management.UserPassword;
+import org.jboss.seam.annotations.security.management.UserPrincipal;
+import org.jboss.seam.annotations.security.management.UserRoles;
 import org.jboss.seam.contexts.Contexts;
 import org.jboss.seam.core.Events;
 import org.jboss.seam.core.Expressions;
 import org.jboss.seam.core.Expressions.ValueExpression;
+import org.jboss.seam.log.LogProvider;
+import org.jboss.seam.log.Logging;
 import org.jboss.seam.security.Identity;
-import org.jboss.seam.security.management.UserAccount.AccountType;
 
 /**
  * The default identity store implementation, uses JPA as its persistence mechanism.
@@ -41,136 +51,273 @@
 {  
    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";
+   public static final String EVENT_USER_CREATED = "org.jboss.seam.security.management.userCreated";
+   public static final String EVENT_PRE_PERSIST_USER = "org.jboss.seam.security.management.prePersistUser";
+   public static final String EVENT_USER_AUTHENTICATED = "org.jboss.seam.security.management.userAuthenticated";
    
-   protected FeatureSet featureSet = new FeatureSet(FeatureSet.FEATURE_ALL);
+   private static final LogProvider log = Logging.getLogProvider(JpaIdentityStore.class);    
    
+   protected FeatureSet featureSet;
+   
    private ValueExpression<EntityManager> entityManager;  
    
-   private Class<? extends UserAccount> accountClass;
+   private Class userClass;
+   private Class roleClass;
    
-   private Map<String,Set<String>> roleCache;
-   
-   private Field firstNameField;
-   private Field lastNameField;
-   
-   private String firstNameFieldName;   
-   private String lastNameFieldName;
-   
-   public String getFirstNameField()
+   protected final class BeanProperty
    {
-      return firstNameFieldName;
+      private Field propertyField;
+      private Method propertyGetter;
+      private Method propertySetter;
+      private Class<? extends Annotation> annotation;
+      private String name;
+      private Class propertyClass;
+      
+      private boolean isFieldProperty;
+      
+      public BeanProperty(Field propertyField, Class<? extends Annotation> annotation)
+      {
+         this.propertyField = propertyField;
+         isFieldProperty = true;
+         this.annotation = annotation;
+         this.name = propertyField.getName();
+         this.propertyClass = propertyField.getDeclaringClass();
+      }
+      
+      public BeanProperty(Method propertyMethod, Class<? extends Annotation> annotation)
+      {
+         if (!(propertyMethod.getName().startsWith("get") || (propertyMethod.getName().startsWith("is"))))
+         {
+            throw new IllegalArgumentException("Bean property method name " + propertyMethod.getClass().getName() +
+                  "." + propertyMethod.getName() + "() must start with \"get\" or \"is\".");
+         }
+         
+         if (propertyMethod.getReturnType().equals(void.class) || propertyMethod.getParameterTypes().length > 0)
+         {
+            throw new IllegalArgumentException("Bean property method " + propertyMethod.getClass().getName() +
+                  "." + propertyMethod.getName() + "() must return a value and take no parameters");
+         }
+         
+         this.propertyGetter = propertyMethod;
+         this.propertyClass = propertyMethod.getReturnType();
+         
+         String methodName = propertyMethod.getName();
+         
+         this.name = methodName.startsWith("get") ?
+               (methodName.substring(3,1).toLowerCase() + methodName.substring(4)) :
+               (methodName.substring(2,1).toLowerCase() + methodName.substring(3));
+         
+         String setterName = propertyMethod.getName().startsWith("get") ?
+               ("set" + methodName.substring(3)) : ("set" + methodName.substring(2));
+               
+         try
+         {
+            propertySetter = propertyMethod.getClass().getMethod(setterName, new Class[] {propertyMethod.getReturnType()});
+         }
+         catch (NoSuchMethodException ex)
+         {
+            throw new IllegalArgumentException("Bean property method " + propertyMethod.getClass().getName() +
+                  "." + propertyMethod.getName() + "() must have a corresponding setter method.");                  
+         }
+         
+         isFieldProperty = false;
+         this.annotation = annotation;
+      }
+      
+      public void setValue(Object bean, Object value)
+      {
+         if (isFieldProperty)
+         {
+            boolean accessible = propertyField.isAccessible();
+            try
+            {
+               propertyField.setAccessible(true);
+               propertyField.set(bean, value);   
+            }
+            catch (IllegalAccessException ex)
+            {
+               throw new RuntimeException("Exception setting bean property", ex);
+            }
+            finally
+            {
+               propertyField.setAccessible(accessible);
+            }            
+         }
+         else
+         {
+            try
+            {
+               propertySetter.invoke(bean, value);
+            }
+            catch (Exception ex)
+            {
+               throw new RuntimeException("Exception setting bean property", ex);
+            }
+         }
+      }
+      
+      public Object getValue(Object bean)
+      {
+         if (isFieldProperty)
+         {
+            boolean accessible = propertyField.isAccessible();
+            try
+            {
+               propertyField.setAccessible(true);
+               return propertyField.get(bean);
+            }
+            catch (IllegalAccessException ex)
+            {
+               throw new RuntimeException("Exception getting bean property", ex);
+            }
+            finally
+            {
+               propertyField.setAccessible(accessible);
+            }
+         }
+         else
+         {
+            try
+            {
+               return propertyGetter.invoke(bean);
+            }
+            catch (Exception ex)
+            {
+               throw new RuntimeException("Exception getting bean property", ex);
+            }
+         }
+      }
+      
+      public Class<? extends Annotation> getAnnotation()
+      {
+         return annotation;
+      }
+      
+      public String getName()
+      {
+         return name;
+      }
+      
+      public Class getPropertyClass()
+      {
+         return propertyClass;
+      }
    }
    
-   public void setFirstNameField(String firstNameFieldName)
-   {
-      this.firstNameFieldName = firstNameFieldName;
-   }
+   private BeanProperty userPrincipalProperty;
+   private BeanProperty userPasswordProperty;
+   private BeanProperty userRolesProperty;
+   private BeanProperty userEnabledProperty;
+   private BeanProperty userFirstNameProperty;
+   private BeanProperty userLastNameProperty;   
+   private BeanProperty roleNameProperty;
+   private BeanProperty roleGroupsProperty;
    
-   public String getLastNameField()
-   {
-      return lastNameFieldName;
-   }
+   private String passwordHash;
    
-   public void setLastNameField(String lastNameFieldName)
+   public Set<Feature> getFeatures()
    {
-      this.lastNameFieldName = lastNameFieldName;
-   }
-   
-   public int getFeatures()
-   {
       return featureSet.getFeatures();
    }
    
-   public void setFeatures(int features)
+   public void setFeatures(Set<Feature> features)
    {
       featureSet = new FeatureSet(features);
    }
    
-   public boolean supportsFeature(int feature)
+   public boolean supportsFeature(Feature feature)
    {
       return featureSet.supports(feature);
    }
    
    @Create
    public void init()
-   {
-      if (entityManager == null)
+   {      
+      if (userClass == null)
       {
-         entityManager = Expressions.instance().createValueExpression("#{entityManager}", EntityManager.class);
+         log.debug("No userClass set, JpaIdentityStore will be unavailable.");
+         return;
       }
       
-      loadRoles();
-      
-      if (getFirstNameField() != null)
+      if (roleClass == null)
       {
-         try
-         {
-            firstNameField = accountClass.getField(getFirstNameField());
-         }
-         catch (NoSuchFieldException ex)
-         {
-            throw new RuntimeException("First name field " + getFirstNameField() + " does not exist " +
-                  "in account class " + accountClass.getName(), ex);
-         }
+         log.debug("No roleClass set, JpaIdentityStore will be unavailable.");
+         return;
       }
       
-      if (getLastNameField() != null)
+      if (featureSet == null)
       {
-         try
-         {
-            lastNameField = accountClass.getField(getLastNameField());
-         }
-         catch (NoSuchFieldException ex)
-         {
-            throw new RuntimeException("Last name field " + getLastNameField() + " does not exist " +
-                  "in account class " + accountClass.getName(), ex);
-         }
+         featureSet = new FeatureSet();
+         featureSet.enableAll();
       }      
+      
+      if (entityManager == null)
+      {
+         entityManager = Expressions.instance().createValueExpression("#{entityManager}", EntityManager.class);
+      }      
+      
+      initProperties();   
    }
    
-   protected void loadRoles()
+   private void initProperties()
    {
-      List<? extends UserAccount> roles = lookupEntityManager().createQuery(
-            "from " + accountClass.getName() + " where enabled = true and accountType = :accountType")
-            .setParameter("accountType", UserAccount.AccountType.role)
-            .getResultList();
+      userPrincipalProperty = scanForProperty(userClass, UserPrincipal.class);
+      userPasswordProperty = scanForProperty(userClass, UserPassword.class);
+      userRolesProperty = scanForProperty(userClass, UserRoles.class);
+      userEnabledProperty = scanForProperty(userClass, UserEnabled.class);
+      userFirstNameProperty = scanForProperty(userClass, UserFirstName.class);
+      userLastNameProperty = scanForProperty(userClass, UserLastName.class);
       
-      roleCache = new HashMap<String,Set<String>>();
+      roleNameProperty = scanForProperty(roleClass, RoleName.class);
+      roleGroupsProperty = scanForProperty(roleClass, RoleGroups.class);
       
-      for (UserAccount role : roles)
+      if (userPrincipalProperty == null) 
       {
-         Set<String> memberships = new HashSet<String>();
-         for (UserAccount m : role.getMemberships())
-         {
-            memberships.add(m.getUsername());
-         }
-         roleCache.put(role.getUsername(), memberships);
+         throw new RuntimeException("Invalid userClass " + userClass.getName() + 
+               " - required annotation @UserPrincipal not found on any Field or Method.");
+      }
+      
+      if (userPasswordProperty == null) 
+      {
+         throw new RuntimeException("Invalid userClass " + userClass.getName() + 
+               " - required annotation @UserPassword not found on any Field or Method.");
       }      
+      
+      if (userRolesProperty == null)
+      {
+         throw new RuntimeException("Invalid userClass " + userClass.getName() + 
+         " - required annotation @UserRoles not found on any Field or Method.");         
+      }
+      
+      if (roleNameProperty == null)
+      {
+         throw new RuntimeException("Invalid roleClass " + roleClass.getName() + 
+         " - required annotation @RoleName not found on any Field or Method.");         
+      }
    }
    
-   private void setFieldValue(Field field, Object instance, Object value) throws Exception
+   private BeanProperty scanForProperty(Class cls, Class<? extends Annotation> annotation)
    {
-      boolean accessible = field.isAccessible();
-      try
+      for (Field f : cls.getFields())
       {
-         field.setAccessible(true);
-         field.set(instance, value);
+         if (f.isAnnotationPresent(annotation)) return new BeanProperty(f, annotation);
       }
-      finally
+      
+      for (Method m : cls.getMethods())
       {
-         field.setAccessible(accessible);
+         if (m.isAnnotationPresent(annotation)) return new BeanProperty(m, annotation);
       }
+      
+      return null;
    }
    
    public boolean createUser(String username, String password, String firstname, String lastname)
    {
       try
       {
-         if (accountClass == null)
+         if (userClass == null)
          {
-            throw new IdentityManagementException("Could not create account, accountClass not set");
+            throw new IdentityManagementException("Could not create account, userClass not set");
          }
          
          if (userExists(username))
@@ -178,27 +325,32 @@
             throw new IdentityManagementException("Could not create account, already exists");
          }
          
-         UserAccount account = accountClass.newInstance();
-         account.setAccountType(UserAccount.AccountType.user);
-         account.setUsername(username);
+         Object user = userClass.newInstance();
+
+         userPrincipalProperty.setValue(user, username);
+
+         if (userFirstNameProperty != null) userFirstNameProperty.setValue(user, firstname);         
+         if (userLastNameProperty != null) userLastNameProperty.setValue(user, lastname);
          
-         if (firstNameField != null) setFieldValue(firstNameField, account, firstname);         
-         if (lastNameField != null) setFieldValue(lastNameField, account, lastname);
-         
          if (password == null)
          {
-            account.setEnabled(false);
+            if (userEnabledProperty != null) userEnabledProperty.setValue(user, false);
          }
          else
          {
-            account.setPasswordHash(PasswordHash.instance().generateSaltedHash(password, getAccountSalt(account)));
-            account.setEnabled(true);            
+            String passwordValue = passwordHash == null ? password :
+               PasswordHash.instance().generateSaltedHash(password, getUserAccountSalt(user));
+            
+            userPasswordProperty.setValue(user, passwordValue);
+            if (userEnabledProperty != null) userEnabledProperty.setValue(user, true);
          }
          
-         persistAccount(account);
+         if (Events.exists()) Events.instance().raiseEvent(EVENT_PRE_PERSIST_USER, user);
          
-         if (Events.exists()) Events.instance().raiseEvent(EVENT_ACCOUNT_CREATED, account);
+         persistEntity(user);
          
+         if (Events.exists()) Events.instance().raiseEvent(EVENT_USER_CREATED, user);
+         
          return true;
       }
       catch (Exception ex)
@@ -214,9 +366,10 @@
       }      
    }
    
-   protected String getAccountSalt(UserAccount account)
+   protected String getUserAccountSalt(Object user)
    {
-      return account.getUsername();
+      // By default, we'll use the user's username as the password salt
+      return userPrincipalProperty.getValue(user).toString();
    }
    
    public boolean createUser(String username, String password)
@@ -226,61 +379,73 @@
    
    public boolean deleteUser(String name)
    {
-      UserAccount account = validateAccount(name);
-      if (account == null || !account.getAccountType().equals(AccountType.user)) 
+      Object user = lookupUser(name);
+      if (user == null) 
       {
-         throw new NoSuchUserException("Could not delete account, no such user '" + name + "'");
+         throw new NoSuchUserException("Could not delete, user '" + name + "' does not exist");
       }
       
-      lookupEntityManager().remove(account);
+      removeEntity(user);
       return true;
    }
    
-   public boolean grantRole(String name, String role)
+   public boolean grantRole(String username, String role)
    {
-      UserAccount account = validateAccount(name);
-      if (account == null)
+      Object user = lookupUser(username);
+      if (user == null)
       {
-         throw new NoSuchUserException("Could not grant role, no such user or role '" + name + "'");
+         throw new NoSuchUserException("Could not grant role, no such user '" + username + "'");
       }
       
-      UserAccount roleToGrant = validateAccount(role);
+      Object roleToGrant = lookupRole(role);
       if (roleToGrant == null)
       {
          throw new NoSuchRoleException("Could not grant role, role '" + role + "' does not exist");
       }
       
-      if (account.getMemberships() == null)
+      Collection userRoles = (Collection) userRolesProperty.getValue(user); 
+      if (userRoles == null)
       {
-         account.setMemberships(new HashSet<UserAccount>());
+         // This should either be a Set, or a List...
+         if (Set.class.isAssignableFrom(userRolesProperty.getPropertyClass()))
+         {
+            userRoles = new HashSet();
+         }
+         else if (List.class.isAssignableFrom(userRolesProperty.getPropertyClass()))
+         {
+            userRoles = new ArrayList();
+         }
+         
+         userRolesProperty.setValue(user, userRoles);
       }
-      else if (account.getMemberships().contains(roleToGrant))
+      else if (((Collection) userRolesProperty.getValue(user)).contains(roleToGrant))
       {
          return false;
       }
 
-      account.getMemberships().add(roleToGrant);
-      mergeAccount(account);
+      ((Collection) userRolesProperty.getValue(user)).add(roleToGrant);
+      mergeEntity(user);
       
       return true;
    }
    
-   public boolean revokeRole(String name, String role)
+   public boolean revokeRole(String username, String role)
    {
-      UserAccount account = validateAccount(name);
-      if (account == null)
+      Object user = lookupUser(username);
+      if (user == null)
       {
-         throw new NoSuchUserException("Could not revoke role, no such user or role '" + name + "'");
+         throw new NoSuchUserException("Could not revoke role, no such user '" + username + "'");
       }
       
-      UserAccount roleToRevoke = validateAccount(role);
+      Object roleToRevoke = lookupRole(role);
       if (roleToRevoke == null)
       {
          throw new NoSuchRoleException("Could not revoke role, role '" + role + "' does not exist");
       }      
        
-      boolean success = account.getMemberships().remove(roleToRevoke);
-      mergeAccount(account);
+      boolean success = ((Collection) userRolesProperty.getValue(user)).remove(roleToRevoke);
+      
+      if (success) mergeEntity(user);
       return success;
    }
    
@@ -288,9 +453,9 @@
    {
       try
       {
-         if (accountClass == null)
+         if (roleClass == null)
          {
-            throw new IdentityManagementException("Could not create role, accountClass not set");
+            throw new IdentityManagementException("Could not create role, roleClass not set");
          }
          
          if (roleExists(role))
@@ -298,12 +463,10 @@
             throw new IdentityManagementException("Could not create role, already exists");
          }
          
-         UserAccount account = accountClass.newInstance();
-         account.setAccountType(UserAccount.AccountType.role);
-         account.setUsername(role);
+         Object instance = roleClass.newInstance();         
+         roleNameProperty.setValue(instance, role);         
+         persistEntity(instance);
          
-         persistAccount(account);
-         
          return true;
       }
       catch (Exception ex)
@@ -321,102 +484,111 @@
    
    public boolean deleteRole(String role)
    {      
-      UserAccount roleToDelete = validateAccount(role);
+      Object roleToDelete = lookupRole(role);
       if (roleToDelete == null)
       {
          throw new NoSuchRoleException("Could not delete role, role '" + role + "' does not exist");
       }        
       
-      lookupEntityManager().remove(roleToDelete);
+      removeEntity(roleToDelete);
       return true;
    }
    
    public boolean enableUser(String name)
    {
-      UserAccount account = validateAccount(name);
-      if (account == null || !account.getAccountType().equals(AccountType.user))
+      if (userEnabledProperty == null)
       {
-         throw new NoSuchUserException("Could not enable account, user '" + name + "' does not exist");
+         log.debug("Can not enable user, no @UserEnabled property configured in userClass " + userClass.getName());
+         return false;
       }
       
+      Object user = lookupUser(name);
+      if (user == null)
+      {
+         throw new NoSuchUserException("Could not enable user, user '" + name + "' does not exist");
+      }
+      
       // If it's already enabled return false
-      if (account.isEnabled())
+      if (((Boolean) userEnabledProperty.getValue(user)) == true)
       {
          return false;
       }
       
-      account.setEnabled(true);
-      mergeAccount(account);
-      
+      userEnabledProperty.setValue(user, true);
+      mergeEntity(user);      
       return true;
    }
    
    public boolean disableUser(String name)
    {
-      UserAccount account = validateAccount(name);
-      if (account == null || !account.getAccountType().equals(AccountType.user))
+      if (userEnabledProperty == null)
       {
-         throw new NoSuchUserException("Could not disable account, user '" + name + "' does not exist");
+         log.debug("Can not disable user, no @UserEnabled property configured in userClass " + userClass.getName());
+         return false;
       }
       
-      // If it's already enabled return false
-      if (!account.isEnabled())
+      Object user = lookupUser(name);
+      if (user == null)
       {
+         throw new NoSuchUserException("Could not disable user, user '" + name + "' does not exist");
+      }
+      
+      // If it's already disabled return false
+      if (((Boolean) userEnabledProperty.getValue(user)) == false)
+      {
          return false;
-      }    
+      }          
       
-      account.setEnabled(false);
-      mergeAccount(account);
+      userEnabledProperty.setValue(user, false);
+      mergeEntity(user);
       
       return true;
    }
    
-   public boolean changePassword(String name, String password)
+   public boolean changePassword(String username, String password)
    {
-      UserAccount account = validateAccount(name);
-      if (account == null || !account.getAccountType().equals(AccountType.user))
+      Object user = lookupUser(username);
+      if (user == null)
       {
-         throw new NoSuchUserException("Could not change password, user '" + name + "' does not exist");
+         throw new NoSuchUserException("Could not change password, user '" + username + "' does not exist");
       }
       
-      account.setPasswordHash(PasswordHash.instance().generateSaltedHash(password, getAccountSalt(account)));
-      mergeAccount(account);
+      userPasswordProperty.setValue(user, PasswordHash.instance().generateSaltedHash(password, getUserAccountSalt(user)));
+      mergeEntity(user);
       return true;
    }
    
    public boolean userExists(String name)
    {
-      UserAccount account = validateAccount(name);
-      return account != null && account.getAccountType().equals(AccountType.user);
+      return lookupUser(name) != null;
    }
    
    public boolean roleExists(String name)
    {
-      UserAccount role = validateAccount(name);
-      return role != null && role.getAccountType().equals(AccountType.role);
+      return lookupRole(name) != null;
    }
    
    public boolean isUserEnabled(String name)
    {
-      UserAccount account = validateAccount(name);
-      return account != null && account.getAccountType().equals(AccountType.user)
-             && account.isEnabled();
+      Object user = lookupUser(name);
+      return user != null && (userEnabledProperty == null || (((Boolean) userEnabledProperty.getValue(user))) == true);
    }
    
    public List<String> getGrantedRoles(String name)
    {
-      UserAccount account = validateAccount(name);
-      if (account == null) throw new NoSuchUserException("No such user '" + name + "'");      
+      Object user = lookupUser(name);
+      if (user == null)
+      {
+         throw new NoSuchUserException("No such user '" + name + "'");      
+      }
 
-      List<String> roles = new ArrayList<String>();      
-      if (account.getMemberships() != null)
+      List<String> roles = new ArrayList<String>();
+      Collection userRoles = (Collection) userRolesProperty.getValue(user);
+      if (userRoles != null)
       {
-         for (UserAccount membership : account.getMemberships())
+         for (Object role : userRoles)
          {
-            if (membership.getAccountType().equals(UserAccount.AccountType.role))
-            {
-               roles.add(membership.getUsername());
-            }
+            roles.add((String) roleNameProperty.getValue(role));
          }
       }
       
@@ -425,55 +597,62 @@
    
    public List<String> getImpliedRoles(String name)
    {
-      UserAccount account = validateAccount(name);
-      if (account == null) throw new NoSuchUserException("No such user '" + name + "'"); 
+      Object user = lookupUser(name);
+      if (user == null) 
+      {
+         throw new NoSuchUserException("No such user '" + name + "'"); 
+      }
 
       Set<String> roles = new HashSet<String>();
-
-      for (UserAccount membership : account.getMemberships())
+      Collection userRoles = (Collection) userRolesProperty.getValue(user);
+      if (userRoles != null)
       {
-         if (membership.getAccountType().equals(UserAccount.AccountType.role))
+         for (Object role : userRoles)
          {
-            addRoleAndMemberships(membership.getUsername(), roles);
+            addRoleAndMemberships((String) roleNameProperty.getValue(role), roles);
          }
-      }            
+      }
       
       return new ArrayList<String>(roles);
    }
    
    private void addRoleAndMemberships(String role, Set<String> roles)
    {
-      roles.add(role);
-      
-      for (String membership : roleCache.get(role))
-      {
-         if (!roles.contains(membership))
+      if (roles.add(role))
+      {      
+         Object instance = lookupRole(role);
+         
+         Collection groups = (Collection) roleGroupsProperty.getValue(instance);
+         
+         if (groups != null)
          {
-            addRoleAndMemberships(membership, roles);
+            for (Object group : groups)
+            {
+               addRoleAndMemberships((String) roleNameProperty.getValue(group), roles);
+            }
          }
-      }            
+      }
    }
    
    public boolean authenticate(String username, String password)
    {
-      UserAccount account = validateAccount(username);          
-      if (account == null || !account.getAccountType().equals(AccountType.user)
-            || !account.isEnabled())
+      Object user = lookupUser(username);          
+      if (user == null || (userEnabledProperty != null && ((Boolean) userEnabledProperty.getValue(user) == false)))
       {
          return false;
       }
       
-      String passwordHash = PasswordHash.instance().generateSaltedHash(password, getAccountSalt(account));
-      boolean success = passwordHash.equals(account.getPasswordHash());
+      String passwordHash = PasswordHash.instance().generateSaltedHash(password, getUserAccountSalt(user));
+      boolean success = passwordHash.equals(userPasswordProperty.getValue(user));
             
       if (success && Events.exists())
       {
          if (Contexts.isEventContextActive())
          {
-            Contexts.getEventContext().set(AUTHENTICATED_USER, account);
+            Contexts.getEventContext().set(AUTHENTICATED_USER, user);
          }
          
-         Events.instance().raiseEvent(EVENT_ACCOUNT_AUTHENTICATED, account);
+         Events.instance().raiseEvent(EVENT_USER_AUTHENTICATED, user);
       }
       
       return success;
@@ -489,28 +668,17 @@
       }
    }
    
-   protected UserAccount validateAccount(String name)       
+   protected Object lookupUser(String username)       
    {
       try
       {
-         UserAccount account = (UserAccount) lookupEntityManager().createQuery(
-            "from " + accountClass.getName() + " where username = :username")
-            .setParameter("username", name)
+         Object user = lookupEntityManager().createQuery(
+            "select u from " + userClass.getName() + "u where " + userPrincipalProperty.getName() +
+            " = :username")
+            .setParameter("username", username)
             .getSingleResult();
          
-         if (account.getAccountType().equals(AccountType.role) && 
-             !roleCache.containsKey(account.getUsername()))
-         {
-            Set<String> memberships = new HashSet<String>();
-            for (UserAccount m : account.getMemberships())
-            {
-               memberships.add(m.getUsername());
-            }
-            
-            roleCache.put(account.getUsername(), memberships);  
-         }
-         
-         return account;
+         return user;
       }
       catch (NoResultException ex)
       {
@@ -518,21 +686,36 @@
       }      
    }
    
+   protected Object lookupRole(String role)       
+   {
+      try
+      {
+         Object value = lookupEntityManager().createQuery(
+            "select r from " + roleClass.getName() + "r where " + roleNameProperty.getName() +
+            " = :role")
+            .setParameter("role", role)
+            .getSingleResult();
+         
+         return value;
+      }
+      catch (NoResultException ex)
+      {
+         return null;        
+      }      
+   }   
+   
    public List<String> listUsers()
    {
       return lookupEntityManager().createQuery(
-            "select username from " + accountClass.getName() + 
-            " where accountType = :accountType")
-            .setParameter("accountType", AccountType.user)
+            "select u." + userPrincipalProperty.getName() + " from " + userClass.getName() + " u")
             .getResultList();      
    }
    
    public List<String> listUsers(String filter)
    {
       return lookupEntityManager().createQuery(
-            "select username from " + accountClass.getName() + 
-            " where accountType = :accountType and lower(username) like :username")
-            .setParameter("accountType", AccountType.user)
+            "select u." + userPrincipalProperty.getName() + " from " + userClass.getName() + 
+            "u where lower(" + userPrincipalProperty.getName() + ") like :username")
             .setParameter("username", "%" + (filter != null ? filter.toLowerCase() : "") + 
                   "%")
             .getResultList();
@@ -541,32 +724,45 @@
    public List<String> listRoles()
    {
       return lookupEntityManager().createQuery(
-            "select username from " + accountClass.getName() + 
-            " where accountType = :accountType")
-            .setParameter("accountType", AccountType.role)
+            "select r." + roleNameProperty.getName() + " from " + roleClass.getName() + " r")
             .getResultList();      
    }   
    
-   protected void persistAccount(UserAccount account)
+   protected void persistEntity(Object entity)
    {
-      lookupEntityManager().persist(account);
+      lookupEntityManager().persist(entity);
    }
    
-   protected UserAccount mergeAccount(UserAccount account)
+   protected Object mergeEntity(Object entity)
    {
-      return lookupEntityManager().merge(account);
+      return lookupEntityManager().merge(entity);
    }
    
-   public Class<? extends UserAccount> getAccountClass()
+   protected void removeEntity(Object entity)
    {
-      return accountClass;
+      lookupEntityManager().remove(entity);
    }
    
-   public void setAccountClass(Class<? extends UserAccount> accountClass)
+   public Class getUserClass()
    {
-      this.accountClass = accountClass;
+      return userClass;
+   }
+   
+   public void setUserClass(Class userClass)
+   {
+      this.userClass = userClass;
    }   
    
+   public Class getRoleClass()
+   {
+      return roleClass;
+   }
+   
+   public void setRoleClass(Class roleClass)
+   {
+      this.roleClass = roleClass;
+   }
+   
    private EntityManager lookupEntityManager()
    {
       return entityManager.getValue();

Modified: trunk/src/main/org/jboss/seam/security/management/LdapIdentityStore.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/management/LdapIdentityStore.java	2008-04-03 11:34:45 UTC (rev 7807)
+++ trunk/src/main/org/jboss/seam/security/management/LdapIdentityStore.java	2008-04-03 11:41:20 UTC (rev 7808)
@@ -47,7 +47,7 @@
    
    private static final LogProvider log = Logging.getLogProvider(LdapIdentityStore.class);   
    
-   protected FeatureSet featureSet = new FeatureSet(FeatureSet.FEATURE_ALL);
+   protected FeatureSet featureSet = new FeatureSet();
    
    private String serverAddress = "localhost";
    
@@ -361,17 +361,17 @@
       }
    }
    
-   public int getFeatures()
+   public Set<Feature> getFeatures()
    {
       return featureSet.getFeatures();
    }
    
-   public void setFeatures(int features)
+   public void setFeatures(Set<Feature> features)
    {
       featureSet = new FeatureSet(features);
    }
    
-   public boolean supportsFeature(int feature)
+   public boolean supportsFeature(Feature feature)
    {
       return featureSet.supports(feature);
    }

Deleted: trunk/src/main/org/jboss/seam/security/management/UserAccount.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/management/UserAccount.java	2008-04-03 11:34:45 UTC (rev 7807)
+++ trunk/src/main/org/jboss/seam/security/management/UserAccount.java	2008-04-03 11:41:20 UTC (rev 7808)
@@ -1,57 +0,0 @@
-package org.jboss.seam.security.management;
-
-import java.io.Serializable;
-import java.util.Set;
-
-/**
- * Abstract base class for user/role accounts.  This class should be extended
- * to create a concrete JPA/Hibernate implementation. The user has no access to
- * this class via the identity management API. 
- *  
- * @author Shane Bryzak
- */
-public abstract class UserAccount implements Serializable
-{
-   public enum AccountType {user, role}
-     
-   public abstract String getUsername();   
-   public abstract void setUsername(String username);
-   
-   public abstract String getPasswordHash();   
-   public abstract void setPasswordHash(String passwordHash);
-
-   public abstract boolean isEnabled();   
-   public abstract void setEnabled(boolean enabled);
-   
-   public abstract AccountType getAccountType();   
-   public abstract void setAccountType(AccountType accountType);
-   
-   public abstract Set<UserAccount> getMemberships();
-   public abstract void setMemberships(Set<UserAccount> memberships);
-   
-   @Override
-   public boolean equals(Object value)
-   {
-      if (!(value instanceof UserAccount))
-      {
-         return false;
-      }
-      
-      UserAccount other = (UserAccount) value;      
-      
-      if (other.getUsername() == null && this.getUsername() == null)
-      {
-         return hashCode() == other.hashCode();
-      }
-      else
-      {
-         return getUsername() == null ? false : getUsername().equals(other.getUsername());
-      }
-   }
-   
-   @Override
-   public int hashCode()
-   {
-      return getUsername() != null ? getUsername().hashCode() : super.hashCode();
-   }
-}




More information about the seam-commits mailing list