Skip to content

Commit

Permalink
adds ManualConfig to set manual configs for internal forms or overrid…
Browse files Browse the repository at this point in the history
…e urls provided by external form frontend configs
  • Loading branch information
thoniTUB committed Aug 22, 2022
1 parent 8d23a86 commit e9a90ad
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.bakdata.conquery.models.config;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;
import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;

import com.bakdata.conquery.io.cps.CPSType;
import lombok.Getter;
import lombok.Setter;

@CPSType(id = "MANUAL", base = PluginConfig.class)
@Getter
@Setter
public class ManualConfig implements PluginConfig {


private Map<String, @ManualURI URI> forms = Collections.emptyMap();

@Target({ANNOTATION_TYPE, FIELD, TYPE_USE})
@Retention(RUNTIME)
@Constraint(validatedBy = ManualURIValidator.class)
@Documented
public @interface ManualURI {
String message() default "";

Class<?>[] groups() default {};

@SuppressWarnings("UnusedDeclaration") Class<? extends Payload>[] payload() default {};
}

public static class ManualURIValidator implements ConstraintValidator<ManualURI, URI> {

@Override
public boolean isValid(URI value, ConstraintValidatorContext context) {

if (value == null) {
return true;
}

context.disableDefaultConstraintViolation();

boolean isValid = true;

if (value.isOpaque()) {
isValid = false;
context.buildConstraintViolationWithTemplate("The URI was opaque")
.addConstraintViolation();
}

if (value.isAbsolute()) {
try {
var unused = value.toURL();
}
catch (MalformedURLException e) {
isValid = false;
context.buildConstraintViolationWithTemplate("Absolute URI is not a valid URL (" + e.getMessage() + ")")
.addConstraintViolation();
}
if (!List.of("http", "https").contains(value.getScheme())) {
isValid = false;
context.buildConstraintViolationWithTemplate("The URI has an unsupported Scheme: " + value.getScheme())
.addConstraintViolation();
}
}
else {
if (value.getAuthority() != null) {
isValid = false;
context.buildConstraintViolationWithTemplate("The URI is not absolute but has an authority: " + value.getAuthority())
.addConstraintViolation();
}
}

return isValid;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.PrintWriter;
import java.lang.reflect.Modifier;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
Expand All @@ -15,6 +16,7 @@
import com.bakdata.conquery.io.cps.CPSTypeIdResolver;
import com.bakdata.conquery.models.config.ConqueryConfig;
import com.bakdata.conquery.models.config.FrontendConfig;
import com.bakdata.conquery.models.config.ManualConfig;
import com.bakdata.conquery.resources.admin.rest.AdminProcessor;
import com.bakdata.conquery.util.QueryUtils;
import com.fasterxml.jackson.databind.JsonNode;
Expand Down Expand Up @@ -118,12 +120,27 @@ private Map<String, FormType> generateFEFormConfigMap() {
}

// Make relative handbook URLs relative to configured handbook base
final JsonNode manualUrl = configTree.get(MANUAL_URL_KEY);
// Config url mappings override urls from frontend config jsons
final URI manualURL = config.getPluginConfig(ManualConfig.class)
// first check override
.map(ManualConfig::getForms)
.map(m -> m.get(fullTypeIdentifier))
// then query the frontend config json
.orElseGet(() -> {
final JsonNode manualUrl = configTree.get(MANUAL_URL_KEY);
if (!manualUrl.isTextual()) {
log.warn("FrontendFormConfig {} contained field 'manualUrl' but it was not a text. Was: '{}'.", fullTypeIdentifier, manualUrl.getNodeType());
return null;
}

return URI.create(manualUrl.textValue());
});
final URL manualBaseUrl = config.getFrontend().getManualUrl();
if (manualBaseUrl != null && manualUrl != null) {
final TextNode manualNode = relativizeManualUrl(fullTypeIdentifier, manualUrl, manualBaseUrl);
if (manualBaseUrl != null && manualURL != null) {

final TextNode manualNode = relativizeManualUrl(fullTypeIdentifier, manualURL, manualBaseUrl);
if (manualNode == null) {
log.warn("Manual url relativiation did not succeed for {}. Skipping registration.", fullTypeIdentifier);
log.warn("Manual url relativization did not succeed for {}. Skipping registration.", fullTypeIdentifier);
continue;
}
configTree.set(MANUAL_URL_KEY, manualNode);
Expand All @@ -137,26 +154,26 @@ private Map<String, FormType> generateFEFormConfigMap() {
return result.build();
}

private TextNode relativizeManualUrl(@NonNull String formTypeIdentifier, @NonNull JsonNode manualUrl, @NonNull URL manualBaseUrl) {
if (!manualUrl.isTextual()) {
log.warn("FrontendFormConfig {} contained field 'manualUrl' but it was not a text. Was: '{}'.", formTypeIdentifier, manualUrl.getNodeType());
return null;
}

final String urlString = manualUrl.textValue();
final URI manualUri = URI.create(urlString);
if (manualUri.isAbsolute()) {
log.trace("Manual url for {} was already absolute: {}. Skipping relativization.", formTypeIdentifier, manualUri);
return new TextNode(urlString);
}
private TextNode relativizeManualUrl(@NonNull String formTypeIdentifier, @NonNull URI manualUri, @NonNull URL manualBaseUrl) {

try {
final String absoluteUrl = manualBaseUrl.toURI().resolve(manualUri).toString();
log.trace("Computed manual url for {}: {}", formTypeIdentifier, absoluteUrl);
return new TextNode(absoluteUrl);
if (manualUri.isAbsolute()) {
log.trace("Manual url for {} was already absolute: {}. Skipping relativization.", formTypeIdentifier, manualUri);
return new TextNode(manualUri.toURL().toString());
}

try {
final String absoluteUrl = manualBaseUrl.toURI().resolve(manualUri).toURL().toString();
log.trace("Computed manual url for {}: {}", formTypeIdentifier, absoluteUrl);
return new TextNode(absoluteUrl);
}
catch (URISyntaxException e) {
log.warn("Unable to resolve manual base url ('{}') and relative manual url ('{}')", manualBaseUrl, manualUri, e);
return null;
}
}
catch (URISyntaxException e) {
log.warn("Unable to resolve manual base url ('{}') and relative manual url ('{}')", manualBaseUrl, manualUri, e);
catch (MalformedURLException e) {
log.error("Unable to build url", e);
return null;
}
}
Expand Down

0 comments on commit e9a90ad

Please sign in to comment.