/* * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein * Staatskanzlei * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung * * Lizenziert unter der EUPL, Version 1.2 oder - sobald * diese von der Europäischen Kommission genehmigt wurden - * Folgeversionen der EUPL ("Lizenz"); * Sie dürfen dieses Werk ausschließlich gemäß * dieser Lizenz nutzen. * Eine Kopie der Lizenz finden Sie hier: * * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 * * Sofern nicht durch anwendbare Rechtsvorschriften * gefordert oder in schriftlicher Form vereinbart, wird * die unter der Lizenz verbreitete Software "so wie sie * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - * ausdrücklich oder stillschweigend - verbreitet. * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ package de.ozgcloud.user; import static org.assertj.core.api.Assertions.*; 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; 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.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; class UserResourceMapperTest { static final String ORGANISATIONS_EINHEIT_ID_KEY = "organisationseinheitId"; static final String ORGANISATIONS_EINHEIT_ID_1 = "0815"; static final String ORGANISATIONS_EINHEIT_ID_2 = "4711"; static final String GROUP_1_PATH = "/group1"; static final String GROUP_2_PATH = "/group2"; static final String GROUP_3_PATH = "/group3"; @Spy @InjectMocks UserResourceMapper mapper = Mappers.getMapper(UserResourceMapper.class); @Mock KeycloakApiProperties properties; @Mock RealmResource realm; final Set<String> organisationsEinheitIds = Set.of(ORGANISATIONS_EINHEIT_ID_1); @DisplayName("To kop user") @Nested class TestToKopUser { @BeforeEach void init() { when(properties.ldapIdKey()).thenReturn("LDAP_ID"); when(properties.client()).thenReturn("alfa"); doReturn(organisationsEinheitIds).when(mapper).mapOrganisationsEinheitIds(any()); } @Test void shouldMapToUser() { var user = toKopUser(); assertThat(user).isNotNull(); } @Test void shouldMapEmail() { var user = toKopUser(); assertThat(user.getEmail()).isEqualTo(UserRepresentationTestFactory.EMAIL); } @DisplayName("externalId") @Nested class TestMapExternalId { @Test void shouldMap() { var user = toKopUser(); assertThat(user.getExternalId()).isEqualTo(UserRepresentationTestFactory.EXTERNAL_ID); } @Test void shouldMapFallbackOnEmptyAttributes() { var user = toKopUser(UserResourceTestFactory.createWithAttributes(Collections.emptyMap())); assertThat(user.getExternalId()).isEqualTo(UserRepresentationTestFactory.EXTERNAL_ID_FALLBACK); } } @Test void shouldMapFirstName() { var user = toKopUser(); assertThat(user.getFirstName()).isEqualTo(UserRepresentationTestFactory.FIRST_NAME); } @Test void shouldMapLastName() { var user = toKopUser(); assertThat(user.getLastName()).isEqualTo(UserRepresentationTestFactory.LAST_NAME); } @Test void shouldMapUserName() { var user = toKopUser(); assertThat(user.getUsername()).isEqualTo(UserRepresentationTestFactory.USER_NAME); } @Test void shouldMapOrganisationsEinheitIds() { var result = toKopUser(); assertThat(result.getOrganisationsEinheitIds()).hasSameElementsAs(organisationsEinheitIds); } @Test void shouldMapRoles() { var user = toKopUser(); assertThat(user.getRoles()).isNotEmpty().contains(UserRepresentationTestFactory.ROLE_NAME); } @Test void shouldMapKeycloakUserId() { var user = toKopUser(); assertThat(user.getKeycloakUserId()).isEqualTo(UserRepresentationTestFactory.EXTERNAL_ID_FALLBACK); } @Test void shouldMapFullName() { var user = toKopUser(); assertThat(user.getFullName()).isEqualTo(UserRepresentationTestFactory.FIRST_NAME + " " + UserRepresentationTestFactory.LAST_NAME); } @Test void shouldMapFullNameReversed() { var user = toKopUser(); assertThat(user.getFullNameReversed()).isEqualTo(UserRepresentationTestFactory.LAST_NAME + " " + UserRepresentationTestFactory.FIRST_NAME); } private User toKopUser() { return toKopUser(UserResourceTestFactory.create()); } private User toKopUser(UserResource userResource) { return mapper.toKopUser(userResource); } } @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); private final GroupRepresentation group3 = GroupRepresentationTestFactory.createWithPathAndAttributes( GROUP_3_PATH, Map.of()); @BeforeEach void beforeEach() { when(properties.organisationsEinheitIdKey()).thenReturn(ORGANISATIONS_EINHEIT_ID_KEY); } @DisplayName("should map no organisations einheit id if group has none") @Test void shouldMapNoOrganisationsEinheitIdIfGroupHasNone() { when(realm.getGroupByPath(GROUP_3_PATH)).thenReturn(group3); var userResource = UserResourceTestFactory.createWithGroups(group3); var result = mapper.mapOrganisationsEinheitIds(userResource); assertThat(result).isEmpty(); } @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, group3); when(realm.getGroupByPath(GROUP_1_PATH)).thenReturn(group1); when(realm.getGroupByPath(GROUP_2_PATH)).thenReturn(group2); when(realm.getGroupByPath(GROUP_3_PATH)).thenReturn(group3); 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 { @Mock UserResource userResource; @Mock RoleMappingResource roleMappingResource; @Mock MappingsRepresentation mappingsRepresentation; @Mock Map<String, ClientMappingsRepresentation> clientMappingsRepresentation; @Mock ClientMappingsRepresentation clientMappingRepresentation; @BeforeEach void init() { when(userResource.roles()).thenReturn(roleMappingResource); when(roleMappingResource.getAll()).thenReturn(mappingsRepresentation); } @DisplayName("on existing roles") @Nested class TestOnAssignedRoles { @BeforeEach void init() { when(properties.client()).thenReturn(UserRepresentationTestFactory.CLIENT_KEY); when(mappingsRepresentation.getClientMappings()).thenReturn(clientMappingsRepresentation); when(clientMappingsRepresentation.containsKey(UserRepresentationTestFactory.CLIENT_KEY)).thenReturn(true); when(clientMappingsRepresentation.get(UserRepresentationTestFactory.CLIENT_KEY)).thenReturn(clientMappingRepresentation); when(clientMappingRepresentation.getMappings()).thenReturn(List.of(createRoleRepresentation())); } private RoleRepresentation createRoleRepresentation() { var roleRepresentation = new RoleRepresentation(); roleRepresentation.setName(UserRepresentationTestFactory.ROLE_NAME); return roleRepresentation; } @Test void shouldReturnRolesIfExists() { var roles = mapper.mapRoles(userResource); assertThat(roles).isNotEmpty(); assertThat(roles.get(0)).isEqualTo(UserRepresentationTestFactory.ROLE_NAME); } } @Nested class TestOnNonExistingClient { @BeforeEach void init() { when(properties.client()).thenReturn(UserRepresentationTestFactory.CLIENT_KEY); when(mappingsRepresentation.getClientMappings()).thenReturn(Collections.emptyMap()); } @Test void shouldReturnEmptyListIfNoRolesAttached() { var roles = mapper.mapRoles(userResource); assertThat(roles).isEmpty(); } } @Nested class TestNullClientMappings { @BeforeEach void init() { when(mappingsRepresentation.getClientMappings()).thenReturn(null); } @Test void shouldReturnEmptyListIfNoRolesAttached() { var roles = mapper.mapRoles(userResource); assertThat(roles).isEmpty(); } } } }