RM-1724 (Inheritance is not off for root categories, unfiled records, holds and transfers)

RM-1725 (Inheritance is not working properly)

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/BRANCHES/V2.1.0.x@88182 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Tuna Aksoy
2014-10-15 16:28:01 +00:00
parent 867f22b20e
commit adb53fe47d
2 changed files with 61 additions and 107 deletions

View File

@@ -21,10 +21,8 @@ package org.alfresco.module.org_alfresco_module_rm.security;
import static org.apache.commons.lang.BooleanUtils.isTrue; import static org.apache.commons.lang.BooleanUtils.isTrue;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService;
import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
@@ -43,7 +41,6 @@ import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.cmr.security.AccessStatus;
import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -404,11 +401,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());
} }
/** private void setUpPermissions(final NodeRef nodeRef)
*
* @param nodeRef
*/
public void setUpPermissions(final NodeRef nodeRef)
{ {
setUpPermissions(nodeRef, null); setUpPermissions(nodeRef, null);
} }
@@ -421,7 +414,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
{ {
public Object doWork() public Object doWork()
{ {
// break inheritance // set inheritance
permissionService.setInheritParentPermissions(nodeRef, isInheritanceAllowed(nodeRef, isParentNodeFilePlan)); permissionService.setInheritParentPermissions(nodeRef, isInheritanceAllowed(nodeRef, isParentNodeFilePlan));
// set extended reader permissions // set extended reader permissions
@@ -436,7 +429,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
private boolean isInheritanceAllowed(NodeRef nodeRef, Boolean isParentNodeFilePlan) private boolean isInheritanceAllowed(NodeRef nodeRef, Boolean isParentNodeFilePlan)
{ {
return !(isFilePlan(nodeRef) || isHold(nodeRef) || isTransfer(nodeRef) || (isRecordCategory(nodeRef) && isTrue(isParentNodeFilePlan))); return !(isFilePlan(nodeRef) || isTransfer(nodeRef) || isHold(nodeRef) || isUnfiledRecordsContainer(nodeRef) || (isRecordCategory(nodeRef) && isTrue(isParentNodeFilePlan)));
} }
/** /**
@@ -452,12 +445,16 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
{ {
public Boolean doWork() throws Exception public Boolean doWork() throws Exception
{ {
if (filePlanService.isFilePlan(nodeRef) || if (canPerformPermissionAction(nodeRef))
filePlanService.isFilePlanContainer(nodeRef) ||
recordsManagementService.isRecordFolder(nodeRef) ||
recordService.isRecord(nodeRef))
{ {
setPermissionDown(nodeRef, authority, permission); if (RMPermissionModel.FILING.equals(permission))
{
// Remove record read permission before adding filing permission
permissionService.deletePermission(nodeRef, authority, RMPermissionModel.READ_RECORDS);
}
// Set the permission on the node
permissionService.setPermission(nodeRef, authority, permission, true);
} }
else else
{ {
@@ -472,57 +469,6 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());
} }
/**
* Helper method to set the permission down the hierarchy
*
* @param nodeRef node reference
* @param authority authority
* @param permission permission
*/
private void setPermissionDown(NodeRef nodeRef, String authority, String permission)
{
// set permissions
setPermissionImpl(nodeRef, authority, permission);
// skip out node's that inherit (for example hold and transfer)
if (!permissionService.getInheritParentPermissions(nodeRef) &&
(filePlanService.isFilePlanContainer(nodeRef) ||
recordsManagementService.isRecordFolder(nodeRef)))
{
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
for (ChildAssociationRef assoc : assocs)
{
NodeRef child = assoc.getChildRef();
if (filePlanService.isFilePlanContainer(child) ||
recordsManagementService.isRecordFolder(child) ||
recordService.isRecord(child) ||
instanceOf(child, TYPE_HOLD) ||
instanceOf(child, TYPE_TRANSFER))
{
setPermissionDown(child, authority, permission);
}
}
}
}
/**
* Set the permission, taking into account that filing is a superset of read
*
* @param nodeRef
* @param authority
* @param permission
*/
private void setPermissionImpl(NodeRef nodeRef, String authority, String permission)
{
if (RMPermissionModel.FILING.equals(permission) == true)
{
// Remove record read permission before adding filing permission
permissionService.deletePermission(nodeRef, authority, RMPermissionModel.READ_RECORDS);
}
permissionService.setPermission(nodeRef, authority, permission, true);
}
/** /**
* @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#deletePermission(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String) * @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#deletePermission(org.alfresco.service.cmr.repository.NodeRef, java.lang.String, java.lang.String)
*/ */
@@ -532,26 +478,16 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
{ {
public Boolean doWork() throws Exception public Boolean doWork() throws Exception
{ {
// Delete permission on this node if (canPerformPermissionAction(nodeRef))
permissionService.deletePermission(nodeRef, authority, permission);
// can't delete permissions if inherited (eg hold and transfer containers)
if (!permissionService.getInheritParentPermissions(nodeRef) &&
(filePlanService.isFilePlanContainer(nodeRef) ||
recordsManagementService.isRecordFolder(nodeRef)))
{ {
List<ChildAssociationRef> assocs = nodeService.getChildAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); // Delete permission on this node
for (ChildAssociationRef assoc : assocs) permissionService.deletePermission(nodeRef, authority, permission);
}
else
{
if (logger.isWarnEnabled())
{ {
NodeRef child = assoc.getChildRef(); logger.warn("Deleting permissions for this node is not supported. (nodeRef=" + nodeRef + ", authority=" + authority + ", permission=" + permission + ")");
if (filePlanService.isFilePlanContainer(child) ||
recordsManagementService.isRecordFolder(child) ||
recordService.isRecord(child)||
instanceOf(child, TYPE_HOLD) ||
instanceOf(child, TYPE_TRANSFER))
{
deletePermission(child, authority, permission);
}
} }
} }
@@ -559,4 +495,9 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl
} }
}, AuthenticationUtil.getSystemUserName()); }, AuthenticationUtil.getSystemUserName());
} }
private boolean canPerformPermissionAction(NodeRef nodeRef)
{
return filePlanService.isFilePlanContainer(nodeRef) || recordsManagementService.isRecordFolder(nodeRef) || recordService.isRecord(nodeRef);
}
} }

