From 667b3908fdeca23ddf46d183f81117f23fa5836d Mon Sep 17 00:00:00 2001 From: Michael Hoennig Date: Thu, 12 Sep 2024 07:43:26 +0200 Subject: [PATCH] refactor DNS lookup result handling --- .../HsDomainSetupHostingAssetValidator.java | 93 +++++++++++-------- 1 file changed, 53 insertions(+), 40 deletions(-) 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 785424ad..a4ad06a4 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 @@ -2,9 +2,9 @@ package net.hostsharing.hsadminng.hs.hosting.asset.validators; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAsset; +import java.util.ArrayList; import java.util.List; import java.util.Optional; -import java.util.function.Supplier; import java.util.regex.Pattern; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.DOMAIN_SETUP; @@ -33,49 +33,15 @@ class HsDomainSetupHostingAssetValidator extends HostingAssetEntityValidator { return violations; } - final var domainName = assetEntity.getIdentifier(); - final var dnsResult = new Dns(domainName).fetchRecordsOfType("TXT"); - final Supplier getCode = () -> assetEntity.getBookingItem().getDirectValue("verificationCode", String.class); + final var dnsResult = new Dns(assetEntity.getIdentifier()).fetchRecordsOfType("TXT"); switch (dnsResult.status()) { - case Dns.Status.SUCCESS: { - final var expectedTxtRecordValue = "Hostsharing-domain-setup-verification-code=" + getCode.get(); - final var verificationFound = findTxtRecord(dnsResult, expectedTxtRecordValue) - .or(() -> superDomain(domainName) - .flatMap(superDomainName -> findTxtRecord( - new Dns(superDomainName).fetchRecordsOfType("TXT"), - expectedTxtRecordValue)) - ); - if (verificationFound.isEmpty()) { - violations.add( - "[DNS] no TXT record '" + expectedTxtRecordValue + - "' found for domain name '" + domainName + "' (nor in its super-domain)"); - } + case Dns.Status.SUCCESS: + violations.addAll(handleDomainNameFound(assetEntity, dnsResult)); break; - } - case Dns.Status.NAME_NOT_FOUND: { - if (isDnsVerificationRequiredForUnregisteredDomain(assetEntity)) { - final var superDomain = superDomain(domainName); - final var expectedTxtRecordValue = "Hostsharing-domain-setup-verification-code=" + getCode.get(); - final var verificationFoundInSuperDomain = superDomain.map(superDomainName -> - { - final Dns.Result superDomainDnsResult = new Dns(superDomainName).fetchRecordsOfType("TXT"); - if (superDomainDnsResult.status() != Dns.Status.SUCCESS) { - violations.add("[DNS] lookup failed for domain name '" + superDomainName + "': " + dnsResult.exception()); - } - return superDomainDnsResult; - } - ) - .flatMap(records -> findTxtRecord(records, expectedTxtRecordValue)); - if (verificationFoundInSuperDomain.isEmpty()) { - violations.add( - "[DNS] no TXT record '" + expectedTxtRecordValue + - "' found for domain name '" + superDomain.orElseThrow() + "'"); - } - } - // otherwise no DNS verification to be able to setup DNS for domains to register + case Dns.Status.NAME_NOT_FOUND: + violations.addAll(handleDomainNameNotFoundError(assetEntity, dnsResult)); break; - } case Dns.Status.INVALID_NAME: // should not happen because we validate the domain name at booking item level @@ -90,6 +56,10 @@ class HsDomainSetupHostingAssetValidator extends HostingAssetEntityValidator { return violations; } + private static String verificationCode(final HsHostingAsset assetEntity) { + return assetEntity.getBookingItem().getDirectValue("verificationCode", String.class); + } + @Override protected Pattern identifierPattern(final HsHostingAsset assetEntity) { if (assetEntity.getBookingItem() != null) { @@ -101,6 +71,49 @@ class HsDomainSetupHostingAssetValidator extends HostingAssetEntityValidator { return Pattern.compile(SUBDOMAIN_NAME_REGEX + "\\." + parentDomainName.replace(".", "\\."), Pattern.CASE_INSENSITIVE); } + private static List handleDomainNameFound(final HsHostingAsset assetEntity, final Dns.Result dnsResult) { + final var violations = new ArrayList(); + final var expectedTxtRecordValue = "Hostsharing-domain-setup-verification-code=" + verificationCode(assetEntity); + final var verificationFound = findTxtRecord(dnsResult, expectedTxtRecordValue) + .or(() -> superDomain(assetEntity.getIdentifier()) + .flatMap(superDomainName -> findTxtRecord( + new Dns(superDomainName).fetchRecordsOfType("TXT"), + expectedTxtRecordValue)) + ); + if (verificationFound.isEmpty()) { + violations.add( + "[DNS] no TXT record '" + expectedTxtRecordValue + + "' found for domain name '" + assetEntity.getIdentifier() + "' (nor in its super-domain)"); + } + return violations; + } + + private static List handleDomainNameNotFoundError(final HsHostingAsset assetEntity, final Dns.Result dnsResult) { + final var violations = new ArrayList(); + if (isDnsVerificationRequiredForUnregisteredDomain(assetEntity)) { + final var superDomain = superDomain(assetEntity.getIdentifier()); + final var expectedTxtRecordValue = "Hostsharing-domain-setup-verification-code=" + verificationCode(assetEntity); + final var verificationFoundInSuperDomain = superDomain.map(superDomainName -> + { + final Dns.Result superDomainDnsResult = new Dns(superDomainName).fetchRecordsOfType("TXT"); + if (superDomainDnsResult.status() != Dns.Status.SUCCESS) { + violations.add("[DNS] lookup failed for domain name '" + superDomainName + "': " + dnsResult.exception()); + } + return superDomainDnsResult; + } + ) + .flatMap(records -> findTxtRecord(records, expectedTxtRecordValue)); + if (verificationFoundInSuperDomain.isEmpty()) { + violations.add( + "[DNS] no TXT record '" + expectedTxtRecordValue + + "' found for domain name '" + superDomain.orElseThrow() + "'"); + } + } else { + // otherwise no DNS verification to be able to setup DNS for domains to register + } + return violations; + } + private static boolean isDnsVerificationRequiredForUnregisteredDomain(final HsHostingAsset assetEntity) { return !Dns.isRegistrableDomain(assetEntity.getIdentifier()) && assetEntity.getParentAsset() == null;