Skip to content
Snippets Groups Projects
Commit b55ccf23 authored by OZGCloud's avatar OZGCloud
Browse files

OZG-7131 refactor url provider

parent 97ec4b1d
Branches
Tags
No related merge requests found
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;
}
......@@ -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;
}
}
......@@ -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;
}
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));
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment