From 4e433635df9d22733ed08ad61341c77afcc79b71 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Fri, 5 Oct 2012 06:03:21 +0000 Subject: [PATCH] RM InPlace Prototype: * permission mapping improvements ... allows filling and declaration of unfiled records * actions of 'records' in doc lib are shown as restricted rm list * "Record" banner is shown in doc lib if content is a record (this differs from the normal record view where the undeclared status is shown, this isn't relevant for a content user) * linked to many record folders indicator not shown unless it really is linked to many record folders git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/DEV/INPLACE@42374 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org_alfresco_module_rm/action-context.xml | 3 +- .../model/recordsModel.xml | 1 - .../rm-service-context.xml | 6 +- .../RecordsManagementServiceImpl.java | 11 ++ .../action/dm/CreateRecordAction.java | 111 +++++------ .../app/evaluator/MultiParentEvaluator.java | 28 ++- .../record/RecordService.java | 8 + .../record/RecordServiceImpl.java | 172 ++++++++++-------- .../RecordsManagementSecurityService.java | 33 +++- .../RecordsManagementSecurityServiceImpl.java | 92 +++++++++- 10 files changed, 304 insertions(+), 161 deletions(-) diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml index 3179870f95..aeaf6af44d 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/action-context.xml @@ -15,8 +15,7 @@ - - + diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml index 50d4493ca5..675b96dc26 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml @@ -726,7 +726,6 @@ Date Filed d:date - true diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml index d27cff9d0d..f316f9938c 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml @@ -481,7 +481,8 @@ org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.createRole=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.updateRole=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.deleteRole=RM_ALLOW - org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.assignRoleToAuthority=RM_ALLOW + org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.assignRoleToAuthority=RM_ALLOW + org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.hasExtendedReaders=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.getExtendedReaders=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.setExtendedReaders=RM_ALLOW org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService.removeExtendedReaders=RM_ALLOW @@ -801,6 +802,8 @@ + + @@ -845,6 +848,7 @@ diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java index eef43031b7..a2411a0c82 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/RecordsManagementServiceImpl.java @@ -33,6 +33,7 @@ import org.alfresco.model.RenditionModel; import org.alfresco.module.org_alfresco_module_rm.action.RecordsManagementActionService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementCustomModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService; import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; @@ -284,7 +285,17 @@ public class RecordsManagementServiceImpl implements RecordsManagementService, NodeRef thumbnail = childAssocRef.getChildRef(); if (nodeService.exists(thumbnail) == true) { + // apply file plan component aspect to thumbnail nodeService.addAspect(thumbnail, ASPECT_FILE_PLAN_COMPONENT, null); + + // manage any extended readers + RecordsManagementSecurityService securityService = serviceRegistry.getRecordsManagementSecurityService(); + NodeRef parent = childAssocRef.getParentRef(); + Set readers = securityService.getExtendedReaders(parent); + if (readers != null && readers.size() != 0) + { + securityService.setExtendedReaders(thumbnail, readers, false); + } } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java index 89f8c020e2..f3febba383 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java @@ -19,23 +19,18 @@ package org.alfresco.module.org_alfresco_module_rm.action.dm; import java.util.List; -import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.repo.action.executer.ActionExecuterAbstractBase; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; -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.security.PermissionService; -import org.alfresco.service.namespace.RegexQNamePattern; /** * Creates a new record from an existing content object. @@ -47,29 +42,31 @@ import org.alfresco.service.namespace.RegexQNamePattern; public class CreateRecordAction extends ActionExecuterAbstractBase implements RecordsManagementModel { + /** Action name */ public static final String NAME = "create-record"; + /** Records management service */ private RecordsManagementService recordsManagementService; - - private RecordsManagementSecurityService recordsManagementSecurityService; - private PermissionService permissionService; + /** Record service */ + private RecordService recordService; private NodeService nodeService; + /** + * @param recordsManagementService records management service + */ public void setRecordsManagementService(RecordsManagementService recordsManagementService) { this.recordsManagementService = recordsManagementService; } - public void setRecordsManagementSecurityService(RecordsManagementSecurityService recordsManagementSecurityService) + /** + * @param recordService record service + */ + public void setRecordService(RecordService recordService) { - this.recordsManagementSecurityService = recordsManagementSecurityService; - } - - public void setPermissionService(PermissionService permissionService) - { - this.permissionService = permissionService; + this.recordService = recordService; } public void setNodeService(NodeService nodeService) @@ -77,64 +74,46 @@ public class CreateRecordAction extends ActionExecuterAbstractBase this.nodeService = nodeService; } + /** + * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) + */ @Override protected void executeImpl(Action action, final NodeRef actionedUponNodeRef) { - // TODO we should use the file plan passed as a parameter - // grab the file plan - List filePlans = recordsManagementService.getFilePlans(); - if (filePlans.size() == 1) + // skip everything if the actioned upon node reference is already a record + if (nodeService.hasAspect(actionedUponNodeRef, ASPECT_RECORD) == false) { - final NodeRef filePlan = filePlans.get(0); - - AuthenticationUtil.runAsSystem(new RunAsWork() + // TODO we should use the file plan passed as a parameter + // grab the file plan + List filePlans = recordsManagementService.getFilePlans(); + if (filePlans.size() == 1) { - @Override - public Void doWork() throws Exception - { - // get the documents readers - Long aclId = nodeService.getNodeAclId(actionedUponNodeRef); - Set readers = permissionService.getReaders(aclId); - - // get the documents primary parent assoc - ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(actionedUponNodeRef); - - /// get the new record container for the file plan - NodeRef newRecordContainer = getNewRecordContainer(filePlan); - if (newRecordContainer == null) - { - throw new AlfrescoRuntimeException("Unable to create record, because new record container could not be found."); - } - - // move the document into the file plan - nodeService.moveNode(actionedUponNodeRef, newRecordContainer, ContentModel.ASSOC_CONTAINS, parentAssoc.getQName()); - - // maintain the original primary location - nodeService.addChild(parentAssoc.getParentRef(), actionedUponNodeRef, parentAssoc.getTypeQName(), parentAssoc.getQName()); - - // set the readers - recordsManagementSecurityService.setExtendedReaders(actionedUponNodeRef, readers); - - return null; - } - }); - } - else - { - throw new AlfrescoRuntimeException("Unable to find file plan."); - } - } + // TODO parameterise the action with the file plan + final NodeRef filePlan = filePlans.get(0); - private NodeRef getNewRecordContainer(NodeRef filePlan) - { - List assocs = nodeService.getChildAssocs(filePlan, ASSOC_UNFILED_RECORDS, RegexQNamePattern.MATCH_ALL); - if (assocs.size() != 1) - { - throw new AlfrescoRuntimeException("Error getting the new record container, because the container cannot be indentified."); + // run record creation as system + AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Void doWork() throws Exception + { + // create record from existing document + recordService.createRecordFromDocument(filePlan, actionedUponNodeRef); + + return null; + } + }); + } + else + { + throw new AlfrescoRuntimeException("Unable to find file plan."); + } } - return assocs.get(0).getChildRef(); - } + } + /** + * @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefinitions(java.util.List) + */ @Override protected void addParameterDefinitions(List params) { diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/MultiParentEvaluator.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/MultiParentEvaluator.java index 805a082711..a90b49c491 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/MultiParentEvaluator.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/evaluator/MultiParentEvaluator.java @@ -22,19 +22,39 @@ import java.util.List; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.jscript.app.BaseEvaluator; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.RegexQNamePattern; /** + * Determines whether a node has multiple parents within a file plan + * * @author Roy Wetherall */ public class MultiParentEvaluator extends BaseEvaluator { @Override - protected boolean evaluateImpl(NodeRef nodeRef) - { - List parents = nodeService.getParentAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); - return (parents.size() > 1); + protected boolean evaluateImpl(final NodeRef nodeRef) + { + return AuthenticationUtil.runAsSystem(new RunAsWork() + { + @Override + public Boolean doWork() throws Exception + { + List parents = nodeService.getParentAssocs(nodeRef, ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); + int count = 0; + for (ChildAssociationRef parent : parents) + { + if (nodeService.hasAspect(parent.getParentRef(), ASPECT_FILE_PLAN_COMPONENT) == true) + { + count++; + } + } + + return (count > 1); + } + }); } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java index 8b4df14e4b..f885c18921 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordService.java @@ -47,6 +47,14 @@ public interface RecordService */ boolean isDeclared(NodeRef nodeRef); + /** + * Create a new record from an existing document. + * + * @param filePlan + * @param document + */ + void createRecordFromDocument(NodeRef filePlan, NodeRef document); + // TODO boolean isRecordFiled(NodeRef record); // TODO boolean isRecordClassified(NodeRef record); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java index e39f5ef22c..00c0aa89fa 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java @@ -20,6 +20,7 @@ package org.alfresco.module.org_alfresco_module_rm.record; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; @@ -27,20 +28,20 @@ import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.identifier.IdentifierService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; -import org.alfresco.repo.policy.JavaBehaviour; +import org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService; import org.alfresco.repo.policy.PolicyComponent; -import org.alfresco.repo.policy.Behaviour.NotificationFrequency; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.cmr.dictionary.AspectDefinition; 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.namespace.NamespaceService; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; /** + * Record service implementation + * * @author Roy Wetherall * @since 2.1 */ @@ -56,6 +57,10 @@ public class RecordServiceImpl implements RecordService, RecordsManagementModel private PolicyComponent policyComponent; + private PermissionService permissionService; + + private RecordsManagementSecurityService recordsManagementSecurityService; + /** List of available record meta-data aspects */ private Set recordMetaDataAspects; @@ -84,42 +89,52 @@ public class RecordServiceImpl implements RecordService, RecordsManagementModel this.policyComponent = policyComponent; } - public void init() + public void setPermissionService(PermissionService permissionService) { - policyComponent.bindAssociationBehaviour( - QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateChildAssociation"), - TYPE_UNFILED_RECORD_CONTAINER, - ContentModel.ASSOC_CONTAINS, - new JavaBehaviour(this, "onCreateNewRecord", NotificationFrequency.TRANSACTION_COMMIT)); + this.permissionService = permissionService; } - public void onCreateNewRecord(final ChildAssociationRef childAssocRef, boolean bNew) + public void setRecordsManagementSecurityService(RecordsManagementSecurityService recordsManagementSecurityService) { - AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public Void doWork() throws Exception - { - NodeRef nodeRef = childAssocRef.getChildRef(); - if (nodeService.exists(nodeRef) == true) - { - QName type = nodeService.getType(nodeRef); - if (ContentModel.TYPE_CONTENT.equals(type) == true || - dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) == true) - { - makeRecord(nodeRef); - } - else - { - throw new AlfrescoRuntimeException("Only content can be created as a record."); - } - } - - return null; - } - }); + this.recordsManagementSecurityService = recordsManagementSecurityService; } + public void init() + { + // policyComponent.bindAssociationBehaviour( + // QName.createQName(NamespaceService.ALFRESCO_URI, "onCreateChildAssociation"), + // TYPE_UNFILED_RECORD_CONTAINER, + // ContentModel.ASSOC_CONTAINS, + // new JavaBehaviour(this, "onCreateNewRecord", NotificationFrequency.TRANSACTION_COMMIT)); + } + +// public void onCreateNewRecord(final ChildAssociationRef childAssocRef, boolean bNew) +// { +// AuthenticationUtil.runAsSystem(new RunAsWork() +// { +// @Override +// public Void doWork() throws Exception +// { +// NodeRef nodeRef = childAssocRef.getChildRef(); +// if (nodeService.exists(nodeRef) == true) +// { +// QName type = nodeService.getType(nodeRef); +// if (ContentModel.TYPE_CONTENT.equals(type) == true || +// dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) == true) +// { +// makeRecord(nodeRef); +// } +// else +// { +// throw new AlfrescoRuntimeException("Only content can be created as a record."); +// } +// } +// +// return null; +// } +// }); +// } + /** * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#getRecordMetaDataAspects() */ @@ -153,47 +168,39 @@ public class RecordServiceImpl implements RecordService, RecordsManagementModel return (nodeService.hasAspect(record, ASPECT_DECLARED_RECORD)); } - /** - * @see org.alfresco.module.org_alfresco_module_rm.record.RecordService#getNewRecordContainer(org.alfresco.service.cmr.repository.NodeRef) - */ -// public NodeRef getNewRecordContainer(NodeRef filePlan) -// { -// NodeRef result = null; -// -// if (recordsManagementService.isFilePlan(filePlan) == true) -// { -// List assocs = nodeService.getChildAssocs(filePlan, ASSOC_NEW_RECORDS, RegexQNamePattern.MATCH_ALL); -// if (assocs.size() != 1) -// { -// throw new AlfrescoRuntimeException("Error getting the new record container, because the container cannot be indentified."); -// } -// result = assocs.get(0).getChildRef(); -// } -// -// return result; -// } + @Override + public void createRecordFromDocument(NodeRef filePlan, NodeRef document) + { + // skip everything if the document is already a record + if (nodeService.hasAspect(document, ASPECT_RECORD) == false) + { + // get the documents readers + Long aclId = nodeService.getNodeAclId(document); + Set readers = permissionService.getReaders(aclId); + + // get the documents primary parent assoc + ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(document); + + /// get the new record container for the file plan + NodeRef newRecordContainer = getNewRecordContainer(filePlan); + if (newRecordContainer == null) + { + throw new AlfrescoRuntimeException("Unable to create record, because new record container could not be found."); + } -// @Override -// public NodeRef createRecord(NodeRef filePlan, NodeRef document) -// { -// // get the documents primary parent assoc -// ChildAssociationRef parentAssoc = nodeService.getPrimaryParent(document); -// -// /// get the new record container for the file plan -// NodeRef newRecordContainer = getNewRecordContainer(filePlan); -// if (newRecordContainer == null) -// { -// throw new AlfrescoRuntimeException("Unable to create record, because new record container could not be found."); -// } -// -// // move the document into the file plan -// nodeService.moveNode(document, newRecordContainer, ContentModel.ASSOC_CONTAINS, parentAssoc.getQName()); -// -// // maintain the original primary location -// nodeService.addChild(parentAssoc.getParentRef(), document, parentAssoc.getTypeQName(), parentAssoc.getQName()); -// -// return document; -// } + // move the document into the file plan + nodeService.moveNode(document, newRecordContainer, ContentModel.ASSOC_CONTAINS, parentAssoc.getQName()); + + // maintain the original primary location + nodeService.addChild(parentAssoc.getParentRef(), document, parentAssoc.getTypeQName(), parentAssoc.getQName()); + + // make the document a record + makeRecord(document); + + // set the readers + recordsManagementSecurityService.setExtendedReaders(document, readers); + } + } /** * @@ -206,5 +213,20 @@ public class RecordServiceImpl implements RecordService, RecordsManagementModel String recordId = identifierService.generateIdentifier(ASPECT_RECORD, nodeService.getPrimaryParent(document).getParentRef()); nodeService.setProperty(document, PROP_IDENTIFIER, recordId); } + + /** + * + * @param filePlan + * @return + */ + private NodeRef getNewRecordContainer(NodeRef filePlan) + { + List assocs = nodeService.getChildAssocs(filePlan, ASSOC_UNFILED_RECORDS, RegexQNamePattern.MATCH_ALL); + if (assocs.size() != 1) + { + throw new AlfrescoRuntimeException("Error getting the new record container, because the container cannot be indentified."); + } + return assocs.get(0).getChildRef(); + } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityService.java index c782db6611..3eba852122 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityService.java @@ -154,16 +154,30 @@ public interface RecordsManagementSecurityService void deletePermission(NodeRef nodeRef, String authority, String permission); /** + * Indicates whether the node has any extended readers set or not. * - * @param nodeRef - * @return + * @param nodeRef node reference + * @return boolean true if the node has extended readers set, false otherwise + * @since 2.1 + */ + boolean hasExtendedReaders(NodeRef nodeRef); + + /** + * Gets the set authorities that are extended readers for the given node. + * + * @param nodeRef node reference + * @return {@link Set}<{@link String}> extended readers + * @since 2.1 */ Set getExtendedReaders(NodeRef nodeRef); /** + * Set the authorities that are extended readers on the node. Applies extended readers to + * file plan parent hierarchy. * - * @param nodeRef - * @param readers + * @param nodeRef node reference + * @param readers extended readers + * @since 2.1 */ void setExtendedReaders(NodeRef nodeRef, Set readers); @@ -171,12 +185,23 @@ public interface RecordsManagementSecurityService * * @param nodeRef * @param readers + * @param applyToParents + * @since 2.1 + */ + void setExtendedReaders(NodeRef nodeRef, Set readers, boolean applyToParents); + + /** + * + * @param nodeRef + * @param readers + * @since 2.1 */ void removeExtendedReaders(NodeRef nodeRef, Set readers); /** * * @param nodeRef + * @since 2.1 */ void removeAllExtendedReaders(NodeRef nodeRef); } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java index c80ff5a520..5d355a0af4 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/RecordsManagementSecurityServiceImpl.java @@ -31,6 +31,7 @@ import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; +import org.alfresco.model.RenditionModel; import org.alfresco.module.org_alfresco_module_rm.RecordsManagementService; import org.alfresco.module.org_alfresco_module_rm.capability.Capability; import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService; @@ -42,6 +43,7 @@ import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; @@ -70,7 +72,8 @@ import org.springframework.context.ApplicationContextAware; */ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSecurityService, RecordsManagementModel, - ApplicationContextAware + ApplicationContextAware, + NodeServicePolicies.OnMoveNodePolicy { /** Capability service */ @@ -205,7 +208,12 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe policyComponent.bindClassBehaviour( NodeServicePolicies.OnCreateNodePolicy.QNAME, TYPE_RECORD_FOLDER, - new JavaBehaviour(this, "onCreateRecordFolder", NotificationFrequency.TRANSACTION_COMMIT)); + new JavaBehaviour(this, "onCreateRecordFolder", NotificationFrequency.TRANSACTION_COMMIT)); + + policyComponent.bindClassBehaviour( + NodeServicePolicies.OnMoveNodePolicy.QNAME, + ASPECT_RECORD, + new JavaBehaviour(this, "onMoveNode", NotificationFrequency.TRANSACTION_COMMIT)); } /** @@ -980,6 +988,24 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe }, AuthenticationUtil.getSystemUserName()); } + /** + * @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#hasExtendedReaders(org.alfresco.service.cmr.repository.NodeRef) + */ + @Override + public boolean hasExtendedReaders(NodeRef nodeRef) + { + boolean result = false; + Set extendedReaders = getExtendedReaders(nodeRef); + if (extendedReaders != null && extendedReaders.size() != 0) + { + result = true; + } + return result; + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#getExtendedReaders(org.alfresco.service.cmr.repository.NodeRef) + */ @SuppressWarnings("unchecked") @Override public Set getExtendedReaders(NodeRef nodeRef) @@ -999,10 +1025,19 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe /** * @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#setExtendedReaders(org.alfresco.service.cmr.repository.NodeRef, java.util.Set) */ - @SuppressWarnings("unchecked") @Override public void setExtendedReaders(NodeRef nodeRef, Set readers) { + setExtendedReaders(nodeRef, readers, true); + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.security.RecordsManagementSecurityService#setExtendedReaders(org.alfresco.service.cmr.repository.NodeRef, java.util.Set, boolean) + */ + @SuppressWarnings("unchecked") + @Override + public void setExtendedReaders(NodeRef nodeRef, java.util.Set readers, boolean applyToParents) + { ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("readers", readers); @@ -1044,12 +1079,26 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe // set the readers property (this will in turn apply the aspect if required) nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)readersMap); - // apply the extended readers up the file plan primary hierarchy - NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef(); - if (parent != null && - recordsManagementService.isFilePlanComponent(parent) == true) + // apply the readers to any renditions of the content + if (recordsManagementService.isRecord(nodeRef) == true) { - setExtendedReaders(parent, readers); + List assocs = nodeService.getChildAssocs(nodeRef, RenditionModel.ASSOC_RENDITION, RegexQNamePattern.MATCH_ALL); + for (ChildAssociationRef assoc : assocs) + { + NodeRef child = assoc.getChildRef(); + setExtendedReaders(child, readers, false); + } + } + + if (applyToParents == true) + { + // apply the extended readers up the file plan primary hierarchy + NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef(); + if (parent != null && + recordsManagementService.isFilePlanComponent(parent) == true) + { + setExtendedReaders(parent, readers); + } } } } @@ -1069,5 +1118,32 @@ public class RecordsManagementSecurityServiceImpl implements RecordsManagementSe { // TODO Auto-generated method stub + } + + @Override + public void onMoveNode(final ChildAssociationRef origAssoc, final ChildAssociationRef newAssoc) + { + // TODO temp solution for demo + + AuthenticationUtil.runAsSystem(new RunAsWork() + { + + @Override + public Void doWork() throws Exception + { + NodeRef record = newAssoc.getChildRef(); + NodeRef parent = newAssoc.getParentRef(); + + Set readers = getExtendedReaders(record); + if (readers != null && readers.size() != 0) + { + setExtendedReaders(parent, readers); + } + + return null; + }}); + + + } }