From 65e01b12a142c197936b3f3836349c14adb85e86 Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Tue, 9 Jul 2024 15:53:03 +0200 Subject: [PATCH] add HsDomainSetupHostingAssetValidator --- .../HostingAssetEntityValidatorRegistry.java | 1 + ...sDomainHttpSetupHostingAssetValidator.java | 56 +++++ .../HsDomainSetupHostingAssetValidator.java | 4 +- .../hs/validation/StringProperty.java | 11 +- .../hs/validation/ValidatableProperty.java | 4 +- .../HsHostingAssetControllerRestTest.java | 53 +++++ ...ingAssetPropsControllerAcceptanceTest.java | 3 +- ...gAssetEntityValidatorRegistryUnitTest.java | 3 +- ...DnsSetupHostingAssetValidatorUnitTest.java | 4 +- ...ttpSetupHostingAssetValidatorUnitTest.java | 197 ++++++++++++++++++ ...edServerHostingAssetValidatorUnitTest.java | 2 +- ...UnixUserHostingAssetValidatorUnitTest.java | 2 +- 12 files changed, 328 insertions(+), 12 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainHttpSetupHostingAssetValidator.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainHttpSetupHostingAssetValidatorUnitTest.java diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistry.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistry.java index 437f5c9a..62e47dec 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistry.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistry.java @@ -22,6 +22,7 @@ public class HostingAssetEntityValidatorRegistry { register(EMAIL_ALIAS, new HsEMailAliasHostingAssetValidator()); register(DOMAIN_SETUP, new HsDomainSetupHostingAssetValidator()); register(DOMAIN_DNS_SETUP, new HsDomainDnsSetupHostingAssetValidator()); + register(DOMAIN_HTTP_SETUP, new HsDomainHttpSetupHostingAssetValidator()); } private static void register(final Enum type, final HsEntityValidator validator) { diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainHttpSetupHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainHttpSetupHostingAssetValidator.java new file mode 100644 index 00000000..9065f7d9 --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainHttpSetupHostingAssetValidator.java @@ -0,0 +1,56 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; + +import java.util.regex.Pattern; + +import static java.util.Optional.ofNullable; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_HTTP_SETUP; +import static net.hostsharing.hsadminng.hs.validation.ArrayProperty.arrayOf; +import static net.hostsharing.hsadminng.hs.validation.BooleanProperty.booleanProperty; +import static net.hostsharing.hsadminng.hs.validation.StringProperty.stringProperty; + +class HsDomainHttpSetupHostingAssetValidator extends HostingAssetEntityValidator { + + public static final String IDENTIFIER_SUFFIX = "|HTTP"; + public static final String FILESYSTEM_PATH = "^/"; + public static final String PARTIAL_DOMAIN_NAME_REGEX = "(?!-)[A-Za-z0-9-]{1,63}(? entity.setIdentifier(pa.getIdentifier() + IDENTIFIER_SUFFIX)); + } + } +} diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainSetupHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainSetupHostingAssetValidator.java index 60ad9283..483472a7 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainSetupHostingAssetValidator.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainSetupHostingAssetValidator.java @@ -9,7 +9,7 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMA class HsDomainSetupHostingAssetValidator extends HostingAssetEntityValidator { - public static final String DOMAIN_NAME_REGEX = "^((?!-)[A-Za-z0-9-]{1,63}(?> extends ValidatableProp protected static final String[] KEY_ORDER = Array.join( ValidatableProperty.KEY_ORDER_HEAD, - Array.of("matchesRegEx", "minLength", "maxLength"), + Array.of("matchesRegEx", "minLength", "maxLength", "provided"), ValidatableProperty.KEY_ORDER_TAIL, Array.of("undisclosed")); + private String[] provided; private Pattern[] matchesRegEx; private Integer minLength; private Integer maxLength; @@ -50,6 +51,12 @@ public class StringProperty

> extends ValidatableProp return self(); } + /// predifined values, similar to fixed values in a combobox + public P provided(final String... provided) { + this.provided = provided; + return self(); + } + /** * The property value is not disclosed in error messages. * @@ -70,7 +77,7 @@ public class StringProperty

> extends ValidatableProp } if (matchesRegEx != null && stream(matchesRegEx).map(p -> p.matcher(propValue)).noneMatch(Matcher::matches)) { - result.add(propertyName + "' is expected to match any of " + Arrays.toString(matchesRegEx) + " but " + display(propValue) + " does not match any"); + result.add(propertyName + "' is expected to match any of " + Arrays.toString(matchesRegEx) + " but " + display(propValue) + " does not match" + (matchesRegEx.length>1?" any":"")); } if (isReadOnly() && propValue != null) { result.add(propertyName + "' is readonly but given as " + display(propValue)); diff --git a/src/main/java/net/hostsharing/hsadminng/hs/validation/ValidatableProperty.java b/src/main/java/net/hostsharing/hsadminng/hs/validation/ValidatableProperty.java index 346ee08b..01daf6aa 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/validation/ValidatableProperty.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/validation/ValidatableProperty.java @@ -182,8 +182,8 @@ protected void setDeferredInit(final Function[], T[]> //noinspection unchecked validate(result, (T) propValue, propsProvider); } else { - result.add(propertyName + "' is expected to be of type " + type + ", " + - "but is of type '" + propValue.getClass().getSimpleName() + "'"); + result.add(propertyName + "' is expected to be of type " + type.getSimpleName() + ", " + + "but is of type " + propValue.getClass().getSimpleName() + ""); } } return result; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java index eed85585..bdaacf04 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetControllerRestTest.java @@ -246,6 +246,59 @@ public class HsHostingAssetControllerRestTest { } } ] + """), + DOMAIN_HTTP_SETUP( + List.of( + HsHostingAssetEntity.builder() + .type(HsHostingAssetType.DOMAIN_HTTP_SETUP) + .identifier("example.org") + .caption("some fake Domain-HTTP-Setup") + .config(Map.ofEntries( + entry("htdocsfallback", false), + entry("indexes", false), + entry("cgi", false), + entry("passenger", false), + entry("passenger-errorpage", true), + entry("fastcgi", false), + entry("autoconfig", false), + entry("greylisting", false), + entry("includes", false), + entry("letsencrypt", false), + entry("multiviews", false), + entry("fcgi-php-bin", "/usr/lib/cgi-bin/php8"), + entry("passenger-nodejs", "/usr/bin/node-js7"), + entry("passenger-python", "/usr/bin/python6"), + entry("passenger-ruby", "/usr/bin/ruby5"), + entry("subdomains", Array.of("www", "test1", "test2")) + )) + .build()), + """ + [ + { + "type": "DOMAIN_HTTP_SETUP", + "identifier": "example.org", + "caption": "some fake Domain-HTTP-Setup", + "alarmContact": null, + "config": { + "autoconfig": false, + "cgi": false, + "fastcgi": false, + "greylisting": false, + "htdocsfallback": false, + "includes": false, + "indexes": false, + "letsencrypt": false, + "multiviews": false, + "passenger": false, + "passenger-errorpage": true, + "passenger-nodejs": "/usr/bin/node-js7", + "passenger-python": "/usr/bin/python6", + "passenger-ruby": "/usr/bin/ruby5", + "fcgi-php-bin": "/usr/lib/cgi-bin/php8", + "subdomains": ["www","test1","test2"] + } + } + ] """); final HsHostingAssetType assetType; diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java index bd571075..dd4afc09 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/HsHostingAssetPropsControllerAcceptanceTest.java @@ -37,7 +37,8 @@ class HsHostingAssetPropsControllerAcceptanceTest { "UNIX_USER", "EMAIL_ALIAS", "DOMAIN_SETUP", - "DOMAIN_DNS_SETUP" + "DOMAIN_DNS_SETUP", + "DOMAIN_HTTP_SETUP" ] """)); // @formatter:on diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistryUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistryUnitTest.java index a3ac41f3..daf0704f 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistryUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HostingAssetEntityValidatorRegistryUnitTest.java @@ -35,7 +35,8 @@ class HostingAssetEntityValidatorRegistryUnitTest { HsHostingAssetType.UNIX_USER, HsHostingAssetType.EMAIL_ALIAS, HsHostingAssetType.DOMAIN_SETUP, - HsHostingAssetType.DOMAIN_DNS_SETUP + HsHostingAssetType.DOMAIN_DNS_SETUP, + HsHostingAssetType.DOMAIN_HTTP_SETUP ); } } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainDnsSetupHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainDnsSetupHostingAssetValidatorUnitTest.java index c858a2f6..715138ec 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainDnsSetupHostingAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainDnsSetupHostingAssetValidatorUnitTest.java @@ -146,7 +146,7 @@ class HsDomainDnsSetupHostingAssetValidatorUnitTest { } @Test - void recectsInvalidProperties() { + void rejectsInvalidProperties() { // given final var mangedServerHostingAssetEntity = validEntityBuilder() .config(Map.ofEntries( @@ -163,7 +163,7 @@ class HsDomainDnsSetupHostingAssetValidatorUnitTest { // then assertThat(result).containsExactlyInAnyOrder( - "'DOMAIN_DNS_SETUP:example.org|DNS.config.TTL' is expected to be of type class java.lang.Integer, but is of type 'String'", + "'DOMAIN_DNS_SETUP:example.org|DNS.config.TTL' is expected to be of type Integer, but is of type String", "'DOMAIN_DNS_SETUP:example.org|DNS.config.user-RR' is expected to match any of [([a-z0-9\\.-]+|@)\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*IN\\s+[A-Z]+\\s+[^;].*(;.*)*, ([a-z0-9\\.-]+|@)\\s+IN\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*[A-Z]+\\s+[^;].*(;.*)*] but '@ 1814400 IN 1814400 BAD1 TTL only allowed once' does not match any", "'DOMAIN_DNS_SETUP:example.org|DNS.config.user-RR' is expected to match any of [([a-z0-9\\.-]+|@)\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*IN\\s+[A-Z]+\\s+[^;].*(;.*)*, ([a-z0-9\\.-]+|@)\\s+IN\\s+(([1-9][0-9]*[mMhHdDwW]{0,1})+\\s+)*[A-Z]+\\s+[^;].*(;.*)*] but 'www BAD1 Record-Class missing / not enough columns' does not match any"); } diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainHttpSetupHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainHttpSetupHostingAssetValidatorUnitTest.java new file mode 100644 index 00000000..fa75cded --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainHttpSetupHostingAssetValidatorUnitTest.java @@ -0,0 +1,197 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemEntity; +import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity.HsHostingAssetEntityBuilder; +import net.hostsharing.hsadminng.mapper.Array; +import org.junit.jupiter.api.Test; + +import java.util.Map; + +import static java.util.Map.entry; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_HTTP_SETUP; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_SETUP; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.MANAGED_WEBSPACE; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.UNIX_USER; +import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsDomainDnsSetupHostingAssetValidator.RR_COMMENT; +import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsDomainDnsSetupHostingAssetValidator.RR_RECORD_DATA; +import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsDomainDnsSetupHostingAssetValidator.RR_RECORD_TYPE; +import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsDomainDnsSetupHostingAssetValidator.RR_REGEX_IN; +import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsDomainDnsSetupHostingAssetValidator.RR_REGEX_NAME; +import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsDomainDnsSetupHostingAssetValidator.RR_REGEX_TTL; +import static org.assertj.core.api.Assertions.assertThat; + +class HsDomainHttpSetupHostingAssetValidatorUnitTest { + + static final HsHostingAssetEntity validDomainSetupEntity = HsHostingAssetEntity.builder() + .type(DOMAIN_SETUP) + .identifier("example.org") + .build(); + + static HsHostingAssetEntityBuilder validEntityBuilder() { + return HsHostingAssetEntity.builder() + .type(DOMAIN_HTTP_SETUP) + .parentAsset(validDomainSetupEntity) + .assignedToAsset(HsHostingAssetEntity.builder().type(UNIX_USER).build()) + .identifier("example.org|HTTP") + .config(Map.ofEntries( + entry("passenger-errorpage", true), + entry("subdomains", Array.of("www", "test") + ) + )); + } + + @Test + void containsExpectedProperties() { + // when + final var validator = HostingAssetEntityValidatorRegistry.forType(DOMAIN_HTTP_SETUP); + + // then + assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder( + "{type=boolean, propertyName=htdocsfallback, defaultValue=true}", + "{type=boolean, propertyName=indexes, defaultValue=true}", + "{type=boolean, propertyName=cgi, defaultValue=true}", + "{type=boolean, propertyName=passenger, defaultValue=true}", + "{type=boolean, propertyName=passenger-errorpage}", + "{type=boolean, propertyName=fastcgi, defaultValue=true}", + "{type=boolean, propertyName=autoconfig, defaultValue=true}", + "{type=boolean, propertyName=greylisting, defaultValue=true}", + "{type=boolean, propertyName=includes, defaultValue=true}", + "{type=boolean, propertyName=letsencrypt, defaultValue=true}", + "{type=boolean, propertyName=multiviews, defaultValue=true}", + "{type=string, propertyName=fcgi-php-bin, matchesRegEx=[^/], provided=[/usr/lib/cgi-bin/php], defaultValue=/usr/lib/cgi-bin/php}", + "{type=string, propertyName=passenger-nodejs, matchesRegEx=[^/], provided=[/usr/bin/node], defaultValue=/usr/bin/node}", + "{type=string, propertyName=passenger-python, matchesRegEx=[^/], provided=[/usr/bin/python3], defaultValue=/usr/bin/python3}", + "{type=string, propertyName=passenger-ruby, matchesRegEx=[^/], provided=[/usr/bin/ruby], defaultValue=/usr/bin/ruby}", + "{type=string[], propertyName=subdomains, elementsOf={type=string, propertyName=subdomains, matchesRegEx=[(?!-)[A-Za-z0-9-]{1,63}(?