diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties index 7be22d2fcf..aa06ff15d3 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties @@ -81,6 +81,12 @@ rm.completerecord.mandatorypropertiescheck.enabled=true # rm.patch.v22.convertToStandardFilePlan=false +# Permission mapping +# these take a comma separated string of permissions from org.alfresco.service.cmr.security.PermissionService +# read maps to ReadRecords and write to FileRecords +rm.haspermissionmap.read=ReadProperties,ReadChildren +rm.haspermissionmap.write=WriteProperties,AddChildren + # # Extended auto-version behaviour. If true and other auto-version properties are satisfied, then # a document will be auto-versioned when its type is changed. diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml index ea70bd391d..e5264e8139 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/extended-repository-context.xml @@ -114,6 +114,12 @@ + + ${rm.haspermissionmap.read} + + + ${rm.haspermissionmap.write} + @@ -262,4 +268,4 @@ - \ No newline at end of file + diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessor.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessor.java index 5b31bdf651..47ca2a4b3e 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessor.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessor.java @@ -27,6 +27,8 @@ package org.alfresco.module.org_alfresco_module_rm.permission; +import java.util.List; + import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.security.permissions.processor.impl.PermissionPostProcessorBaseImpl; @@ -55,20 +57,21 @@ public class RecordsManagementPermissionPostProcessor extends PermissionPostProc * @see org.alfresco.repo.security.permissions.processor.PermissionPostProcessor#process(org.alfresco.service.cmr.security.AccessStatus, org.alfresco.service.cmr.repository.NodeRef, java.lang.String) */ @Override - public AccessStatus process(AccessStatus accessStatus, NodeRef nodeRef, String perm) + public AccessStatus process(AccessStatus accessStatus, NodeRef nodeRef, String perm, + List configuredReadPermissions, List configuredFilePermissions) { AccessStatus result = accessStatus; if (AccessStatus.DENIED.equals(accessStatus) && nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT)) { // if read denied on rm artifact - if (PermissionService.READ.equals(perm)) + if (PermissionService.READ.equals(perm) || configuredReadPermissions.contains(perm)) { // check for read record result = permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS); } // if write deinied on rm artificat - else if (PermissionService.WRITE.equals(perm) || PermissionService.ADD_CHILDREN.equals(perm)) + else if (PermissionService.WRITE.equals(perm) || configuredFilePermissions.contains(perm)) { // check for file record result = permissionService.hasPermission(nodeRef, RMPermissionModel.FILE_RECORDS); diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java index 8309c84f44..d45d9745c2 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImpl.java @@ -30,6 +30,7 @@ package org.alfresco.repo.security.permissions.impl; import static org.apache.commons.lang.StringUtils.isNotBlank; import java.io.Serializable; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -40,6 +41,7 @@ import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.repo.cache.SimpleCache; + import org.alfresco.repo.security.permissions.AccessControlEntry; import org.alfresco.repo.security.permissions.AccessControlList; import org.alfresco.repo.security.permissions.processor.PermissionPostProcessor; @@ -55,6 +57,7 @@ import org.alfresco.util.PropertyCheck; import org.apache.commons.lang.StringUtils; import org.springframework.context.ApplicationEvent; + /** * Extends the core permission service implementation allowing the consideration of the read records permission. *

