Merged V2.2 to HEAD

7732: Support to cache null QName look ups ...
   7733: Support for store ACLs
   7741: Fix for over keen stiore ACLs ....
   7794: Fix for WCM-1019, tasks show all assets as modified when only one has
   7996: Fix for AWC-1519: cancelling discussion creation results in error


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@8448 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Derek Hulley
2008-03-07 01:50:03 +00:00
parent 513a32a71b
commit 6ce34484fc
22 changed files with 838 additions and 129 deletions

View File

@@ -25,31 +25,27 @@
package org.alfresco.repo.security.permissions.impl;
import org.alfresco.repo.security.permissions.NodePermissionEntry;
import org.alfresco.util.EqualsHelper;
/**
* This class provides common support for hash code and equality.
*
* @author andyh
*/
public abstract class AbstractNodePermissionEntry implements
NodePermissionEntry
public abstract class AbstractNodePermissionEntry implements NodePermissionEntry
{
public AbstractNodePermissionEntry()
{
super();
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder(200);
sb.append("NodePermissionEntry")
.append("[ node=").append(getNodeRef())
.append(", entries=").append(getPermissionEntries())
.append(", inherits=").append(inheritPermissions())
.append("]");
sb.append("NodePermissionEntry").append("[ node=").append(getNodeRef()).append(", entries=").append(getPermissionEntries()).append(", inherits=").append(
inheritPermissions()).append("]");
return sb.toString();
}
@@ -66,14 +62,21 @@ public abstract class AbstractNodePermissionEntry implements
}
AbstractNodePermissionEntry other = (AbstractNodePermissionEntry) o;
return this.getNodeRef().equals(other.getNodeRef())
&& (this.inheritPermissions() == other.inheritPermissions())
&& (this.getPermissionEntries().equals(other.getPermissionEntries()));
return EqualsHelper.nullSafeEquals(this.getNodeRef(), other.getNodeRef()) &&
EqualsHelper.nullSafeEquals(this.inheritPermissions(), other.inheritPermissions()) &&
EqualsHelper.nullSafeEquals(this.getPermissionEntries(), other.getPermissionEntries());
}
@Override
public int hashCode()
{
return getNodeRef().hashCode();
if (getNodeRef() != null)
{
return getNodeRef().hashCode();
}
else
{
return 0;
}
}
}

View File

@@ -54,14 +54,17 @@ public abstract class AbstractPermissionEntry implements PermissionEntry
AbstractPermissionEntry other = (AbstractPermissionEntry) o;
return EqualsHelper.nullSafeEquals(this.getNodeRef(), other.getNodeRef())
&& EqualsHelper.nullSafeEquals(this.getPermissionReference(), other.getPermissionReference())
&& EqualsHelper.nullSafeEquals(this.getAuthority(), other.getAuthority())
&& EqualsHelper.nullSafeEquals(this.getAccessStatus(), other.getAccessStatus());
&& EqualsHelper.nullSafeEquals(this.getAuthority(), other.getAuthority()) && EqualsHelper.nullSafeEquals(this.getAccessStatus(), other.getAccessStatus());
}
@Override
public int hashCode()
{
int hashCode = getNodeRef().hashCode();
int hashCode = 0;
if (getNodeRef() != null)
{
getNodeRef().hashCode();
}
if (getPermissionReference() != null)
{
hashCode = hashCode * 37 + getPermissionReference().hashCode();
@@ -70,9 +73,9 @@ public abstract class AbstractPermissionEntry implements PermissionEntry
{
hashCode = hashCode * 37 + getAuthority().hashCode();
}
if(getAccessStatus() != null)
if (getAccessStatus() != null)
{
hashCode = hashCode * 37 + getAccessStatus().hashCode();
hashCode = hashCode * 37 + getAccessStatus().hashCode();
}
return hashCode;
}
@@ -81,13 +84,9 @@ public abstract class AbstractPermissionEntry implements PermissionEntry
public String toString()
{
StringBuilder sb = new StringBuilder(200);
sb.append("PermissionEntry")
.append("[ authority=").append(getAuthority())
.append(", permission=").append(getPermissionReference())
.append(", access=").append(getAccessStatus())
.append("]");
sb.append("PermissionEntry").append("[ authority=").append(getAuthority()).append(", permission=").append(getPermissionReference()).append(", access=").append(
getAccessStatus()).append("]");
return sb.toString();
}
}

View File