View File

@@ -40,7 +40,7 @@ import org.springframework.context.ApplicationContextAware;
/** /**
* Helper base class for service implementations. * Helper base class for service implementations.
* *
* @author Roy Wetherall * @author Roy Wetherall
* @since 2.1 * @since 2.1
*/ */
@@ -54,7 +54,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
/** Application context */ /** Application context */
protected ApplicationContext applicationContext; protected ApplicationContext applicationContext;
/** internal node service */ /** internal node service */
private NodeService internalNodeService; private NodeService internalNodeService;
@@ -82,7 +82,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
this.dictionaryService = dictionaryService; this.dictionaryService = dictionaryService;
} }
/** /**
* Helper to get internal node service. * Helper to get internal node service.
* <p> * <p>
@@ -94,10 +94,10 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
internalNodeService = (NodeService)applicationContext.getBean("dbNodeService"); internalNodeService = (NodeService)applicationContext.getBean("dbNodeService");
} }
return internalNodeService; return internalNodeService;
} }
/** /**
* Gets the file plan component kind from the given node reference * Gets the file plan component kind from the given node reference
* *
@@ -117,7 +117,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
if (isFilePlanComponent(nodeRef)) if (isFilePlanComponent(nodeRef))
{ {
result = FilePlanComponentKind.FILE_PLAN_COMPONENT; result = FilePlanComponentKind.FILE_PLAN_COMPONENT;
if (isFilePlan(nodeRef)) if (isFilePlan(nodeRef))
{ {
result = FilePlanComponentKind.FILE_PLAN; result = FilePlanComponentKind.FILE_PLAN;
@@ -146,12 +146,12 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
result = FilePlanComponentKind.DISPOSITION_SCHEDULE; result = FilePlanComponentKind.DISPOSITION_SCHEDULE;
} }
else if (instanceOf(nodeRef, TYPE_UNFILED_RECORD_CONTAINER)) else if (isUnfiledRecordsContainer(nodeRef))
{ {
result = FilePlanComponentKind.UNFILED_RECORD_CONTAINER; result = FilePlanComponentKind.UNFILED_RECORD_CONTAINER;
} }
} }
if (result != null) if (result != null)
{ {
map.put(nodeRef, result); map.put(nodeRef, result);
@@ -297,7 +297,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
boolean isHold = false; boolean isHold = false;
if (getInternalNodeService().exists(nodeRef) && if (getInternalNodeService().exists(nodeRef) &&
instanceOf(nodeRef, TYPE_HOLD)) instanceOf(nodeRef, TYPE_HOLD))
{ {
isHold = true; isHold = true;
@@ -316,10 +316,23 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
return instanceOf(nodeRef, TYPE_TRANSFER); return instanceOf(nodeRef, TYPE_TRANSFER);
} }
/**
* Indicates whether the given node reference is an unfiled records container or not.
*
* @param nodeRef node reference
* @return boolean true if rma:unfiledRecordContainer or sub-type, false otherwise
*/
public boolean isUnfiledRecordsContainer(NodeRef nodeRef)
{
ParameterCheck.mandatory("nodeRef", nodeRef);
return instanceOf(nodeRef, TYPE_UNFILED_RECORD_CONTAINER);
}
/** /**
* Indicates whether a record is complete or not. * Indicates whether a record is complete or not.
* *
* @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isDeclared(org.alfresco.service.cmr.repository.NodeRef) * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#isDeclared(org.alfresco.service.cmr.repository.NodeRef)
*/ */
public boolean isDeclared(NodeRef record) public boolean isDeclared(NodeRef record)
@@ -338,12 +351,12 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
public NodeRef getFilePlan(final NodeRef nodeRef) public NodeRef getFilePlan(final NodeRef nodeRef)
{ {
NodeRef result = null; NodeRef result = null;
if (nodeRef != null) if (nodeRef != null)
{ {
Map<NodeRef, NodeRef> transactionCache = TransactionalResourceHelper.getMap("rm.servicebase.getFilePlan"); Map<NodeRef, NodeRef> transactionCache = TransactionalResourceHelper.getMap("rm.servicebase.getFilePlan");
if (transactionCache.containsKey(nodeRef)) if (transactionCache.containsKey(nodeRef))
{ {
result = transactionCache.get(nodeRef); result = transactionCache.get(nodeRef);
} }
else else
{ {
@@ -363,7 +376,7 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
} }
} }
} }
// cache result in transaction // cache result in transaction
transactionCache.put(nodeRef, result); transactionCache.put(nodeRef, result);
} }
@@ -381,11 +394,11 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
protected boolean instanceOf(NodeRef nodeRef, QName ofClassName) protected boolean instanceOf(NodeRef nodeRef, QName ofClassName)
{ {
ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("nodeRef", nodeRef);
ParameterCheck.mandatory("ofClassName", ofClassName); ParameterCheck.mandatory("ofClassName", ofClassName);
QName className = getInternalNodeService().getType(nodeRef); QName className = getInternalNodeService().getType(nodeRef);
return instanceOf(className, ofClassName); return instanceOf(className, ofClassName);
} }
private static Map<String, Boolean> instanceOfCache = new HashMap<String, Boolean>(); private static Map<String, Boolean> instanceOfCache = new HashMap<String, Boolean>();
/** /**
@@ -399,25 +412,25 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte
{ {
ParameterCheck.mandatory("className", className); ParameterCheck.mandatory("className", className);
ParameterCheck.mandatory("ofClassName", ofClassName); ParameterCheck.mandatory("ofClassName", ofClassName);
boolean result = false; boolean result = false;
String key = className.toString() + "|" + ofClassName.toString(); String key = className.toString() + "|" + ofClassName.toString();
if (instanceOfCache.containsKey(key)) if (instanceOfCache.containsKey(key))
{ {
result = instanceOfCache.get(key); result = instanceOfCache.get(key);
} }
else else
{ {
if (ofClassName.equals(className) || if (ofClassName.equals(className) ||
dictionaryService.isSubClass(className, ofClassName)) dictionaryService.isSubClass(className, ofClassName))
{ {
result = true; result = true;
} }
instanceOfCache.put(key, result); instanceOfCache.put(key, result);
} }
return result; return result;
} }