@@ -67,6 +70,20 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl impleme /** Writers simple cache */ protected SimpleCache> writersCache; + /** + * Configured Permission mapping. + *

+ * This string comes from alfresco-global.properties and allows fine tuning of the how permissions are mapped. + * This was added as a fix for MNT-16852 to enhance compatibility with our Outlook Integration. + */ + protected List configuredReadPermissions; + /** + * Configured Permission mapping. + *

+ * This string also comes from alfresco-global.properties. + */ + protected List configuredFilePermissions; + /** File plan service */ private FilePlanService filePlanService; @@ -124,6 +141,28 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl impleme this.writersCache = writersCache; } + /** + * Maps the string from the properties file (rm.haspermissionmap.read) + * to the list used in the hasPermission method + * + * @param readMapping the mapping of permissions to ReadRecord + */ + public void setConfiguredReadPermissions(String readMapping) + { + this.configuredReadPermissions = Arrays.asList(readMapping.split(",")); + } + + /** + * Maps the string set in the properties file (rm.haspermissionmap.write) + * to the list used in the hasPermission method + * + * @param fileMapping the mapping of permissions to FileRecord + */ + public void setConfiguredFilePermissions(String fileMapping) + { + this.configuredFilePermissions = Arrays.asList(fileMapping.split(",")); + } + /** * @see org.alfresco.repo.security.permissions.impl.PermissionServiceImpl#onBootstrap(org.springframework.context.ApplicationEvent) */ @@ -166,7 +205,7 @@ public class ExtendedPermissionServiceImpl extends PermissionServiceImpl impleme for (PermissionPostProcessor postProcessor : postProcessors) { // post process permission - result = postProcessor.process(result, nodeRef, perm); + result = postProcessor.process(result, nodeRef, perm, this.configuredReadPermissions, this.configuredFilePermissions); } } return result; diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/processor/PermissionPostProcessor.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/processor/PermissionPostProcessor.java index 5740594975..175c5f1392 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/processor/PermissionPostProcessor.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/security/permissions/processor/PermissionPostProcessor.java @@ -27,6 +27,8 @@ package org.alfresco.repo.security.permissions.processor; +import java.util.List; + import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AccessStatus; @@ -46,7 +48,9 @@ public interface PermissionPostProcessor * @param accessStatus current access status * @param nodeRef node reference * @param perm permission + * * @return {@link AccessStatus} */ - AccessStatus process(AccessStatus accessStatus, NodeRef nodeRef, String perm); + AccessStatus process(AccessStatus accessStatus, NodeRef nodeRef, String perm, + List configuredReadPermissions, List configuredFilePermissions); } diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessorUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessorUnitTest.java new file mode 100644 index 0000000000..e578c587e2 --- /dev/null +++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/permission/RecordsManagementPermissionPostProcessorUnitTest.java @@ -0,0 +1,120 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2016 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * - + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * - + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + * #L% + */ + +package org.alfresco.module.org_alfresco_module_rm.permission; + +import static java.util.Arrays.asList; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +import java.util.List; + +import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Unit tests for {@link RecordsManagementPermissionPostProcessor}. + * + * @author David Webster + * @since 2.4.1 + */ +public class RecordsManagementPermissionPostProcessorUnitTest +{ + + private @InjectMocks + RecordsManagementPermissionPostProcessor recordsManagementPermissionPostProcessor = new RecordsManagementPermissionPostProcessor(); + + private @Mock NodeService nodeService; + private @Mock PermissionService permissionService; + + @Before + public void setup() + { + MockitoAnnotations.initMocks(this); + } + + /** + * Given the configured permissions are set + * When process is called + * Then access is allowed + */ + @Test + public void configurePermissionsAllowed() + { + AccessStatus accessStatus = AccessStatus.DENIED; + NodeRef nodeRef = new NodeRef("node://ref/"); + String perm = AlfMock.generateText(); + // permissions includes the perm created above + List configuredReadPermissions = asList("ReadProperties", "ReadChildren", perm); + List configuredFilePermissions = asList("WriteProperties", "AddChildren"); + + when(nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT)) + .thenReturn(true); + when(permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS)) + .thenReturn(AccessStatus.ALLOWED); + + AccessStatus result = recordsManagementPermissionPostProcessor.process(accessStatus, nodeRef, perm, configuredReadPermissions, configuredFilePermissions); + + assertEquals(AccessStatus.ALLOWED, result); + } + + /** + * Given the configured permissions are not set + * When process is called + * Then access is denied + */ + @Test + public void configurePermissionsDenied() + { + AccessStatus accessStatus = AccessStatus.DENIED; + NodeRef nodeRef = new NodeRef("node://ref/"); + String perm = AlfMock.generateText(); + // permissions do not include perm created above + List configuredReadPermissions = asList("ReadProperties", "ReadChildren"); + List configuredFilePermissions = asList("WriteProperties", "AddChildren"); + + when(nodeService.hasAspect(nodeRef, RecordsManagementModel.ASPECT_FILE_PLAN_COMPONENT)) + .thenReturn(true); + when(permissionService.hasPermission(nodeRef, RMPermissionModel.READ_RECORDS)) + .thenReturn(AccessStatus.ALLOWED); + + AccessStatus result = recordsManagementPermissionPostProcessor.process(accessStatus, nodeRef, perm, configuredReadPermissions, configuredFilePermissions); + + assertEquals(AccessStatus.DENIED, result); + } +} diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImplUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImplUnitTest.java index 48686b492f..06ca96df8a 100644 --- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImplUnitTest.java +++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/repo/security/permissions/impl/ExtendedPermissionServiceImplUnitTest.java @@ -35,6 +35,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -146,15 +147,21 @@ public class ExtendedPermissionServiceImplUnitTest extends BaseUnitTest { NodeRef nodeRef = generateCmContent("anyname"); String perm = AlfMock.generateText(); + List configuredReadPermissions = asList("ReadProperties", "ReadChildren"); + List configuredFilePermissions = asList("WriteProperties", "AddChildren"); + + extendedPermissionServiceImpl.setConfiguredReadPermissions("ReadProperties,ReadChildren"); + extendedPermissionServiceImpl.setConfiguredFilePermissions("WriteProperties,AddChildren"); + when(mockedPermissionProcessorRegistry.getPermissionPostProcessors()) .thenReturn(asList(mockedPermissionPostProcessor)); - when(mockedPermissionPostProcessor.process(AccessStatus.UNDETERMINED, nodeRef, perm)) + when(mockedPermissionPostProcessor.process(AccessStatus.UNDETERMINED, nodeRef, perm, configuredReadPermissions, configuredFilePermissions)) .thenReturn(AccessStatus.ALLOWED); AccessStatus result = extendedPermissionServiceImpl.hasPermission(nodeRef, perm); assertEquals(AccessStatus.ALLOWED, result); - verify(mockedPermissionPostProcessor).process(AccessStatus.UNDETERMINED, nodeRef, perm); + verify(mockedPermissionPostProcessor).process(AccessStatus.UNDETERMINED, nodeRef, perm, configuredReadPermissions, configuredFilePermissions); verify(extendedPermissionServiceImpl).hasPermissionImpl(nodeRef, perm); }