diff --git a/user-manager-server/src/main/java/de/ozgcloud/user/UserResourceMapper.java b/user-manager-server/src/main/java/de/ozgcloud/user/UserResourceMapper.java index 52f53b25185c18d5c163bdb4ff695a0adc353266..f9f2486ea48654c5493876af69f760f9b1367daf 100644 --- a/user-manager-server/src/main/java/de/ozgcloud/user/UserResourceMapper.java +++ b/user-manager-server/src/main/java/de/ozgcloud/user/UserResourceMapper.java @@ -23,18 +23,20 @@ */ package de.ozgcloud.user; +import java.util.Collection; import java.util.Collections; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; import jakarta.inject.Inject; +import org.apache.commons.lang3.StringUtils; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.UserResource; import org.keycloak.representations.idm.ClientMappingsRepresentation; @@ -78,18 +80,27 @@ public abstract class UserResourceMapper { Set<String> mapOrganisationsEinheitIds(UserResource userRes) { var groups = userRes.groups(); - var organisationsEinheitIds = getOrganisationsEinheitIdsFromGroups(groups); - return new HashSet<>(organisationsEinheitIds); + return Stream.concat( + getOrganisationsEinheitIdsFromGroups(groups), + getOrganisationsEinheitIdsFromUser(userRes) + ) + .filter(StringUtils::isNotBlank) + .collect(Collectors.toSet()); } - private List<String> getOrganisationsEinheitIdsFromGroups(List<GroupRepresentation> groups) { + private Stream<String> getOrganisationsEinheitIdsFromGroups(List<GroupRepresentation> groups) { return groups.stream() .map(this::mapGroup) .filter(Objects::nonNull) .map(attributeMap -> attributeMap.get(properties.organisationsEinheitIdKey())) - .filter(Objects::nonNull) - .map(attributeValues -> attributeValues.get(0)) - .toList(); + .flatMap(Collection::stream); + } + + private Stream<String> getOrganisationsEinheitIdsFromUser(UserResource userRes) { + return getUserAttributes(userRes) + .map(attributes -> attributes.get(properties.organisationsEinheitIdKey())) + .orElse(Collections.emptyList()) + .stream(); } private Map<String, List<String>> mapGroup(GroupRepresentation group) { @@ -113,7 +124,7 @@ public abstract class UserResourceMapper { return Optional.ofNullable(userRepresentation.getAttributes()) .map(attributes -> attributes.get(properties.ldapIdKey())) - .map(id -> id.get(0)) + .map(List::getFirst) .orElseGet(userRepresentation::getId); } @@ -147,4 +158,8 @@ public abstract class UserResourceMapper { return String.join(" ", Stream.of(userRes.toRepresentation().getLastName(), userRes.toRepresentation().getFirstName()) .filter(Objects::nonNull).toArray(String[]::new)); } + + private Optional<Map<String, List<String>>> getUserAttributes(UserResource userResource) { + return Optional.ofNullable(userResource.toRepresentation().getAttributes()); + } } diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/GroupRepresentationTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/GroupRepresentationTestFactory.java index fcc0dd786ad938ab75905d6b23e6efbde16cb725..ef6f392a0ca35993bd50422df19a42ac3a69367b 100644 --- a/user-manager-server/src/test/java/de/ozgcloud/user/GroupRepresentationTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/GroupRepresentationTestFactory.java @@ -35,12 +35,12 @@ class GroupRepresentationTestFactory { return group; } - public static GroupRepresentation createByPathAndOrganisationEinheitId(String groupPath, String organisationEinheitId) { + public static GroupRepresentation createByPathAndOrganisationEinheitIds(String groupPath, String... organisationEinheitIds) { var groupRepresentation = new GroupRepresentation(); groupRepresentation.setName(groupPath); groupRepresentation.setPath(groupPath); groupRepresentation.setAttributes(Map.of(UserResourceMapperTest.ORGANISATIONS_EINHEIT_ID_KEY, - List.of(organisationEinheitId))); + List.of(organisationEinheitIds))); return groupRepresentation; } } diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceMapperTest.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceMapperTest.java index d50c9ee0fca676dfa08335cc4d7fc16ff3f8c519..effcd75641189d1acd52922498cabd394175d55f 100644 --- a/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceMapperTest.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceMapperTest.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.*; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -36,14 +37,15 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.RoleMappingResource; -import org.keycloak.admin.client.resource.RoleScopeResource; import org.keycloak.admin.client.resource.UserResource; import org.keycloak.representations.idm.ClientMappingsRepresentation; +import org.keycloak.representations.idm.GroupRepresentation; import org.keycloak.representations.idm.MappingsRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.mapstruct.factory.Mappers; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; import de.ozgcloud.user.keycloak.KeycloakApiProperties; @@ -55,9 +57,7 @@ class UserResourceMapperTest { static final String GROUP_1_PATH = "/group1"; static final String GROUP_2_PATH = "/group2"; - static final Map<String, List<String>> ATTRIBUTES_1 = Map.of(ORGANISATIONS_EINHEIT_ID_KEY, List.of(ORGANISATIONS_EINHEIT_ID_1)); - static final Map<String, List<String>> ATTRIBUTES_2 = Map.of(ORGANISATIONS_EINHEIT_ID_KEY, List.of(ORGANISATIONS_EINHEIT_ID_2)); - + @Spy @InjectMocks UserResourceMapper mapper = Mappers.getMapper(UserResourceMapper.class); @@ -67,6 +67,8 @@ class UserResourceMapperTest { @Mock RealmResource realm; + final Set<String> organisationsEinheitIds = Set.of(ORGANISATIONS_EINHEIT_ID_1); + @DisplayName("To kop user") @Nested class TestToKopUser { @@ -74,13 +76,8 @@ class UserResourceMapperTest { @BeforeEach void init() { when(properties.ldapIdKey()).thenReturn("LDAP_ID"); - when(properties.organisationsEinheitIdKey()).thenReturn("organisationseinheitId"); - when(properties.client()).thenReturn("alfa"); - when(realm.getGroupByPath(GROUP_1_PATH)) - .thenReturn(GroupRepresentationTestFactory.createByPathAndOrganisationEinheitId(GROUP_1_PATH, ORGANISATIONS_EINHEIT_ID_1)); - when(properties.ldapIdKey()).thenReturn("LDAP_ID"); - when(properties.organisationsEinheitIdKey()).thenReturn("organisationseinheitId"); when(properties.client()).thenReturn("alfa"); + doReturn(organisationsEinheitIds).when(mapper).mapOrganisationsEinheitIds(any()); } @Test @@ -139,26 +136,9 @@ class UserResourceMapperTest { @Test void shouldMapOrganisationsEinheitIds() { - var user = toKopUser(); + var result = toKopUser(); - assertThat(user.getOrganisationsEinheitIds()).isNotEmpty().contains(ORGANISATIONS_EINHEIT_ID_1); - } - - @Test - void shouldMapMultipleOrganisationsEinheitIds() { - var groupRepresentation = GroupRepresentationTestFactory.createByPathAndOrganisationEinheitId(GROUP_2_PATH, - ORGANISATIONS_EINHEIT_ID_2); - when(realm.getGroupByPath(GROUP_2_PATH)).thenReturn(groupRepresentation); - - var user = toKopUser(buildUserResourceWithGroups()); - - assertThat(user.getOrganisationsEinheitIds()).isNotEmpty().hasSize(2).contains(ORGANISATIONS_EINHEIT_ID_2); - } - - private UserResource buildUserResourceWithGroups() { - return UserResourceTestFactory.createWithGroups(List.of( - GroupRepresentationTestFactory.createGroup(UserResourceMapperTest.GROUP_1_PATH), - GroupRepresentationTestFactory.createGroup(UserResourceMapperTest.GROUP_2_PATH))); + assertThat(result.getOrganisationsEinheitIds()).hasSameElementsAs(organisationsEinheitIds); } @Test @@ -198,6 +178,65 @@ class UserResourceMapperTest { } } + @DisplayName("Map organisations einheit ids") + @Nested + class TestMapOrganisationsEinheitIds { + static final String ORGANISATIONS_EINHEIT_ID_3 = "6287"; + private final GroupRepresentation group1 = GroupRepresentationTestFactory.createByPathAndOrganisationEinheitIds( + GROUP_1_PATH, ORGANISATIONS_EINHEIT_ID_1, ORGANISATIONS_EINHEIT_ID_3); + private final GroupRepresentation group2 = GroupRepresentationTestFactory.createByPathAndOrganisationEinheitIds( + GROUP_2_PATH, ORGANISATIONS_EINHEIT_ID_2); + + @BeforeEach + void beforeEach() { + when(properties.organisationsEinheitIdKey()).thenReturn(ORGANISATIONS_EINHEIT_ID_KEY); + } + + @Test + void shouldMapOrganisationsEinheitIdsFromSingleGroup() { + var userResource = UserResourceTestFactory.createWithGroups(group1); + when(realm.getGroupByPath(GROUP_1_PATH)).thenReturn(group1); + + var result = mapper.mapOrganisationsEinheitIds(userResource); + + assertThat(result).containsExactlyInAnyOrder(ORGANISATIONS_EINHEIT_ID_1, ORGANISATIONS_EINHEIT_ID_3); + } + + @Test + void shouldMapOrganisationsEinheitIdsFromGroups() { + var userResource = UserResourceTestFactory.createWithGroups(group1, group2); + when(realm.getGroupByPath(GROUP_1_PATH)).thenReturn(group1); + when(realm.getGroupByPath(GROUP_2_PATH)).thenReturn(group2); + + var result = mapper.mapOrganisationsEinheitIds(userResource); + + assertThat(result).containsExactlyInAnyOrder( + ORGANISATIONS_EINHEIT_ID_1, + ORGANISATIONS_EINHEIT_ID_2, + ORGANISATIONS_EINHEIT_ID_3 + ); + } + + @Test + void shouldMapOrganisationsEinheitIdsFromUser() { + var attributes = Map.of(ORGANISATIONS_EINHEIT_ID_KEY, List.of(ORGANISATIONS_EINHEIT_ID_1, ORGANISATIONS_EINHEIT_ID_2)); + var userResource = UserResourceTestFactory.createWithAttributes(attributes); + + var result = mapper.mapOrganisationsEinheitIds(userResource); + + assertThat(result).containsExactlyInAnyOrder(ORGANISATIONS_EINHEIT_ID_1, ORGANISATIONS_EINHEIT_ID_2); + } + + @Test + void shouldReturnEmptyIfNoOrganisationsEinheitIds() { + var userResource = UserResourceTestFactory.create(); + + var result = mapper.mapOrganisationsEinheitIds(userResource); + + assertThat(result).isEmpty(); + } + } + @DisplayName("Get client roles") @Nested class TestGetClientRoles { @@ -208,8 +247,6 @@ class UserResourceMapperTest { @Mock RoleMappingResource roleMappingResource; @Mock - RoleScopeResource roleScopeResource; - @Mock MappingsRepresentation mappingsRepresentation; @Mock Map<String, ClientMappingsRepresentation> clientMappingsRepresentation; diff --git a/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceTestFactory.java b/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceTestFactory.java index 8de656cf0a2c8641d95ee03c699effe298d21937..2f13398abda21539fa80efbe44034aa99447ab38 100644 --- a/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceTestFactory.java +++ b/user-manager-server/src/test/java/de/ozgcloud/user/UserResourceTestFactory.java @@ -39,7 +39,7 @@ public class UserResourceTestFactory { return new UserResourceStub(attributes); } - public static UserResource createWithGroups(List<GroupRepresentation> groups) { - return new UserResourceStub(groups); + public static UserResource createWithGroups(GroupRepresentation... groups) { + return new UserResourceStub(List.of(groups)); } }