diff --git a/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/FachstelleProperties.java b/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/FachstelleProperties.java index f7af41f49b8778af927df2f44918c18e071d65ec..7aa6e3a64b9923a77d0a339c4d98abaf8ebcfc30 100644 --- a/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/FachstelleProperties.java +++ b/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/FachstelleProperties.java @@ -1,18 +1,25 @@ package de.ozgcloud.collaboration; +import jakarta.validation.constraints.NotEmpty; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; import lombok.Getter; import lombok.Setter; @Configuration @ConfigurationProperties(prefix = FachstelleProperties.PREFIX) +@ConditionalOnProperty(prefix = FachstelleProperties.PREFIX, name = { "host" }) @Getter @Setter +@Validated class FachstelleProperties { static final String PREFIX = "ozgcloud.fachstelle"; + @NotEmpty private String host; } diff --git a/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/FachstelleVorgangUrlProvider.java b/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/FachstelleVorgangUrlProvider.java index 5952aeab811e7d0eec5c8a9d211886a0a3b7953c..a4f624b13c37912889e932c5e359205a1368565a 100644 --- a/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/FachstelleVorgangUrlProvider.java +++ b/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/FachstelleVorgangUrlProvider.java @@ -25,47 +25,50 @@ package de.ozgcloud.collaboration; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; -import java.util.regex.Pattern; -import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; -import de.ozgcloud.common.errorhandling.TechnicalException; -import lombok.RequiredArgsConstructor; - @Component -@RequiredArgsConstructor +@ConditionalOnProperty(prefix = FachstelleProperties.PREFIX, name = { "host" }) class FachstelleVorgangUrlProvider { - private final FachstelleProperties fachstelleProperties; - @Qualifier(CollaborationManagerConfiguration.VORGANG_MANAGER_PROPERTIES_NAME) // NOSONAR - private final VorgangManagerProperties vorgangManagerProperties; + static final String URL_PATH_RESOURCES = "/resources?"; // NOSONAR + static final String QUERY_PARAM_URI = "uri="; + static final String URI_PATH_TEMPLATE = "%s/vorgangs/"; - public static final String VORGANG_URL_TEMPLATE = "%s/resources?uri=%s"; - private static final String RESOURCE_URI_TEMPLATE = "%s/vorgangs/%s"; - private static final String SERVICE_DOMAIN_NAME_PATTERN = "^(.*:/+)?([a-zA-Z.-]+)(:\\d*)?$"; + private final String vorgangUrlPrefix; - public String getUrl(String vorgangId) { - var fachstelleHost = fachstelleProperties.getHost(); - var serviceAddress = vorgangManagerProperties.getServiceAddress(); - if (StringUtils.isAnyBlank(fachstelleHost, serviceAddress)) { - throw new TechnicalException("Link to Fachstelle is not configured!"); - } - return VORGANG_URL_TEMPLATE.formatted(fachstelleHost, buildVorgangUri(vorgangId, serviceAddress)); + FachstelleVorgangUrlProvider(FachstelleProperties fachstelleProperties, + @Qualifier(CollaborationManagerConfiguration.VORGANG_MANAGER_PROPERTIES_NAME) VorgangManagerProperties vorgangManagerProperties) { + this.vorgangUrlPrefix = getFachstelleHost(fachstelleProperties) + URL_PATH_RESOURCES + buildUriQuery(vorgangManagerProperties); + } + + String getFachstelleHost(FachstelleProperties fachstelleProperties) { + return fachstelleProperties.getHost().startsWith("http") ? fachstelleProperties.getHost() : "https://" + fachstelleProperties.getHost(); + } + + private String buildUriQuery(VorgangManagerProperties vorgangManagerProperties) { + var uriPath = URI_PATH_TEMPLATE.formatted(getServiceName(vorgangManagerProperties)); + return QUERY_PARAM_URI + URLEncoder.encode(uriPath, StandardCharsets.UTF_8); } - String buildVorgangUri(String vorgangId, String serviceAddress) { - var domainName = extractServiceDomainName(serviceAddress); - var vorgangUri = RESOURCE_URI_TEMPLATE.formatted(domainName, vorgangId); - return URLEncoder.encode(vorgangUri, StandardCharsets.UTF_8); + String getServiceName(VorgangManagerProperties vorgangManagerProperties) { + return getDomainWithoutPort(getDomainWithoutProtocol(vorgangManagerProperties.getServiceAddress())); } - String extractServiceDomainName(String serviceAddress) { - var match = Pattern.compile(SERVICE_DOMAIN_NAME_PATTERN).matcher(serviceAddress); - if (!match.find()) { - throw new TechnicalException("No domain name found in " + serviceAddress); - } - return match.group(2); + private String getDomainWithoutProtocol(String serviceAddress) { + var protocolEnd = serviceAddress.lastIndexOf("/"); + return protocolEnd == -1 ? serviceAddress : serviceAddress.substring(protocolEnd + 1); + } + + private String getDomainWithoutPort(String serviceAddress) { + var portStart = serviceAddress.lastIndexOf(":"); + return portStart == -1 ? serviceAddress : serviceAddress.substring(0, portStart); + } + + public String getUrl(String vorgangId) { + return vorgangUrlPrefix + vorgangId; } } diff --git a/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/VorgangManagerProperties.java b/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/VorgangManagerProperties.java index 97d517e31f5e0a2308ef28fcfe188701a1cb2507..0057e9185929d7b765eddcc4dd1853683dc54e3e 100644 --- a/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/VorgangManagerProperties.java +++ b/collaboration-manager-server/src/main/java/de/ozgcloud/collaboration/VorgangManagerProperties.java @@ -23,8 +23,11 @@ */ package de.ozgcloud.collaboration; +import jakarta.validation.constraints.NotEmpty; + import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; +import org.springframework.validation.annotation.Validated; import lombok.Getter; import lombok.Setter; @@ -33,9 +36,11 @@ import lombok.Setter; @ConfigurationProperties(prefix = VorgangManagerProperties.PREFIX) @Getter @Setter +@Validated class VorgangManagerProperties { static final String PREFIX = "ozgcloud.vorgang-manager"; + @NotEmpty private String serviceAddress; } diff --git a/collaboration-manager-server/src/test/java/de/ozgcloud/collaboration/FachstelleVorgangUrlProviderTest.java b/collaboration-manager-server/src/test/java/de/ozgcloud/collaboration/FachstelleVorgangUrlProviderTest.java index 161eb0af86cc6e7c5d936de4d76ccd73272a1cf3..a23474f528ab5c2526cb1d39f36c5010393aac0d 100644 --- a/collaboration-manager-server/src/test/java/de/ozgcloud/collaboration/FachstelleVorgangUrlProviderTest.java +++ b/collaboration-manager-server/src/test/java/de/ozgcloud/collaboration/FachstelleVorgangUrlProviderTest.java @@ -1,139 +1,79 @@ package de.ozgcloud.collaboration; import static org.assertj.core.api.Assertions.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; +import java.util.UUID; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.NullAndEmptySource; import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Spy; +import org.springframework.test.util.ReflectionTestUtils; -import de.ozgcloud.collaboration.vorgang.VorgangTestFactory; -import de.ozgcloud.common.errorhandling.TechnicalException; +import com.thedeanda.lorem.LoremIpsum; class FachstelleVorgangUrlProviderTest { + private static final String FACHSTELLE_HOST = "https://" + LoremIpsum.getInstance().getWords(1); + private static final String VORGANG_MANAGER_SERVICE_ADDRESS = "vorgang-manager.test-namespace"; + + private FachstelleVorgangUrlProvider provider; + @Mock private FachstelleProperties fachstelleProperties; @Mock private VorgangManagerProperties vorgangManagerProperties; - @Spy - @InjectMocks - private FachstelleVorgangUrlProvider provider; + @BeforeEach + void init() { + when(fachstelleProperties.getHost()).thenReturn(FACHSTELLE_HOST); + when(vorgangManagerProperties.getServiceAddress()).thenReturn(VORGANG_MANAGER_SERVICE_ADDRESS); + provider = spy(new FachstelleVorgangUrlProvider(fachstelleProperties, vorgangManagerProperties)); + } @Nested - class TestGetUrl { - - private static final String FACHSTELLE_HOST = "https://test.fachstelle.de"; - private static final String VORGANG_MANAGER_SERVICE_ADDRESS = "vorgang-manager.test-namespace"; - - @Nested - class OnPropertiesSet { - - private static final String RESOURCES_URL = FACHSTELLE_HOST + "/resources"; - private static final String URI_PARAM = VORGANG_MANAGER_SERVICE_ADDRESS + "/vorgangs/" + VorgangTestFactory.ID_STR; - - @BeforeEach - void mock() { - when(fachstelleProperties.getHost()).thenReturn(FACHSTELLE_HOST); - when(vorgangManagerProperties.getServiceAddress()).thenReturn(VORGANG_MANAGER_SERVICE_ADDRESS); - - } - - @Test - void shouldGetFachstelleHost() { - provider.getUrl(VorgangTestFactory.ID_STR); - - verify(fachstelleProperties).getHost(); - } - - @Test - void shouldGetVorgangManagerServiceAddress() { - provider.getUrl(VorgangTestFactory.ID_STR); - - verify(vorgangManagerProperties).getServiceAddress(); - } - - @Test - void shouldCallBuildVorgangUri() { - provider.getUrl(VorgangTestFactory.ID_STR); - - verify(provider).buildVorgangUri(VorgangTestFactory.ID_STR, VORGANG_MANAGER_SERVICE_ADDRESS); - } - - @Test - void shouldReturnUrl() { - doReturn(URI_PARAM).when(provider).buildVorgangUri(any(), any()); - - var vorgangUrl = provider.getUrl(VorgangTestFactory.ID_STR); + class TestSetVorgangUrlPrefix { - assertThat(vorgangUrl).isEqualTo(RESOURCES_URL + "?uri=" + URI_PARAM); - } - } - - @Nested - class OnPropertiesNotSet { - - @ParameterizedTest - @NullAndEmptySource - void shouldThrowExceptionIfFachstelleHostIsNotSet(String host) { - when(fachstelleProperties.getHost()).thenReturn(host); - when(vorgangManagerProperties.getServiceAddress()).thenReturn(VORGANG_MANAGER_SERVICE_ADDRESS); - - assertThrows(TechnicalException.class, () -> provider.getUrl(VorgangTestFactory.ID_STR)); - } + @Test + void shouldBuildVorgangUrlPrefix() { + var encodedResourceUri = FachstelleVorgangUrlProvider.QUERY_PARAM_URI + VORGANG_MANAGER_SERVICE_ADDRESS + "%2Fvorgangs%2F"; + var vorgagUrlPrefix = FACHSTELLE_HOST + FachstelleVorgangUrlProvider.URL_PATH_RESOURCES + encodedResourceUri; - @ParameterizedTest - @NullAndEmptySource - void shouldThrowExceptionIfServiceAddressIsNotSet(String serviceAddress) { - when(vorgangManagerProperties.getServiceAddress()).thenReturn(serviceAddress); - when(fachstelleProperties.getHost()).thenReturn(FACHSTELLE_HOST); + var provider = createProvider(); - assertThrows(TechnicalException.class, () -> provider.getUrl(VorgangTestFactory.ID_STR)); - } + assertThat(provider).extracting("vorgangUrlPrefix").isEqualTo(vorgagUrlPrefix); } } @Nested - class TestBuildVorgangUri { + class TestGetFachstelleHost { - private static final String VORGANG_MANAGER_DOMAIN_NAME = "vorgang-manager.by-kiel-dev"; - private static final String VORGANG_MANAGER_SERVICE_ADDRESS = "dns:///vorgang-manager.by-kiel-dev:9090"; + @ParameterizedTest + @ValueSource(strings = { "http://localhost", "https://localhost" }) + void shouldReturnUnchanged(String fachstelleHost) { + when(fachstelleProperties.getHost()).thenReturn(fachstelleHost); - @BeforeEach - void setUp() { - doReturn(VORGANG_MANAGER_DOMAIN_NAME).when(provider).extractServiceDomainName(any()); - } + var result = provider.getFachstelleHost(fachstelleProperties); - @Test - void shouldCallExtractServiceDomainName() { - buildVorgangUri(); - - verify(provider).extractServiceDomainName(VORGANG_MANAGER_SERVICE_ADDRESS); + assertThat(result).isEqualTo(fachstelleHost); } @Test - void shouldReturnEncodedVorgangUri() { - var vorgangUri = buildVorgangUri(); + void shouldAddHttps() { + when(fachstelleProperties.getHost()).thenReturn("localhost"); - assertThat(vorgangUri).isEqualTo(VORGANG_MANAGER_DOMAIN_NAME + "%2Fvorgangs%2F" + VorgangTestFactory.ID_STR); - } + var result = provider.getFachstelleHost(fachstelleProperties); - private String buildVorgangUri() { - return provider.buildVorgangUri(VorgangTestFactory.ID_STR, VORGANG_MANAGER_SERVICE_ADDRESS); + assertThat(result).isEqualTo("https://localhost"); } } @Nested class TestExtractServiceDomainName { + @ParameterizedTest @ValueSource(strings = { "dns:///vorgang-manager.by-kiel-dev:9090", @@ -146,17 +86,31 @@ class FachstelleVorgangUrlProviderTest { "dns:/vorgang-manager.by-kiel-dev:1", "abc:/vorgang-manager.by-kiel-dev:9090" }) void shouldReturnDomainName(String serviceAddress) { - var address = provider.extractServiceDomainName(serviceAddress); + when(vorgangManagerProperties.getServiceAddress()).thenReturn(serviceAddress); + + var address = provider.getServiceName(vorgangManagerProperties); assertThat(address).isEqualTo("vorgang-manager.by-kiel-dev"); } + } + + @Nested + class TestGetUrl { + + private static final String VORGANG_URL_PREFIX = LoremIpsum.getInstance().getUrl(); @Test - void shouldThrowTechnicalException() { - var invalidServiceAddress = "123"; + void shouldReturnUrl() { + ReflectionTestUtils.setField(provider, "vorgangUrlPrefix", VORGANG_URL_PREFIX); + var vorgangId = UUID.randomUUID().toString(); + + var url = provider.getUrl(vorgangId); - assertThatThrownBy(() -> provider.extractServiceDomainName(invalidServiceAddress)).isInstanceOf( - TechnicalException.class).hasMessageStartingWith("No domain name found in " + invalidServiceAddress); + assertThat(url).isEqualTo(VORGANG_URL_PREFIX + vorgangId); } } + + private FachstelleVorgangUrlProvider createProvider() { + return spy(new FachstelleVorgangUrlProvider(fachstelleProperties, vorgangManagerProperties)); + } }