diff --git a/nachrichten-manager-interface/pom.xml b/nachrichten-manager-interface/pom.xml index e2741639bd1a779001d0cf6f84563a71f70702e9..525544d7ea16d624325341b9ecc01d87b52e7e4c 100644 --- a/nachrichten-manager-interface/pom.xml +++ b/nachrichten-manager-interface/pom.xml @@ -31,7 +31,7 @@ <parent> <groupId>de.ozgcloud.common</groupId> <artifactId>ozgcloud-common-dependencies</artifactId> - <version>4.5.0</version> + <version>4.7.0</version> <relativePath/> </parent> diff --git a/nachrichten-manager-server/pom.xml b/nachrichten-manager-server/pom.xml index b4ea2eabbd4d93cd403e523190a0f70a2fdc8a4b..e393b6f5fbb947a585621989f3d17c533d2fa26b 100644 --- a/nachrichten-manager-server/pom.xml +++ b/nachrichten-manager-server/pom.xml @@ -49,7 +49,7 @@ <vorgang-manager.version>2.17.0</vorgang-manager.version> <muk-postfach.version>0.1.0</muk-postfach.version> <api-lib.version>0.15.0-SNAPSHOT</api-lib.version> - <ozgcloud-common.version>4.5.0</ozgcloud-common.version> + <ozgcloud-common.version>4.7.0</ozgcloud-common.version> </properties> <dependencies> @@ -241,6 +241,10 @@ <type>test-jar</type> <scope>test</scope> </dependency> + <dependency> + <groupId>de.ozgcloud.common</groupId> + <artifactId>ozgcloud-common-lib</artifactId> + </dependency> </dependencies> <build> diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/NachrichtenManagerCallContextProvider.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/NachrichtenManagerCallContextProvider.java index c64af3e512b11fece4881f0875c96b738561622d..fcf82624f923b069927a5aa7a70c65451905b77c 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/NachrichtenManagerCallContextProvider.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/NachrichtenManagerCallContextProvider.java @@ -4,6 +4,7 @@ import org.springframework.stereotype.Component; import de.ozgcloud.apilib.common.callcontext.CallContext; import de.ozgcloud.apilib.common.callcontext.OzgCloudCallContextProvider; +import de.ozgcloud.apilib.vorgang.OzgCloudUserIdMapper; import de.ozgcloud.nachrichten.common.grpc.NachrichtenCallContextAttachingInterceptor; import lombok.RequiredArgsConstructor; @@ -11,8 +12,11 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor class NachrichtenManagerCallContextProvider implements OzgCloudCallContextProvider { + private final OzgCloudUserIdMapper userIdMapper; + @Override public CallContext provideContext() { - return CallContext.builder().clientName(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_CLIENT_NAME).build(); + return CallContext.builder().clientName(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_CLIENT_NAME) + .userId(userIdMapper.toUserId(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_SENDER_USER_ID)).build(); } } \ No newline at end of file diff --git a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/grpc/NachrichtenCallContextAttachingInterceptor.java b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/grpc/NachrichtenCallContextAttachingInterceptor.java index d3fa03da97bf23b79dfc2d31325b28777260d8be..90f7c91aa41ea10460a606281743bb1d6f47d2ef 100644 --- a/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/grpc/NachrichtenCallContextAttachingInterceptor.java +++ b/nachrichten-manager-server/src/main/java/de/ozgcloud/nachrichten/common/grpc/NachrichtenCallContextAttachingInterceptor.java @@ -23,10 +23,11 @@ */ package de.ozgcloud.nachrichten.common.grpc; -import static de.ozgcloud.common.grpc.GrpcUtil.*; - import java.util.UUID; +import org.apache.logging.log4j.ThreadContext; + +import de.ozgcloud.common.grpc.GrpcUtil; import io.grpc.CallOptions; import io.grpc.Channel; import io.grpc.ClientCall; @@ -37,12 +38,10 @@ import io.grpc.MethodDescriptor; public class NachrichtenCallContextAttachingInterceptor implements ClientInterceptor { - static final String KEY_USER_ID = "USER_ID-bin"; - static final String KEY_CLIENT_NAME = "CLIENT_NAME-bin"; - static final String KEY_REQUEST_ID = "REQUEST_ID-bin"; + static final String REQUEST_ID_KEY = "requestId"; public static final String NACHRICHTEN_MANAGER_CLIENT_NAME = "OzgCloud_NachrichtenManager"; - static final String NACHRICHTEN_MANAGER_SENDER_USER_ID = "system-nachrichten_manager-sender"; + public static final String NACHRICHTEN_MANAGER_SENDER_USER_ID = "system-nachrichten_manager-sender"; // <A> = Request, <B> = Response @Override @@ -52,7 +51,7 @@ public class NachrichtenCallContextAttachingInterceptor implements ClientInterce final class CallContextAttachingClientCall<A, B> extends SimpleForwardingClientCall<A, B> { - protected CallContextAttachingClientCall(ClientCall<A, B> delegate) { + CallContextAttachingClientCall(ClientCall<A, B> delegate) { super(delegate); } @@ -62,19 +61,18 @@ public class NachrichtenCallContextAttachingInterceptor implements ClientInterce super.start(responseListener, headers); } - private Metadata buildCallContextMetadata() { + Metadata buildCallContextMetadata() { var metadata = new Metadata(); - metadata.put(createKeyOf(KEY_USER_ID), NACHRICHTEN_MANAGER_SENDER_USER_ID.getBytes()); - metadata.put(createKeyOf(KEY_CLIENT_NAME), NACHRICHTEN_MANAGER_CLIENT_NAME.getBytes()); - metadata.put(createKeyOf(KEY_REQUEST_ID), generateRequestId().getBytes()); + metadata.put(GrpcUtil.HEADER_KEY_USER_ID, NACHRICHTEN_MANAGER_SENDER_USER_ID.getBytes()); + metadata.put(GrpcUtil.HEADER_KEY_CLIENT_NAME, NACHRICHTEN_MANAGER_CLIENT_NAME.getBytes()); + metadata.put(GrpcUtil.HEADER_KEY_REQUEST_ID, getRequestId()); return metadata; } - // TODO OZG-1974 requestId zentraler erzeugen - private String generateRequestId() { - return UUID.randomUUID().toString(); + byte[] getRequestId() { + return ThreadContext.getContext().getOrDefault(REQUEST_ID_KEY, UUID.randomUUID().toString()).getBytes(); } } diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/NachrichtenManagerCallContextProviderTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/NachrichtenManagerCallContextProviderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7ac62d8ed944b5c1565472216f3ccccc909f6a5d --- /dev/null +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/NachrichtenManagerCallContextProviderTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2024 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.nachrichten; + +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 de.ozgcloud.apilib.user.OzgCloudUserId; +import de.ozgcloud.apilib.vorgang.OzgCloudUserIdMapper; +import de.ozgcloud.nachrichten.common.grpc.NachrichtenCallContextAttachingInterceptor; + +class NachrichtenManagerCallContextProviderTest { + + @InjectMocks + private NachrichtenManagerCallContextProvider callContextProvider; + + @Mock + private OzgCloudUserIdMapper userIdMapper; + + @Nested + class TestProvideContext { + + @BeforeEach + void init() { + when(userIdMapper.toUserId(anyString())).thenReturn( + OzgCloudUserId.from(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_SENDER_USER_ID)); + } + + @Test + void shouldSetClientName() { + var result = callContextProvider.provideContext(); + + assertThat(result.getClientName()).isEqualTo(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_CLIENT_NAME); + } + + @Test + void shouldCallUserIdMapper() { + callContextProvider.provideContext(); + + verify(userIdMapper).toUserId(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_SENDER_USER_ID); + } + + @Test + void shouldSetUserId() { + var result = callContextProvider.provideContext(); + + assertThat(result.getUserId()).hasToString(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_SENDER_USER_ID); + } + } + +} \ No newline at end of file diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/NachrichtenManagerTestApplication.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/NachrichtenManagerTestApplication.java index 8b90c6bbd747c0263e5327651074fd17b993ac82..6403b80171ca2e8f10953186048b44b90ca20ebb 100644 --- a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/NachrichtenManagerTestApplication.java +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/NachrichtenManagerTestApplication.java @@ -10,6 +10,7 @@ import org.springframework.context.annotation.ComponentScan; import de.ozgcloud.apilib.common.command.OzgCloudCommandService; import de.ozgcloud.apilib.file.OzgCloudFileService; import de.ozgcloud.apilib.vorgang.OzgCloudFileIdMapper; +import de.ozgcloud.apilib.vorgang.OzgCloudUserIdMapper; import de.ozgcloud.nachrichten.postfach.muk.MukPostfachConfiguration; @SpringBootApplication @@ -30,4 +31,9 @@ public class NachrichtenManagerTestApplication { OzgCloudFileIdMapper ozgCloudFileIdMapper() { return Mappers.getMapper(OzgCloudFileIdMapper.class); } + + @Bean + OzgCloudUserIdMapper ozgCloudUserIdMapper() { + return Mappers.getMapper(OzgCloudUserIdMapper.class); + } } diff --git a/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/grpc/NachrichtenCallContextAttachingInterceptorTest.java b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/grpc/NachrichtenCallContextAttachingInterceptorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..8deb34be0350b52067847f983e13063f20745cbb --- /dev/null +++ b/nachrichten-manager-server/src/test/java/de/ozgcloud/nachrichten/common/grpc/NachrichtenCallContextAttachingInterceptorTest.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2024 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.nachrichten.common.grpc; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.Map; +import java.util.UUID; + +import org.apache.logging.log4j.ThreadContext; +import org.junit.jupiter.api.AfterEach; +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.MockedStatic; +import org.mockito.Mockito; + +import de.ozgcloud.common.grpc.GrpcUtil; +import io.grpc.ClientCall; +import io.grpc.Metadata; + +class NachrichtenCallContextAttachingInterceptorTest { + + @InjectMocks + private NachrichtenCallContextAttachingInterceptor interceptor; + + @Mock + private ClientCall<RequestTest, ResponseTest> delegateCall; + @Mock + private ClientCall.Listener<ResponseTest> responseTestListener; + @Mock + private Metadata requestMetadata; + + private NachrichtenCallContextAttachingInterceptor.CallContextAttachingClientCall<RequestTest, ResponseTest> clientCall; + + @BeforeEach + void init() { + clientCall = spy(interceptor.new CallContextAttachingClientCall<>(delegateCall)); + } + + @Nested + class TestStart { + + @Mock + private Metadata customMetadata; + + @BeforeEach + void init() { + doReturn(customMetadata).when(clientCall).buildCallContextMetadata(); + } + + @Test + void shouldCallBuildCallContextMetadata() { + clientCall.start(responseTestListener, requestMetadata); + + verify(clientCall).buildCallContextMetadata(); + } + + @Test + void shouldMergeMetadata() { + clientCall.start(responseTestListener, requestMetadata); + + verify(requestMetadata).merge(customMetadata); + } + } + + @Nested + class TestBuildCallContextMetadata { + + @Test + void shouldSetUserId() { + var result = clientCall.buildCallContextMetadata(); + + assertThat(result.get(GrpcUtil.HEADER_KEY_USER_ID)) + .isEqualTo(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_SENDER_USER_ID.getBytes()); + } + + @Test + void shouldSetClientName() { + var result = clientCall.buildCallContextMetadata(); + + assertThat(result.get(GrpcUtil.HEADER_KEY_CLIENT_NAME)) + .isEqualTo(NachrichtenCallContextAttachingInterceptor.NACHRICHTEN_MANAGER_CLIENT_NAME.getBytes()); + } + + @Test + void shouldCallGetrequestId() { + clientCall.buildCallContextMetadata(); + + verify(clientCall).getRequestId(); + } + + @Test + void shouldSetRequestId() { + var requestId = UUID.randomUUID().toString().getBytes(); + doReturn(requestId).when(clientCall).getRequestId(); + + var result = clientCall.buildCallContextMetadata(); + + assertThat(result.get(GrpcUtil.HEADER_KEY_REQUEST_ID)).isEqualTo(requestId); + } + } + + @Nested + class TestGetRequestId { + + private MockedStatic<ThreadContext> threadContextMocked; + + @BeforeEach + void init() { + threadContextMocked = Mockito.mockStatic(ThreadContext.class); + } + + @AfterEach + void close() { + threadContextMocked.close(); + } + + @Test + void shouldCallGetContext() { + clientCall.getRequestId(); + + threadContextMocked.verify(ThreadContext::getContext); + } + + @Test + void shouldReturnRequestIdFromThreadContext() { + var requestId = UUID.randomUUID().toString(); + + threadContextMocked.when(ThreadContext::getContext) + .thenReturn(Map.of(NachrichtenCallContextAttachingInterceptor.REQUEST_ID_KEY, requestId)); + + var result = clientCall.getRequestId(); + + assertThat(result).isEqualTo(requestId.getBytes()); + } + + @Test + void shouldReturnNewRequestId() { + var result = clientCall.getRequestId(); + + assertThat(result).isNotNull(); + } + } + + private record RequestTest() { + } + + private record ResponseTest() { + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index a1265e9ac60cb1fb3c219d3fde293153aae4df77..0e9e340350700284443522feefae9c335268da76 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ <parent> <groupId>de.ozgcloud.common</groupId> <artifactId>ozgcloud-common-parent</artifactId> - <version>4.5.0</version> + <version>4.7.0</version> </parent> <groupId>de.ozgcloud.nachrichten</groupId>