From 34c146341e20d6b2da81cd67c955bb08ce11fe1e Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Wed, 3 Jul 2024 17:32:05 +0200 Subject: [PATCH] add domain dns setup, WIP --- ...HsDomainDnsSetupHostingAssetValidator.java | 51 ++++++++++ .../HsDomainSetupHostingAssetValidator.java | 2 +- ...HsHostingAssetEntityValidatorRegistry.java | 1 + ...ingAssetPropsControllerAcceptanceTest.java | 3 +- ...DnsSetupHostingAssetValidatorUnitTest.java | 94 +++++++++++++++++++ 5 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainDnsSetupHostingAssetValidator.java create mode 100644 src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainDnsSetupHostingAssetValidatorUnitTest.java diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainDnsSetupHostingAssetValidator.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainDnsSetupHostingAssetValidator.java new file mode 100644 index 00000000..f924c71c --- /dev/null +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainDnsSetupHostingAssetValidator.java @@ -0,0 +1,51 @@ +package net.hostsharing.hsadminng.hs.hosting.asset.validators; + +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetEntity; +import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType; + +import java.util.regex.Pattern; + +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.IntegerProperty.integerProperty; +import static net.hostsharing.hsadminng.hs.validation.StringProperty.stringProperty; + +class HsDomainDnsSetupHostingAssetValidator extends HsHostingAssetEntityValidator { + + final static String RR_REGEX = + "[a-z0-9\\.-]+\\s+" + // a (e.g. domain) name + "([1-9][0-9]*[HDW]\\s+){0,1}" + // optional TTL + "IN\\s+" + // record class IN for Internet + "([1-9][0-9]*[HDW]\\s+){0,1}" + // optional TTL + "[A-Z]+\\s+([a-z0-9\\.-]+|\"[^\"]*\")\\s*" + // either a simple argument or a more complex in quotes + "(;.*)*"; // optional comment at the end of the line + + HsDomainDnsSetupHostingAssetValidator() { + super( BookingItem.mustBeNull(), + ParentAsset.mustBeOfType(HsHostingAssetType.DOMAIN_SETUP), + AssignedToAsset.mustBeNull(), + AlarmContact.isOptional(), + + integerProperty("TTL").min(0).withDefault(21600), + booleanProperty("auto-SOA-RR").withDefault(true), + booleanProperty("auto-NS-RR").withDefault(true), + booleanProperty("auto-MX-RR").withDefault(true), + booleanProperty("auto-A+AAAA-RR").withDefault(true), + booleanProperty("auto-MAILSERVICES-RR").withDefault(true), // incl. AUTOCONFIG_RR, AUTODISCOVER_RR + booleanProperty("auto-DKIM-RR").withDefault(true), + booleanProperty("auto-SPF-RR").withDefault(true), + booleanProperty("auto-WILDCARD-MX-RR").withDefault(true), + booleanProperty("auto-WILDCARD-A+AAAA-RR").withDefault(true), + booleanProperty("auto-WILDCARD-DKIM-RR").withDefault(true), // TODO.spec: ask Peter + booleanProperty("auto-WILDCARD-SPF-RR").withDefault(true), + arrayOf( + stringProperty("user-RR").matchesRegEx(RR_REGEX).required() + ).optional()); + } + + @Override + protected Pattern identifierPattern(final HsHostingAssetEntity assetEntity) { + // FIXME: should be auto-initialized + return Pattern.compile("^" + assetEntity.getParentAsset().getIdentifier() + "$"); + } +} 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 af671f46..d2693f7e 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 @@ -6,7 +6,7 @@ import java.util.regex.Pattern; class HsDomainSetupHostingAssetValidator extends HsHostingAssetEntityValidator { - private static final String DOMAIN_NAME_REGEX = "^((?!-)[A-Za-z0-9-]{1,63}(? type, final HsEntityValidator validator) { 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 1a3d2e0d..bd571075 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 @@ -36,7 +36,8 @@ class HsHostingAssetPropsControllerAcceptanceTest { "CLOUD_SERVER", "UNIX_USER", "EMAIL_ALIAS", - "DOMAIN_SETUP" + "DOMAIN_SETUP", + "DOMAIN_DNS_SETUP" ] """)); // @formatter:on 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 new file mode 100644 index 00000000..9da99764 --- /dev/null +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainDnsSetupHostingAssetValidatorUnitTest.java @@ -0,0 +1,94 @@ +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.CLOUD_SERVER; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_DNS_SETUP; +import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_SETUP; +import static org.assertj.core.api.Assertions.assertThat; + +class HsDomainDnsSetupHostingAssetValidatorUnitTest { + + static final HsHostingAssetEntity validDomainSetupEntity = HsHostingAssetEntity.builder() + .type(DOMAIN_SETUP) + .identifier("example.org") + .build(); + + static HsHostingAssetEntityBuilder validEntityBuilder() { + return HsHostingAssetEntity.builder() + .type(DOMAIN_DNS_SETUP) + .parentAsset(validDomainSetupEntity) + .identifier("example.org") + .config(Map.ofEntries( + entry("user-RR", Array.of( + "www IN CNAME example.com. ; www.example.com is an alias for example.com", + "ns IN A 192.0.2.2 ; IPv4 address for ns.example.com") + ) + )); + } + + @Test + void rejectsInvalidIdentifier() { + // given + final var givenEntity = validEntityBuilder().identifier("wrong.org").build(); + final var validator = HsHostingAssetEntityValidatorRegistry.forType(givenEntity.getType()); + + // when + final var result = validator.validateEntity(givenEntity); + + // then + assertThat(result).containsExactly( + "'identifier' expected to match '^example.org$', but is 'wrong.org'" + ); + } + + @Test + void acceptsValidIdentifier() { + // given + final var givenEntity = validEntityBuilder().identifier(validDomainSetupEntity.getIdentifier()).build(); + final var validator = HsHostingAssetEntityValidatorRegistry.forType(givenEntity.getType()); + + // when + final var result = validator.validateEntity(givenEntity); + + // then + assertThat(result).isEmpty(); + } + + @Test + void containsNoProperties() { + // when + final var validator = HsHostingAssetEntityValidatorRegistry.forType(CLOUD_SERVER); + + // then + assertThat(validator.properties()).map(Map::toString).isEmpty(); + } + + @Test + void validatesReferencedEntities() { + // given + final var mangedServerHostingAssetEntity = validEntityBuilder() + .parentAsset(HsHostingAssetEntity.builder().build()) + .assignedToAsset(HsHostingAssetEntity.builder().build()) + .bookingItem(HsBookingItemEntity.builder().type(HsBookingItemType.CLOUD_SERVER).build()) + .build(); + final var validator = HsHostingAssetEntityValidatorRegistry.forType(mangedServerHostingAssetEntity.getType()); + + // when + final var result = validator.validateEntity(mangedServerHostingAssetEntity); + + // then + assertThat(result).containsExactlyInAnyOrder( + "'DOMAIN_DNS_SETUP:example.org.bookingItem' must be null but is set to D-???????-?:null", + "'DOMAIN_DNS_SETUP:example.org.parentAsset' must be of type DOMAIN_SETUP but is of type null", + "'DOMAIN_DNS_SETUP:example.org.assignedToAsset' must be null but is set to D-???????-?:null"); + } +}