@@ -36,6 +36,8 @@ import net.sf.acegisecurity.GrantedAuthority;
import net.sf.acegisecurity.providers.dao.User;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.avm.AVMNodeConverter;
import org.alfresco.repo.avm.AVMRepository;
import org.alfresco.repo.cache.SimpleCache;
import org.alfresco.repo.policy.JavaBehaviour;
import org.alfresco.repo.policy.PolicyComponent;
@@ -54,6 +56,7 @@ import org.alfresco.service.cmr.dictionary.DictionaryService;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.AuthorityService;
@@ -283,6 +286,17 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
return accessPermissions;
}
public Set<AccessPermission> getAllSetPermissions(StoreRef storeRef)
{
HashSet<AccessPermission> accessPermissions = new HashSet<AccessPermission>();
NodePermissionEntry nodePremissionEntry = getSetPermissions(storeRef);
for (PermissionEntry pe : nodePremissionEntry.getPermissionEntries())
{
accessPermissions.add(new AccessPermissionImpl(getPermission(pe.getPermissionReference()), pe.getAccessStatus(), pe.getAuthority()));
}
return accessPermissions;
}
private Set<AccessPermission> getAllPermissionsImpl(NodeRef nodeRef, boolean includeTrue, boolean includeFalse)
{
String userName = authenticationComponent.getCurrentUserName();
@@ -331,6 +345,11 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
return permissionsDaoComponent.getPermissions(tenantService.getName(nodeRef));
}
public NodePermissionEntry getSetPermissions(StoreRef storeRef)
{
return permissionsDaoComponent.getPermissions(storeRef);
}
public AccessStatus hasPermission(final NodeRef nodeRefIn, final PermissionReference permIn)
{
// If the node ref is null there is no sensible test to do - and there
@@ -349,12 +368,20 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
return AccessStatus.DENIED;
}
// AVM nodes - test for existence underneath
if (nodeRef.getStoreRef().getProtocol().equals(StoreRef.PROTOCOL_AVM))
{
return doAvmCan(nodeRef, permIn);
}
// Allow permissions for nodes that do not exist
if (!nodeService.exists(nodeRef))
{
return AccessStatus.ALLOWED;
}
final PermissionReference perm;
if (permIn.equals(OLD_ALL_PERMISSIONS_REFERENCE))
{
@@ -436,6 +463,16 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
}
private AccessStatus doAvmCan(NodeRef nodeRef, PermissionReference permission)
{
org.alfresco.util.Pair<Integer, String> avmVersionPath = AVMNodeConverter.ToAVMVersionPath(nodeRef);
int version = avmVersionPath.getFirst();
String path = avmVersionPath.getSecond();
boolean result = AVMRepository.GetInstance().can(nodeRef.getStoreRef().getIdentifier(), version, path, permission.getName());
AccessStatus status = result ? AccessStatus.ALLOWED : AccessStatus.DENIED;
return status;
}
/*
* (non-Javadoc)
*
@@ -493,11 +530,22 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
{
permission = getAllPermissionReference();
}
AclTest aclTest = new AclTest(permission, typeQname, aspectQNames);
boolean result = aclTest.evaluate(authorisations, aclId);
boolean result;
if (context.getStoreAcl() == null)
{
AclTest aclTest = new AclTest(permission, typeQname, aspectQNames);
result = aclTest.evaluate(authorisations, aclId);
}
else
{
Set<String> storeAuthorisations = getAuthorisations(auth, (PermissionContext)null);
AclTest aclTest = new AclTest(permission, typeQname, aspectQNames);
result = aclTest.evaluate(authorisations, aclId) && aclTest.evaluate(storeAuthorisations, context.getStoreAcl());
}
AccessStatus status = result ? AccessStatus.ALLOWED : AccessStatus.DENIED;
return status;
}
enum CacheType
@@ -608,6 +656,43 @@ public class PermissionServiceImpl implements PermissionServiceSPI, Initializing
return null;
}
public void clearPermission(StoreRef storeRef, String authority)
{
permissionsDaoComponent.deletePermissions(storeRef, authority);
accessCache.clear();
}
public void deletePermission(StoreRef storeRef, String authority, String perm)
{
deletePermission(storeRef, authority, getPermissionReference(perm));
}
public void deletePermission(StoreRef storeRef, String authority, PermissionReference perm)
{
permissionsDaoComponent.deletePermission(storeRef, authority, perm);
accessCache.clear();
}
public void deletePermissions(StoreRef storeRef)
{
permissionsDaoComponent.deletePermissions(storeRef);
accessCache.clear();
}
public void setPermission(StoreRef storeRef, String authority, String perm, boolean allow)
{
setPermission(storeRef, authority, getPermissionReference(perm), allow);
}
public void setPermission(StoreRef storeRef, String authority, PermissionReference permission, boolean allow)
{
permissionsDaoComponent.setPermission(storeRef, authority, permission, allow);
accessCache.clear();
}
public void deletePermissions(NodeRef nodeRef)
{
permissionsDaoComponent.deletePermissions(tenantService.getName(nodeRef));

View File

@@ -949,7 +949,42 @@ public class PermissionServiceTest extends AbstractPermissionTest
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CHILDREN)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_CONTENT)) == AccessStatus.ALLOWED);
}
public void testPerformance() throws Exception
{
runAs("admin");
// TransactionService transactionService = serviceRegistry.getTransactionService();
// UserTransaction tx = transactionService.getUserTransaction();
// tx.begin();
NodeRef n1 = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, QName.createQName("{namespace}one"), ContentModel.TYPE_FOLDER).getChildRef();
NodeRef n2 = nodeService.createNode(n1, ContentModel.ASSOC_CONTAINS, QName.createQName("{namespace}two"), ContentModel.TYPE_FOLDER).getChildRef();
NodeRef n3 = nodeService.createNode(n2, ContentModel.ASSOC_CONTAINS, QName.createQName("{namespace}three"), ContentModel.TYPE_FOLDER).getChildRef();
NodeRef n4 = nodeService.createNode(n3, ContentModel.ASSOC_CONTAINS, QName.createQName("{namespace}four"), ContentModel.TYPE_FOLDER).getChildRef();
NodeRef n5 = nodeService.createNode(n4, ContentModel.ASSOC_CONTAINS, QName.createQName("{namespace}five"), ContentModel.TYPE_FOLDER).getChildRef();
NodeRef n6 = nodeService.createNode(n5, ContentModel.ASSOC_CONTAINS, QName.createQName("{namespace}six"), ContentModel.TYPE_FOLDER).getChildRef();
NodeRef n7 = nodeService.createNode(n6, ContentModel.ASSOC_CONTAINS, QName.createQName("{namespace}seven"), ContentModel.TYPE_FOLDER).getChildRef();
NodeRef n8 = nodeService.createNode(n7, ContentModel.ASSOC_CONTAINS, QName.createQName("{namespace}eight"), ContentModel.TYPE_FOLDER).getChildRef();
NodeRef n9 = nodeService.createNode(n8, ContentModel.ASSOC_CONTAINS, QName.createQName("{namespace}nine"), ContentModel.TYPE_FOLDER).getChildRef();
NodeRef n10 = nodeService.createNode(n9, ContentModel.ASSOC_CONTAINS, QName.createQName("{namespace}ten"), ContentModel.TYPE_FOLDER).getChildRef();
permissionService.setPermission(new SimplePermissionEntry(rootNodeRef, getPermission(PermissionService.READ), "andy", AccessStatus.ALLOWED));
runAs("andy");
permissionService.hasPermission(n5, PermissionService.READ);
long start = System.nanoTime();
for(int i = 0; i < 10000; i++)
{
permissionService.hasPermission(n5, PermissionService.READ);
}
long end = System.nanoTime();
System.out.println("Can in "+((end-start)/10e9f/10000));
System.out.println("Can per second "+(1/((end-start)/10e9f/10000)));
}
public void testPerf() throws Exception
{
runAs("admin");
@@ -1527,6 +1562,8 @@ public class PermissionServiceTest extends AbstractPermissionTest
permissionService.setPermission(new SimplePermissionEntry(rootNodeRef, getPermission(PermissionService.READ_PROPERTIES), "ANDY", AccessStatus.ALLOWED));
permissionService.setPermission(new SimplePermissionEntry(rootNodeRef, getPermission(PermissionService.READ_CONTENT), "AnDy", AccessStatus.ALLOWED));
permissionService.getAllSetPermissions(rootNodeRef);
runAs("andy");
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ)) == AccessStatus.ALLOWED);
assertFalse(permissionService.hasPermission(rootNodeRef, getPermission(PermissionService.READ_PROPERTIES)) == AccessStatus.ALLOWED);

View File

@@ -31,6 +31,7 @@ import org.alfresco.repo.security.permissions.NodePermissionEntry;
import org.alfresco.repo.security.permissions.PermissionEntry;
import org.alfresco.repo.security.permissions.PermissionReference;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.AccessPermission;
/**
@@ -137,4 +138,45 @@ public interface PermissionsDaoComponent
* @return - the set of matching nodes
*/
public Set<NodeRef> findNodeByPermission(String authority, PermissionReference permission, boolean allow);
/**
* Delete entries from a permission mask on a store by authority
*
* @param storeRef
* @param authority
*/
public void deletePermissions(StoreRef storeRef, String authority);
/**
* Remove part of a permission mask from a store
*
* @param storeRef
* @param authority
* @param perm
*/
public void deletePermission(StoreRef storeRef, String authority, PermissionReference perm);
/**
* Remove all permission masks from a store
*
* @param storeRef
*/
public void deletePermissions(StoreRef storeRef);
/**
* Set part of a permission mask on a store.
*
* @param storeRef
* @param authority
* @param permission
* @param allow
*/
public void setPermission(StoreRef storeRef, String authority, PermissionReference permission, boolean allow);
/**
* Get permission masks set on a store
* @param storeRef
* @return
*/
public NodePermissionEntry getPermissions(StoreRef storeRef);
}

