From c7649861a6a0323ccba6991ca1e901c054e4f309 Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Wed, 6 Nov 2024 18:26:52 +0100
Subject: [PATCH] OZG-6990 extend grpc util: add more keys and methods

---
 README.md                                     |   1 +
 .../de/ozgcloud/common/grpc/GrpcUtil.java     |  42 +++-
 .../de/ozgcloud/common/grpc/GrpcUtilTest.java | 213 ++++++++++++------
 3 files changed, 185 insertions(+), 71 deletions(-)

diff --git a/README.md b/README.md
index e28c961..733b1ac 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,7 @@
 
 ### 4.6.0-SNAPSHOT
 * Update [OZGCloud License Generator](ozgcloud-common-license/readme.md)
+* `GrpcUtil` erweitern: mehr Schlüsseln hinzufügen und Methoden, um diese Schlüssel aus gRPC-Metadaten zu extrahieren.
 
 ### 4.5.0
 * common-lib erweitern: gRPC Server Downloader für binäre Dateien hinzufügen
diff --git a/ozgcloud-common-lib/src/main/java/de/ozgcloud/common/grpc/GrpcUtil.java b/ozgcloud-common-lib/src/main/java/de/ozgcloud/common/grpc/GrpcUtil.java
index 8373093..b5c1bf0 100644
--- a/ozgcloud-common-lib/src/main/java/de/ozgcloud/common/grpc/GrpcUtil.java
+++ b/ozgcloud-common-lib/src/main/java/de/ozgcloud/common/grpc/GrpcUtil.java
@@ -24,10 +24,10 @@
 package de.ozgcloud.common.grpc;
 
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
 import io.grpc.Metadata;
