diff --git a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/Dns.java b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/Dns.java index 1eb7366f..63303110 100644 --- a/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/Dns.java +++ b/src/main/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/Dns.java @@ -4,6 +4,7 @@ import org.apache.commons.collections4.EnumerationUtils; import javax.naming.InvalidNameException; import javax.naming.NameNotFoundException; +import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.ServiceUnavailableException; import javax.naming.directory.Attribute; @@ -23,7 +24,6 @@ public class Dns { public enum Status { SUCCESS, - RECORD_TYPE_NOT_FOUND, NAME_NOT_FOUND, INVALID_NAME, SERVICE_UNAVAILABLE, @@ -31,6 +31,22 @@ public class Dns { } public record Result(Status status, List records, NamingException exception) { + + public static Result fromRecords(final NamingEnumeration enumeration) { + final List records = enumeration == null + ? emptyList() + : EnumerationUtils.toList(enumeration).stream().map(Object::toString).toList(); + return new Result(Status.SUCCESS, records, null); + } + + public static Result fromException(final NamingException exception) { + return switch (exception) { + case ServiceUnavailableException exc -> new Result(Status.SERVICE_UNAVAILABLE, null, exc); + case NameNotFoundException exc -> new Result(Status.NAME_NOT_FOUND, null, exc); + case InvalidNameException exc -> new Result(Status.INVALID_NAME, null, exc); + case NamingException exc -> new Result(Status.UNKNOWN_FAILURE, null, exc); + }; + } } private final String domainName; @@ -51,23 +67,12 @@ public class Dns { try { final var env = new Hashtable<>(); env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); - final Attribute r = new InitialDirContext(env) + final Attribute records = new InitialDirContext(env) .getAttributes(domainName, new String[] { recordType }) .get(recordType); - return new Result( - r == null ? Status.RECORD_TYPE_NOT_FOUND : Status.SUCCESS, - r == null - ? emptyList() - : EnumerationUtils.toList(r.getAll()).stream().map(Object::toString).toList(), - null); - } catch (final ServiceUnavailableException e) { - return new Result(Status.SERVICE_UNAVAILABLE, null, e); - } catch (final NameNotFoundException e) { - return new Result(Status.NAME_NOT_FOUND, null, e); - } catch (InvalidNameException e) { - return new Result(Status.INVALID_NAME, null, e); - } catch (NamingException e) { - return new Result(Status.UNKNOWN_FAILURE, null, e); + return Result.fromRecords(records != null ? records.getAll() : null); + } catch (final NamingException exception) { + return Result.fromException(exception); } } 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 26eec252..afd4ca85 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 @@ -54,12 +54,9 @@ class HsDomainSetupHostingAssetValidator extends HostingAssetEntityValidator { if (found.isPresent()) { break; } - case Dns.Status.RECORD_TYPE_NOT_FOUND: - violations.add("Domain " + assetEntity.getIdentifier() + " exists, but no record 'TXT Hostsharing-domain-setup-challenge:FIXME' found "); - break; case Dns.Status.NAME_NOT_FOUND: - // no DNS verification necessary + // no DNS verification necessary / FIXME: at least if the superdomain is at registrar level break; case Dns.Status.INVALID_NAME: diff --git a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainSetupHostingAssetValidatorUnitTest.java b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainSetupHostingAssetValidatorUnitTest.java index baebdf40..867fd4f7 100644 --- a/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainSetupHostingAssetValidatorUnitTest.java +++ b/src/test/java/net/hostsharing/hsadminng/hs/hosting/asset/validators/HsDomainSetupHostingAssetValidatorUnitTest.java @@ -9,6 +9,10 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.ValueSource; +import javax.naming.InvalidNameException; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; +import javax.naming.ServiceUnavailableException; import java.util.Map; import static net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetType.CLOUD_SERVER; @@ -176,6 +180,49 @@ class HsDomainSetupHostingAssetValidatorUnitTest { assertThat(result).isEmpty(); } + enum DnsLookupFailureTestCase { + SERVICE_UNAVAILABLE( + new ServiceUnavailableException("no Internet connection"), + "DNS request for example.org failed: javax.naming.ServiceUnavailableException: no Internet connection"), + NAME_NOT_FOUND( + new NameNotFoundException("domain not registered"), + null), // no + INVALID_NAME( + new InvalidNameException("domain name too long or whatever"), + "Invalid domain name example.org"), + UNKNOWN_FAILURE( + new NamingException("some other problem"), + "DNS request for example.org failed: javax.naming.NamingException: some other problem"); + + public final NamingException givenException; + public final String expectedErrorMessage; + + DnsLookupFailureTestCase(final NamingException givenException, final String expectedErrorMessage) { + this.givenException = givenException; + this.expectedErrorMessage = expectedErrorMessage; + } + } + + @ParameterizedTest + @EnumSource(DnsLookupFailureTestCase.class) + void handlesDnsLookupFailures(final DnsLookupFailureTestCase testCase) { + + // given + Dns.fakeNextResult(Dns.Result.fromException(testCase.givenException)); + final var domainSetupHostingAssetEntity = validEntityBuilder().build(); + final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType()); + + // when + final var result = validator.validateEntity(domainSetupHostingAssetEntity); + + // then + if (testCase.expectedErrorMessage != null) { + assertThat(result).containsExactly(testCase.expectedErrorMessage); + } else { + assertThat(result).isEmpty(); + } + } + private static HsHostingAssetRealEntity createValidParentDomainSetupAsset(final String parentDomainName) { final var bookingItem = HsBookingItemRealEntity.builder() .type(HsBookingItemType.DOMAIN_SETUP)