View File

@@ -27,6 +27,7 @@ package org.alfresco.repo.security.permissions.impl.model;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -97,7 +98,7 @@ public class PermissionModel implements ModelDAO, InitializingBean
private String model;
// Aprrox 6 - default size OK
private Map<QName, PermissionSet> permissionSets = new HashMap<QName, PermissionSet>();
private Map<QName, PermissionSet> permissionSets = new HashMap<QName, PermissionSet>(128, 1.0f);
// Global permissions - default size OK
private Set<GlobalPermissionEntry> globalPermissions = new HashSet<GlobalPermissionEntry>();
@@ -105,13 +106,13 @@ public class PermissionModel implements ModelDAO, InitializingBean
private AccessStatus defaultPermission;
// Cache granting permissions
private HashMap<PermissionReference, Set<PermissionReference>> grantingPermissions = new HashMap<PermissionReference, Set<PermissionReference>>(128, 1.0f);
private HashMap<PermissionReference, Set<PermissionReference>> grantingPermissions = new HashMap<PermissionReference, Set<PermissionReference>>(256, 1.0f);
// Cache grantees
private HashMap<PermissionReference, Set<PermissionReference>> granteePermissions = new HashMap<PermissionReference, Set<PermissionReference>>(128, 1.0f);
private HashMap<PermissionReference, Set<PermissionReference>> granteePermissions = new HashMap<PermissionReference, Set<PermissionReference>>(256, 1.0f);
// Cache the mapping of extended groups to the base
private HashMap<PermissionGroup, PermissionGroup> groupsToBaseGroup = new HashMap<PermissionGroup, PermissionGroup>(128, 1.0f);
private HashMap<PermissionGroup, PermissionGroup> groupsToBaseGroup = new HashMap<PermissionGroup, PermissionGroup>(256, 1.0f);
private HashMap<String, PermissionReference> uniqueMap;
@@ -121,9 +122,11 @@ public class PermissionModel implements ModelDAO, InitializingBean
private HashMap<String, PermissionReference> permissionReferenceMap;
private Map<QName, Set<PermissionReference>> cachedTypePermissionsExposed = new HashMap<QName, Set<PermissionReference>>(128, 1.0f);
private Map<QName, Set<PermissionReference>> cachedTypePermissionsExposed = new HashMap<QName, Set<PermissionReference>>(256, 1.0f);
private Map<QName, Set<PermissionReference>> cachedTypePermissionsUnexposed = new HashMap<QName, Set<PermissionReference>>(128, 1.0f);
private Map<QName, Set<PermissionReference>> cachedTypePermissionsUnexposed = new HashMap<QName, Set<PermissionReference>>(256, 1.0f);
private Collection<QName> allAspects;
public PermissionModel()
{
@@ -226,6 +229,10 @@ public class PermissionModel implements ModelDAO, InitializingBean
globalPermissions.add(globalPermission);
}
// Cache all aspect list
allAspects = dictionaryService.getAllAspects();
}
/*
@@ -308,7 +315,7 @@ public class PermissionModel implements ModelDAO, InitializingBean
Set<PermissionReference> permissions = cache.get(type);
if (permissions == null)
{
permissions = new LinkedHashSet<PermissionReference>(128, 1.0f);
permissions = new LinkedHashSet<PermissionReference>(256, 1.0f);
ClassDefinition cd = dictionaryService.getClass(type);
if (cd != null)
{
@@ -428,12 +435,12 @@ public class PermissionModel implements ModelDAO, InitializingBean
private void mergeGeneralAspectPermissions(Set<PermissionReference> target, boolean exposedOnly)
{
for (QName aspect : dictionaryService.getAllAspects())
for (QName aspect : allAspects)
{
mergePermissions(target, aspect, exposedOnly, false);
}
}
public Set<PermissionReference> getAllPermissions(NodeRef nodeRef)
{
return getAllPermissionsImpl(nodeService.getType(nodeRef), nodeService.getAspects(nodeRef), false);
@@ -451,20 +458,14 @@ public class PermissionModel implements ModelDAO, InitializingBean
private Set<PermissionReference> getAllPermissionsImpl(QName typeName, Set<QName> aspects, boolean exposedOnly)
{
Set<PermissionReference> permissions = new LinkedHashSet<PermissionReference>(128, 1.0f);
Set<PermissionReference> permissions = new LinkedHashSet<PermissionReference>(256, 1.0f);
ClassDefinition cd = dictionaryService.getClass(typeName);
permissions.addAll(getAllPermissionsImpl(typeName, exposedOnly));
ClassDefinition cd = dictionaryService.getClass(typeName);
if (cd != null)
{
if (cd.isAspect())
{
// Do not merge in all general aspects
}
else
{
mergeGeneralAspectPermissions(permissions, exposedOnly);
}
Set<QName> defaultAspects = new HashSet<QName>();
for (AspectDefinition aspDef : cd.getDefaultAspects())
{
@@ -500,7 +501,7 @@ public class PermissionModel implements ModelDAO, InitializingBean
private Set<PermissionReference> getGrantingPermissionsImpl(PermissionReference permissionReference)
{
// Query the model
HashSet<PermissionReference> permissions = new HashSet<PermissionReference>(128, 1.0f);
HashSet<PermissionReference> permissions = new HashSet<PermissionReference>(256, 1.0f);
permissions.add(permissionReference);
for (PermissionSet ps : permissionSets.values())
{
@@ -573,7 +574,7 @@ public class PermissionModel implements ModelDAO, InitializingBean
private Set<PermissionReference> getGranteePermissionsImpl(PermissionReference permissionReference)
{
// Query the model
HashSet<PermissionReference> permissions = new HashSet<PermissionReference>(128, 1.0f);
HashSet<PermissionReference> permissions = new HashSet<PermissionReference>(256, 1.0f);
permissions.add(permissionReference);
for (PermissionSet ps : permissionSets.values())
{
@@ -636,7 +637,7 @@ public class PermissionModel implements ModelDAO, InitializingBean
private Set<PermissionReference> getAllPermissions()
{
HashSet<PermissionReference> permissions = new HashSet<PermissionReference>(128, 1.0f);
HashSet<PermissionReference> permissions = new HashSet<PermissionReference>(256, 1.0f);
for (PermissionSet ps : permissionSets.values())
{
for (PermissionGroup pg : ps.getPermissionGroups())
@@ -817,7 +818,7 @@ public class PermissionModel implements ModelDAO, InitializingBean
*/
private Set<PermissionReference> getRequirementsForPermissionGroup(PermissionGroup target, RequiredPermission.On on, QName qName, Set<QName> aspectQNames)
{
HashSet<PermissionReference> requiredPermissions = new HashSet<PermissionReference>(8, 1.0f);
HashSet<PermissionReference> requiredPermissions = new HashSet<PermissionReference>(16, 1.0f);
if (target == null)
{
return requiredPermissions;
@@ -960,11 +961,11 @@ public class PermissionModel implements ModelDAO, InitializingBean
private void buildUniquePermissionMap()
{
Set<String> excluded = new HashSet<String>(64, 1.0f);
uniqueMap = new HashMap<String, PermissionReference>(128, 1.0f);
permissionReferenceMap = new HashMap<String, PermissionReference>(128, 1.0f);
permissionGroupMap = new HashMap<PermissionReference, PermissionGroup>(64, 1.0f);
permissionMap = new HashMap<PermissionReference, Permission>(32, 1.0f);
Set<String> excluded = new HashSet<String>(128, 1.0f);
uniqueMap = new HashMap<String, PermissionReference>(256, 1.0f);
permissionReferenceMap = new HashMap<String, PermissionReference>(256, 1.0f);
permissionGroupMap = new HashMap<PermissionReference, PermissionGroup>(128, 1.0f);
permissionMap = new HashMap<PermissionReference, Permission>(64, 1.0f);
for (PermissionSet ps : permissionSets.values())
{
for (PermissionGroup pg : ps.getPermissionGroups())