check-domain-setup-permission #97
@ -44,7 +44,7 @@ class HsDomainSetupHostingAssetValidator extends HostingAssetEntityValidator {
|
||||
if (verificationFound.isEmpty()) {
|
||||
violations.add(
|
||||
"[DNS] no TXT record '" + expectedTxtRecordValue +
|
||||
"' found for domain name '" + domainName + "'");
|
||||
"' found for domain name '" + domainName + "' (nor in its super-domain)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -16,7 +16,9 @@ import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.ServiceUnavailableException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.util.Map.entry;
|
||||
import static java.util.Map.ofEntries;
|
||||
@ -27,13 +29,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
|
||||
static HsHostingAssetRbacEntity.HsHostingAssetRbacEntityBuilder<?, ?> validEntityBuilder(final String domainName) {
|
||||
final HsBookingItemRealEntity bookingItem = HsBookingItemRealEntity.builder()
|
||||
public static final Dns.Result DOMAIN_NOT_REGISTERED = Dns.Result.fromException(new NameNotFoundException(
|
||||
"domain not registered"));
|
||||
|
||||
static HsHostingAssetRbacEntity.HsHostingAssetRbacEntityBuilder<?, ?> validEntityBuilder(
|
||||
final String domainName,
|
||||
final Function<HsBookingItemRealEntity.HsBookingItemRealEntityBuilder<?, ?>, HsBookingItemRealEntity> buildBookingItem) {
|
||||
final HsBookingItemRealEntity bookingItem = buildBookingItem.apply(
|
||||
HsBookingItemRealEntity.builder()
|
||||
.type(HsBookingItemType.DOMAIN_SETUP)
|
||||
.resources(new HashMap<>(ofEntries(
|
||||
entry("domainName", domainName)
|
||||
)))
|
||||
.build();
|
||||
))));
|
||||
HsBookingItemEntityValidatorRegistry.forType(HsBookingItemType.DOMAIN_SETUP).prepareProperties(null, bookingItem);
|
||||
return HsHostingAssetRbacEntity.builder()
|
||||
.type(DOMAIN_SETUP)
|
||||
@ -41,8 +48,8 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
.identifier(domainName);
|
||||
}
|
||||
|
||||
static HsHostingAssetRbacEntity.HsHostingAssetRbacEntityBuilder<?, ?> validEntityBuilder() {
|
||||
return validEntityBuilder("example.org");
|
||||
static HsHostingAssetRbacEntity.HsHostingAssetRbacEntityBuilder<?, ?> validEntityBuilder(final String domainName) {
|
||||
return validEntityBuilder(domainName, HsBookingItemRealEntity.HsBookingItemRealEntityBuilder::build);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -50,6 +57,8 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
Dns.resetFakeResults();
|
||||
}
|
||||
|
||||
//=====================================================================================================================
|
||||
|
||||
enum InvalidDomainNameIdentifier {
|
||||
EMPTY(""),
|
||||
TOO_LONG("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456890123456789.de"),
|
||||
@ -68,7 +77,12 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
@EnumSource(InvalidDomainNameIdentifier.class)
|
||||
void rejectsInvalidIdentifier(final InvalidDomainNameIdentifier testCase) {
|
||||
// given
|
||||
final var givenEntity = validEntityBuilder().identifier(testCase.domainName).build();
|
||||
final var givenEntity = validEntityBuilder(testCase.domainName,
|
||||
bib -> bib.resources(new HashMap<>(ofEntries(
|
||||
entry("domainName", "example.org")
|
||||
))).build()
|
||||
).build();
|
||||
fakeValidDnsVerification(givenEntity);
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(givenEntity.getType());
|
||||
|
||||
// when
|
||||
@ -98,11 +112,7 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
void acceptsValidIdentifier(final ValidDomainNameIdentifier testCase) {
|
||||
// given
|
||||
final var givenEntity = validEntityBuilder(testCase.domainName).identifier(testCase.domainName).build();
|
||||
final var expectedHash = givenEntity.getBookingItem()
|
||||
.getDirectValue("verificationCode", String.class);
|
||||
Dns.fakeResultForDomain(
|
||||
testCase.domainName,
|
||||
Dns.Result.fromRecords("Hostsharing-domain-setup-verification-code=" + expectedHash));
|
||||
fakeValidDnsVerification(givenEntity);
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(givenEntity.getType());
|
||||
|
||||
// when
|
||||
@ -112,6 +122,13 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
||||
private static void fakeValidDnsVerification(final HsHostingAssetRbacEntity givenEntity) {
|
||||
final var expectedHash = givenEntity.getBookingItem().getDirectValue("verificationCode", String.class);
|
||||
Dns.fakeResultForDomain(
|
||||
givenEntity.getIdentifier(),
|
||||
Dns.Result.fromRecords("Hostsharing-domain-setup-verification-code=" + expectedHash));
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsNoProperties() {
|
||||
// when
|
||||
@ -124,10 +141,10 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
@Test
|
||||
void validatesReferencedEntities() {
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder()
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder("example.org",
|
||||
bib -> bib.type(HsBookingItemType.CLOUD_SERVER).build())
|
||||
.parentAsset(HsHostingAssetRealEntity.builder().type(CLOUD_SERVER).build())
|
||||
.assignedToAsset(HsHostingAssetRealEntity.builder().type(MANAGED_SERVER).build())
|
||||
.bookingItem(HsBookingItemRealEntity.builder().type(HsBookingItemType.CLOUD_SERVER).build())
|
||||
.build();
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
|
||||
|
||||
@ -144,9 +161,11 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
@Test
|
||||
void rejectsDomainNameNotMatchingBookingItemDomainName() {
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder()
|
||||
.identifier("not-matching-booking-item-domain-name.org")
|
||||
.build();
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder("not-matching-booking-item-domain-name.org",
|
||||
bib -> bib.resources(new HashMap<>(ofEntries(
|
||||
entry("domainName", "example.org")
|
||||
))).build()
|
||||
).build();
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
|
||||
|
||||
// when
|
||||
@ -161,10 +180,9 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
@ValueSource(strings = { "not-matching-booking-item-domain-name.org", "indirect.subdomain.example.org" })
|
||||
void rejectsDomainNameWhichIsNotADirectSubdomainOfParentAsset(final String newDomainName) {
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder()
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder(newDomainName)
|
||||
.bookingItem(null)
|
||||
.parentAsset(createValidParentDomainSetupAsset("example.org"))
|
||||
.identifier(newDomainName)
|
||||
.build();
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
|
||||
|
||||
@ -178,10 +196,13 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void expectsEitherParentAssetOrBookingItem() {
|
||||
void rejectsIfNeitherBookingItemNorParentAssetAreSet() {
|
||||
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder().build();
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder("example.org")
|
||||
.bookingItem(null)
|
||||
.parentAsset(null)
|
||||
.build();
|
||||
Dns.fakeResultForDomain(
|
||||
domainSetupHostingAssetEntity.getIdentifier(),
|
||||
new Dns.Result(Dns.Status.NAME_NOT_FOUND, null, null));
|
||||
@ -191,7 +212,7 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
assertThat(result).containsExactly("'DOMAIN_SETUP:example.org.bookingItem' must be of type DOMAIN_SETUP but is null");
|
||||
}
|
||||
|
||||
enum DnsLookupFailureTestCase {
|
||||
@ -222,7 +243,7 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
void handlesDnsLookupFailures(final DnsLookupFailureTestCase testCase) {
|
||||
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder().build();
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder("example.org").build();
|
||||
Dns.fakeResultForDomain(
|
||||
domainSetupHostingAssetEntity.getIdentifier(),
|
||||
Dns.Result.fromException(testCase.givenException));
|
||||
@ -239,153 +260,65 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================================================================================
|
||||
|
||||
@Test
|
||||
void allowSetupOfAvailableRegistrableDomain() {
|
||||
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder().build();
|
||||
final var domainName = domainSetupHostingAssetEntity.getIdentifier();
|
||||
Dns.fakeResultForDomain(
|
||||
domainName,
|
||||
Dns.Result.fromException(new NameNotFoundException("domain not registered")));
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
|
||||
|
||||
// when
|
||||
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
domainSetupFor("example.com").notRegistered()
|
||||
.isAccepted();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectSetupOfExistingRegistrableDomainWithoutValidDnsVerification() {
|
||||
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder().build();
|
||||
final var domainName = domainSetupHostingAssetEntity.getIdentifier();
|
||||
final var expectedHash = domainSetupHostingAssetEntity.getBookingItem()
|
||||
.getDirectValue("verificationCode", String.class);
|
||||
Dns.fakeResultForDomain(
|
||||
domainName,
|
||||
Dns.Result.fromRecords("Hostsharing-domain-setup-verification-code=SOME-DEFINITELY-WRONG-HASH"));
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
|
||||
|
||||
// when
|
||||
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
|
||||
|
||||
// then
|
||||
assertThat(result).contains("[DNS] no TXT record 'Hostsharing-domain-setup-verification-code=" + expectedHash
|
||||
+ "' found for domain name 'example.org'");
|
||||
domainSetupFor("example.com").registered()
|
||||
.isRejectedWithCauseMissingVerificationIn("example.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
void allowSetupOfExistingRegistrableDomainWithValidDnsVerification() {
|
||||
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder().build();
|
||||
final var domainName = domainSetupHostingAssetEntity.getIdentifier();
|
||||
final var expectedHash = domainSetupHostingAssetEntity.getBookingItem()
|
||||
.getDirectValue("verificationCode", String.class);
|
||||
Dns.fakeResultForDomain(
|
||||
domainName,
|
||||
Dns.Result.fromRecords("Hostsharing-domain-setup-verification-code=" + expectedHash));
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
|
||||
|
||||
// when
|
||||
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
domainSetupFor("example.org").registeredWithVerification()
|
||||
.isAccepted();
|
||||
}
|
||||
|
||||
@Test
|
||||
void allowSetupOfUnregisteredSubdomainWithValidDnsVerificationInSuperDomain() {
|
||||
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder("sub.example.org").build();
|
||||
// ... the new subdomain is not yet registered:
|
||||
Dns.fakeResultForDomain(
|
||||
"sub.example.org",
|
||||
Dns.Result.fromException(new NameNotFoundException("domain not registered")));
|
||||
// ... and a valid verification-code in the super-domain:
|
||||
final var expectedHash = domainSetupHostingAssetEntity.getBookingItem()
|
||||
.getDirectValue("verificationCode", String.class);
|
||||
Dns.fakeResultForDomain(
|
||||
"example.org",
|
||||
Dns.Result.fromRecords("Hostsharing-domain-setup-verification-code=" + expectedHash));
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
|
||||
|
||||
// when
|
||||
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
domainSetupFor("sub.example.org").notRegistered().withVerificationIn("example.org")
|
||||
.isAccepted();
|
||||
}
|
||||
|
||||
@Test
|
||||
void RejectSetupOfUnregisteredSubdomainWithoutDnsVerificationInSuperDomain() {
|
||||
void rejectSetupOfExistingRegistrableDomainWithInvalidDnsVerification() {
|
||||
domainSetupFor("example.com").registeredWithInvalidVerification()
|
||||
.isRejectedWithCauseMissingVerificationIn("example.com");
|
||||
}
|
||||
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder("sub.example.org").build();
|
||||
// ... the new subdomain is not yet registered:
|
||||
Dns.fakeResultForDomain(
|
||||
"sub.example.org",
|
||||
Dns.Result.fromException(new NameNotFoundException("domain not registered")));
|
||||
// ... and a valid verification-code in the super-domain:
|
||||
final var expectedHash = domainSetupHostingAssetEntity.getBookingItem()
|
||||
.getDirectValue("verificationCode", String.class);
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
|
||||
@Test
|
||||
void acceptSetupOfRegisteredSubdomainWithInvalidDnsVerificationButValidDnsVerificationInSuperDomain() {
|
||||
domainSetupFor("sub.example.com").registeredWithInvalidVerification().withVerificationIn("example.com")
|
||||
.isAccepted();
|
||||
}
|
||||
|
||||
// when
|
||||
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
|
||||
|
||||
// then
|
||||
assertThat(result).containsExactly(
|
||||
"[DNS] no TXT record 'Hostsharing-domain-setup-verification-code=" + expectedHash
|
||||
+ "' found for domain name 'example.org'");
|
||||
@Test
|
||||
void rejectSetupOfUnregisteredSubdomainWithoutDnsVerificationInSuperDomain() {
|
||||
domainSetupFor("sub.example.org").notRegistered()
|
||||
.isRejectedWithCauseMissingVerificationIn("example.org");
|
||||
}
|
||||
|
||||
@Test
|
||||
void allowSetupOfExistingSubdomainWithValidDnsVerificationInSuperDomain() {
|
||||
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder("sub.example.org").build();
|
||||
// ... the new subdomain is already registered:
|
||||
Dns.fakeResultForDomain("sub.example.org", Dns.Result.fromRecords());
|
||||
// ... and a valid verification-code in the super-domain:
|
||||
final var expectedHash = domainSetupHostingAssetEntity.getBookingItem()
|
||||
.getDirectValue("verificationCode", String.class);
|
||||
Dns.fakeResultForDomain(
|
||||
"example.org",
|
||||
Dns.Result.fromRecords("Hostsharing-domain-setup-verification-code=" + expectedHash));
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
|
||||
|
||||
// when
|
||||
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
|
||||
|
||||
// then
|
||||
assertThat(result).isEmpty();
|
||||
domainSetupFor("sub.example.org").registered()
|
||||
.withVerificationIn("example.org")
|
||||
.isAccepted();
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectSetupOfExistingSubdomainWithoutDnsVerification() {
|
||||
|
||||
// given
|
||||
final var domainSetupHostingAssetEntity = validEntityBuilder("sub.example.org").build();
|
||||
// ... the new subdomain is already registered:
|
||||
Dns.fakeResultForDomain("sub.example.org", Dns.Result.fromRecords());
|
||||
final var expectedHash = domainSetupHostingAssetEntity.getBookingItem()
|
||||
.getDirectValue("verificationCode", String.class);
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(domainSetupHostingAssetEntity.getType());
|
||||
|
||||
// when
|
||||
final var result = validator.validateEntity(domainSetupHostingAssetEntity);
|
||||
|
||||
// then
|
||||
assertThat(result).contains("[DNS] no TXT record 'Hostsharing-domain-setup-verification-code=" + expectedHash
|
||||
+ "' found for domain name 'sub.example.org'");
|
||||
domainSetupFor("sub.example.org").registered()
|
||||
.isRejectedWithCauseMissingVerificationIn("sub.example.org");
|
||||
}
|
||||
|
||||
//====================================================================================================================
|
||||
|
||||
private static HsHostingAssetRealEntity createValidParentDomainSetupAsset(final String parentDomainName) {
|
||||
final var bookingItem = HsBookingItemRealEntity.builder()
|
||||
.type(HsBookingItemType.DOMAIN_SETUP)
|
||||
@ -399,4 +332,65 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
|
||||
.identifier(parentDomainName).build();
|
||||
return parentAsset;
|
||||
}
|
||||
|
||||
class DomainSetupBuilder {
|
||||
|
||||
private final HsHostingAssetRbacEntity domainAsset;
|
||||
private final String expectedHash;
|
||||
|
||||
public DomainSetupBuilder(final String domainName) {
|
||||
domainAsset = validEntityBuilder(domainName).build();
|
||||
expectedHash = domainAsset.getBookingItem().getDirectValue("verificationCode", String.class);
|
||||
}
|
||||
|
||||
DomainSetupBuilder notRegistered() {
|
||||
Dns.fakeResultForDomain(domainAsset.getIdentifier(), DOMAIN_NOT_REGISTERED);
|
||||
return this;
|
||||
}
|
||||
|
||||
DomainSetupBuilder registered() {
|
||||
Dns.fakeResultForDomain(
|
||||
domainAsset.getIdentifier(),
|
||||
Dns.Result.fromRecords());
|
||||
return this;
|
||||
}
|
||||
|
||||
DomainSetupBuilder registeredWithInvalidVerification() {
|
||||
Dns.fakeResultForDomain(
|
||||
domainAsset.getIdentifier(),
|
||||
Dns.Result.fromRecords("Hostsharing-domain-setup-verification-code=SOME-DEFINITELY-WRONG-HASH"));
|
||||
return this;
|
||||
}
|
||||
|
||||
DomainSetupBuilder registeredWithVerification() {
|
||||
withVerificationIn(domainAsset.getIdentifier());
|
||||
return this;
|
||||
}
|
||||
|
||||
DomainSetupBuilder withVerificationIn(final String domainName) {
|
||||
Dns.fakeResultForDomain(
|
||||
domainName,
|
||||
Dns.Result.fromRecords("Hostsharing-domain-setup-verification-code=" + expectedHash));
|
||||
return this;
|
||||
}
|
||||
|
||||
void isRejectedWithCauseMissingVerificationIn(final String domainName) {
|
||||
assertThat(validate()).contains(
|
||||
"[DNS] no TXT record 'Hostsharing-domain-setup-verification-code=" + expectedHash
|
||||
+ "' found for domain name '" + domainName + "' (nor in its super-domain)");
|
||||
}
|
||||
|
||||
void isAccepted() {
|
||||
assertThat(validate()).isEmpty();
|
||||
}
|
||||
|
||||
private List<String> validate() {
|
||||
final var validator = HostingAssetEntityValidatorRegistry.forType(DOMAIN_SETUP);
|
||||
return validator.validateEntity(domainAsset);
|
||||
}
|
||||
}
|
||||
|
||||
private DomainSetupBuilder domainSetupFor(final String domainName) {
|
||||
return new DomainSetupBuilder(domainName);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user