From 43a961237e1052a37fc48532d949f73597c3740c Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Tue, 2 Aug 2016 11:20:55 +1000 Subject: [PATCH] RM-3074: groups assigned to RM roles, not authorities * IPR groups are now assigned to RM roles rather than the individual authorities * more unit tests --- .../role/FilePlanRoleServiceImpl.java | 2 - .../security/ExtendedSecurityServiceImpl.java | 67 +-- .../ExtendedSecurityServiceImplUnitTest.java | 423 ++++++++++++++++-- 3 files changed, 416 insertions(+), 76 deletions(-) diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java index e70baa4f45..e4357d3d24 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java @@ -45,8 +45,6 @@ import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; 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.security.ExtendedReaderDynamicAuthority; -import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authority.RMAuthority; import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException; diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java index ac7d792915..9b7aeb1311 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java @@ -224,14 +224,12 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl public void addExtendedSecurity(NodeRef nodeRef, Set readers, Set writers) { ParameterCheck.mandatory("nodeRef", nodeRef); - - if (nodeRef != null) - { - addExtendedSecurityImpl(nodeRef, readers, writers); - - // add to the extended security roles - addExtendedSecurityRoles(nodeRef, readers, writers); - } + + // TODO what happens if the node already has some extended permissions assigned?! + // TODO need to clear existing groups and add new ones + + // add extended security impl + addExtendedSecurityImpl(nodeRef, readers, writers); } /** @@ -249,6 +247,11 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl // find groups Pair iprGroups = createOrFindIPRGroups(readers, writers); + // assign groups to correct fileplan roles + NodeRef filePlan = filePlanService.getFilePlan(nodeRef); + filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, iprGroups.first); + filePlanRoleService.assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, iprGroups.second); + // assign groups to node assignIPRGroupsToNode(iprGroups, nodeRef); @@ -306,8 +309,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl * the set of groups that require exact match. A further index is used to handle * a situation where there is a hash clash, but a difference in the authority lists. *

- * When no match is found the groups are created. + * When no match is found the groups are created. Once created * + * @param filePlan file plan * @param readers authorities with read * @param writers authorities with write * @return Pair where first is the full name of the read group and @@ -441,6 +445,8 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl * Get IPR group short name. *

* Note this excludes the "GROUP_" prefix. + *

+ * 'package' scope to help testing. * * @param prefix prefix * @param readers read authorities @@ -448,7 +454,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl * @param index group index * @return String group short name */ - private String getIPRGroupShortName(String prefix, Set readers, Set writers, int index) + /*package*/ String getIPRGroupShortName(String prefix, Set readers, Set writers, int index) { return getIPRGroupShortName(prefix, readers, writers, Integer.toString(index)); } @@ -511,7 +517,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl } /** - * Creates new IPR groups. + * Creates new IPR groups and assigns then to the correct RM roles. * * @param readers read authorities * @param writers write authorities @@ -562,7 +568,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl } /** - * Assign IPR groups to a node reference with the appropraite permissions. + * Assign IPR groups to a node reference with the correct permissions. * * @param iprGroups iprGroups, first read and second write * @param nodeRef node reference @@ -572,43 +578,6 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl permissionService.setPermission(nodeRef, iprGroups.first, RMPermissionModel.READ_RECORDS, true); permissionService.setPermission(nodeRef, iprGroups.second, RMPermissionModel.FILING, true); } - - /** - * Add authorities to extended security roles. - * - * @param nodeRef node reference - * @param readers read authorities - * @param writers write authorities - */ - private void addExtendedSecurityRoles(NodeRef nodeRef, Set readers, Set writers) - { - NodeRef filePlan = filePlanService.getFilePlan(nodeRef); - - addExtendedSecurityRolesImpl(filePlan, readers, FilePlanRoleService.ROLE_EXTENDED_READERS); - addExtendedSecurityRolesImpl(filePlan, writers, FilePlanRoleService.ROLE_EXTENDED_WRITERS); - } - - /** - * Add extended security roles implementation - * - * @param filePlan file plan - * @param authorities authorities - * @param roleName role name - */ - private void addExtendedSecurityRolesImpl(NodeRef filePlan, Set authorities, String roleName) - { - if (authorities != null) - { - for (String authority : authorities) - { - if ((!authority.equals(PermissionService.ALL_AUTHORITIES) && !authority.equals(PermissionService.OWNER_AUTHORITY))) - { - // add the authority to the role - filePlanRoleService.assignRoleToAuthority(filePlan, roleName, authority); - } - } - } - } /** * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#removeAllExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef) diff --git a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImplUnitTest.java b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImplUnitTest.java index 62254d2aec..ceb231c6b3 100644 --- a/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImplUnitTest.java +++ b/rm-community/rm-community-repo/unit-test/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImplUnitTest.java @@ -30,22 +30,32 @@ import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecuri import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityServiceImpl.ROOT_IPR_GROUP; import static org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityServiceImpl.WRITER_GROUP_PREFIX; import static org.alfresco.service.cmr.security.PermissionService.GROUP_PREFIX; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anySet; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.module.org_alfresco_module_rm.test.util.AlfMock; +import org.alfresco.query.PagingRequest; +import org.alfresco.query.PagingResults; import org.alfresco.repo.security.authority.RMAuthority; import org.alfresco.repo.security.permissions.impl.AccessPermissionImpl; import org.alfresco.repo.transaction.RetryingTransactionHelper; @@ -65,6 +75,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; +import org.springframework.context.ApplicationContext; import org.springframework.context.event.ContextRefreshedEvent; /** @@ -83,23 +94,29 @@ public class ExtendedSecurityServiceImplUnitTest @Mock private TransactionService mockedTransactionService; @Mock private RetryingTransactionHelper mockedRetryingTransactionHelper; @Mock private NodeService mockedNodeService; + @Mock private PagingResults mockedPagingResults; + @Mock private ApplicationContext mockedApplicationContext; /** test component */ @InjectMocks private ExtendedSecurityServiceImpl extendedSecurityService; /** read/write group full names */ - private static final String READER_GROUP_FULL_NAME = GROUP_PREFIX + READER_GROUP_PREFIX; - private static final String WRITER_GROUP_FULL_NAME = GROUP_PREFIX + WRITER_GROUP_PREFIX; + private static final String READER_GROUP_FULL_PREFIX = GROUP_PREFIX + READER_GROUP_PREFIX; + private static final String WRITER_GROUP_FULL_PREFIX = GROUP_PREFIX + WRITER_GROUP_PREFIX; /** test authorities */ private static final String USER = AlfMock.generateText(); private static final String GROUP = GROUP_PREFIX + AlfMock.generateText(); + private static final String USER_W = AlfMock.generateText(); + private static final String GROUP_W = GROUP_PREFIX + AlfMock.generateText(); + private static final Set READERS = Stream.of(USER, GROUP).collect(Collectors.toSet()); + private static final Set WRITERS = Stream.of(USER_W, GROUP_W).collect(Collectors.toSet()); /** has extended security permission set */ private static final Set HAS_EXTENDED_SECURITY = Stream - .of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, READER_GROUP_FULL_NAME, 0), + .of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, READER_GROUP_FULL_PREFIX, 0), new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 1), - new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, WRITER_GROUP_FULL_NAME, 2)) + new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, WRITER_GROUP_FULL_PREFIX, 2)) .collect(Collectors.toSet()); /** has no extended security permission set */ @@ -111,25 +128,29 @@ public class ExtendedSecurityServiceImplUnitTest /** test data */ private NodeRef nodeRef; + private NodeRef filePlan; /** * Before tests */ + @SuppressWarnings("unchecked") @Before public void before() { // initialise mocks MockitoAnnotations.initMocks(this); - // setup nodeRef + // setup node nodeRef = AlfMock.generateNodeRef(mockedNodeService); - } - - /** - * Helper to setup retrying transaction helper - */ - @SuppressWarnings("unchecked") - private void setupRetryingTransactionHelper() - { + + // setup file plan + filePlan = AlfMock.generateNodeRef(mockedNodeService); + when(mockedFilePlanService.getFilePlan(any(NodeRef.class))) + .thenReturn(filePlan); + + // set-up application context + when(mockedApplicationContext.getBean("dbNodeService")) + .thenReturn(mockedNodeService); + // setup retrying transaction helper Answer doInTransactionAnswer = new Answer() { @@ -146,6 +167,18 @@ public class ExtendedSecurityServiceImplUnitTest .doInTransaction(any(RetryingTransactionCallback.class)); when(mockedTransactionService.getRetryingTransactionHelper()) .thenReturn(mockedRetryingTransactionHelper); + + // setup create authority + Answer createAuthorityAnswer = new Answer() + { + public String answer(InvocationOnMock invocation) throws Throwable + { + return PermissionService.GROUP_PREFIX + (String)invocation.getArguments()[1]; + } + + }; + when(mockedAuthorityService.createAuthority(any(AuthorityType.class), anyString(), anyString(), anySet())) + .thenAnswer(createAuthorityAnswer); } /** @@ -155,9 +188,6 @@ public class ExtendedSecurityServiceImplUnitTest */ @Test public void rootAuthorityDoesNotExist() { - // setup retrying transaction helper - setupRetryingTransactionHelper(); - // group doesn't exist when(mockedAuthorityService.authorityExists(GROUP_PREFIX + ExtendedSecurityServiceImpl.ROOT_IPR_GROUP)) .thenReturn(false); @@ -176,9 +206,6 @@ public class ExtendedSecurityServiceImplUnitTest */ @Test public void rootAuthorityDoesExist() { - // setup retrying transaction helper - setupRetryingTransactionHelper(); - // group doesn't exist when(mockedAuthorityService.authorityExists(GROUP_PREFIX + ROOT_IPR_GROUP)) .thenReturn(true); @@ -268,7 +295,7 @@ public class ExtendedSecurityServiceImplUnitTest * When I try and get the extended readers * The I will get an empty set */ - @Test public void getExtendedReadersNoIPRGoupsAssigned() + @Test public void getExtendedReadersNoIPRGroupsAssigned() { // setup permissions when(mockedPermissionService.getAllSetPermissions(nodeRef)) @@ -289,9 +316,9 @@ public class ExtendedSecurityServiceImplUnitTest when(mockedPermissionService.getAllSetPermissions(nodeRef)) .thenReturn(HAS_EXTENDED_SECURITY); - when(mockedAuthorityService.getContainedAuthorities(null, READER_GROUP_FULL_NAME, true)) + when(mockedAuthorityService.getContainedAuthorities(null, READER_GROUP_FULL_PREFIX, true)) .thenReturn(Stream - .of(USER, GROUP, WRITER_GROUP_FULL_NAME) + .of(USER, GROUP, WRITER_GROUP_FULL_PREFIX) .collect(Collectors.toSet())); // get extended readers @@ -307,14 +334,360 @@ public class ExtendedSecurityServiceImplUnitTest * When I try and get the extended writers * The I will get an empty set */ + @Test public void getExtendedWritersNoIPRGroupsAssigned() + { + // setup permissions + when(mockedPermissionService.getAllSetPermissions(nodeRef)) + .thenReturn(HAS_NO_EXTENDED_SECURITY); + + // get extended writers + assertTrue(extendedSecurityService.getExtendedWriters(nodeRef).isEmpty()); + } /** * Given that there are IPR groups assigned * When I try and get the extended writers * The I will get the set of writers */ + @Test public void getExtendedWriters() + { + // setup permissions + when(mockedPermissionService.getAllSetPermissions(nodeRef)) + .thenReturn(HAS_EXTENDED_SECURITY); + + when(mockedAuthorityService.getContainedAuthorities(null, WRITER_GROUP_FULL_PREFIX, true)) + .thenReturn(Stream + .of(USER, GROUP) + .collect(Collectors.toSet())); + + // get extended writers + Set extendedWriters = extendedSecurityService.getExtendedWriters(nodeRef); + assertEquals(Stream + .of(USER, GROUP) + .collect(Collectors.toSet()), + extendedWriters); + } - // TODO add AC for adding extended security marks + /** + * Given a node with no previous IPR groups assigned + * And no IPR group matching authorities + * When I add some read and write authorities + * Then new IPR groups are created + * And they are assigned to the node + * And they are added to the RM roles + */ + @Test public void addExtendedSecurityForTheFirstTimeAndCreateGroups() + { + // group names + String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_PREFIX, READERS, WRITERS, 0); + String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_PREFIX, READERS, WRITERS, 0); + + // setup query results + when(mockedPagingResults.getPage()) + .thenReturn(Collections.emptyList()); + when(mockedAuthorityService.getAuthorities( + eq(AuthorityType.GROUP), + eq(RMAuthority.ZONE_APP_RM), + any(String.class), + eq(false), + eq(false), + any(PagingRequest.class))) + .thenReturn(mockedPagingResults); + + // add extended security + extendedSecurityService.addExtendedSecurity(nodeRef, READERS, WRITERS); + + // verify read group created correctly + verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, readGroup, readGroup, Collections.singleton(RMAuthority.ZONE_APP_RM)); + readGroup = GROUP_PREFIX + readGroup; + verify(mockedAuthorityService).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, readGroup); + verify(mockedAuthorityService).addAuthority(readGroup, USER); + verify(mockedAuthorityService).addAuthority(readGroup, GROUP); + + // verify write group created correctly + verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, writeGroup, writeGroup, Collections.singleton(RMAuthority.ZONE_APP_RM)); + writeGroup = GROUP_PREFIX + writeGroup; + verify(mockedAuthorityService).addAuthority(readGroup, writeGroup); + verify(mockedAuthorityService).addAuthority(writeGroup, USER_W); + verify(mockedAuthorityService).addAuthority(writeGroup, GROUP_W); + + // verify groups assigned to RM roles + verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, readGroup); + verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, writeGroup); + + // verify permissions are assigned to node + verify(mockedPermissionService).setPermission(nodeRef, readGroup, RMPermissionModel.READ_RECORDS, true); + verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true); + } - // TODO add AC for removing extended security marks + /** + * Given a node with no previous IPR groups assigned + * And existing IPR groups matching + * When I add some read and write authorities + * Then the existing IPR groups are used + * And they are assigned to the node + * And do not not need to be re-added to the RM roles + */ + @Test public void addExtendedSecurityForTheFirstTimeAndReuseGroups() + { + // group names + String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_PREFIX, READERS, WRITERS, 0); + String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_PREFIX, READERS, WRITERS, 0); + + // setup query results + when(mockedPagingResults.getPage()) + .thenReturn(Stream.of(GROUP_PREFIX + readGroup).collect(Collectors.toList())); + when(mockedAuthorityService.getAuthorities( + eq(AuthorityType.GROUP), + eq(RMAuthority.ZONE_APP_RM), + any(String.class), + eq(false), + eq(false), + any(PagingRequest.class))) + .thenReturn(mockedPagingResults); + + // setup exact match + when(mockedAuthorityService.authorityExists(GROUP_PREFIX + writeGroup)) + .thenReturn(true); + when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + readGroup, true)) + .thenReturn(Stream + .of(GROUP_PREFIX + writeGroup, USER, GROUP) + .collect(Collectors.toSet())); + when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + writeGroup, true)) + .thenReturn(Stream + .of(USER_W, GROUP_W) + .collect(Collectors.toSet())); + + // add extended security + extendedSecurityService.addExtendedSecurity(nodeRef, READERS, WRITERS); + + // verify read group is not recreated + verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, readGroup, readGroup, Collections.singleton(RMAuthority.ZONE_APP_RM)); + readGroup = GROUP_PREFIX + readGroup; + verify(mockedAuthorityService, never()).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, readGroup); + verify(mockedAuthorityService, never()).addAuthority(readGroup, USER); + verify(mockedAuthorityService, never()).addAuthority(readGroup, GROUP); + + // verify write group is not recreated + verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, writeGroup, writeGroup, Collections.singleton(RMAuthority.ZONE_APP_RM)); + writeGroup = GROUP_PREFIX + writeGroup; + verify(mockedAuthorityService, never()).addAuthority(readGroup, writeGroup); + verify(mockedAuthorityService, never()).addAuthority(writeGroup, USER_W); + verify(mockedAuthorityService, never()).addAuthority(writeGroup, GROUP_W); + + // verify groups assigned to RM roles + verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, readGroup); + verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, writeGroup); + + // verify permissions are assigned to node + verify(mockedPermissionService).setPermission(nodeRef, readGroup, RMPermissionModel.READ_RECORDS, true); + verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true); + + } + + /** + * Given a node with no previous IPR groups assigned + * And existing IPR groups matches existing has, but not exact match + * When I add some read and write authorities + * Then new groups are created + * And they are assigned to the node + * And added to the RM roles + */ + @Test public void addExtendedSecurityForTheFirstTimeAndCreateGroupsAfterClash() + { + // group names + String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_PREFIX, READERS, WRITERS, 0); + String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_PREFIX, READERS, WRITERS, 0); + + // setup query results + when(mockedPagingResults.getPage()) + .thenReturn(Stream.of(GROUP_PREFIX + readGroup).collect(Collectors.toList())); + when(mockedAuthorityService.getAuthorities( + eq(AuthorityType.GROUP), + eq(RMAuthority.ZONE_APP_RM), + any(String.class), + eq(false), + eq(false), + any(PagingRequest.class))) + .thenReturn(mockedPagingResults); + + // setup exact match + when(mockedAuthorityService.authorityExists(GROUP_PREFIX + writeGroup)) + .thenReturn(true); + when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + readGroup, true)) + .thenReturn(Stream + .of(GROUP_PREFIX + writeGroup, USER, GROUP) + .collect(Collectors.toSet())); + when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + writeGroup, true)) + .thenReturn(Stream + .of(USER_W, AlfMock.generateText()) + .collect(Collectors.toSet())); + + // add extended security + extendedSecurityService.addExtendedSecurity(nodeRef, READERS, WRITERS); + + // new group names + readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_PREFIX, READERS, WRITERS, 1); + writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_PREFIX, READERS, WRITERS, 1); + + // verify read group created correctly + verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, readGroup, readGroup, Collections.singleton(RMAuthority.ZONE_APP_RM)); + readGroup = GROUP_PREFIX + readGroup; + verify(mockedAuthorityService).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, readGroup); + verify(mockedAuthorityService).addAuthority(readGroup, USER); + verify(mockedAuthorityService).addAuthority(readGroup, GROUP); + + // verify write group created correctly + verify(mockedAuthorityService).createAuthority(AuthorityType.GROUP, writeGroup, writeGroup, Collections.singleton(RMAuthority.ZONE_APP_RM)); + writeGroup = GROUP_PREFIX + writeGroup; + verify(mockedAuthorityService).addAuthority(readGroup, writeGroup); + verify(mockedAuthorityService).addAuthority(writeGroup, USER_W); + verify(mockedAuthorityService).addAuthority(writeGroup, GROUP_W); + + // verify groups assigned to RM roles + verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, readGroup); + verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, writeGroup); + + // verify permissions are assigned to node + verify(mockedPermissionService).setPermission(nodeRef, readGroup, RMPermissionModel.READ_RECORDS, true); + verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true); + } + + /** + * Given a node with no previous IPR groups assigned + * And existing IPR groups matching, but found on second page of find results + * When I add some read and write authorities + * Then the existing IPR groups are used + * And they are assigned to the node + * And do not not need to be re-added to the RM roles + */ + @Test public void addExtendedSecurityWithResultPaging() + { + // group names + String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_PREFIX, READERS, WRITERS, 0); + String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_PREFIX, READERS, WRITERS, 0); + + List fiftyResults = new ArrayList(50); + for (int i = 0; i < 50; i++) + { + fiftyResults.add(AlfMock.generateText()); + } + + // setup query results + when(mockedPagingResults.getPage()) + .thenReturn(fiftyResults) + .thenReturn(Stream.of(GROUP_PREFIX + readGroup).collect(Collectors.toList())); + when(mockedAuthorityService.getAuthorities( + eq(AuthorityType.GROUP), + eq(RMAuthority.ZONE_APP_RM), + any(String.class), + eq(false), + eq(false), + any(PagingRequest.class))) + .thenReturn(mockedPagingResults); + + // setup exact match + when(mockedAuthorityService.authorityExists(GROUP_PREFIX + writeGroup)) + .thenReturn(true); + when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + readGroup, true)) + .thenReturn(Stream + .of(GROUP_PREFIX + writeGroup, USER, GROUP) + .collect(Collectors.toSet())); + when(mockedAuthorityService.getContainedAuthorities(null, GROUP_PREFIX + writeGroup, true)) + .thenReturn(Stream + .of(USER_W, GROUP_W) + .collect(Collectors.toSet())); + + // add extended security + extendedSecurityService.addExtendedSecurity(nodeRef, READERS, WRITERS); + + // verify read group is not recreated + verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, readGroup, readGroup, Collections.singleton(RMAuthority.ZONE_APP_RM)); + readGroup = GROUP_PREFIX + readGroup; + verify(mockedAuthorityService, never()).addAuthority(GROUP_PREFIX + ROOT_IPR_GROUP, readGroup); + verify(mockedAuthorityService, never()).addAuthority(readGroup, USER); + verify(mockedAuthorityService, never()).addAuthority(readGroup, GROUP); + + // verify write group is not recreated + verify(mockedAuthorityService, never()).createAuthority(AuthorityType.GROUP, writeGroup, writeGroup, Collections.singleton(RMAuthority.ZONE_APP_RM)); + writeGroup = GROUP_PREFIX + writeGroup; + verify(mockedAuthorityService, never()).addAuthority(readGroup, writeGroup); + verify(mockedAuthorityService, never()).addAuthority(writeGroup, USER_W); + verify(mockedAuthorityService, never()).addAuthority(writeGroup, GROUP_W); + + // verify groups assigned to RM roles + verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_READERS, readGroup); + verify(mockedFilePlanRoleService).assignRoleToAuthority(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS, writeGroup); + + // verify permissions are assigned to node + verify(mockedPermissionService).setPermission(nodeRef, readGroup, RMPermissionModel.READ_RECORDS, true); + verify(mockedPermissionService).setPermission(nodeRef, writeGroup, RMPermissionModel.FILING, true); + + } + + /** + * Given that a node already has extended security + * When I add extended security + * Then the existing extended security is replaced with the new extended security + */ + // TODO + + /** + * Given that a node has renditions + * When I add extended security + * Then it applied to the renditions + */ + // TODO + + /** + * Given that a node has extended security + * When I remove the extended security + * Then the inplace groups permissions are removed + */ + @Test public void removeAllExtendedSecurity() + { + // group names + String readGroup = extendedSecurityService.getIPRGroupShortName(READER_GROUP_FULL_PREFIX, READERS, WRITERS, 0); + String writeGroup = extendedSecurityService.getIPRGroupShortName(WRITER_GROUP_FULL_PREFIX, READERS, WRITERS, 0); + + // setup permissions + Set permissions = Stream + .of(new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, readGroup, 0), + new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, AlfMock.generateText(), 1), + new AccessPermissionImpl(AlfMock.generateText(), AccessStatus.ALLOWED, writeGroup, 2)) + .collect(Collectors.toSet()); + when(mockedPermissionService.getAllSetPermissions(nodeRef)) + .thenReturn(permissions); + + // remove extended security + extendedSecurityService.removeAllExtendedSecurity(nodeRef); + + // verify that the groups permissions have been removed + verify(mockedPermissionService).clearPermission(nodeRef, readGroup); + verify(mockedPermissionService).clearPermission(nodeRef, writeGroup); + } + + /** + * Given that a node has no extended security + * When I remove the extended security + * Then nothing happens + */ + @Test public void noExtendedSecurityToRemove() + { + when(mockedPermissionService.getAllSetPermissions(nodeRef)) + .thenReturn(HAS_NO_EXTENDED_SECURITY); + + // remove extended security + extendedSecurityService.removeAllExtendedSecurity(nodeRef); + + // verify that the groups permissions have been removed + verify(mockedPermissionService, never()).clearPermission(eq(nodeRef), anyString()); + } + + /** + * Given that node has renditions + * When I remove the extended security for a node + * Then the extended security is also removed from the rentitions + */ + // TODO }