diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java index 3662dfb9e9..35c0835ceb 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java @@ -886,7 +886,7 @@ public class RecordServiceImpl extends BaseBehaviourBean ParameterCheck.mandatory("isLinked", isLinked); recordCreationSanityCheckOnNode(nodeRef); - final NodeRef checkedFilePlan = recordCreationSanityCheckOnFilePlan(filePlan); + final NodeRef newRecordContainer = recordCreationSanityCheckOnDestinationNode(destinationNodeRef, filePlan); invokeBeforeRecordDeclaration(nodeRef); // do the work of creating the record as the system user @@ -901,35 +901,6 @@ public class RecordServiceImpl extends BaseBehaviourBean ruleService.disableRuleType("outbound"); try { - NodeRef newRecordContainer = destinationNodeRef; - // if optional location not specified, use the unfiledContainer - if (newRecordContainer == null) - { - // get the unfiled record container node for the file plan - newRecordContainer = filePlanService.getUnfiledContainer(checkedFilePlan); - if (newRecordContainer == null) - { - throw new AlfrescoRuntimeException("Unable to create record, because record container could not be found."); - } - } - // if optional location supplied, check that it is a valid record folder, unfiled record container or folder - else - { - final QName nodeType = nodeService.getType(newRecordContainer); - if(!(nodeType.equals(RecordsManagementModel.TYPE_RECORD_FOLDER) || - nodeType.equals(RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER) || - nodeType.equals(RecordsManagementModel.TYPE_UNFILED_RECORD_CONTAINER))) - { - throw new AlfrescoRuntimeException("Unable to create record, because container is not a valid type for new record."); - } - - Boolean isClosed = (Boolean) nodeService.getProperty(newRecordContainer, PROP_IS_CLOSED); - if (isClosed != null && isClosed) - { - throw new AlfrescoRuntimeException("Unable to create record, because container is closed."); - } - } - // get the documents readers and writers Pair, Set> readersAndWriters = extendedPermissionService.getReadersAndWriters(nodeRef); @@ -1052,6 +1023,53 @@ public class RecordServiceImpl extends BaseBehaviourBean return result; } + /** + * Helper method to check the given destination before trying to declare a record in it. + * + * @param destinationNodeRef The reference of the container in which the record will be created + * @param filePlan The reference of the file plan node + */ + private NodeRef recordCreationSanityCheckOnDestinationNode(NodeRef destinationNodeRef, final NodeRef filePlan) + { + final NodeRef checkedFilePlan = recordCreationSanityCheckOnFilePlan(filePlan); + NodeRef newRecordContainer = destinationNodeRef; + // if optional location not specified, use the unfiledContainer + if (newRecordContainer == null) + { + // get the unfiled record container node for the file plan + newRecordContainer = AuthenticationUtil.runAsSystem(() -> filePlanService.getUnfiledContainer(checkedFilePlan)); + + if (newRecordContainer == null) + { + throw new AlfrescoRuntimeException("Unable to create record, because record container could not be found."); + } + } + // if optional location supplied, check that it is a valid record folder, unfiled record container or folder + else + { + final QName nodeType = nodeService.getType(newRecordContainer); + if (!(nodeType.equals(RecordsManagementModel.TYPE_RECORD_FOLDER) || + nodeType.equals(RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER) || + nodeType.equals(RecordsManagementModel.TYPE_UNFILED_RECORD_CONTAINER))) + { + throw new AlfrescoRuntimeException("Unable to create record, because container is not a valid type for new record."); + } + + Boolean isClosed = (Boolean) nodeService.getProperty(newRecordContainer, PROP_IS_CLOSED); + if (isClosed != null && isClosed) + { + throw new AlfrescoRuntimeException("Unable to create record, because container is closed."); + } + + if (extendedPermissionService.hasPermission(newRecordContainer, RMPermissionModel.FILING) == AccessStatus.DENIED) + { + throw new AccessDeniedException(I18NUtil.getMessage("permissions.err_access_denied")); + } + } + + return newRecordContainer; + } + /** * Helper method to check the given node before trying to declare it as record * diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java index 43a717d4b3..0a9c127d56 100644 --- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java +++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImplUnitTest.java @@ -47,9 +47,11 @@ import java.util.Set; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; import org.alfresco.repo.policy.Behaviour; +import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AccessStatus; @@ -74,7 +76,6 @@ public class RecordServiceImplUnitTest extends BaseUnitTest private NodeRef nonStandardFilePlan; private NodeRef dmNodeRef; private NodeRef unfiledRecordContainer; - private NodeRef unfiledRecordFolder; private ChildAssociationRef parentAssoc; private static QName TYPE_MY_FILE_PLAN = generateQName(); @@ -93,7 +94,6 @@ public class RecordServiceImplUnitTest extends BaseUnitTest nonStandardFilePlan = generateNodeRef(TYPE_MY_FILE_PLAN); dmNodeRef = generateNodeRef(TYPE_CONTENT); unfiledRecordContainer = generateNodeRef(TYPE_UNFILED_RECORD_CONTAINER); - unfiledRecordFolder = generateNodeRef(TYPE_UNFILED_RECORD_FOLDER); parentAssoc = mock(ChildAssociationRef.class); // set-up node service @@ -495,6 +495,22 @@ public class RecordServiceImplUnitTest extends BaseUnitTest parentAssoc.getQName()); } + /** + * Given a file that is not yet a record + * And the unfiled record container can't be found + * When I create the record without specifying a location + * Then an exception is thrown + */ + @Test (expected = AlfrescoRuntimeException.class) + public void createRecordWhenUnfiledRecordContainerIsNull() + { + mocksForRecordCreation(); + when(mockedFilePlanService.getUnfiledContainer(filePlan)).thenReturn(null); + + // create the record + recordService.createRecord(filePlan, dmNodeRef); + } + /** * Given a file that is not yet a record * When I create the record specifying the unfiled record container @@ -552,6 +568,21 @@ public class RecordServiceImplUnitTest extends BaseUnitTest recordService.createRecord(filePlan, dmNodeRef, recordCategory); } + /** + * Given a file that is not yet a record + * When I create the record specifying a location where I don't have permissions + * Then an exception is thrown + */ + @Test (expected = AccessDeniedException.class) + public void createRecordIntoSpecifiedRecordFolderWithoutFilePermission() + { + mocksForRecordCreation(); + when(mockedExtendedPermissionService.hasPermission(recordFolder, RMPermissionModel.FILING)).thenReturn(AccessStatus.DENIED); + + // create the record + recordService.createRecord(filePlan, dmNodeRef, recordFolder); + } + /* Helper method to set up the mocks for record creation */ private void mocksForRecordCreation() {