From a9bc2ea5c7f953020d9340f417e2a98204f7c6de Mon Sep 17 00:00:00 2001 From: Tom Page Date: Wed, 6 May 2015 15:27:35 +0000 Subject: [PATCH] RM-2119 Java API to change a user's security clearance. +review RM git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/HEAD@103777 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../SecurityClearanceService.java | 8 +++ .../SecurityClearanceServiceImpl.java | 34 +++++++++- .../SecurityClearanceServiceImplUnitTest.java | 65 +++++++++++++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceService.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceService.java index 367c0b56d5..c372d08d4f 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceService.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceService.java @@ -44,4 +44,12 @@ public interface SecurityClearanceService * @return security clearances for the specified page of users. */ PagingResults getUsersSecurityClearance(UserQueryParams queryParams); + + /** + * Set the clearance level for a user. + * + * @param userName The username of the user. + * @param clearanceId The identifier for the new clearance level. + */ + void setUserSecurityClearance(String userName, String clearanceId); } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImpl.java index 8fd75ff60d..dfdec3af08 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImpl.java @@ -21,18 +21,22 @@ package org.alfresco.module.org_alfresco_module_rm.classification; import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.ASPECT_SECURITY_CLEARANCE; import static org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel.PROP_CLEARANCE_LEVEL; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.query.PagingRequest; import org.alfresco.query.PagingResults; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.security.PersonService.PersonInfo; +import org.alfresco.service.namespace.QName; import org.alfresco.util.Pair; import org.alfresco.util.ParameterCheck; -import java.util.ArrayList; -import java.util.List; - /** * @author Neil Mc Erlean * @since 3.0 @@ -45,6 +49,7 @@ public class SecurityClearanceServiceImpl extends ServiceBaseImpl implements Sec public void setClassificationService(ClassificationService service) { this.classificationService = service; } public void setPersonService (PersonService service) { this.personService = service; } + @Override public SecurityClearance getUserSecurityClearance() { final String currentUser = authenticationUtil.getFullyAuthenticatedUser(); @@ -72,6 +77,7 @@ public class SecurityClearanceServiceImpl extends ServiceBaseImpl implements Sec return new SecurityClearance(personInfo, classificationLevel); } + @Override public PagingResults getUsersSecurityClearance(UserQueryParams queryParams) { final PagingRequest pagingRequest = new PagingRequest(queryParams.getSkipCount(), @@ -102,4 +108,26 @@ public class SecurityClearanceServiceImpl extends ServiceBaseImpl implements Sec @Override public String getQueryExecutionId() { return p.getQueryExecutionId(); } }; } + + @Override + public void setUserSecurityClearance(String userName, String clearanceId) + { + ParameterCheck.mandatoryString("userName", userName); + ParameterCheck.mandatoryString("clearanceId", clearanceId); + + final NodeRef personNode = personService.getPerson(userName, false); + // This is just used to check the current user has clearance to see the specified level; it will throw a + // LevelIdNotFound exception if not. + classificationService.getClassificationLevelById(clearanceId); + + if (nodeService.hasAspect(personNode, ASPECT_SECURITY_CLEARANCE)) + { + nodeService.setProperty(personNode, PROP_CLEARANCE_LEVEL, clearanceId); + } + else + { + Map properties = ImmutableMap.of(PROP_CLEARANCE_LEVEL, clearanceId); + nodeService.addAspect(personNode, ASPECT_SECURITY_CLEARANCE, properties); + } + } } diff --git a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImplUnitTest.java b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImplUnitTest.java index 1fe38cf153..82662b38ae 100644 --- a/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImplUnitTest.java +++ b/rm-server/unit-test/java/org/alfresco/module/org_alfresco_module_rm/classification/SecurityClearanceServiceImplUnitTest.java @@ -23,8 +23,14 @@ import static org.alfresco.module.org_alfresco_module_rm.classification.model.Cl import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.io.Serializable; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; +import org.alfresco.module.org_alfresco_module_rm.classification.ClassificationServiceException.LevelIdNotFound; import org.alfresco.module.org_alfresco_module_rm.test.util.MockAuthenticationUtilHelper; import org.alfresco.module.org_alfresco_module_rm.util.AuthenticationUtil; import org.alfresco.service.cmr.dictionary.DictionaryService; @@ -33,6 +39,7 @@ import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.security.PersonService; import org.alfresco.service.cmr.security.PersonService.PersonInfo; +import org.alfresco.service.namespace.QName; import org.junit.Before; import org.junit.Test; import org.mockito.InjectMocks; @@ -92,4 +99,62 @@ public class SecurityClearanceServiceImplUnitTest assertEquals("default", clearance.getClassificationLevel().getId()); } + + /** Check that a user can have their clearance set for the first time. */ + @Test public void setUserSecurityClearance_initialClearance() + { + // Create the user. + String userName = "User 1"; + NodeRef personNode = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, userName); + when(mockPersonService.getPerson(userName, false)).thenReturn(personNode); + // The user has no previous clearance. + when(mockNodeService.hasAspect(personNode, ASPECT_SECURITY_CLEARANCE)).thenReturn(false); + // Create the clearance. + String clearanceId = "ClearanceId"; + ClassificationLevel level = new ClassificationLevel(clearanceId, "TopSecretKey"); + when(mockClassificationService.getClassificationLevelById(clearanceId)).thenReturn(level); + + // Call the method under test. + securityClearanceServiceImpl.setUserSecurityClearance(userName, clearanceId); + + Map expectedProperties = ImmutableMap.of(PROP_CLEARANCE_LEVEL, clearanceId); + verify(mockNodeService).addAspect(personNode, ASPECT_SECURITY_CLEARANCE, expectedProperties); + } + + /** Check that a user can have their clearance edited. */ + @Test public void setUserSecurityClearance_updateClearance() + { + // Create the user. + String userName = "User 1"; + NodeRef personNode = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, userName); + when(mockPersonService.getPerson(userName, false)).thenReturn(personNode); + // The user has a previous clearance. + when(mockNodeService.hasAspect(personNode, ASPECT_SECURITY_CLEARANCE)).thenReturn(true); + // Create the clearance. + String clearanceId = "ClearanceId"; + ClassificationLevel level = new ClassificationLevel(clearanceId, "TopSecretKey"); + when(mockClassificationService.getClassificationLevelById(clearanceId)).thenReturn(level); + + // Call the method under test. + securityClearanceServiceImpl.setUserSecurityClearance(userName, clearanceId); + + verify(mockNodeService).setProperty(personNode, PROP_CLEARANCE_LEVEL, clearanceId); + } + + /** + * Check that a user cannot raise someone's clearance above their own. Here we check that an exception thrown by the + * classification service is passed through. + */ + @Test(expected = LevelIdNotFound.class) + public void setUserSecurityClearance_insufficientClearance() + { + String userName = "User 1"; + NodeRef personNode = new NodeRef(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, userName); + when(mockPersonService.getPerson(userName, false)).thenReturn(personNode); + String clearanceId = "ClearanceId"; + // If the user has insufficient clearance then they cannot access the level. + when(mockClassificationService.getClassificationLevelById(clearanceId)).thenThrow(new LevelIdNotFound(clearanceId)); + + securityClearanceServiceImpl.setUserSecurityClearance(userName, clearanceId); + } }