diff --git a/src/main/java/de/itvsh/kop/user/UserResourceMapper.java b/src/main/java/de/itvsh/kop/user/UserResourceMapper.java index 82f9c22b2d2af9b497bbc17ee19433ee52b32525..fa1bc9b91404c371605623a97412eb18173667ca 100644 --- a/src/main/java/de/itvsh/kop/user/UserResourceMapper.java +++ b/src/main/java/de/itvsh/kop/user/UserResourceMapper.java @@ -1,16 +1,19 @@ package de.itvsh.kop.user; -import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import javax.inject.Inject; +import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.UserResource; import org.keycloak.representations.idm.ClientMappingsRepresentation; +import org.keycloak.representations.idm.GroupRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -24,6 +27,9 @@ public abstract class UserResourceMapper { @Inject KeycloakApiProperties properties; + @Inject + RealmResource realm; + @Mapping(target = "createdAt", expression = "java(mapCreatedAt(userRes))") @Mapping(target = "email", expression = "java(mapEmail(userRes))") @Mapping(target = "firstName", expression = "java(mapFirstName(userRes))") @@ -42,13 +48,23 @@ public abstract class UserResourceMapper { return createdAt != null ? new Date(createdAt) : new Date(); } - List<String> mapOrganisationsEinheitIds(UserResource userRes) { - return getOrganisationsEinheitIdsFromUserAttributes(userRes); + Set<String> mapOrganisationsEinheitIds(UserResource userRes) { + var groups = userRes.groups(); + var organisationsEinheitIds = getOrganisationsEinheitIdsFromGroups(groups); + return new HashSet<>(organisationsEinheitIds); } - private List<String> getOrganisationsEinheitIdsFromUserAttributes(UserResource userResource) { - var attributes = userResource.toRepresentation().getAttributes(); - return attributes != null ? attributes.get(properties.organisationsEinheitIdKey()) : new ArrayList<>(); + private List<String> getOrganisationsEinheitIdsFromGroups(List<GroupRepresentation> groups) { + return groups.stream() + .map(group -> { + var groupFromRealm = realm.getGroupByPath(group.getPath()); + return groupFromRealm != null ? groupFromRealm.getAttributes() : null; + }) + .filter(Objects::nonNull) + .map(attributeMap -> attributeMap.get(properties.organisationsEinheitIdKey())) + .filter(Objects::nonNull) + .map(attributeValues -> attributeValues.get(0)) + .toList(); } List<String> mapRoles(UserResource userRes) { diff --git a/src/test/java/de/itvsh/kop/user/GroupRepresentationTestFactory.java b/src/test/java/de/itvsh/kop/user/GroupRepresentationTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..7d1dfadb544dabc643658d869ec769b27ae0d695 --- /dev/null +++ b/src/test/java/de/itvsh/kop/user/GroupRepresentationTestFactory.java @@ -0,0 +1,23 @@ +package de.itvsh.kop.user; + +import java.util.List; +import java.util.Map; + +import org.keycloak.representations.idm.GroupRepresentation; + +class GroupRepresentationTestFactory { + static final GroupRepresentation createGroup(String path) { + var group = new GroupRepresentation(); + group.setPath(path); + return group; + } + + public static GroupRepresentation createByPathAndOrganisationEinheitId(String groupPath, String organisationEinheitId) { + var groupRepresentation = new GroupRepresentation(); + groupRepresentation.setName(groupPath); + groupRepresentation.setPath(groupPath); + groupRepresentation.setAttributes(Map.of(UserResourceMapperTest.ORGANISATIONS_EINHEIT_ID_KEY, + List.of(organisationEinheitId))); + return groupRepresentation; + } +} diff --git a/src/test/java/de/itvsh/kop/user/StubUserResource.java b/src/test/java/de/itvsh/kop/user/StubUserResource.java index da5decc3b8706ae4e4a1e340bcefd5877f5f7e8f..3e21ac946e9ef29cfcaa0b932c552c2f4761454a 100644 --- a/src/test/java/de/itvsh/kop/user/StubUserResource.java +++ b/src/test/java/de/itvsh/kop/user/StubUserResource.java @@ -22,11 +22,16 @@ import lombok.NoArgsConstructor; @NoArgsConstructor class StubUserResource implements UserResource { private UserRepresentation userRepresentation = UserRepresentationTestFactory.create(); + private List<GroupRepresentation> groups = List.of(GroupRepresentationTestFactory.createGroup(UserResourceMapperTest.GROUP_1_PATH)); public StubUserResource(Map<String, List<String>> attributes) { userRepresentation = UserRepresentationTestFactory.createWithAttributes(attributes); } + public StubUserResource(List<GroupRepresentation> groups) { + this.groups = groups; + } + @Override public UserRepresentation toRepresentation() { return userRepresentation; @@ -44,13 +49,7 @@ class StubUserResource implements UserResource { @Override public List<GroupRepresentation> groups() { - return List.of(createGroup()); - } - - private GroupRepresentation createGroup() { - var group = new GroupRepresentation(); - group.setAttributes(UserRepresentationTestFactory.ATTRIBUTES); - return group; + return groups; } @Override diff --git a/src/test/java/de/itvsh/kop/user/UserRepresentationTestFactory.java b/src/test/java/de/itvsh/kop/user/UserRepresentationTestFactory.java index 7cf0e921d65abccb661e761c2e569867ddafee87..d13f4031e36b987a7bd4ec4999d02a7a60c2c9b2 100644 --- a/src/test/java/de/itvsh/kop/user/UserRepresentationTestFactory.java +++ b/src/test/java/de/itvsh/kop/user/UserRepresentationTestFactory.java @@ -24,12 +24,7 @@ public class UserRepresentationTestFactory { static final String ORGANSISATIONS_EINHEIT_ID = "0815"; private static final String LDAP_ID_KEY = "LDAP_ID"; - private static final String ORGANISATIONS_EINHEIT_ID_KEY = "organisationseinheitId"; - - // CHECKME: Wie verhaelt es sich, wenn nur ein Wert kommt? - static final Map<String, List<String>> ATTRIBUTES = Map.of( - LDAP_ID_KEY, List.of(EXTERNAL_ID), - ORGANISATIONS_EINHEIT_ID_KEY, List.of(ORGANSISATIONS_EINHEIT_ID)); + static final Map<String, List<String>> ATTRIBUTES = Map.of(LDAP_ID_KEY, List.of(EXTERNAL_ID)); private static final String CLIENT_KEY = "sh-kiel-dev-goofy"; private static final Map<String, List<String>> CLIENT_ROLED = Map.of(CLIENT_KEY, List.of(ROLE)); diff --git a/src/test/java/de/itvsh/kop/user/UserResourceMapperTest.java b/src/test/java/de/itvsh/kop/user/UserResourceMapperTest.java index ed09c68d2dd46b470072c76cc03344a865c3f94a..1c49206c0d7c83763f87b27849d66eb052b2b86e 100644 --- a/src/test/java/de/itvsh/kop/user/UserResourceMapperTest.java +++ b/src/test/java/de/itvsh/kop/user/UserResourceMapperTest.java @@ -3,11 +3,14 @@ package de.itvsh.kop.user; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import java.util.List; import java.util.Map; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.representations.idm.GroupRepresentation; import org.mapstruct.factory.Mappers; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -15,12 +18,24 @@ import org.mockito.Mock; import de.itvsh.kop.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 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)); + @InjectMocks private UserResourceMapper mapper = Mappers.getMapper(UserResourceMapper.class); @Mock private KeycloakApiProperties apiProperties; + @Mock + private RealmResource realm; + @Nested class TestMapping { @@ -29,6 +44,8 @@ class UserResourceMapperTest { when(apiProperties.ldapIdKey()).thenReturn("LDAP_ID"); when(apiProperties.organisationsEinheitIdKey()).thenReturn("organisationseinheitId"); when(apiProperties.client()).thenReturn("sh-kiel-dev-goofy"); + when(realm.getGroupByPath(GROUP_1_PATH)) + .thenReturn(GroupRepresentationTestFactory.createByPathAndOrganisationEinheitId(GROUP_1_PATH, ORGANISATIONS_EINHEIT_ID_1)); } @Test @@ -84,7 +101,21 @@ class UserResourceMapperTest { void shouldMapOrganisationsEinheitIds() { User user = mapper.toKopUser(UserResourceTestFactory.create()); - assertThat(user.getOrganisationsEinheitIds()).isNotEmpty().contains(UserRepresentationTestFactory.ORGANSISATIONS_EINHEIT_ID); + assertThat(user.getOrganisationsEinheitIds()).isNotEmpty().contains(ORGANISATIONS_EINHEIT_ID_1); + } + + @Test + void shouldMapMultipleOrganisationsEinheitIds() { + GroupRepresentation groupRepresentation = GroupRepresentationTestFactory.createByPathAndOrganisationEinheitId(GROUP_2_PATH, + ORGANISATIONS_EINHEIT_ID_2); + + when(realm.getGroupByPath(GROUP_2_PATH)).thenReturn(groupRepresentation); + + User user = mapper.toKopUser( + UserResourceTestFactory.createWithGroups(List.of(GroupRepresentationTestFactory.createGroup(UserResourceMapperTest.GROUP_1_PATH), + GroupRepresentationTestFactory.createGroup(UserResourceMapperTest.GROUP_2_PATH)))); + + assertThat(user.getOrganisationsEinheitIds()).isNotEmpty().hasSize(2).contains(ORGANISATIONS_EINHEIT_ID_2); } @Test diff --git a/src/test/java/de/itvsh/kop/user/UserResourceTestFactory.java b/src/test/java/de/itvsh/kop/user/UserResourceTestFactory.java index 36d9ac59617a40034f4d0fdf026b826c53849874..6330d09473b026a84a2b6c55fd8b26a46dcf9a3d 100644 --- a/src/test/java/de/itvsh/kop/user/UserResourceTestFactory.java +++ b/src/test/java/de/itvsh/kop/user/UserResourceTestFactory.java @@ -4,15 +4,19 @@ import java.util.List; import java.util.Map; import org.keycloak.admin.client.resource.UserResource; +import org.keycloak.representations.idm.GroupRepresentation; public class UserResourceTestFactory { public static UserResource create() { - return new StubUserResource(); } public static UserResource createWithAttributes(Map<String, List<String>> attributes) { return new StubUserResource(attributes); } + + public static UserResource createWithGroups(List<GroupRepresentation> groups) { + return new StubUserResource(groups); + } }