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 ab4d930ada..18f7391019 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 @@ -424,11 +424,8 @@ - - - - - + + @@ -489,6 +486,7 @@ init-method="init"> + @@ -532,6 +530,7 @@ results = new HashSet(); Set aspects = new HashSet(1); aspects.add(ASPECT_RECORDS_MANAGEMENT_ROOT); - getNodeDAO().getNodesWithAspects(aspects, Long.MIN_VALUE, Long.MAX_VALUE, new NodeDAO.NodeRefQueryCallback() + nodeDAO.getNodesWithAspects(aspects, Long.MIN_VALUE, Long.MAX_VALUE, new NodeDAO.NodeRefQueryCallback() { @Override public boolean handle(Pair nodePair) @@ -273,13 +145,14 @@ public class FilePlanServiceImpl extends ServiceBaseImpl public NodeRef getFilePlanBySiteId(String siteId) { NodeRef filePlan = null; - - SiteInfo siteInfo = getSiteService().getSite(siteId); + SiteService siteService = getSiteService(); + + SiteInfo siteInfo = siteService.getSite(siteId); if (siteInfo != null) { - if (getSiteService().hasContainer(siteId, FILE_PLAN_CONTAINER)) + if (siteService.hasContainer(siteId, FILE_PLAN_CONTAINER)) { - NodeRef nodeRef = getSiteService().getContainer(siteId, FILE_PLAN_CONTAINER); + NodeRef nodeRef = siteService.getContainer(siteId, FILE_PLAN_CONTAINER); if (instanceOf(nodeRef, TYPE_FILE_PLAN)) { filePlan = nodeRef; @@ -398,8 +271,6 @@ public class FilePlanServiceImpl extends ServiceBaseImpl throw new AlfrescoRuntimeException("Unable to create file plan root container, because passed node is not a file plan."); } - String allRoles = getFilePlanRoleService().getAllRolesContainerGroup(filePlan); - // create the properties map Map properties = new HashMap(1); properties.put(ContentModel.PROP_NAME, containerName); @@ -411,19 +282,9 @@ public class FilePlanServiceImpl extends ServiceBaseImpl QName.createQName(RM_URI, containerName), containerType, properties).getChildRef(); - - // set inheritance to false - getPermissionService().setInheritParentPermissions(container, false); - // give all roles read permissions on the container by default - getPermissionService().setPermission(container, allRoles, RMPermissionModel.READ_RECORDS, true); - - // setup the extended reader permissions - getPermissionService().setPermission(container, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true); - getPermissionService().setPermission(container, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true); - - // setup the administrator permissions - getPermissionService().setPermission(container, "Administrator", RMPermissionModel.FILING, true); + // setup the permissions + filePlanPermissionService.setupPermissions(filePlan, container); return container; } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionService.java index 12fdaa9382..f8e05c0556 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionService.java @@ -34,6 +34,14 @@ public interface FilePlanPermissionService */ void setupRecordCategoryPermissions(NodeRef recordCategory); + /** + * Setup permissions for an object within a given parent. + * + * @param parent parent node to inherit permissions from + * @param nodeRef node ref to setup permissions on + */ + void setupPermissions(NodeRef parent, NodeRef nodeRef); + /** * Sets a permission on a file plan object. Assumes allow is true. Cascades permission down to record folder. * Cascades ReadRecord up to file plan. diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImpl.java index a59ee8e57e..a29d3ffb05 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImpl.java @@ -25,6 +25,7 @@ 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.fileplan.FilePlanComponentKind; import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.Behaviour.NotificationFrequency; @@ -38,6 +39,7 @@ import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.OwnableService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; @@ -57,6 +59,9 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl { /** Permission service */ protected PermissionService permissionService; + + /** Ownable service */ + protected OwnableService ownableService; /** Policy component */ protected PolicyComponent policyComponent; @@ -94,6 +99,14 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl { this.policyComponent = policyComponent; } + + /** + * @param ownableService ownable service + */ + public void setOwnableService(OwnableService ownableService) + { + this.ownableService = ownableService; + } /** * @see org.alfresco.module.org_alfresco_module_rm.security.FilePlanPermissionService#setupRecordCategoryPermissions(org.alfresco.service.cmr.repository.NodeRef) @@ -109,44 +122,9 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl throw new AlfrescoRuntimeException("Unable to setup record category permissions, because node is not a record category."); } - // init permissions - initPermissions(recordCategory); - - // Pull any permissions found on the parent (ie the record category) - final NodeRef parentNodeRef = nodeService.getPrimaryParent(recordCategory).getParentRef(); - if (parentNodeRef != null && nodeService.exists(parentNodeRef)) - { - AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() - { - public Object doWork() - { - boolean fillingOnly = isFilePlan(parentNodeRef); - - // since this is not a root category, inherit from parent - Set perms = permissionService.getAllSetPermissions(parentNodeRef); - for (AccessPermission perm : perms) - { - if (!fillingOnly || - RMPermissionModel.FILING.equals(perm.getPermission())) - { - AccessStatus accessStatus = perm.getAccessStatus(); - boolean allow = false; - if (AccessStatus.ALLOWED.equals(accessStatus)) - { - allow = true; - } - permissionService.setPermission( - recordCategory, - perm.getAuthority(), - perm.getPermission(), - allow); - } - } - - return null; - } - }); - } + // setup category permissions + NodeRef parentNodeRef = nodeService.getPrimaryParent(recordCategory).getParentRef(); + setupPermissions(parentNodeRef, recordCategory); } /** @@ -225,6 +203,9 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl */ public void setupPermissions(final NodeRef parent, final NodeRef nodeRef) { + ParameterCheck.mandatory("parent", parent); + ParameterCheck.mandatory("nodeRef", nodeRef); + if (nodeService.exists(nodeRef)) { // initialise permissions @@ -232,7 +213,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl if (nodeService.exists(parent)) { - AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() + runAsSystem(new AuthenticationUtil.RunAsWork() { public Object doWork() { @@ -240,20 +221,29 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl Set perms = permissionService.getAllSetPermissions(parent); for (AccessPermission perm : perms) { - if (!ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(perm.getAuthority()) && - !ExtendedWriterDynamicAuthority.EXTENDED_WRITER.equals(perm.getAuthority())) + // only copy filling permissions if the parent is the file plan + if (!inheritFillingOnly(parent, nodeRef) || + RMPermissionModel.FILING.equals(perm.getPermission())) { - AccessStatus accessStatus = perm.getAccessStatus(); - boolean allow = false; - if (AccessStatus.ALLOWED.equals(accessStatus)) + // don't copy the extended reader or writer permissions as they have already been set + if (!ExtendedReaderDynamicAuthority.EXTENDED_READER.equals(perm.getAuthority()) && + !ExtendedWriterDynamicAuthority.EXTENDED_WRITER.equals(perm.getAuthority())) { - allow = true; + // get the access status details + AccessStatus accessStatus = perm.getAccessStatus(); + boolean allow = false; + if (AccessStatus.ALLOWED.equals(accessStatus)) + { + allow = true; + } + + // set the permission on the target node + permissionService.setPermission( + nodeRef, + perm.getAuthority(), + perm.getPermission(), + allow); } - permissionService.setPermission( - nodeRef, - perm.getAuthority(), - perm.getPermission(), - allow); } } @@ -263,6 +253,30 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl } } } + + /** + * Helper method to determine whether all or just filling permissions should be inherited. + * + * @param parent parent node + * @param child child node + * @return boolean true if inherit filling only, false otherwise + */ + private boolean inheritFillingOnly(NodeRef parent, NodeRef child) + { + boolean result = false; + + // if root category or + // if in root of unfiled container or + // if in root of hold container + if ((isFilePlan(parent) && isRecordCategory(child)) || + FilePlanComponentKind.UNFILED_RECORD_CONTAINER.equals(getFilePlanComponentKind(parent)) || + FilePlanComponentKind.HOLD_CONTAINER.equals(getFilePlanComponentKind(parent))) + { + result = true; + } + + return result; + } /** * Sets ups records permission when aspect is added. @@ -274,7 +288,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl */ public void onAddRecord(final NodeRef record, final QName aspectTypeQName) { - runAs(new AuthenticationUtil.RunAsWork() + runAsSystem(new AuthenticationUtil.RunAsWork() { public Object doWork() { @@ -286,7 +300,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl return null; } - }, AuthenticationUtil.getSystemUserName()); + }); } /** @@ -343,7 +357,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl } /** - * Initiliase the permissions for the given node. + * Init the permissions for the given node. * * @param nodeRef node reference */ @@ -351,20 +365,26 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl { if (nodeService.exists(nodeRef)) { - runAs(new AuthenticationUtil.RunAsWork() + runAsSystem(new AuthenticationUtil.RunAsWork() { public Object doWork() { // break inheritance permissionService.setInheritParentPermissions(nodeRef, false); + + // clear all existing permissions + permissionService.clearPermission(nodeRef, null); // set extended reader permissions permissionService.setPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true); permissionService.setPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true); + + // remove owner + ownableService.setOwner(nodeRef, OwnableService.NO_OWNER); return null; } - }, AuthenticationUtil.getSystemUserName()); + }); } } @@ -383,6 +403,7 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl { if (isFilePlan(nodeRef)) { + // set the permission down the file plan hierarchy setPermissionDown(nodeRef, authority, permission); } else if (isFilePlanContainer(nodeRef) || @@ -390,7 +411,10 @@ public class FilePlanPermissionServiceImpl extends ServiceBaseImpl isRecord(nodeRef) || isHold(nodeRef)) { + // set read permission to the parents of the node setReadPermissionUp(nodeRef, authority); + + // set the permission on the node and it's children setPermissionDown(nodeRef, authority, permission); } else diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/transfer/TransferServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/transfer/TransferServiceImpl.java index 8c004ddbfc..836186636d 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/transfer/TransferServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/transfer/TransferServiceImpl.java @@ -53,7 +53,8 @@ import org.springframework.extensions.surf.util.ParameterCheck; * @author Tuna Aksoy * @since 2.2 */ -public class TransferServiceImpl extends ServiceBaseImpl implements TransferService, RecordsManagementModel +public class TransferServiceImpl extends ServiceBaseImpl + implements TransferService, RecordsManagementModel { /** Transfer node reference key */ public static final String KEY_TRANSFER_NODEREF = "transferNodeRef"; @@ -105,16 +106,6 @@ public class TransferServiceImpl extends ServiceBaseImpl implements TransferServ this.recordFolderService = recordFolderService; } - /** - * @see org.alfresco.module.org_alfresco_module_rm.transfer.TransferService#isTransfer(NodeRef) - */ - @Override - public boolean isTransfer(NodeRef nodeRef) - { - ParameterCheck.mandatory("nodeRef", nodeRef); - return instanceOf(nodeRef, TYPE_TRANSFER); - } - /** * @see org.alfresco.module.org_alfresco_module_rm.transfer.TransferService#transfer(NodeRef, boolean) */ diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java index cca1d1f49f..6aef2dfa41 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/util/ServiceBaseImpl.java @@ -20,6 +20,8 @@ package org.alfresco.module.org_alfresco_module_rm.util; import java.util.Set; +import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanComponentKind; +import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.hold.HoldService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.security.authentication.AuthenticationUtil; @@ -77,6 +79,110 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte this.dictionaryService = dictionaryService; } + /** + * Gets the file plan component kind from the given node reference + * + * @see org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService#getFilePlanComponentKind(org.alfresco.service.cmr.repository.NodeRef) + */ + public FilePlanComponentKind getFilePlanComponentKind(NodeRef nodeRef) + { + FilePlanComponentKind result = null; + + if (isFilePlanComponent(nodeRef)) + { + result = FilePlanComponentKind.FILE_PLAN_COMPONENT; + + if (isFilePlan(nodeRef)) + { + result = FilePlanComponentKind.FILE_PLAN; + } + else if (isRecordCategory(nodeRef)) + { + result = FilePlanComponentKind.RECORD_CATEGORY; + } + else if (isRecordFolder(nodeRef)) + { + result = FilePlanComponentKind.RECORD_FOLDER; + } + else if (isRecord(nodeRef)) + { + result = FilePlanComponentKind.RECORD; + } + else if (instanceOf(nodeRef, TYPE_HOLD_CONTAINER)) + { + result = FilePlanComponentKind.HOLD_CONTAINER; + } + else if (isHold(nodeRef)) + { + result = FilePlanComponentKind.HOLD; + } + else if (isTransfer(nodeRef)) + { + result = FilePlanComponentKind.TRANSFER; + } + else if (instanceOf(nodeRef, TYPE_DISPOSITION_SCHEDULE) || instanceOf(nodeRef, TYPE_DISPOSITION_ACTION_DEFINITION)) + { + result = FilePlanComponentKind.DISPOSITION_SCHEDULE; + } + else if (instanceOf(nodeRef, TYPE_UNFILED_RECORD_CONTAINER)) + { + result = FilePlanComponentKind.UNFILED_RECORD_CONTAINER; + } + else if (instanceOf(nodeRef, TYPE_UNFILED_RECORD_FOLDER)) + { + result = FilePlanComponentKind.UNFILED_RECORD_FOLDER; + } + } + + return result; + } + + /** + * Gets the file plan component kind from the given type. + * + * @see FilePlanService#getFilePlanComponentKindFromType(QName) + */ + public FilePlanComponentKind getFilePlanComponentKindFromType(QName type) + { + FilePlanComponentKind result = null; + + if (ASPECT_FILE_PLAN_COMPONENT.equals(type)) + { + result = FilePlanComponentKind.FILE_PLAN_COMPONENT; + } + else if (instanceOf(type, ASPECT_RECORD)) + { + result = FilePlanComponentKind.RECORD; + } + else if (instanceOf(type, TYPE_FILE_PLAN)) + { + result = FilePlanComponentKind.FILE_PLAN; + } + else if (instanceOf(type, TYPE_RECORD_CATEGORY)) + { + result = FilePlanComponentKind.RECORD_CATEGORY; + } + else if (instanceOf(type, TYPE_RECORD_FOLDER)) + { + result = FilePlanComponentKind.RECORD_FOLDER; + } + else if (instanceOf(type, TYPE_HOLD)) + { + result = FilePlanComponentKind.HOLD; + } + else if (instanceOf(type, TYPE_TRANSFER)) + { + result = FilePlanComponentKind.TRANSFER; + } + else if (instanceOf(type, TYPE_DISPOSITION_SCHEDULE) || + instanceOf(type, TYPE_DISPOSITION_ACTION_DEFINITION)) + { + result = FilePlanComponentKind.DISPOSITION_SCHEDULE; + } + + return result; + } + /** * Indicates whether the given node is a file plan component or not. *

@@ -177,6 +283,18 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte } return isHold; } + + /** + * Indicates whether the given node reference is a transfer or not. + * + * @see org.alfresco.module.org_alfresco_module_rm.transfer.TransferService#isTransfer(NodeRef) + */ + public boolean isTransfer(NodeRef nodeRef) + { + ParameterCheck.mandatory("nodeRef", nodeRef); + + return instanceOf(nodeRef, TYPE_TRANSFER); + } /** * Gets the file plan that a given file plan component resides within. @@ -241,6 +359,26 @@ public class ServiceBaseImpl implements RecordsManagementModel, ApplicationConte } return result; } + + /** + * Utility method to quickly determine whether one class is equal to or sub of another. + * + * @param className class name + * @param ofClassName class name to check against + * @return boolean true if equal to or sub, false otherwise + */ + protected boolean instanceOf(QName className, QName ofClassName) + { + ParameterCheck.mandatory("className", className); + ParameterCheck.mandatory("ofClassName", ofClassName); + boolean result = false; + if (ofClassName.equals(className) || + dictionaryService.isSubClass(className, ofClassName)) + { + result = true; + } + return result; + } /** * Utility method to get the next counter for a node. diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/issue/RM1008Test.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/issue/RM1008Test.java index 4dfb9ca8cd..c31693246c 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/issue/RM1008Test.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/issue/RM1008Test.java @@ -155,7 +155,7 @@ public class RM1008Test extends BaseRMTestCase Capability viewRecords = capabilityService.getCapability("ViewRecords"); assertNotNull(viewRecords); - assertEquals(AccessStatus.ALLOWED, viewRecords.hasPermission(hold)); + assertEquals(AccessStatus.DENIED, viewRecords.hasPermission(hold)); assertEquals(AccessStatus.DENIED, permissionService.hasPermission(hold, RMPermissionModel.FILING)); return null; @@ -173,8 +173,6 @@ public class RM1008Test extends BaseRMTestCase } }, rmAdminName); - // FIXME: After fixing RM:1315 this should be fixed - /* doTestInTransaction(new Test() { @Override @@ -189,7 +187,6 @@ public class RM1008Test extends BaseRMTestCase return null; } }, myUser); - */ doTestInTransaction(new Test() { @@ -210,7 +207,7 @@ public class RM1008Test extends BaseRMTestCase Capability viewRecords = capabilityService.getCapability("ViewRecords"); assertNotNull(viewRecords); - assertEquals(AccessStatus.ALLOWED, viewRecords.hasPermission(hold)); + assertEquals(AccessStatus.DENIED, viewRecords.hasPermission(hold)); assertEquals(AccessStatus.DENIED, permissionService.hasPermission(hold, RMPermissionModel.FILING)); return null; diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImplUnitTest.java index 66f4adea3f..ea570c3ed8 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImplUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/FilePlanPermissionServiceImplUnitTest.java @@ -24,15 +24,24 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import java.util.HashSet; +import java.util.Set; import org.alfresco.model.ContentModel; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseUnitTest; +import org.alfresco.repo.security.permissions.impl.AccessPermissionImpl; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.security.AccessPermission; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.OwnableService; import org.alfresco.service.namespace.QName; import org.junit.Test; import org.mockito.InjectMocks; import org.mockito.Spy; +import org.mockito.verification.VerificationMode; /** * File plan permission service implementation unit test. @@ -47,6 +56,13 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest { /** test authority */ protected static final String AUTHORITY = "anAuthority"; + protected static final String AUTHORITY2 = "anOtherAuthority"; + + /** fileplan nodes */ + protected NodeRef rootRecordCategory; + protected NodeRef recordCategory; + protected NodeRef newRecordFolder; + protected NodeRef newRecord; /** unfiled nodes */ protected NodeRef unfiledRecordContainer; @@ -81,20 +97,36 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest holdContainer = generateContainerNodeRef(TYPE_HOLD_CONTAINER); hold = generateHoldNodeRef("my test hold"); heldRecord = generateRecord(); + rootRecordCategory = generateContainerNodeRef(TYPE_RECORD_CATEGORY); + recordCategory = generateContainerNodeRef(TYPE_RECORD_CATEGORY); + newRecordFolder = generateRecordFolder(); + newRecord = generateRecord(); // setup parent hierarchy - makePrimaryParentOf(filePlan, generateNodeRef(ContentModel.TYPE_FOLDER)); + makePrimaryParentOf(filePlan, generateNodeRef(ContentModel.TYPE_FOLDER)); + + makePrimaryParentOf(rootRecordCategory, filePlan); + makePrimaryParentOf(recordCategory, rootRecordCategory); + makePrimaryParentOf(newRecordFolder, recordCategory); + makePrimaryParentOf(newRecord, newRecordFolder); makePrimaryParentOf(unfiledRecordFolder, unfiledRecordContainer); - makePrimaryParentOf(unfiledRecordContainer, filePlan); + makePrimaryParentOf(unfiledRecordContainer, filePlan); makePrimaryParentOf(hold, holdContainer); makePrimaryParentOf(holdContainer, filePlan); - // setup child hierarchy - makeChildrenOf(unfiledRecordFolder, unfiledRecordFolderChild); - makeChildrenOf(unfiledRecordFolderChild, unfiledRecord); + // setup child hierarchy + makeChildrenOf(filePlan, rootRecordCategory); + makeChildrenOf(rootRecordCategory, recordCategory); + makeChildrenOf(recordCategory, newRecordFolder); + makeChildrenOf(newRecordFolder, newRecord); + + makeChildrenOf(unfiledRecordFolder, unfiledRecordFolderChild); + makeChildrenOf(unfiledRecordFolderChild, unfiledRecord); + + makeChildrenOf(holdContainer, hold); makeChildrenOf(hold, heldRecord); } @@ -179,6 +211,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest /** * Set read permission on hold container */ + @Test public void setReadPermissionOnHoldContainer() { // set read permission on hold @@ -201,6 +234,7 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest /** * Set filing permission on hold container */ + @Test public void setFilingPermissionOnHoldContainer() { // set read permission on hold @@ -259,5 +293,207 @@ public class FilePlanPermissionServiceImplUnitTest extends BaseUnitTest // verify permission not set on child of hold verify(mockedPermissionService, never()).setPermission(eq(heldRecord), eq(AUTHORITY), anyString(), eq(true)); } + + /** + * Helper method to setup permissions on mock objects + */ + private void setupPermissions(NodeRef nodeRef) + { + Set perms = new HashSet(4); + + // setup basic file and read for authorities + perms.add(new AccessPermissionImpl(RMPermissionModel.READ_RECORDS, AccessStatus.ALLOWED, AUTHORITY, 0)); + perms.add(new AccessPermissionImpl(RMPermissionModel.FILING, AccessStatus.ALLOWED, AUTHORITY2, 1)); + + // setup in-place readers and writers + perms.add(new AccessPermissionImpl(RMPermissionModel.READ_RECORDS, AccessStatus.ALLOWED, ExtendedReaderDynamicAuthority.EXTENDED_READER, 2)); + perms.add(new AccessPermissionImpl(RMPermissionModel.FILING, AccessStatus.ALLOWED, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, 3)); + doReturn(perms).when(mockedPermissionService).getAllSetPermissions(nodeRef); + } + + /** + * Helper to verify the core permissions have been initialized correctly + */ + private void verifyInitPermissions(NodeRef nodeRef) + { + verify(mockedPermissionService, times(1)).setInheritParentPermissions(nodeRef, false); + verify(mockedPermissionService, times(1)).clearPermission(nodeRef, null); + verify(mockedPermissionService, times(1)).setPermission(nodeRef, ExtendedReaderDynamicAuthority.EXTENDED_READER, RMPermissionModel.READ_RECORDS, true); + verify(mockedPermissionService, times(1)).setPermission(nodeRef, ExtendedWriterDynamicAuthority.EXTENDED_WRITER, RMPermissionModel.FILING, true); + verify(mockedOwnableService, times(1)).setOwner(nodeRef, OwnableService.NO_OWNER); + } + + /** + * Helper to verify that permissions have been set correctly on the child + * + * @param parent parent node + * @param child child node + * @param read verification mode relating to setting read on the child + * @param filling verification mode relating to setting filling on the child + */ + private void verifyInitPermissions(NodeRef parent, NodeRef child, VerificationMode read, VerificationMode filling) + { + // verify the core permissions are set-up correctly + verifyInitPermissions(child); + + // verify the permissions came from the correct parent + verify(mockedPermissionService).getAllSetPermissions(parent); + + // verify all the inherited permissions are set correctly (note read are not inherited from fileplan) + verify(mockedPermissionService, filling).setPermission(child, AUTHORITY2, RMPermissionModel.FILING, true); + verify(mockedPermissionService, read).setPermission(child, AUTHORITY, RMPermissionModel.READ_RECORDS, true); + + // verify that there are no unaccounted for interactions with the permission service + verifyNoMoreInteractions(mockedPermissionService); + + } + + /** + * Test the initialisation of permissions for a new root category + */ + @Test + public void initPermissionsForNewRootRecordCategory() + { + // setup permissions for file plan + setupPermissions(filePlan); + + // setup permissions + filePlanPermissionService.setupRecordCategoryPermissions(rootRecordCategory); + + // verify permission init + verifyInitPermissions(filePlan, rootRecordCategory, never(), times(1)); + } + + /** + * Test the initialisation of permissions for a new category + */ + @Test + public void initPermissionsForNewRecordCategory() + { + // setup permissions for parent + setupPermissions(rootRecordCategory); + + // setup permissions + filePlanPermissionService.setupRecordCategoryPermissions(recordCategory); + + // verify permission init + verifyInitPermissions(rootRecordCategory, recordCategory, times(1), times(1)); + } + + /** + * Test initialisation new record folder permissions + */ + @Test + public void initPermissionsForNewRecordFolder() + { + // setup permissions for parent + setupPermissions(recordCategory); + + // setup permissions + filePlanPermissionService.setupPermissions(recordCategory, newRecordFolder); + + // verify permission init + verifyInitPermissions(recordCategory, newRecordFolder, times(1), times(1)); + + } + + /** + * Test setup of new record permissions + */ + @Test + public void initPermissionsForNewRecord() + { + // setup permissions for parent + setupPermissions(newRecordFolder); + + // setup permissions for record + filePlanPermissionService.setupPermissions(newRecordFolder, newRecord); + + // verify permission init + verifyInitPermissions(newRecordFolder, newRecord, times(1), times(1)); + } + + /** + * Test setup of permissions for new hold container + */ + @Test + public void initPermnissionsForNewHoldContainer() + { + // setup permissions for parent + setupPermissions(filePlan); + + // setup permissions for record + filePlanPermissionService.setupPermissions(filePlan, holdContainer); + + // verify permissions are set-up correctly + verifyInitPermissions(filePlan, holdContainer, times(1), times(1)); + } + + /** + * Test setup of permissions for new hold + */ + @Test + public void initPermissionsForNewHold() + { + // setup permissions for parent + setupPermissions(holdContainer); + + // setup permissions for record + filePlanPermissionService.setupPermissions(holdContainer, hold); + + // verify permissions are set-up correctly + verifyInitPermissions(holdContainer, hold, never(), times(1)); + + } + + /** + * Test setup of permissions for new unfiled container + */ + @Test + public void initPermissionsForNewUnfiledContainer() + { + // setup permissions for parent + setupPermissions(filePlan); + + // setup permissions for record + filePlanPermissionService.setupPermissions(filePlan, unfiledRecordContainer); + + // verify permissions are set-up correctly + verifyInitPermissions(filePlan, unfiledRecordContainer, times(1), times(1)); + } + + /** + * Test setup of permissions for new unfiled record folder + */ + @Test + public void initPermissionsForNewUnfiledRecordFolder() + { + // setup permissions for parent + setupPermissions(unfiledRecordContainer); + + // setup permissions for record + filePlanPermissionService.setupPermissions(unfiledRecordContainer, unfiledRecordFolder); + + // verify permissions are set-up correctly + verifyInitPermissions(unfiledRecordContainer, unfiledRecordFolder, never(), times(1)); + + } + + /** + * Test setup of permissions for new unfiled record + */ + @Test + public void initPermissionsForNewUnfiledRecord() + { + // setup permissions for parent + setupPermissions(unfiledRecordFolder); + + // setup permissions for record + filePlanPermissionService.setupPermissions(unfiledRecordFolder, unfiledRecord); + + // verify permission init + verifyInitPermissions(unfiledRecordFolder, unfiledRecord, times(1), times(1)); + + } } diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java index 2b7a3e02d3..7f04b41bca 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/AllUnitTestSuite.java @@ -42,8 +42,10 @@ import org.junit.runners.Suite.SuiteClasses; @SuiteClasses( { RecordMetadataBootstrapUnitTest.class, - RecordServiceImplUnitTest.class, RecordsManagementTypeFormFilterUnitTest.class, + + // services + RecordServiceImplUnitTest.class, HoldServiceImplUnitTest.class, FilePlanPermissionServiceImplUnitTest.class, diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java index 6325c296a1..4c3afa8474 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/test/util/BaseUnitTest.java @@ -43,6 +43,7 @@ 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.OwnableService; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; @@ -82,6 +83,7 @@ public class BaseUnitTest implements RecordsManagementModel @Mock(name="namespaceService") protected NamespaceService mockedNamespaceService; @Mock(name="identifierService") protected IdentifierService mockedIdentifierService; @Mock(name="permissionService") protected PermissionService mockedPermissionService; + @Mock(name="ownableService") protected OwnableService mockedOwnableService; /** rm service mocks */ @Mock(name="filePlanService") protected FilePlanService mockedFilePlanService;