diff --git a/src/main/java/de/ozgcloud/admin/keycloak/Group.java b/src/main/java/de/ozgcloud/admin/keycloak/Group.java index 6c8f960a8312f4d23dad4bd29333a8300fe17dcb..4234dff31e43fcc0610ffb052d0c4837ed63b3c4 100644 --- a/src/main/java/de/ozgcloud/admin/keycloak/Group.java +++ b/src/main/java/de/ozgcloud/admin/keycloak/Group.java @@ -11,5 +11,5 @@ public class Group { private String name; private String organisationsEinheitId; - private List<Group> subgroups; + private List<Group> subGroups; } diff --git a/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java b/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java index a36e5cdb894fc90dd6c3f398d6d1df300e61bbe5..6a8b49969152c9ab293019448f7394ad4bae167e 100644 --- a/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java +++ b/src/main/java/de/ozgcloud/admin/keycloak/GroupMapper.java @@ -8,15 +8,31 @@ import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.NullValueCheckStrategy; +import lombok.extern.log4j.Log4j2; + @Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) -interface GroupMapper { +@Log4j2 +abstract class GroupMapper { + + static final String ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE = "organisationseinheitId"; - List<Group> fromGroupRepresentations(List<GroupRepresentation> groupRepresentations); + public abstract List<Group> fromGroupRepresentations(List<GroupRepresentation> groupRepresentations); @Mapping(target = "organisationsEinheitId", source = "attributes") - Group fromGroupRepresentation(GroupRepresentation groupRepresentation); + @Mapping(target = "subGroups", expression = "java(new ArrayList<Group>())") + abstract Group fromGroupRepresentation(GroupRepresentation groupRepresentation); - default String getOrganisationsEinheitId(Map<String, List<String>> attributes) { - return "dummy"; + String getOrganisationsEinheitId(Map<String, List<String>> attributes) { + if (attributes == null) { + return null; + } + var values = attributes.get(ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE); + if (values == null) { + return null; + } + if (values.size() > 1 && values.stream().distinct().count() > 1) { + log.warn("Group contains multiple values for {}. The first one is taken.", ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE); + } + return values.getFirst(); } } diff --git a/src/test/java/de/ozgcloud/admin/keycloak/GroupMapperTest.java b/src/test/java/de/ozgcloud/admin/keycloak/GroupMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e5389ed148ab2a1c47923746ba6fb05b06b88b59 --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/keycloak/GroupMapperTest.java @@ -0,0 +1,130 @@ +package de.ozgcloud.admin.keycloak; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.keycloak.representations.idm.GroupRepresentation; +import org.mapstruct.factory.Mappers; +import org.mockito.Spy; + +class GroupMapperTest { + + @Spy + private final GroupMapper mapper = Mappers.getMapper(GroupMapper.class); + + @Nested + class TestGetOrganisationsEinheitId { + + @Test + void shouldReturnNullIfAttributesAreNull() { + var result = mapper.getOrganisationsEinheitId(null); + + assertThat(result).isNull(); + } + + @Test + void shouldReturnNullIfAttributeIsAbsent() { + var result = mapper.getOrganisationsEinheitId(Map.of("dummy-attribute", List.of("123"))); + + assertThat(result).isNull(); + } + + @Test + void shouldReturnOrganisationsEinheitId() { + var value = GroupRepresentationTestFactory.ORGANISATIONS_EINHEIT_ID; + var result = mapper.getOrganisationsEinheitId(Map.of(GroupMapper.ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE, List.of(value))); + + assertThat(result).isEqualTo(value); + } + + @Test + void shouldReturnFirstValueIfMultipleAreAvailable() { + var value = GroupRepresentationTestFactory.ORGANISATIONS_EINHEIT_ID; + var value2 = UUID.randomUUID().toString(); + + var result = mapper.getOrganisationsEinheitId(Map.of(GroupMapper.ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE, List.of(value, value2))); + + assertThat(result).isEqualTo(value); + } + } + + @Nested + class TestFromGroupRepresentation { + + private final GroupRepresentation groupRepresentation = GroupRepresentationTestFactory.create(); + + @BeforeEach + void init() { + doReturn(GroupRepresentationTestFactory.ORGANISATIONS_EINHEIT_ID).when(mapper).getOrganisationsEinheitId(groupRepresentation.getAttributes()); + } + + @Test + void shouldGetOrganisationsEinheitId() { + callMapper(); + + verify(mapper).getOrganisationsEinheitId(groupRepresentation.getAttributes()); + } + + @Test + void shouldSetOrganisationsEinheitId() { + var group = callMapper(); + + assertThat(group.getOrganisationsEinheitId()).isEqualTo(GroupRepresentationTestFactory.ORGANISATIONS_EINHEIT_ID); + } + + @Test + void shouldSetName() { + var group = callMapper(); + + assertThat(group.getName()).isEqualTo(GroupRepresentationTestFactory.NAME); + } + + @Test + void shouldSetSubGroupsToEmptyList() { + var group = callMapper(); + + assertThat(group.getSubGroups()).isEmpty(); + } + + private Group callMapper() { + return mapper.fromGroupRepresentation(groupRepresentation); + } + } + + @Nested + class TestFromGroupRepresentations { + + private GroupRepresentation groupRepresentation = GroupRepresentationTestFactory.create(); + private Group group = GroupTestFactory.createWithEmptySubGroups(); + + @BeforeEach + void init() { + doReturn(group).when(mapper).fromGroupRepresentation(groupRepresentation); + } + + @Test + void shouldMapFromGroupRepresentation() { + callMapper(); + + verify(mapper).fromGroupRepresentation(groupRepresentation); + } + + @Test + void shouldReturnListWithGroupRepresentation() { + var groups = callMapper(); + + assertThat(groups).containsExactly(group); + } + + private List<Group> callMapper() { + return mapper.fromGroupRepresentations(List.of(groupRepresentation)); + } + } +} diff --git a/src/test/java/de/ozgcloud/admin/keycloak/GroupRepresentationTestFactory.java b/src/test/java/de/ozgcloud/admin/keycloak/GroupRepresentationTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..9d9df97ae5f7ff97d6de6b611a8d54e0b127ca37 --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/keycloak/GroupRepresentationTestFactory.java @@ -0,0 +1,20 @@ +package de.ozgcloud.admin.keycloak; + +import java.util.UUID; + +import org.keycloak.representations.idm.GroupRepresentation; + +import com.thedeanda.lorem.LoremIpsum; + +class GroupRepresentationTestFactory { + + public static final String NAME = LoremIpsum.getInstance().getName(); + public static final String ORGANISATIONS_EINHEIT_ID = UUID.randomUUID().toString(); + + public static GroupRepresentation create() { + var groupRepresentation = new GroupRepresentation() + .singleAttribute(GroupMapper.ORGANIZATIONS_EINHEIT_ID_ATTRIBUTE, ORGANISATIONS_EINHEIT_ID); + groupRepresentation.setName(NAME); + return groupRepresentation; + } +} diff --git a/src/test/java/de/ozgcloud/admin/keycloak/GroupTestFactory.java b/src/test/java/de/ozgcloud/admin/keycloak/GroupTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..bd8413d09ccb283c1676331d643e6e914e556626 --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/keycloak/GroupTestFactory.java @@ -0,0 +1,30 @@ +package de.ozgcloud.admin.keycloak; + +import java.util.List; +import java.util.UUID; + +import com.thedeanda.lorem.LoremIpsum; + +class GroupTestFactory { + + public static final String NAME = GroupRepresentationTestFactory.NAME; + public static final String ORGANISATIONS_EINHEIT_ID = GroupRepresentationTestFactory.ORGANISATIONS_EINHEIT_ID; + + public static final String SUB_GROUP_NAME = LoremIpsum.getInstance().getName(); + public static final String SUB_GROUP_ORGANISATIONS_EINHEIT_ID = UUID.randomUUID().toString(); + + public static Group create() { + return createBuilder().build(); + } + + public static Group createWithEmptySubGroups() { + return createBuilder().subGroups(List.of()).build(); + } + + public static Group.GroupBuilder createBuilder() { + return new Group.GroupBuilder() + .name(NAME) + .organisationsEinheitId(ORGANISATIONS_EINHEIT_ID) + .subGroups(List.of(Group.builder().name(SUB_GROUP_NAME).organisationsEinheitId(SUB_GROUP_ORGANISATIONS_EINHEIT_ID).build())); + } +}