From 3cb385b642537f4c2aa1924d85497ec29c582d2e Mon Sep 17 00:00:00 2001 From: OZGCloud <ozgcloud@mgm-tp.com> Date: Fri, 18 Oct 2024 18:25:33 +0200 Subject: [PATCH] OZG-6867 OZG-6899 implement remote service --- pom.xml | 16 +++- .../de/ozgcloud/admin/common/GrpcUtil.java | 43 ++++++++++ .../OrganisationsEinheit.java | 1 - .../OrganisationsEinheitMapper.java | 14 ++++ .../OrganisationsEinheitRemoteService.java | 32 +++++++ src/main/resources/application-local.yaml | 7 +- src/main/resources/application.yaml | 8 +- ...anisationsEinheitIdRequestTestFactory.java | 18 ++++ ...nisationsEinheitIdResponseTestFactory.java | 18 ++++ .../GrpcOrganisationsEinheitTestFactory.java | 23 +++++ .../GrpcXzufiIdTestFactory.java | 21 +++++ .../OrganisationsEinheitITCase.java | 2 - .../OrganisationsEinheitMapperTest.java | 38 +++++++++ ...OrganisationsEinheitRemoteServiceTest.java | 84 +++++++++++++++++++ .../OrganisationsEinheitTestFactory.java | 2 - 15 files changed, 318 insertions(+), 9 deletions(-) create mode 100644 src/main/java/de/ozgcloud/admin/common/GrpcUtil.java create mode 100644 src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapper.java create mode 100644 src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRemoteService.java create mode 100644 src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcGetByOrganisationsEinheitIdRequestTestFactory.java create mode 100644 src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcGetByOrganisationsEinheitIdResponseTestFactory.java create mode 100644 src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcOrganisationsEinheitTestFactory.java create mode 100644 src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcXzufiIdTestFactory.java create mode 100644 src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapperTest.java create mode 100644 src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRemoteServiceTest.java diff --git a/pom.xml b/pom.xml index 45252f6f..b5c8cff4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>de.ozgcloud.common</groupId> @@ -26,9 +26,17 @@ <mongock.version>5.4.0</mongock.version> <lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version> <mapstruct-processor.version>${mapstruct.version}</mapstruct-processor.version> + <zufi-manager.version>1.5.0-SNAPSHOT</zufi-manager.version> </properties> <dependencies> + <!-- OZG Cloud API --> + <dependency> + <groupId>de.ozgcloud.zufi</groupId> + <artifactId>zufi-manager-interface</artifactId> + <version>${zufi-manager.version}</version> + </dependency> + <!-- Spring --> <dependency> <groupId>org.springframework.boot</groupId> @@ -72,6 +80,10 @@ <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> + <dependency> + <groupId>net.devh</groupId> + <artifactId>grpc-client-spring-boot-starter</artifactId> + </dependency> <!-- Keycloak --> <dependency> diff --git a/src/main/java/de/ozgcloud/admin/common/GrpcUtil.java b/src/main/java/de/ozgcloud/admin/common/GrpcUtil.java new file mode 100644 index 00000000..d78580fa --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/common/GrpcUtil.java @@ -0,0 +1,43 @@ +package de.ozgcloud.admin.common; + +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Optional; +import java.util.stream.StreamSupport; + +import io.grpc.Metadata; +import io.grpc.Metadata.Key; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class GrpcUtil { + + public static final String ZUFI_MANAGER_GRPC_CLIENT = "zufi-manager"; + + public static final String SERVICE_KEY = "GRPC_SERVICE"; + + public static Key<String> keyOfString(String key) { + return Key.of(key, Metadata.ASCII_STRING_MARSHALLER); + } + + public static Key<byte[]> createKeyOf(String key) { + return Key.of(key, Metadata.BINARY_BYTE_MARSHALLER); + } + + public static String getFromHeaders(String key, Metadata headers) { + return Optional.ofNullable(headers.get(createKeyOf(key))) + .map(GrpcUtil::byteToString) + .orElse(null); + } + + public static Collection<String> getCollection(String key, Metadata headers) { + return StreamSupport.stream(headers.getAll(createKeyOf(key)).spliterator(), false) + .map(GrpcUtil::byteToString) + .toList(); + } + + private static String byteToString(byte[] bytes) { + return new String(bytes, StandardCharsets.UTF_8); + } +} \ No newline at end of file diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java index 65da662c..d7de6c6f 100644 --- a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java +++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheit.java @@ -25,7 +25,6 @@ public class OrganisationsEinheit { @Id private String id; private String name; - private String anschrift; private String organisationsEinheitId; private String uebergeordneteOrganisationseinheitId; private List<String> untergeordneteOrganisationseinheitIds; diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapper.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapper.java new file mode 100644 index 00000000..0d0d7db3 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapper.java @@ -0,0 +1,14 @@ +package de.ozgcloud.admin.organisationseinheit; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; + +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcOrganisationsEinheit; + +@Mapper +interface OrganisationsEinheitMapper { + + @Mapping(target = "organisationsEinheitId", source = "xzufiId.id") + @Mapping(target = "zufiId", source = "id") + OrganisationsEinheit fromGrpc(GrpcOrganisationsEinheit grpcOrganisationsEinheit); +} diff --git a/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRemoteService.java b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRemoteService.java new file mode 100644 index 00000000..7847a921 --- /dev/null +++ b/src/main/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRemoteService.java @@ -0,0 +1,32 @@ +package de.ozgcloud.admin.organisationseinheit; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import de.ozgcloud.admin.common.GrpcUtil; +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcGetByOrganisationsEinheitIdRequest; +import de.ozgcloud.zufi.grpc.organisationseinheit.OrganisationsEinheitServiceGrpc.OrganisationsEinheitServiceBlockingStub; +import net.devh.boot.grpc.client.inject.GrpcClient; + +@Service +class OrganisationsEinheitRemoteService { + + @GrpcClient(GrpcUtil.ZUFI_MANAGER_GRPC_CLIENT) + private OrganisationsEinheitServiceBlockingStub serviceStub; + + @Autowired + private OrganisationsEinheitMapper organisationsEinheitMapper; + + public List<OrganisationsEinheit> getByOrganisationsEinheitId(String organisationsEinheitId) { + var request = buildGetByOrganisationsEinheitIdRequest(organisationsEinheitId); + var response = serviceStub.getByOrganisationsEinheitId(request); + return response.getOrganisationsEinheitenList().stream().map(organisationsEinheitMapper::fromGrpc).toList(); + } + + GrpcGetByOrganisationsEinheitIdRequest buildGetByOrganisationsEinheitIdRequest(String organisationsEinheitId) { + return GrpcGetByOrganisationsEinheitIdRequest.newBuilder().setOrganisationsEinheitId(organisationsEinheitId).build(); + } + +} diff --git a/src/main/resources/application-local.yaml b/src/main/resources/application-local.yaml index 368820ad..7c4f421b 100644 --- a/src/main/resources/application-local.yaml +++ b/src/main/resources/application-local.yaml @@ -11,4 +11,9 @@ ozgcloud: oauth2: auth-server-url: http://localhost:8088 realm: by-kiel-dev - resource: admin \ No newline at end of file + resource: admin + +grpc: + client: + zufi-manager: + negotiationType: PLAINTEXT \ No newline at end of file diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 26660e83..563cb144 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -81,4 +81,10 @@ ozgcloud: password: administrationApiUser realm: ${ozgcloud.oauth2.realm} client: ${ozgcloud.oauth2.resource} - organisations-einheit-id-key: organisationseinheitId \ No newline at end of file + organisations-einheit-id-key: organisationseinheitId + +grpc: + client: + zufi-manager: + address: static://127.0.0.1:9190 + negotiationType: TLS \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcGetByOrganisationsEinheitIdRequestTestFactory.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcGetByOrganisationsEinheitIdRequestTestFactory.java new file mode 100644 index 00000000..8e3c8221 --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcGetByOrganisationsEinheitIdRequestTestFactory.java @@ -0,0 +1,18 @@ +package de.ozgcloud.admin.organisationseinheit; + +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcGetByOrganisationsEinheitIdRequest; + +public class GrpcGetByOrganisationsEinheitIdRequestTestFactory { + + public static final String ORGANISATIONS_EINHEIT_ID = OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID; + + public static GrpcGetByOrganisationsEinheitIdRequest create() { + return createBuilder().build(); + } + + public static GrpcGetByOrganisationsEinheitIdRequest.Builder createBuilder() { + return GrpcGetByOrganisationsEinheitIdRequest.newBuilder() + .setOrganisationsEinheitId(ORGANISATIONS_EINHEIT_ID); + } + +} diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcGetByOrganisationsEinheitIdResponseTestFactory.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcGetByOrganisationsEinheitIdResponseTestFactory.java new file mode 100644 index 00000000..e71492d4 --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcGetByOrganisationsEinheitIdResponseTestFactory.java @@ -0,0 +1,18 @@ +package de.ozgcloud.admin.organisationseinheit; + +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcGetByOrganisationsEinheitIdResponse; +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcOrganisationsEinheit; + +public class GrpcGetByOrganisationsEinheitIdResponseTestFactory { + + public static final GrpcOrganisationsEinheit GRPC_ORGANISATIONS_EINHEIT = GrpcOrganisationsEinheitTestFactory.create(); + + public static GrpcGetByOrganisationsEinheitIdResponse create() { + return createBuilder().build(); + } + + public static GrpcGetByOrganisationsEinheitIdResponse.Builder createBuilder() { + return GrpcGetByOrganisationsEinheitIdResponse.newBuilder() + .addOrganisationsEinheiten(GRPC_ORGANISATIONS_EINHEIT); + } +} diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcOrganisationsEinheitTestFactory.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcOrganisationsEinheitTestFactory.java new file mode 100644 index 00000000..ed0a83ac --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcOrganisationsEinheitTestFactory.java @@ -0,0 +1,23 @@ +package de.ozgcloud.admin.organisationseinheit; + +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcOrganisationsEinheit; +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcXzufiId; + +public class GrpcOrganisationsEinheitTestFactory { + + public static final String ID = OrganisationsEinheitTestFactory.ZUFI_ID; + public static final String NAME = OrganisationsEinheitTestFactory.NAME; + public static final GrpcXzufiId XZUFI_ID = GrpcXzufiIdTestFactory.create(); + + public static GrpcOrganisationsEinheit create() { + return createBuilder().build(); + } + + public static GrpcOrganisationsEinheit.Builder createBuilder() { + return GrpcOrganisationsEinheit.newBuilder() + .setId(ID) + .setName(NAME) + .setXzufiId(XZUFI_ID); + } + +} diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcXzufiIdTestFactory.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcXzufiIdTestFactory.java new file mode 100644 index 00000000..7c7b71e2 --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/GrpcXzufiIdTestFactory.java @@ -0,0 +1,21 @@ +package de.ozgcloud.admin.organisationseinheit; + +import java.util.UUID; + +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcXzufiId; + +public class GrpcXzufiIdTestFactory { + + public static final String ORGANISATIONS_EINHEIT_ID = OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID; + public static final String SCHEME_AGENCY_ID = UUID.randomUUID().toString(); + + public static GrpcXzufiId create() { + return createBuilder().build(); + } + + public static GrpcXzufiId.Builder createBuilder() { + return GrpcXzufiId.newBuilder() + .setId(ORGANISATIONS_EINHEIT_ID) + .setSchemeAgencyId(SCHEME_AGENCY_ID); + } +} diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitITCase.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitITCase.java index 4abc4c3c..82e3e304 100644 --- a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitITCase.java +++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitITCase.java @@ -67,7 +67,6 @@ class OrganisationsEinheitITCase { void shouldContainOrganisationsEinheit() { mockMvc.perform(get(PATH)) .andExpect(jsonPath("$._embedded.organisationsEinheitList[0].name").value(OrganisationsEinheitTestFactory.NAME)) - .andExpect(jsonPath("$._embedded.organisationsEinheitList[0].anschrift").value(OrganisationsEinheitTestFactory.ANSCHRIFT)) .andExpect(jsonPath("$._embedded.organisationsEinheitList[0].organisationsEinheitId").value( OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID)) .andExpect(jsonPath("$._embedded.organisationsEinheitList[0].uebergeordneteOrganisationseinheitId").value( @@ -98,7 +97,6 @@ class OrganisationsEinheitITCase { response .andExpect(jsonPath("$.name").value(OrganisationsEinheitTestFactory.NAME)) - .andExpect(jsonPath("$.anschrift").value(OrganisationsEinheitTestFactory.ANSCHRIFT)) .andExpect(jsonPath("$.organisationsEinheitId").value( OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID)) .andExpect(jsonPath("$.uebergeordneteOrganisationseinheitId").value( diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapperTest.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapperTest.java new file mode 100644 index 00000000..6d044f3d --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitMapperTest.java @@ -0,0 +1,38 @@ +package de.ozgcloud.admin.organisationseinheit; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; + +class OrganisationsEinheitMapperTest { + + private final OrganisationsEinheitMapper mapper = Mappers.getMapper(OrganisationsEinheitMapper.class); + + @Nested + class TestFromGrpc { + + @Test + void shouldMap() { + var mapped = mapper.fromGrpc(GrpcOrganisationsEinheitTestFactory.create()); + + assertThat(mapped).extracting( + OrganisationsEinheit::getName, + OrganisationsEinheit::getOrganisationsEinheitId, + OrganisationsEinheit::getZufiId, + OrganisationsEinheit::getUntergeordneteOrganisationseinheitIds, + OrganisationsEinheit::getUebergeordneteOrganisationseinheitId, + OrganisationsEinheit::getSyncResult + ).containsExactly( + OrganisationsEinheitTestFactory.NAME, + OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID, + OrganisationsEinheitTestFactory.ZUFI_ID, + null, + null, + null + ); + } + } + +} \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRemoteServiceTest.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRemoteServiceTest.java new file mode 100644 index 00000000..fde08bce --- /dev/null +++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitRemoteServiceTest.java @@ -0,0 +1,84 @@ +package de.ozgcloud.admin.organisationseinheit; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; + +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcGetByOrganisationsEinheitIdRequest; +import de.ozgcloud.zufi.grpc.organisationseinheit.GrpcGetByOrganisationsEinheitIdResponse; +import de.ozgcloud.zufi.grpc.organisationseinheit.OrganisationsEinheitServiceGrpc.OrganisationsEinheitServiceBlockingStub; + +class OrganisationsEinheitRemoteServiceTest { + + @Spy + @InjectMocks + private OrganisationsEinheitRemoteService service; + + @Mock + private OrganisationsEinheitServiceBlockingStub serviceStub; + + @Mock + private OrganisationsEinheitMapper mapper; + + @Nested + class TestGetByOrganisationsEinheitId { + + private final GrpcGetByOrganisationsEinheitIdRequest request = GrpcGetByOrganisationsEinheitIdRequestTestFactory.create(); + private final GrpcGetByOrganisationsEinheitIdResponse response = GrpcGetByOrganisationsEinheitIdResponseTestFactory.create(); + private final OrganisationsEinheit organisationsEinheit = OrganisationsEinheitTestFactory.create(); + + @BeforeEach + void setUp() { + doReturn(request).when(service).buildGetByOrganisationsEinheitIdRequest(OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID); + when(serviceStub.getByOrganisationsEinheitId(request)).thenReturn(response); + when(mapper.fromGrpc(GrpcGetByOrganisationsEinheitIdResponseTestFactory.GRPC_ORGANISATIONS_EINHEIT)).thenReturn(organisationsEinheit); + } + + @Test + void shouldBuildRequest() { + service.getByOrganisationsEinheitId(OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID); + + verify(service).buildGetByOrganisationsEinheitIdRequest(OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID); + } + + @Test + void shouldCallServiceStub() { + service.getByOrganisationsEinheitId(OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID); + + verify(serviceStub).getByOrganisationsEinheitId(request); + } + + @Test + void shouldMapResponse() { + service.getByOrganisationsEinheitId(OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID); + + verify(mapper).fromGrpc(GrpcGetByOrganisationsEinheitIdResponseTestFactory.GRPC_ORGANISATIONS_EINHEIT); + } + + @Test + void shouldReturnOrganisationsEinheiten() { + var organisationsEinheiten = service.getByOrganisationsEinheitId(OrganisationsEinheitTestFactory.ORGANISATIONS_EINHEIT_ID); + + assertThat(organisationsEinheiten).containsExactly(organisationsEinheit); + + } + } + + @Nested + class TestBuildGetByOrganisationsEinheitIdRequest { + + @Test + void shouldBuild() { + var request = service.buildGetByOrganisationsEinheitIdRequest(OrganisationsEinheitTestFactory.ID); + + assertThat(request.getOrganisationsEinheitId()).isEqualTo(OrganisationsEinheitTestFactory.ID); + } + } + +} \ No newline at end of file diff --git a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitTestFactory.java b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitTestFactory.java index 9f4f1363..74466874 100644 --- a/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitTestFactory.java +++ b/src/test/java/de/ozgcloud/admin/organisationseinheit/OrganisationsEinheitTestFactory.java @@ -9,7 +9,6 @@ public class OrganisationsEinheitTestFactory { public static final String ID = UUID.randomUUID().toString(); public static final String NAME = LoremIpsum.getInstance().getName(); - public static final String ANSCHRIFT = LoremIpsum.getInstance().getCity(); public static final String ORGANISATIONS_EINHEIT_ID = UUID.randomUUID().toString(); public static final String UEBERGEORDNETE_ORGANISATIONSEINHEIT_ID = UUID.randomUUID().toString(); public static final List<String> UNTERGEORDNETE_ORGANISATIONSEINHEIT_ID = List.of(UUID.randomUUID().toString()); @@ -24,7 +23,6 @@ public class OrganisationsEinheitTestFactory { return OrganisationsEinheit.builder() .id(ID) .name(NAME) - .anschrift(ANSCHRIFT) .organisationsEinheitId(ORGANISATIONS_EINHEIT_ID) .uebergeordneteOrganisationseinheitId(UEBERGEORDNETE_ORGANISATIONSEINHEIT_ID) .untergeordneteOrganisationseinheitIds(UNTERGEORDNETE_ORGANISATIONSEINHEIT_ID) -- GitLab