@@ -39,8 +39,11 @@ import lombok.NoArgsConstructor;
 public class GrpcUtil {
 
 	public static final Key<byte[]> HEADER_KEY_USER_ID = createKeyOf("USER_ID-bin");
+	public static final Key<byte[]> HEADER_KEY_USER_NAME = createKeyOf("USER_NAME-bin");
 	public static final Key<byte[]> HEADER_KEY_CLIENT_NAME = createKeyOf("CLIENT_NAME-bin");
 	public static final Key<byte[]> HEADER_KEY_REQUEST_ID = createKeyOf("REQUEST_ID-bin");
+	public static final Key<byte[]> HEADER_KEY_ACCESS_LIMITED_ORGAID = createKeyOf("ACCESS_LIMITED_TO_ORGANISATORISCHEEINHEITENID-bin");
+	public static final Key<byte[]> HEADER_KEY_ACCESS_LIMITED = createKeyOf("ACCESS_LIMITED-bin");
 
 	public static Key<String> keyOfString(String key) {
 		return Key.of(key, Metadata.ASCII_STRING_MARSHALLER);
@@ -50,6 +53,30 @@ public class GrpcUtil {
 		return Key.of(key, Metadata.BINARY_BYTE_MARSHALLER);
 	}
 
+	public static Optional<String> getRequestId(Metadata headers) {
+		return getFromHeaders(HEADER_KEY_REQUEST_ID, headers);
+	}
+
+	public static Optional<String> getClientName(Metadata headers) {
+		return getFromHeaders(HEADER_KEY_CLIENT_NAME, headers);
+	}
+
+	public static Optional<String> getUserId(Metadata headers) {
+		return getFromHeaders(HEADER_KEY_USER_ID, headers);
+	}
+
+	public static Optional<String> getUserName(Metadata headers) {
+		return getFromHeaders(HEADER_KEY_USER_NAME, headers);
+	}
+
+	public static List<String> getAccessLimitedOrgaIds(Metadata headers) {
+		return getList(HEADER_KEY_ACCESS_LIMITED_ORGAID, headers);
+	}
+
+	public static Optional<String> getAccessLimited(Metadata headers) {
+		return getFromHeaders(HEADER_KEY_ACCESS_LIMITED, headers);
+	}
+
 	public static Optional<String> getFromHeaders(String key, Metadata headers) {
 		return getFromHeaders(createKeyOf(key), headers);
 	}
@@ -58,14 +85,13 @@ public class GrpcUtil {
 		return Optional.ofNullable(headers.get(key)).map(GrpcUtil::byteToString);
 	}
 
-	public static Collection<String> getCollection(String key, Metadata headers) {
-		final List<String> result = new ArrayList<>();
-		var valuesOptional = Optional.ofNullable(headers.getAll(createKeyOf(key)));
-		valuesOptional.ifPresent(valuesBytes -> result.addAll(StreamSupport.stream(valuesBytes.spliterator(), false)
-				.map(GrpcUtil::byteToString)
-				.toList()));
+	public static List<String> getList(String key, Metadata headers) {
+		return getList(createKeyOf(key), headers);
+	}
 
-		return result;
+	public static List<String> getList(Key<byte[]> key, Metadata headers) {
+		return Optional.ofNullable(headers.getAll(key)).map(valuesBytes -> StreamSupport.stream(valuesBytes.spliterator(), false))
+				.orElseGet(Stream::empty).map(GrpcUtil::byteToString).toList();
 	}
 
 	private static String byteToString(byte[] bytes) {
diff --git a/ozgcloud-common-lib/src/test/java/de/ozgcloud/common/grpc/GrpcUtilTest.java b/ozgcloud-common-lib/src/test/java/de/ozgcloud/common/grpc/GrpcUtilTest.java
index 340d732..f3bb604 100644
--- a/ozgcloud-common-lib/src/test/java/de/ozgcloud/common/grpc/GrpcUtilTest.java
+++ b/ozgcloud-common-lib/src/test/java/de/ozgcloud/common/grpc/GrpcUtilTest.java
@@ -2,6 +2,7 @@ package de.ozgcloud.common.grpc;
 
 import static org.assertj.core.api.Assertions.*;
 
+import com.thedeanda.lorem.LoremIpsum;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -9,98 +10,184 @@ import org.junit.jupiter.api.Test;
 
 import io.grpc.Metadata;
 
+import java.util.UUID;
+
 class GrpcUtilTest {
+
 	private static final String KEY_VALUE_BIN = "key_value-bin";
 	private static final String KEY_VALUE_STRING = "key_value";
 	private static final String UNKNOWN_KEY_BIN = "unknown_key-bin";
 
-	@DisplayName("Test Grpc Utility methods")
+	private final Metadata header = new Metadata();
+
+	@DisplayName("Test creation of MetaData keys")
+	@Nested
+	class TestKeyGeneration {
+
+		@Test
+		void shouldCreateBinaryKey() {
+			var key = GrpcUtil.createKeyOf(KEY_VALUE_BIN);
+
+			assertThat(key.name()).isEqualTo(KEY_VALUE_BIN);
+		}
+
+		@Test
+		void shouldThrowExceptionBecauseOfMissingBinSuffix() {
+			assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> GrpcUtil.createKeyOf("key"));
+		}
+
+		@Test
+		void shouldCreateAsciiKey() {
+			var key = GrpcUtil.keyOfString(KEY_VALUE_STRING);
+
+			assertThat(key.name()).isEqualTo(KEY_VALUE_STRING);
+		}
+
+		@Test
+		void shouldThrowExceptionBecauseOfBinSuffix() {
+			assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> GrpcUtil.keyOfString(KEY_VALUE_BIN));
+		}
+	}
+
+	@DisplayName("Test reading values from the grpc header")
+	@Nested
+	class TestReadingFromHeader {
+		private static final String TEST_VALUE = LoremIpsum.getInstance().getWords(1);
+
+		@BeforeEach
+		void initMetadata() {
+			header.put(GrpcUtil.createKeyOf(KEY_VALUE_BIN), TEST_VALUE.getBytes());
+		}
+
+		@Test
+		void shouldReadFromHeader() {
+			var value = GrpcUtil.getFromHeaders(KEY_VALUE_BIN, header);
+
+			assertThat(value).contains(TEST_VALUE);
+		}
+
+		@Test
+		void shouldReturnNullOnUnknownKey() {
+			var value = GrpcUtil.getFromHeaders(UNKNOWN_KEY_BIN, header);
+
+			assertThat(value).isEmpty();
+		}
+	}
+
+	@DisplayName("Test reading multiple values of a key from the grpc header")
+	@Nested
+	class TestReadingCollection {
+		private static final String TEST_VALUE_1 = LoremIpsum.getInstance().getWords(1);
+		private static final String TEST_VALUE_2 = LoremIpsum.getInstance().getWords(2);
+
+		@BeforeEach
+		void initMetadata() {
+			header.put(GrpcUtil.createKeyOf(KEY_VALUE_BIN), TEST_VALUE_1.getBytes());
+			header.put(GrpcUtil.createKeyOf(KEY_VALUE_BIN), TEST_VALUE_2.getBytes());
+		}
+
+		@Test
+		void shouldReadFromHeader() {
+			var values = GrpcUtil.getList(KEY_VALUE_BIN, header);
+
+			assertThat(values).hasSize(2).contains(TEST_VALUE_1, TEST_VALUE_2);
+		}
+
+		@Test
+		void shouldGetEmptyCollectionOnUnknownKey() {
+			var values = GrpcUtil.getList(UNKNOWN_KEY_BIN, header);
+
+			assertThat(values).isEmpty();
+		}
+	}
+
 	@Nested
-	class TestGrpcUtils {
+	class TestGetRequestId {
 
-		@DisplayName("Test creation of MetaData keys")
-		@Nested
-		class TestKeyGeneration {
+		private static final String REQUEST_ID = UUID.randomUUID().toString();
 
-			@Test
-			void shouldCreateBinaryKey() {
-				var key = GrpcUtil.createKeyOf(KEY_VALUE_BIN);
+		@Test
+		void shouldCallGetFromHeader() {
+			header.put(GrpcUtil.HEADER_KEY_REQUEST_ID, REQUEST_ID.getBytes());
 
-				assertThat(key.name()).isEqualTo(KEY_VALUE_BIN);
-			}
+			var result = GrpcUtil.getRequestId(header);
 
-			@Test
-			void shouldThrowExceptionBecauseOfMissingBinSuffix() {
-				assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> GrpcUtil.createKeyOf("key"));
-			}
+			assertThat(result).contains(REQUEST_ID);
+		}
+	}
+
+	@Nested
+	class TestGetClientName {
 
-			@Test
-			void shouldCreateAsciiKey() {
-				var key = GrpcUtil.keyOfString(KEY_VALUE_STRING);
+		private static final String CLIENT_NAME = LoremIpsum.getInstance().getWords(1);
 
-				assertThat(key.name()).isEqualTo(KEY_VALUE_STRING);
-			}
+		@Test
+		void shouldCallGetFromHeader() {
+			header.put(GrpcUtil.HEADER_KEY_CLIENT_NAME, CLIENT_NAME.getBytes());
 
-			@Test
-			void shouldThrowExceptionBecauseOfBinSuffix() {
-				assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> GrpcUtil.keyOfString(KEY_VALUE_BIN));
-			}
+			var result = GrpcUtil.getClientName(header);
+
+			assertThat(result).contains(CLIENT_NAME);
 		}
+	}
 
-		@DisplayName("Test reading values from the grpc header")
-		@Nested
-		class TestReadingFromHeader {
-			private static final String TEST_VALUE = "test-value";
+	@Nested
+	class TestGetUserId {
 
-			private Metadata header = new Metadata();
+		private static final String USER_ID = LoremIpsum.getInstance().getWords(1);
 
-			@BeforeEach
-			void initMetadata() {
-				header.put(GrpcUtil.createKeyOf(KEY_VALUE_BIN), TEST_VALUE.getBytes());
-			}
+		@Test
+		void shouldCallGetFromHeader() {
+			header.put(GrpcUtil.HEADER_KEY_USER_ID, USER_ID.getBytes());
 
-			@Test
-			void shouldReadFromHeader() {
-				var value = GrpcUtil.getFromHeaders(KEY_VALUE_BIN, header);
+			var result = GrpcUtil.getUserId(header);
 
-				assertThat(value).contains(TEST_VALUE);
-			}
+			assertThat(result).contains(USER_ID);
+		}
+	}
+
+	@Nested
+	class TestGetUserName {
 
-			@Test
-			void shouldReturnNullOnUnknownKey() {
-				var value = GrpcUtil.getFromHeaders(UNKNOWN_KEY_BIN, header);
+		private static final String USER_NAME = LoremIpsum.getInstance().getWords(1);
 
-				assertThat(value).isEmpty();
-			}
+		@Test
+		void shouldCallGetFromHeader() {
+			header.put(GrpcUtil.HEADER_KEY_USER_NAME, USER_NAME.getBytes());
+
+			var result = GrpcUtil.getUserName(header);
+
+			assertThat(result).contains(USER_NAME);
 		}
+	}
 
-		@DisplayName("Test reading multiple values of a key from the grpc header")
-		@Nested
-		class TestReadingCollection {
-			private static final String TEST_VALUE_1 = "test-value-1";
-			private static final String TEST_VALUE_2 = "test-value-2";
+	@Nested
+	class TestGetAccessLimitedOrgaId {
+
+		private static final String ACCESS_LIMITED_ORGAID = LoremIpsum.getInstance().getWords(1);
 
-			private Metadata header = new Metadata();
+		@Test
+		void shouldCallGetFromHeader() {
+			header.put(GrpcUtil.HEADER_KEY_ACCESS_LIMITED_ORGAID, ACCESS_LIMITED_ORGAID.getBytes());
 
-			@BeforeEach
-			void initMetadata() {
-				header.put(GrpcUtil.createKeyOf(KEY_VALUE_BIN), TEST_VALUE_1.getBytes());
-				header.put(GrpcUtil.createKeyOf(KEY_VALUE_BIN), TEST_VALUE_2.getBytes());
-			}
+			var result = GrpcUtil.getAccessLimitedOrgaIds(header);
+
+			assertThat(result).containsExactly(ACCESS_LIMITED_ORGAID);
+		}
+	}
+
+	@Nested
+	class TestGetAccessLimited {
 
-			@Test
-			void shouldReadFromHeader() {
-				var values = GrpcUtil.getCollection(KEY_VALUE_BIN, header);
+		private static final String ACCESS_LIMITED = "access-limited";
 
-				assertThat(values).hasSize(2).contains(TEST_VALUE_1, TEST_VALUE_2);
-			}
+		@Test
+		void shouldCallGetFromHeader() {
+			header.put(GrpcUtil.HEADER_KEY_ACCESS_LIMITED, ACCESS_LIMITED.getBytes());
 
-			@Test
-			void shouldGetEmptyCollectionOnUnknownKey() {
-				var values = GrpcUtil.getCollection(UNKNOWN_KEY_BIN, header);
+			var result = GrpcUtil.getAccessLimited(header);
 
-				assertThat(values).isEmpty();
-			}
+			assertThat(result).contains(ACCESS_LIMITED);
 		}
 	}
 }
-- 
GitLab