package jnpf.dmsPermission; import jnpf.dmsEntity.permission.model.DmsSubjectSet; import jnpf.permission.OrganizeApi; import jnpf.permission.PositionApi; import jnpf.permission.RoleRelationApi; import jnpf.permission.UserApi; import jnpf.permission.UserRelationApi; import jnpf.permission.entity.OrganizeEntity; import jnpf.permission.entity.PositionEntity; import jnpf.permission.entity.RoleRelationEntity; import jnpf.permission.entity.UserEntity; import jnpf.permission.entity.UserRelationEntity; import jnpf.permission.model.rolerelaiton.RoleRelationModel; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class DmsUserSubjectBatchResolverTest { private final UserApi userApi = mock(UserApi.class); private final UserRelationApi userRelationApi = mock(UserRelationApi.class); private final RoleRelationApi roleRelationApi = mock(RoleRelationApi.class); private final OrganizeApi organizeApi = mock(OrganizeApi.class); private final PositionApi positionApi = mock(PositionApi.class); private final DmsSubjectHierarchyResolver hierarchyResolver = new DmsSubjectHierarchyResolver(organizeApi, positionApi); private final DmsUserSubjectBatchResolver resolver = new DmsUserSubjectBatchResolver( userApi, userRelationApi, roleRelationApi, hierarchyResolver); @Test void resolvesUsersWithBatchedRelationsAndSharedOrganizationRoles() { List userIds = Arrays.asList("user-1", "user-2"); when(userApi.getUserName(userIds)).thenReturn(Arrays.asList( user("user-1", "tenant-1"), user("user-2", "tenant-1"), null)); when(userRelationApi.getListByUserIdAll(userIds)).thenReturn(Arrays.asList( relation("user-1", "ORGANIZE", "org-1"), relation("user-1", "position", "position-1"), relation("user-1", "GrOuP", "group-1"), relation("user-2", "organize", "org-1"), relation("user-2", "organize", "org-2"), relation("user-2", "POSITION", "position-2"), relation("other-user", "organize", "ignored-org"), null)); when(organizeApi.getListByIds(Arrays.asList("org-1", "org-2"))).thenReturn(Arrays.asList( organization("org-1", "root-org, parent-org, org-1"), organization("org-2", "root-org,org-2"), null)); when(positionApi.getListByIds(Arrays.asList("position-1", "position-2"))).thenReturn(Arrays.asList( position("position-1", "root-position,parent-position,position-1", "org-1"), position("position-2", "root-position,position-2", "org-2"), null)); when(roleRelationApi.getListByObjectId(org.mockito.ArgumentMatchers.any(RoleRelationModel.class))) .thenReturn(Arrays.asList( role("user-1", "user", "role-user"), role("org-1", "organize", "role-org"), role("org-2", "organize", "role-second-org"), role("position-2", "position", "role-position"), role("unknown", "user", "role-ignored"), role("position-1", "position", " "), null)); List result = resolver.resolve(" tenant-1 ", userIds); assertEquals(2, result.size()); DmsSubjectSet first = result.get(0); assertEquals("user-1", first.getUserId()); assertEquals(set("org-1"), first.getDirectOrgIds()); assertEquals(set("parent-org"), first.getImmediateParentOrgIds()); assertEquals(set("root-org", "parent-org", "org-1"), first.getAncestorOrgIds()); assertEquals(set("position-1"), first.getPositionIds()); assertEquals(set("parent-position"), first.getImmediateParentPositionIds()); assertEquals(set("root-position", "parent-position", "position-1"), first.getAncestorPositionIds()); assertEquals(set("group-1"), first.getPlatformGroupIds()); assertEquals(set("role-user", "role-org"), first.getRoleIds()); assertEquals(set("role-user"), first.getDirectUserRoleIds()); DmsSubjectSet second = result.get(1); assertEquals("user-2", second.getUserId()); assertEquals(set("org-1", "org-2"), second.getDirectOrgIds()); assertEquals(set("parent-org", "root-org"), second.getImmediateParentOrgIds()); assertEquals(set("root-org", "parent-org", "org-1", "org-2"), second.getAncestorOrgIds()); assertEquals(set("position-2"), second.getPositionIds()); assertEquals(set("root-position"), second.getImmediateParentPositionIds()); assertEquals(set("root-position", "position-2"), second.getAncestorPositionIds()); assertEquals(set("role-org", "role-second-org", "role-position"), second.getRoleIds()); assertEquals(Collections.emptySet(), second.getDirectUserRoleIds()); verify(userApi, times(1)).getUserName(userIds); verify(userRelationApi, times(1)).getListByUserIdAll(userIds); verify(organizeApi, times(1)).getListByIds(Arrays.asList("org-1", "org-2")); verify(organizeApi, never()).upWardRecursion(org.mockito.ArgumentMatchers.anyString()); verify(positionApi, times(1)).getListByIds(Arrays.asList("position-1", "position-2")); ArgumentCaptor request = ArgumentCaptor.forClass(RoleRelationModel.class); verify(roleRelationApi, times(1)).getListByObjectId(request.capture()); assertNull(request.getValue().getObjectType()); assertEquals(set("user-1", "org-1", "position-1", "user-2", "org-2", "position-2"), new LinkedHashSet<>(request.getValue().getObjectId())); } @Test void rejectsUsersMissingFromTheRequestedTenantBeforeResolvingRelations() { List userIds = Arrays.asList("user-1", "user-2"); when(userApi.getUserName(userIds)).thenReturn(Arrays.asList( user("user-1", "tenant-1"), user("user-2", "tenant-2"))); DmsPermissionException error = assertThrows(DmsPermissionException.class, () -> resolver.resolve("tenant-1", userIds)); assertEquals(DmsPermissionError.PRINCIPAL_NOT_FOUND, error.getError()); verify(userRelationApi, never()).getListByUserIdAll(anyList()); verify(roleRelationApi, never()).getListByObjectId( org.mockito.ArgumentMatchers.any(RoleRelationModel.class)); } @Test void treatsNullRemoteResultsAsEmptyCollections() { List userIds = Collections.singletonList("user-1"); when(userApi.getUserName(userIds)).thenReturn(Collections.singletonList(user("user-1", "tenant-1"))); when(userRelationApi.getListByUserIdAll(userIds)).thenReturn(null); when(roleRelationApi.getListByObjectId(org.mockito.ArgumentMatchers.any(RoleRelationModel.class))) .thenReturn(null); DmsSubjectSet result = resolver.resolve("tenant-1", userIds).get(0); assertEquals("user-1", result.getUserId()); assertEquals(Collections.emptySet(), result.getDirectOrgIds()); assertEquals(Collections.emptySet(), result.getAncestorOrgIds()); assertEquals(Collections.emptySet(), result.getPositionIds()); assertEquals(Collections.emptySet(), result.getAncestorPositionIds()); assertEquals(Collections.emptySet(), result.getRoleIds()); verify(organizeApi, never()).getListByIds(anyList()); verify(positionApi, never()).getListByIds(anyList()); } @Test void rejectsMissingDirectOrganizationsBeforeResolvingRoles() { List userIds = Collections.singletonList("user-1"); when(userApi.getUserName(userIds)).thenReturn(Collections.singletonList(user("user-1", "tenant-1"))); when(userRelationApi.getListByUserIdAll(userIds)).thenReturn(Collections.singletonList( relation("user-1", "organize", "missing-org"))); when(organizeApi.getListByIds(Collections.singletonList("missing-org"))) .thenReturn(Collections.emptyList()); DmsPermissionException error = assertThrows(DmsPermissionException.class, () -> resolver.resolve("tenant-1", userIds)); assertEquals(DmsPermissionError.PRINCIPAL_NOT_FOUND, error.getError()); verify(organizeApi, times(1)).getListByIds(Collections.singletonList("missing-org")); verify(roleRelationApi, never()).getListByObjectId( org.mockito.ArgumentMatchers.any(RoleRelationModel.class)); } @Test void rejectsMissingDirectPositionsBeforeResolvingRoles() { List userIds = Collections.singletonList("user-1"); when(userApi.getUserName(userIds)).thenReturn(Collections.singletonList(user("user-1", "tenant-1"))); when(userRelationApi.getListByUserIdAll(userIds)).thenReturn(Collections.singletonList( relation("user-1", "position", "missing-position"))); when(positionApi.getListByIds(Collections.singletonList("missing-position"))) .thenReturn(Collections.emptyList()); DmsPermissionException error = assertThrows(DmsPermissionException.class, () -> resolver.resolve("tenant-1", userIds)); assertEquals(DmsPermissionError.PRINCIPAL_NOT_FOUND, error.getError()); verify(positionApi, times(1)).getListByIds(Collections.singletonList("missing-position")); verify(roleRelationApi, never()).getListByObjectId( org.mockito.ArgumentMatchers.any(RoleRelationModel.class)); } @Test void derivesDirectOrganizationFromPositionWhenNoOrganizationRelationExists() { List userIds = Collections.singletonList("user-1"); when(userApi.getUserName(userIds)).thenReturn(Collections.singletonList(user("user-1", "tenant-1"))); when(userRelationApi.getListByUserIdAll(userIds)).thenReturn(Collections.singletonList( relation("user-1", "position", "position-1"))); when(positionApi.getListByIds(Collections.singletonList("position-1"))).thenReturn( Collections.singletonList(position("position-1", "position-root,position-1", "org-derived"))); when(organizeApi.getListByIds(Collections.singletonList("org-derived"))).thenReturn( Collections.singletonList(organization("org-derived", "org-root,org-derived"))); DmsSubjectSet result = resolver.resolve("tenant-1", userIds).get(0); assertEquals(set("org-derived"), result.getDirectOrgIds()); assertEquals(set("org-root", "org-derived"), result.getAncestorOrgIds()); assertEquals(set("position-1"), result.getPositionIds()); verify(positionApi, times(1)).getListByIds(Collections.singletonList("position-1")); verify(organizeApi, times(1)).getListByIds(Collections.singletonList("org-derived")); } @Test void rejectsBlankInputsAsInvalidRequests() { DmsPermissionException tenantError = assertThrows(DmsPermissionException.class, () -> resolver.resolve(" ", Collections.singletonList("user-1"))); DmsPermissionException usersError = assertThrows(DmsPermissionException.class, () -> resolver.resolve("tenant-1", Collections.singletonList(" "))); assertEquals(DmsPermissionError.INVALID_REQUEST, tenantError.getError()); assertEquals(DmsPermissionError.INVALID_REQUEST, usersError.getError()); } private UserEntity user(String id, String tenantId) { UserEntity result = new UserEntity(); result.setId(id); result.setTenantId(tenantId); return result; } private UserRelationEntity relation(String userId, String objectType, String objectId) { UserRelationEntity result = new UserRelationEntity(); result.setUserId(userId); result.setObjectType(objectType); result.setObjectId(objectId); return result; } private OrganizeEntity organization(String id, String organizeIdTree) { OrganizeEntity result = new OrganizeEntity(); result.setId(id); result.setOrganizeIdTree(organizeIdTree); return result; } private PositionEntity position(String id, String positionIdTree, String organizationId) { PositionEntity result = new PositionEntity(); result.setId(id); result.setPositionIdTree(positionIdTree); result.setOrganizeId(organizationId); return result; } private RoleRelationEntity role(String objectId, String objectType, String roleId) { RoleRelationEntity result = new RoleRelationEntity(); result.setObjectId(objectId); result.setObjectType(objectType); result.setRoleId(roleId); return result; } private LinkedHashSet set(String... values) { return new LinkedHashSet<>(Arrays.asList(values)); } }