[seam-commits] Seam SVN: r8150 - in trunk/src/main/org/jboss/seam: security/permission and 1 other directories.
seam-commits at lists.jboss.org
seam-commits at lists.jboss.org
Sat May 10 09:33:34 EDT 2008
Author: shane.bryzak at jboss.com
Date: 2008-05-10 09:33:34 -0400 (Sat, 10 May 2008)
New Revision: 8150
Modified:
trunk/src/main/org/jboss/seam/annotations/security/permission/Permission.java
trunk/src/main/org/jboss/seam/security/permission/JpaPermissionStore.java
trunk/src/main/org/jboss/seam/security/permission/PermissionMetadata.java
trunk/src/main/org/jboss/seam/security/permission/action/PermissionSearch.java
Log:
made bulk permission updates way more efficient
Modified: trunk/src/main/org/jboss/seam/annotations/security/permission/Permission.java
===================================================================
--- trunk/src/main/org/jboss/seam/annotations/security/permission/Permission.java 2008-05-10 02:39:00 UTC (rev 8149)
+++ trunk/src/main/org/jboss/seam/annotations/security/permission/Permission.java 2008-05-10 13:33:34 UTC (rev 8150)
@@ -21,5 +21,5 @@
public @interface Permission
{
String action();
- long mask() default 0;
+ long mask() default 0L;
}
Modified: trunk/src/main/org/jboss/seam/security/permission/JpaPermissionStore.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/permission/JpaPermissionStore.java 2008-05-10 02:39:00 UTC (rev 8149)
+++ trunk/src/main/org/jboss/seam/security/permission/JpaPermissionStore.java 2008-05-10 13:33:34 UTC (rev 8150)
@@ -9,6 +9,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
@@ -33,6 +34,7 @@
import org.jboss.seam.security.SimplePrincipal;
import org.jboss.seam.security.management.JpaIdentityStore;
import org.jboss.seam.util.AnnotatedBeanProperty;
+import org.jboss.seam.security.permission.PermissionMetadata.ActionSet;
/**
* A permission store implementation that uses JPA as its persistence mechanism.
@@ -154,15 +156,13 @@
}
}
- protected Query createPermissionQuery(Object target, String action, Principal recipient,
- Discrimination discrimination)
+ protected Query createPermissionQuery(Object target, Principal recipient, Discrimination discrimination)
{
int queryKey = ((target != null) ? 1 : 0);
- queryKey |= (action != null ? 2 : 0);
- queryKey |= (recipient != null ? 4 : 0);
- queryKey |= (discrimination.equals(Discrimination.user) ? 8 : 0);
- queryKey |= (discrimination.equals(Discrimination.role) ? 16 : 0);
- queryKey |= (discrimination.equals(Discrimination.either) ? 32 : 0);
+ queryKey |= (recipient != null ? 2 : 0);
+ queryKey |= (discrimination.equals(Discrimination.user) ? 4 : 0);
+ queryKey |= (discrimination.equals(Discrimination.role) ? 8 : 0);
+ queryKey |= (discrimination.equals(Discrimination.either) ? 16 : 0);
boolean isRole = discrimination.equals(Discrimination.role) && rolePermissionClass != null;
@@ -183,14 +183,6 @@
conditionsAdded = true;
}
- if (action != null)
- {
- q.append(conditionsAdded ? " and " : " where ");
- q.append(isRole ? roleActionProperty.getName() : actionProperty.getName());
- q.append(" = :action");
- conditionsAdded = true;
- }
-
if (recipient != null)
{
q.append(conditionsAdded ? " and " : " where ");
@@ -214,7 +206,6 @@
Query query = lookupEntityManager().createQuery(queryCache.get(queryKey));
if (target != null) query.setParameter("target", identifierPolicy.getIdentifier(target));
- if (action != null) query.setParameter("action", action);
if (recipient != null) query.setParameter("recipient", resolvePrincipal(recipient));
if (!discrimination.equals(Discrimination.either) && discriminatorProperty != null)
@@ -228,19 +219,98 @@
public boolean grantPermission(Permission permission)
{
- boolean recipientIsRole = permission.getRecipient() instanceof Role;
+ return updatePermissionActions(permission.getTarget(), permission.getRecipient(),
+ new String[] {permission.getAction()}, true);
+ }
+
+ public boolean revokePermission(Permission permission)
+ {
+ return updatePermissionActions(permission.getTarget(), permission.getRecipient(),
+ new String[] { permission.getAction() }, false);
+ }
+ /**
+ * This is where the bulk of the actual work happens.
+ *
+ * @param target The target object to update permissions for
+ * @param recipient The recipient to update permissions for
+ * @param actions The actions that will be updated
+ * @param set true if the specified actions are to be granted, false if they are to be revoked
+ * @return true if the operation is successful
+ */
+ protected boolean updatePermissionActions(Object target, Principal recipient, String[] actions,
+ boolean set)
+ {
+ boolean recipientIsRole = recipient instanceof Role;
+
try
{
if (recipientIsRole)
{
if (rolePermissionClass != null)
{
- Object instance = rolePermissionClass.newInstance();
- roleTargetProperty.setValue(instance, identifierPolicy.getIdentifier(permission.getTarget()));
- roleActionProperty.setValue(instance, permission.getAction());
- roleProperty.setValue(instance, permission.getRecipient().getName());
- lookupEntityManager().persist(instance);
+ List permissions = createPermissionQuery(target, recipient, Discrimination.role).getResultList();
+
+ if (permissions.isEmpty())
+ {
+ if (!set) return true;
+
+ ActionSet actionSet = metadata.createActionSet(target.getClass(), null);
+ for (String action : actions)
+ {
+ actionSet.add(action);
+ }
+
+ Object instance = rolePermissionClass.newInstance();
+ roleTargetProperty.setValue(instance, identifierPolicy.getIdentifier(target));
+ roleActionProperty.setValue(instance, actionSet.toString());
+ roleProperty.setValue(instance, resolvePrincipal(recipient));
+ lookupEntityManager().persist(instance);
+ return true;
+ }
+
+ Object instance = permissions.get(0);
+
+ ActionSet actionSet = metadata.createActionSet(target.getClass(),
+ roleActionProperty.getValue(instance).toString());
+
+ for (String action : actions)
+ {
+ if (set)
+ {
+ actionSet.add(action);
+ }
+ else
+ {
+ actionSet.remove(action);
+ }
+ }
+
+ if (permissions.size() > 1)
+ {
+ // This is where it gets a little messy.. if there is more than one permission
+ // record, then we need to consolidate them all into just the first one
+ for (Object p : permissions)
+ {
+ actionSet.addMembers(roleActionProperty.getValue(p).toString());
+ if (!p.equals(instance))
+ {
+ lookupEntityManager().remove(p);
+ }
+ }
+ }
+
+ if (!actionSet.isEmpty())
+ {
+ roleActionProperty.setValue(instance, actionSet.toString());
+ lookupEntityManager().merge(instance);
+ }
+ else
+ {
+ // No actions remaining in set, so just remove the record
+ lookupEntityManager().remove(instance);
+ }
+
return true;
}
@@ -254,64 +324,167 @@
{
throw new RuntimeException("Could not grant permission, userPermissionClass not set");
}
-
- Object instance = userPermissionClass.newInstance();
- targetProperty.setValue(instance, identifierPolicy.getIdentifier(permission.getTarget()));
- actionProperty.setValue(instance, permission.getAction());
- userProperty.setValue(instance, resolvePrincipal(permission.getRecipient()));
+
+ List permissions = createPermissionQuery(target, recipient, recipientIsRole ?
+ Discrimination.role : Discrimination.user).getResultList();
+
+ if (permissions.isEmpty())
+ {
+ if (!set) return true;
+
+ ActionSet actionSet = metadata.createActionSet(target.getClass(), null);
+ for (String action : actions)
+ {
+ actionSet.add(action);
+ }
+
+ Object instance = userPermissionClass.newInstance();
+ targetProperty.setValue(instance, identifierPolicy.getIdentifier(target));
+ actionProperty.setValue(instance, actionSet.toString());
+ userProperty.setValue(instance, resolvePrincipal(recipient));
+
+ if (discriminatorProperty != null)
+ {
+ PermissionDiscriminator discriminator = discriminatorProperty.getAnnotation();
+ discriminatorProperty.setValue(instance, recipientIsRole ? discriminator.roleValue() :
+ discriminator.userValue());
+ }
+
+ lookupEntityManager().persist(instance);
+ return true;
+ }
+
+ Object instance = permissions.get(0);
- if (discriminatorProperty != null)
+ ActionSet actionSet = metadata.createActionSet(target.getClass(),
+ actionProperty.getValue(instance).toString());
+
+ for (String action : actions)
{
- discriminatorProperty.setValue(instance, getDiscriminatorValue(recipientIsRole));
+ if (set)
+ {
+ actionSet.add(action);
+ }
+ else
+ {
+ actionSet.remove(action);
+ }
}
- lookupEntityManager().persist(instance);
+ if (permissions.size() > 1)
+ {
+ // Same as with roles, consolidate the records if there is more than one
+ for (Object p : permissions)
+ {
+ actionSet.addMembers(actionProperty.getValue(p).toString());
+ if (!p.equals(instance))
+ {
+ lookupEntityManager().remove(p);
+ }
+ }
+ }
+
+ if (!actionSet.isEmpty())
+ {
+ actionProperty.setValue(instance, actionSet.toString());
+ lookupEntityManager().merge(instance);
+ }
+ else
+ {
+ // No actions remaining in set, so just remove the record
+ lookupEntityManager().remove(instance);
+ }
- return true;
+ return true;
}
catch (Exception ex)
{
throw new RuntimeException("Could not grant permission", ex);
- }
+ }
}
public boolean grantPermissions(List<Permission> permissions)
{
- // TODO implement
+ // Target/Recipient/Action map
+ Map<Object,Map<Principal,List<Permission>>> groupedPermissions = groupPermissions(permissions);
- return false;
+ for (Object target : groupedPermissions.keySet())
+ {
+ Map<Principal,List<Permission>> recipientPermissions = groupedPermissions.get(target);
+
+ for (Principal recipient : recipientPermissions.keySet())
+ {
+ List<Permission> ps = recipientPermissions.get(recipient);
+ String[] actions = new String[ps.size()];
+ for (int i = 0; i < ps.size(); i++) actions[i] = ps.get(i).getAction();
+ updatePermissionActions(target, recipient, actions, true);
+ }
+ }
+
+ return true;
}
- private String getDiscriminatorValue(boolean isRole)
+ public boolean revokePermissions(List<Permission> permissions)
{
- PermissionDiscriminator discriminator = discriminatorProperty.getAnnotation();
- return isRole ? discriminator.roleValue() : discriminator.userValue();
- }
+ // Target/Recipient/Action map
+ Map<Object,Map<Principal,List<Permission>>> groupedPermissions = groupPermissions(permissions);
+
+ for (Object target : groupedPermissions.keySet())
+ {
+ Map<Principal,List<Permission>> recipientPermissions = groupedPermissions.get(target);
+
+ for (Principal recipient : recipientPermissions.keySet())
+ {
+ List<Permission> ps = recipientPermissions.get(recipient);
+ String[] actions = new String[ps.size()];
+ for (int i = 0; i < ps.size(); i++) actions[i] = ps.get(i).getAction();
+ updatePermissionActions(target, recipient, actions, false);
+ }
+ }
+
+ return true;
+ }
- public boolean revokePermission(Permission permission)
+ /**
+ * Groups a list of arbitrary permissions into a more easily-consumed structure
+ *
+ * @param permissions The list of permissions to group
+ * @return
+ */
+ private Map<Object,Map<Principal,List<Permission>>> groupPermissions(List<Permission> permissions)
{
- Query qry = createPermissionQuery(permission.getTarget(), permission.getAction(),
- permission.getRecipient(), permission.getRecipient() instanceof Role ?
- Discrimination.role : Discrimination.user);
-
- try
+ // Target/Recipient/Action map
+ Map<Object,Map<Principal,List<Permission>>> groupedPermissions = new HashMap<Object,Map<Principal,List<Permission>>>();
+
+ for (Permission permission : permissions)
{
- Object instance = qry.getSingleResult();
- lookupEntityManager().remove(instance);
- return true;
+ if (!groupedPermissions.containsKey(permission.getTarget()))
+ {
+ groupedPermissions.put(permission.getTarget(), new HashMap<Principal,List<Permission>>());
+ }
+
+ Map<Principal,List<Permission>> recipientPermissions = groupedPermissions.get(permission.getTarget());
+ if (!recipientPermissions.containsKey(permission.getRecipient()))
+ {
+ List<Permission> perms = new ArrayList<Permission>();
+ perms.add(permission);
+ recipientPermissions.put(permission.getRecipient(), perms);
+ }
+ else
+ {
+ recipientPermissions.get(permission.getRecipient()).add(permission);
+ }
}
- catch (NoResultException ex)
- {
- return false;
- }
+
+ return groupedPermissions;
}
- public boolean revokePermissions(List<Permission> permissions)
+ private String getDiscriminatorValue(boolean isRole)
{
- // TODO implement
- return false;
+ PermissionDiscriminator discriminator = discriminatorProperty.getAnnotation();
+ return isRole ? discriminator.roleValue() : discriminator.userValue();
}
-
+
/**
* If the user or role properties in the entity class refer to other entities, then this method
* uses the JpaIdentityStore (if available) to lookup that user or role entity. Otherwise it
@@ -375,7 +548,7 @@
List<Permission> permissions = new ArrayList<Permission>();
// First query for user permissions
- Query permissionQuery = createPermissionQuery(target, action, null, Discrimination.either);
+ Query permissionQuery = createPermissionQuery(target, null, Discrimination.either);
List userPermissions = permissionQuery.getResultList();
Map<String,Principal> principalCache = new HashMap<String,Principal>();
@@ -384,50 +557,28 @@
for (Object permission : userPermissions)
{
- Principal principal;
- boolean isUser = true;
+ ActionSet actionSet = metadata.createActionSet(target.getClass(),
+ actionProperty.getValue(permission).toString());
- if (useDiscriminator &&
- discriminatorProperty.getAnnotation().roleValue().equals(discriminatorProperty.getValue(permission)))
- {
- isUser = false;
- }
-
- String name = resolvePrincipalName(isUser ? userProperty.getValue(permission) :
- roleProperty.getValue(permission), isUser);
-
- String key = (isUser ? "u:" : "r:") + name;
-
- if (!principalCache.containsKey(key))
- {
- principal = isUser ? new SimplePrincipal(name) : new Role(name);
- principalCache.put(key, principal);
- }
- else
- {
- principal = principalCache.get(key);
- }
-
- permissions.add(new Permission(target, (String) (action != null ? action : actionProperty.getValue(permission)),
- principal));
- }
-
- // If we have a separate class for role permissions, then query them now
- if (rolePermissionClass != null)
- {
- permissionQuery = createPermissionQuery(target, action, null, Discrimination.role);
- List rolePermissions = permissionQuery.getResultList();
-
- for (Object permission : rolePermissions)
- {
+ if (action == null || actionSet.contains(action))
+ {
Principal principal;
+ boolean isUser = true;
- String name = resolvePrincipalName(roleProperty.getValue(permission), false);
- String key = "r:" + name;
+ if (useDiscriminator &&
+ discriminatorProperty.getAnnotation().roleValue().equals(discriminatorProperty.getValue(permission)))
+ {
+ isUser = false;
+ }
+
+ String name = resolvePrincipalName(isUser ? userProperty.getValue(permission) :
+ roleProperty.getValue(permission), isUser);
+ String key = (isUser ? "u:" : "r:") + name;
+
if (!principalCache.containsKey(key))
{
- principal = new Role(name);
+ principal = isUser ? new SimplePrincipal(name) : new Role(name);
principalCache.put(key, principal);
}
else
@@ -435,11 +586,63 @@
principal = principalCache.get(key);
}
- permissions.add(new Permission(target, (String) (action != null ? action :
- roleActionProperty.getValue(permission)), principal));
+ if (action != null)
+ {
+ permissions.add(new Permission(target, action, principal));
+ }
+ else
+ {
+ for (String a : actionSet.members())
+ {
+ permissions.add(new Permission(target, a, principal));
+ }
+ }
}
}
+ // If we have a separate class for role permissions, then query them now
+ if (rolePermissionClass != null)
+ {
+ permissionQuery = createPermissionQuery(target, null, Discrimination.role);
+ List rolePermissions = permissionQuery.getResultList();
+
+ for (Object permission : rolePermissions)
+ {
+ ActionSet actionSet = metadata.createActionSet(target.getClass(),
+ roleActionProperty.getValue(permission).toString());
+
+ if (action == null || actionSet.contains(action))
+ {
+ Principal principal;
+
+ String name = resolvePrincipalName(roleProperty.getValue(permission), false);
+ String key = "r:" + name;
+
+ if (!principalCache.containsKey(key))
+ {
+ principal = new Role(name);
+ principalCache.put(key, principal);
+ }
+ else
+ {
+ principal = principalCache.get(key);
+ }
+
+ if (action != null)
+ {
+ permissions.add(new Permission(target, action, principal));
+ }
+ else
+ {
+ for (String a : actionSet.members())
+ {
+ permissions.add(new Permission(target, a, principal));
+ }
+ }
+ }
+ }
+ }
+
return permissions;
}
Modified: trunk/src/main/org/jboss/seam/security/permission/PermissionMetadata.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/permission/PermissionMetadata.java 2008-05-10 02:39:00 UTC (rev 8149)
+++ trunk/src/main/org/jboss/seam/security/permission/PermissionMetadata.java 2008-05-10 13:33:34 UTC (rev 8150)
@@ -3,6 +3,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -83,7 +84,7 @@
}
}
- private class ActionSet
+ protected class ActionSet
{
private Set<String> members = new HashSet<String>();
private Class targetClass;
@@ -91,6 +92,12 @@
public ActionSet(Class targetClass, String members)
{
this.targetClass = targetClass;
+ addMembers(members);
+ }
+
+ public void addMembers(String members)
+ {
+ if (members == null) return;
if (usesActionMask.get(targetClass))
{
@@ -115,9 +122,14 @@
{
this.members.add(action);
}
- }
+ }
}
+ public boolean contains(String action)
+ {
+ return members.contains(action);
+ }
+
public ActionSet add(String action)
{
members.add(action);
@@ -130,6 +142,16 @@
return this;
}
+ public Set<String> members()
+ {
+ return members;
+ }
+
+ public boolean isEmpty()
+ {
+ return members.isEmpty();
+ }
+
@Override
public String toString()
{
Modified: trunk/src/main/org/jboss/seam/security/permission/action/PermissionSearch.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/permission/action/PermissionSearch.java 2008-05-10 02:39:00 UTC (rev 8149)
+++ trunk/src/main/org/jboss/seam/security/permission/action/PermissionSearch.java 2008-05-10 13:33:34 UTC (rev 8150)
@@ -3,7 +3,11 @@
import static org.jboss.seam.ScopeType.CONVERSATION;
import java.io.Serializable;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.In;
@@ -19,11 +23,13 @@
@Name("org.jboss.seam.security.permission.permissionSearch")
public class PermissionSearch implements Serializable
{
+ private Map<Principal,List<Permission>> groupedPermissions = new HashMap<Principal,List<Permission>>();
+
@DataModel
- List<Permission> permissions;
+ List<Principal> recipients;
@DataModelSelection
- Permission selectedPermission;
+ Principal selectedRecipient;
@In IdentityManager identityManager;
@@ -39,16 +45,60 @@
public void refresh()
{
- permissions = permissionManager.listPermissions(target);
+ List<Permission> permissions = permissionManager.listPermissions(target);
+ groupedPermissions.clear();
+
+ for (Permission permission : permissions)
+ {
+ List<Permission> recipientPermissions = null;
+
+ if (!groupedPermissions.containsKey(permission.getRecipient()))
+ {
+ recipientPermissions = new ArrayList<Permission>();
+ groupedPermissions.put(permission.getRecipient(), recipientPermissions);
+ }
+ else
+ {
+ recipientPermissions = groupedPermissions.get(permission.getRecipient());
+ }
+
+ recipientPermissions.add(permission);
+ }
+
+ recipients = new ArrayList<Principal>(groupedPermissions.keySet());
}
+ public String getActions(Principal recipient)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ for (Permission permission : groupedPermissions.get(recipient))
+ {
+ if (sb.length() > 0) sb.append(", ");
+ sb.append(permission.getAction());
+ }
+
+ return sb.toString();
+ }
+
public Object getTarget()
{
return target;
}
- public Permission getSelectedPermission()
+ public void revokeSelected()
{
- return selectedPermission;
+ permissionManager.revokePermissions(getSelectedPermissions());
+ refresh();
}
+
+ public Principal getSelectedRecipient()
+ {
+ return selectedRecipient;
+ }
+
+ public List<Permission> getSelectedPermissions()
+ {
+ return groupedPermissions.get(selectedRecipient);
+ }
}
More information about the seam-commits
mailing list