From 38d8be8fbe78eb2a0e34f7e7665a8e817ac37f48 Mon Sep 17 00:00:00 2001
From: Felix Reichenbach <felix.reichenbach@mgm-tp.com>
Date: Wed, 12 Feb 2025 17:06:01 +0100
Subject: [PATCH 1/5] OZG-7615 add documentation link

---
 .../admin/DocumentationProperties.java        |  19 +++
 .../de/ozgcloud/admin/RootModelAssembler.java |  22 ++-
 .../admin/RootModelAssemblerTest.java         | 133 +++++++++++-------
 3 files changed, 111 insertions(+), 63 deletions(-)
 create mode 100644 src/main/java/de/ozgcloud/admin/DocumentationProperties.java

diff --git a/src/main/java/de/ozgcloud/admin/DocumentationProperties.java b/src/main/java/de/ozgcloud/admin/DocumentationProperties.java
new file mode 100644
index 00000000..956faa74
--- /dev/null
+++ b/src/main/java/de/ozgcloud/admin/DocumentationProperties.java
@@ -0,0 +1,19 @@
+package de.ozgcloud.admin;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Setter
+@Getter
+@Configuration
+@ConfigurationProperties(prefix = DocumentationProperties.DOCUMENTATION_PROPERTIES_PREFIX)
+public class DocumentationProperties {
+
+	static final String DOCUMENTATION_PROPERTIES_PREFIX = "ozgcloud.user-assistance.documentation";
+
+	private String url;
+
+}
diff --git a/src/main/java/de/ozgcloud/admin/RootModelAssembler.java b/src/main/java/de/ozgcloud/admin/RootModelAssembler.java
index 3b564cf3..09e8c615 100644
--- a/src/main/java/de/ozgcloud/admin/RootModelAssembler.java
+++ b/src/main/java/de/ozgcloud/admin/RootModelAssembler.java
@@ -23,8 +23,7 @@
  */
 package de.ozgcloud.admin;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Objects;
 
 import org.springframework.boot.autoconfigure.data.rest.RepositoryRestProperties;
 import org.springframework.hateoas.EntityModel;
