Merge branch 'feature/RM-4357_AllowableOperations' into 'master'

Feature/rm 4357 allowable operations

RM-4357 - fileplanComponent's allowable actions don't reflect RM security

RM's capabilities overrides core's security so it is enough to test the capabilities. Please see the table from the issue's comment.

See merge request !624
This commit is contained in:
Ana Bozianu
2016-11-17 07:33:42 +00:00
3 changed files with 122 additions and 52 deletions

View File

@@ -37,6 +37,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.alfresco.model.ContentModel;
import org.alfresco.module.org_alfresco_module_rm.RecordsManagementServiceRegistry;
import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule;
import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService;
import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService;
@@ -64,6 +65,8 @@ import org.alfresco.service.namespace.QName;
import org.alfresco.util.Pair;
import org.alfresco.util.ParameterCheck;
import net.sf.acegisecurity.vote.AccessDecisionVoter;
/**
* Centralizes access to the repository.
*
@@ -84,6 +87,7 @@ public class RMNodesImpl extends NodesImpl implements RMNodes
private Repository repositoryHelper;
private DictionaryService dictionaryService;
private DispositionService dispositionService;
private CapabilityService capabilityService;
/**
* TODO to remove this after isSpecialNode is made protected in core implementation(REPO-1459)
@@ -113,6 +117,11 @@ public class RMNodesImpl extends NodesImpl implements RMNodes
this.filePlanService = filePlanService;
}
public void setCapabilityService(CapabilityService capabilityService)
{
this.capabilityService = capabilityService;
}
@Override
public Node getFolderOrDocument(final NodeRef nodeRef, NodeRef parentNodeRef, QName nodeTypeQName, List<String> includeParam, Map<String, UserInfo> mapUserInfo)
{
@@ -123,26 +132,6 @@ public class RMNodesImpl extends NodesImpl implements RMNodes
nodeTypeQName = nodeService.getType(nodeRef);
}
//TODO to remove this part of code after isSpecialNode will be made protected on core, will not need this anymore since the right allowed operations will be returned from core(REPO-1459).
if (includeParam.contains(PARAM_INCLUDE_ALLOWABLEOPERATIONS) && originalNode.getAllowableOperations() != null)
{
List<String> allowableOperations = originalNode.getAllowableOperations();
List<String> modifiedAllowableOperations = new ArrayList<>();
modifiedAllowableOperations.addAll(allowableOperations);
for (String op : allowableOperations)
{
if (op.equals(OP_DELETE) && (isSpecialNode(nodeRef, nodeTypeQName)))
{
// special case: do not return "delete" (as an allowable op) for specific system nodes
modifiedAllowableOperations.remove(op);
}
}
originalNode.setAllowableOperations((modifiedAllowableOperations.size() > 0 )? modifiedAllowableOperations : null);
}
RMNodeType type = getType(nodeTypeQName, nodeRef);
FileplanComponentNode node = null;
if (mapUserInfo == null)
@@ -193,9 +182,56 @@ public class RMNodesImpl extends NodesImpl implements RMNodes
}
}
if (includeParam.contains(PARAM_INCLUDE_ALLOWABLEOPERATIONS))
{
node.setAllowableOperations(getAllowableOperations(nodeRef, type));
}
return node;
}
/**
* Helper method that generates allowable operation for the provided node
* @param nodeRef the node to get the allowable operations for
* @param type the type of the provided nodeRef
* @return a sublist of [{@link Nodes.OP_DELETE}, {@link Nodes.OP_CREATE}, {@link Nodes.OP_UPDATE}] representing the allowable operations for the provided node
*/
private List<String> getAllowableOperations(NodeRef nodeRef, RMNodeType type)
{
List<String> allowableOperations = new ArrayList<>();
NodeRef filePlan = filePlanService.getFilePlanBySiteId(FilePlanService.DEFAULT_RM_SITE_ID);
boolean isFilePlan = nodeRef.equals(filePlan);
boolean isTransferContainer = nodeRef.equals(filePlanService.getTransferContainer(filePlan));
boolean isUnfiledContainer = nodeRef.equals(filePlanService.getUnfiledContainer(filePlan));
boolean isHoldsContainer = nodeRef.equals(filePlanService.getHoldContainer(filePlan)) ;
boolean isSpecialContainer = isFilePlan || isTransferContainer || isUnfiledContainer || isHoldsContainer;
// DELETE
if(!isSpecialContainer &&
capabilityService.getCapability("Delete").evaluate(nodeRef) == AccessDecisionVoter.ACCESS_GRANTED)
{
allowableOperations.add(OP_DELETE);
}
// CREATE
if(type != RMNodeType.FILE &&
!isFilePlan &&
!isTransferContainer &&
capabilityService.getCapability("FillingPermissionOnly").evaluate(nodeRef) == AccessDecisionVoter.ACCESS_GRANTED)
{
allowableOperations.add(OP_CREATE);
}
// UPDATE
if (capabilityService.getCapability("Update").evaluate(nodeRef) == AccessDecisionVoter.ACCESS_GRANTED)
{
allowableOperations.add(OP_UPDATE);
}
return allowableOperations;
}
@Override
public NodeRef validateNode(String nodeId)
{