@@ -40,24 +39,19 @@ import lombok.RequiredArgsConstructor;
 @RequiredArgsConstructor
 public class RootModelAssembler implements RepresentationModelAssembler<Root, EntityModel<Root>> {
 	static final String REL_CONFIGURATION = "configuration";
+	static final String REL_DOCUMENTATIONS = "documentations";
 
 	private final RepositoryRestProperties restProperties;
 	private final CurrentUserService currentUserService;
+	private final DocumentationProperties documentationProperties;
 
 	@Override
 	public EntityModel<Root> toModel(Root root) {
-		List<Link> links = buildRootModelLinks();
-		return EntityModel.of(root, links);
-	}
-
-	List<Link> buildRootModelLinks() {
-		List<Link> links = new ArrayList<>();
-		var rootLinkBuilder = WebMvcLinkBuilder.linkTo(RootController.class);
-		links.add(rootLinkBuilder.withSelfRel());
-		if (currentUserService.hasConfigurationPermission()) {
-			links.add(buildConfigLink());
-		}
-		return links;
+		var rootModel = EntityModel.of(root);
+		rootModel.add(WebMvcLinkBuilder.linkTo(RootController.class).withSelfRel());
+		rootModel.addIf(currentUserService.hasConfigurationPermission(), this::buildConfigLink);
+		rootModel.addIf(Objects.nonNull(documentationProperties.getUrl()), () -> Link.of(documentationProperties.getUrl(), REL_DOCUMENTATIONS));
+		return rootModel;
 	}
 
 	private Link buildConfigLink() {
diff --git a/src/test/java/de/ozgcloud/admin/RootModelAssemblerTest.java b/src/test/java/de/ozgcloud/admin/RootModelAssemblerTest.java
index d3933e76..89338923 100644
--- a/src/test/java/de/ozgcloud/admin/RootModelAssemblerTest.java
+++ b/src/test/java/de/ozgcloud/admin/RootModelAssemblerTest.java
@@ -27,8 +27,6 @@ import static de.ozgcloud.admin.RootModelAssembler.*;
 import static org.assertj.core.api.Assertions.*;
 import static org.mockito.Mockito.*;
 
-import java.util.List;
-
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Nested;
@@ -37,8 +35,11 @@ import org.mockito.InjectMocks;
 import org.mockito.Mock;
 import org.mockito.Spy;
 import org.springframework.boot.autoconfigure.data.rest.RepositoryRestProperties;
+import org.springframework.hateoas.IanaLinkRelations;
 import org.springframework.hateoas.Link;
 
+import com.thedeanda.lorem.LoremIpsum;
+
 import de.ozgcloud.admin.common.user.CurrentUserService;
 
 class RootModelAssemblerTest {
@@ -53,82 +54,116 @@ class RootModelAssemblerTest {
 	private RepositoryRestProperties restProperties;
 	@Mock
 	private CurrentUserService currentUserService;
+	@Mock
+	private DocumentationProperties documentationProperties;
 
 	@DisplayName("Entity Model")
 	@Nested
-	class TestEntityModel {
-
-		private final List<Link> links = List.of(Link.of(RootController.PATH));
+	class TestToModel {
 
-		@BeforeEach
-		void beforeEach() {
-			doReturn(links).when(modelAssembler).buildRootModelLinks();
-		}
+		private final Root root = RootTestFactory.create();
 
 		@Test
-		void shouldHaveRoot() {
-			var givenRoot = RootTestFactory.create();
-
-			var resultRoot = modelAssembler.toModel(givenRoot).getContent();
+		void shouldHaveRootContent() {
+			var resultRoot = modelAssembler.toModel(root).getContent();
 
-			assertThat(resultRoot).isEqualTo(givenRoot);
+			assertThat(resultRoot).isEqualTo(root);
 		}
 
 		@Test
-		void shouldHaveLinks() {
-			var modelLinks = modelAssembler.toModel(RootTestFactory.create()).getLinks();
+		void shouldHaveSelfLink() {
+			var model = modelAssembler.toModel(root);
 
-			assertThat(modelLinks).containsAll(links);
+			assertThat(model.getLink(IanaLinkRelations.SELF)).get().extracting(Link::getHref).isEqualTo(RootController.PATH);
 		}
-	}
 
-	@DisplayName("Root Model Links")
-	@Nested
-	class TestBuildRootModelLinks {
+		@Nested
+		class TestConfigurationLink {
 
-		@Test
-		void shouldCheckConfigurationPermission() {
-			modelAssembler.buildRootModelLinks();
+			@Test
+			void shouldCallHasConfigurationPermission() {
+				modelAssembler.toModel(root);
 
-			verify(currentUserService).hasConfigurationPermission();
-		}
+				verify(currentUserService).hasConfigurationPermission();
+			}
 
-		@Nested
-		class TestOnHasConfigurationPermission {
+			@Nested
+			class TestOnHasConfigurationPermission {
+
+				@BeforeEach
+				void hasConfigurationPermission() {
+					when(currentUserService.hasConfigurationPermission()).thenReturn(true);
+					when(restProperties.getBasePath()).thenReturn(BASE_PATH);
+				}
+
+				@Test
+				void shouldHaveHrefToConfiguration() {
+					var model = modelAssembler.toModel(root);
 
-			@BeforeEach
-			void hasConfigurationPermission() {
-				when(currentUserService.hasConfigurationPermission()).thenReturn(true);
-				when(restProperties.getBasePath()).thenReturn(BASE_PATH);
+					assertThat(model.getLink(REL_CONFIGURATION)).get().extracting(Link::getHref).isEqualTo(BASE_PATH);
+				}
 			}
 
-			@Test
-			void shouldHaveHrefToConfiguration() {
-				var links = modelAssembler.buildRootModelLinks();
+			@Nested
+			class TestOnHasNotConfigurationPermission {
+
+				@BeforeEach
+				void hasNotConfigurationPermission() {
+					when(currentUserService.hasConfigurationPermission()).thenReturn(false);
+				}
 
-				assertThat(links).containsExactly(
-						Link.of(RootController.PATH),
-						Link.of(BASE_PATH, REL_CONFIGURATION));
+				@Test
+				void shouldNotHaveConfigurationLink() {
+					var model = modelAssembler.toModel(root);
+
+					assertThat(model.getLink(REL_CONFIGURATION)).isEmpty();
+				}
 			}
 		}
 
 		@Nested
-		class TestOnNotHasConfigurationPermission {
+		class TestDocumentationLink {
+
+			@Test
+			void shouldGetDocumentationUrl() {
+				modelAssembler.toModel(root);
 
-			@BeforeEach
-			void hasNotConfigurationPermission() {
-				when(currentUserService.hasConfigurationPermission()).thenReturn(false);
+				verify(documentationProperties).getUrl();
 			}
 
-			@Test
-			void shouldHaveOnlySelfLink() {
-				var links = modelAssembler.buildRootModelLinks();
+			@Nested
+			class TestOnDocumentationUrlGiven {
+
+				private final String documentationUrl = LoremIpsum.getInstance().getUrl();
+
+				@BeforeEach
+				void mock() {
+					when(documentationProperties.getUrl()).thenReturn(documentationUrl);
+				}
 
-				assertThat(links).containsExactly(
-						Link.of(RootController.PATH));
+				@Test
+				void shouldHaveDocumentationLink() {
+					var model = modelAssembler.toModel(root);
+
+					assertThat(model.getLink(REL_DOCUMENTATIONS)).get().extracting(Link::getHref).isEqualTo(documentationUrl);
+				}
 			}
-		}
 
-	}
+			@Nested
+			class TestOnDocumentationUrlNotGiven {
+
+				@BeforeEach
+				void mock() {
+					when(documentationProperties.getUrl()).thenReturn(null);
+				}
 
+				@Test
+				void shouldNotHaveDocumentationLink() {
+					var model = modelAssembler.toModel(root);
+
+					assertThat(model.getLink(REL_DOCUMENTATIONS)).isEmpty();
+				}
+			}
+		}
+	}
 }
\ No newline at end of file
-- 
GitLab


From 31d8a49189ce46ea419f2b1b57334cf8e316add6 Mon Sep 17 00:00:00 2001
From: Felix Reichenbach <felix.reichenbach@mgm-tp.com>
Date: Wed, 12 Feb 2025 17:10:00 +0100
Subject: [PATCH 2/5] OZG-7615 add helm configuration for documantation url

---
 src/main/helm/templates/deployment.yaml |  4 ++++
 src/test/helm/deployment_env_test.yaml  | 14 ++++++++++++--
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/src/main/helm/templates/deployment.yaml b/src/main/helm/templates/deployment.yaml
index 58ff6b8a..7131cc9d 100644
--- a/src/main/helm/templates/deployment.yaml
+++ b/src/main/helm/templates/deployment.yaml
@@ -70,6 +70,10 @@ spec:
             value: {{ include "app.ssoClientName" . }}
           - name: ozgcloud_oauth2_auth-server-url
             value: {{ include "app.ssoServerUrl" . }}
+          {{- if (((.Values.ozgcloud).user_assistance).documentation).url }}
+          - name: ozgcloud_user-assistance_documentation_url
+            value: {{ .Values.ozgcloud.user_assistance.documentation.url }}
+          {{- end }}
           {{- if not (.Values.database).useExternal }}
           - name: spring_data_mongodb_uri
             valueFrom:
diff --git a/src/test/helm/deployment_env_test.yaml b/src/test/helm/deployment_env_test.yaml
index dfa90b4d..f6c863d2 100644
--- a/src/test/helm/deployment_env_test.yaml
+++ b/src/test/helm/deployment_env_test.yaml
@@ -54,5 +54,15 @@ tests:
           content:
             name: ozgcloud_administration_sync_organisationseinheiten_cron
             value: "*/15 * * * *"
-
-
+  - it: should have user assistance documentation url
+    set:
+      ozgcloud:
+        user_assistance:
+          documentation:
+            url: http://hier/geht/es/zum/benutzerleitfaden.de
+    asserts:
+      - contains:
+          path: spec.template.spec.containers[0].env
+          content:
+            name: ozgcloud_user-assistance_documentation_url
+            value: http://hier/geht/es/zum/benutzerleitfaden.de
-- 
GitLab


From afbf34d550b5897f2cb187bfdf3e506c12cb2a27 Mon Sep 17 00:00:00 2001
From: Felix Reichenbach <felix.reichenbach@mgm-tp.com>
Date: Wed, 12 Feb 2025 17:10:58 +0100
Subject: [PATCH 3/5] OZG-7615 update common parent

---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 16673c5c..a36bcae4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,7 +31,7 @@
 	<parent>
 		<groupId>de.ozgcloud.common</groupId>
 		<artifactId>ozgcloud-common-parent</artifactId>
-		<version>4.9.0</version>
+		<version>4.11.0-SNAPSHOT</version>
 		<relativePath />
 	</parent>
 
-- 
GitLab


From b034f9d40b990062bbfaf7308a4cea9885d294cc Mon Sep 17 00:00:00 2001
From: Felix Reichenbach <felix.reichenbach@mgm-tp.com>
Date: Wed, 12 Feb 2025 17:23:18 +0100
Subject: [PATCH 4/5] OZG-7615 extract method in RootModelAssembler

---
 src/main/java/de/ozgcloud/admin/RootModelAssembler.java | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/main/java/de/ozgcloud/admin/RootModelAssembler.java b/src/main/java/de/ozgcloud/admin/RootModelAssembler.java
index 09e8c615..6e19dd78 100644
--- a/src/main/java/de/ozgcloud/admin/RootModelAssembler.java
+++ b/src/main/java/de/ozgcloud/admin/RootModelAssembler.java
@@ -48,10 +48,14 @@ public class RootModelAssembler implements RepresentationModelAssembler<Root, En
 	@Override
 	public EntityModel<Root> toModel(Root root) {
 		var rootModel = EntityModel.of(root);
+		addLinks(rootModel);
+		return rootModel;
+	}
+
+	private void addLinks(EntityModel<Root> rootModel) {
 		rootModel.add(WebMvcLinkBuilder.linkTo(RootController.class).withSelfRel());
 		rootModel.addIf(currentUserService.hasConfigurationPermission(), this::buildConfigLink);
 		rootModel.addIf(Objects.nonNull(documentationProperties.getUrl()), () -> Link.of(documentationProperties.getUrl(), REL_DOCUMENTATIONS));
-		return rootModel;
 	}
 
 	private Link buildConfigLink() {
-- 
GitLab


From b2fb30f03133e9d7ecafd58f4fde49ff2a535ace Mon Sep 17 00:00:00 2001
From: Felix Reichenbach <felix.reichenbach@mgm-tp.com>
Date: Tue, 18 Feb 2025 11:06:20 +0100
Subject: [PATCH 5/5] OZG-7615 add doc string for property and rename before
 each test methods

---
 src/main/java/de/ozgcloud/admin/DocumentationProperties.java | 4 ++++
 src/test/java/de/ozgcloud/admin/RootModelAssemblerTest.java  | 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/main/java/de/ozgcloud/admin/DocumentationProperties.java b/src/main/java/de/ozgcloud/admin/DocumentationProperties.java
index 956faa74..fb90234e 100644
--- a/src/main/java/de/ozgcloud/admin/DocumentationProperties.java
+++ b/src/main/java/de/ozgcloud/admin/DocumentationProperties.java
@@ -14,6 +14,10 @@ public class DocumentationProperties {
 
 	static final String DOCUMENTATION_PROPERTIES_PREFIX = "ozgcloud.user-assistance.documentation";
 
+	/*
+	 * Url pointing to the documentation (Benutzerleitfaden fuer die
+	 * Administration).
+	 */
 	private String url;
 
 }
diff --git a/src/test/java/de/ozgcloud/admin/RootModelAssemblerTest.java b/src/test/java/de/ozgcloud/admin/RootModelAssemblerTest.java
index 89338923..c7d0c03d 100644
--- a/src/test/java/de/ozgcloud/admin/RootModelAssemblerTest.java
+++ b/src/test/java/de/ozgcloud/admin/RootModelAssemblerTest.java
@@ -91,7 +91,7 @@ class RootModelAssemblerTest {
 			class TestOnHasConfigurationPermission {
 
 				@BeforeEach
-				void hasConfigurationPermission() {
+				void mock() {
 					when(currentUserService.hasConfigurationPermission()).thenReturn(true);
 					when(restProperties.getBasePath()).thenReturn(BASE_PATH);
 				}
@@ -108,7 +108,7 @@ class RootModelAssemblerTest {
 			class TestOnHasNotConfigurationPermission {
 
 				@BeforeEach
-				void hasNotConfigurationPermission() {
+				void mock() {
 					when(currentUserService.hasConfigurationPermission()).thenReturn(false);
 				}
 
-- 
GitLab