Compare commits

..

No commits in common. "ca10f7a99886cce68aa2555faa30b31b702687f1" and "b1ab1afbb670c05b5211a9f1b126a31ec3be87b6" have entirely different histories.

5 changed files with 18 additions and 79 deletions

View File

@ -25,9 +25,8 @@ class HsDomainSetupBookingItemValidator extends HsBookingItemEntityValidator {
.notMatchesRegEx(REGISTRAR_LEVEL_DOMAINS).describedAs("is a forbidden registrar-level domain name") .notMatchesRegEx(REGISTRAR_LEVEL_DOMAINS).describedAs("is a forbidden registrar-level domain name")
.required(), .required(),
stringProperty(VERIFICATION_CODE_PROPERTY_NAME) stringProperty(VERIFICATION_CODE_PROPERTY_NAME)
.minLength(12) .readOnly().initializedBy(HsDomainSetupBookingItemValidator::generateVerificationCode)
.maxLength(64)
.initializedBy(HsDomainSetupBookingItemValidator::generateVerificationCode)
); );
} }

View File

@ -13,6 +13,7 @@ import static net.hostsharing.hsadminng.hs.hosting.asset.validators.HsDomainHttp
class HsDomainSetupHostingAssetValidator extends HostingAssetEntityValidator { class HsDomainSetupHostingAssetValidator extends HostingAssetEntityValidator {
public static final String FQDN_REGEX = "^((?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)+[A-Za-z]{2,12}";
public static final String DOMAIN_NAME_PROPERTY_NAME = "domainName"; public static final String DOMAIN_NAME_PROPERTY_NAME = "domainName";
HsDomainSetupHostingAssetValidator() { HsDomainSetupHostingAssetValidator() {

View File

@ -266,7 +266,7 @@ public abstract class ValidatableProperty<P extends ValidatableProperty<?, ?>, T
private boolean isSpecPotentiallyComplete() { private boolean isSpecPotentiallyComplete() {
return required == null && requiresAtLeastOneOf == null && requiresAtMaxOneOf == null && !readOnly && !writeOnly return required == null && requiresAtLeastOneOf == null && requiresAtMaxOneOf == null && !readOnly && !writeOnly
&& defaultValue == null && computedBy == null; && defaultValue == null;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -28,7 +28,7 @@ class HsDomainSetupBookingItemValidatorUnitTest {
private EntityManager em; private EntityManager em;
@Test @Test
void acceptsRegisterableDomainWithGeneratedVerificationCode() { void acceptsRegisterableDomain() {
// given // given
final var domainSetupBookingItemEntity = HsBookingItemRealEntity.builder() final var domainSetupBookingItemEntity = HsBookingItemRealEntity.builder()
.type(DOMAIN_SETUP) .type(DOMAIN_SETUP)
@ -46,26 +46,6 @@ class HsDomainSetupBookingItemValidatorUnitTest {
assertThat(result).isEmpty(); assertThat(result).isEmpty();
} }
@Test
void acceptsRegisterableDomainWithExplicitVerifiactionCode() {
// given
final var domainSetupBookingItemEntity = HsBookingItemRealEntity.builder()
.type(DOMAIN_SETUP)
.project(project)
.caption("Test-Domain")
.resources(Map.ofEntries(
entry("domainName", "example.org"),
entry("verificationCode", "1234-5678-9100")
))
.build();
// when
final var result = HsBookingItemEntityValidatorRegistry.doValidate(em, domainSetupBookingItemEntity);
// then
assertThat(result).isEmpty();
}
@Test @Test
void acceptsMaximumDomainNameLength() { void acceptsMaximumDomainNameLength() {
final var domainSetupBookingItemEntity = HsBookingItemRealEntity.builder() final var domainSetupBookingItemEntity = HsBookingItemRealEntity.builder()
@ -170,6 +150,6 @@ class HsDomainSetupBookingItemValidatorUnitTest {
// then // then
assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder( assertThat(validator.properties()).map(Map::toString).containsExactlyInAnyOrder(
"{type=string, propertyName=domainName, matchesRegEx=[^((?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)+[A-Za-z]{2,12}], matchesRegExDescription=is not a (non-top-level) fully qualified domain name, notMatchesRegEx=[[^.]+, (co|org|gov|ac|sch)\\.uk, (com|net|org|edu|gov|asn|id)\\.au, (co|ne|or|ac|go)\\.jp, (com|net|org|gov|edu|ac)\\.cn, (com|net|org|gov|edu|mil|art)\\.br, (co|net|org|gen|firm|ind)\\.in, (com|net|org|gob|edu)\\.mx, (gov|edu)\\.it, (co|net|org|govt|ac|school|geek|kiwi)\\.nz, (co|ne|or|go|re|pe)\\.kr], notMatchesRegExDescription=is a forbidden registrar-level domain name, maxLength=253, required=true, writeOnce=true}", "{type=string, propertyName=domainName, matchesRegEx=[^((?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)+[A-Za-z]{2,12}], matchesRegExDescription=is not a (non-top-level) fully qualified domain name, notMatchesRegEx=[[^.]+, (co|org|gov|ac|sch)\\.uk, (com|net|org|edu|gov|asn|id)\\.au, (co|ne|or|ac|go)\\.jp, (com|net|org|gov|edu|ac)\\.cn, (com|net|org|gov|edu|mil|art)\\.br, (co|net|org|gen|firm|ind)\\.in, (com|net|org|gob|edu)\\.mx, (gov|edu)\\.it, (co|net|org|govt|ac|school|geek|kiwi)\\.nz, (co|ne|or|go|re|pe)\\.kr], notMatchesRegExDescription=is a forbidden registrar-level domain name, maxLength=253, required=true, writeOnce=true}",
"{type=string, propertyName=verificationCode, minLength=12, maxLength=64, computed=IN_INIT}"); "{type=string, propertyName=verificationCode, readOnly=true, computed=IN_INIT}");
} }
} }

View File

@ -3,7 +3,6 @@ package net.hostsharing.hsadminng.hs.hosting.asset.validators;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealEntity; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemRealEntity;
import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType; import net.hostsharing.hsadminng.hs.booking.item.HsBookingItemType;
import net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidatorRegistry; import net.hostsharing.hsadminng.hs.booking.item.validators.HsBookingItemEntityValidatorRegistry;
import net.hostsharing.hsadminng.hs.booking.project.HsBookingProjectRealEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRbacEntity; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRbacEntity;
import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity; import net.hostsharing.hsadminng.hs.hosting.asset.HsHostingAssetRealEntity;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
@ -36,10 +35,8 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
static HsHostingAssetRbacEntity.HsHostingAssetRbacEntityBuilder<?, ?> validEntityBuilder( static HsHostingAssetRbacEntity.HsHostingAssetRbacEntityBuilder<?, ?> validEntityBuilder(
final String domainName, final String domainName,
final Function<HsBookingItemRealEntity.HsBookingItemRealEntityBuilder<?, ?>, HsBookingItemRealEntity> buildBookingItem) { final Function<HsBookingItemRealEntity.HsBookingItemRealEntityBuilder<?, ?>, HsBookingItemRealEntity> buildBookingItem) {
final var project = HsBookingProjectRealEntity.builder().build(); final HsBookingItemRealEntity bookingItem = buildBookingItem.apply(
final var bookingItem = buildBookingItem.apply(
HsBookingItemRealEntity.builder() HsBookingItemRealEntity.builder()
.project(project)
.type(HsBookingItemType.DOMAIN_SETUP) .type(HsBookingItemType.DOMAIN_SETUP)
.resources(new HashMap<>(ofEntries( .resources(new HashMap<>(ofEntries(
entry("domainName", domainName) entry("domainName", domainName)
@ -93,8 +90,7 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
// then // then
assertThat(result).contains( assertThat(result).contains(
"'identifier' expected to match '(\\*|(?!-)[A-Za-z0-9-]{1,63}(?<!-))\\.example\\.org', but is '" "'identifier' expected to match '(\\*|(?!-)[A-Za-z0-9-]{1,63}(?<!-))\\.example\\.org', but is '" + testCase.domainName + "'"
+ testCase.domainName + "'"
); );
} }
@ -145,8 +141,7 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
@Test @Test
void validatesReferencedEntities() { void validatesReferencedEntities() {
// given // given
final var domainSetupHostingAssetEntity = validEntityBuilder( final var domainSetupHostingAssetEntity = validEntityBuilder("example.org",
"example.org",
bib -> bib.type(HsBookingItemType.CLOUD_SERVER).build()) bib -> bib.type(HsBookingItemType.CLOUD_SERVER).build())
.parentAsset(HsHostingAssetRealEntity.builder().type(CLOUD_SERVER).build()) .parentAsset(HsHostingAssetRealEntity.builder().type(CLOUD_SERVER).build())
.assignedToAsset(HsHostingAssetRealEntity.builder().type(MANAGED_SERVER).build()) .assignedToAsset(HsHostingAssetRealEntity.builder().type(MANAGED_SERVER).build())
@ -166,8 +161,7 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
@Test @Test
void rejectsDomainNameNotMatchingBookingItemDomainName() { void rejectsDomainNameNotMatchingBookingItemDomainName() {
// given // given
final var domainSetupHostingAssetEntity = validEntityBuilder( final var domainSetupHostingAssetEntity = validEntityBuilder("not-matching-booking-item-domain-name.org",
"not-matching-booking-item-domain-name.org",
bib -> bib.resources(new HashMap<>(ofEntries( bib -> bib.resources(new HashMap<>(ofEntries(
entry("domainName", "example.org") entry("domainName", "example.org")
))).build() ))).build()
@ -268,24 +262,6 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
//===================================================================================================================== //=====================================================================================================================
@Test
void rejectsSetupOfRegistrar1stLevelDomain() {
domainSetupFor("org").notRegistered()
.isRejectedWithCauseForbidden("registrar-level domain name");
}
@Test
void rejectsSetupOfRegistrar2ndLevelDomain() {
domainSetupFor("co.uk").notRegistered()
.isRejectedWithCauseForbidden("registrar-level domain name");
}
@Test
void rejectsSetupOfHostsharingDmain() {
domainSetupFor("hostsharing.net").notRegistered()
.isRejectedWithCauseForbidden("Hostsharing domain name");
}
@Test @Test
void allowSetupOfAvailableRegistrableDomain() { void allowSetupOfAvailableRegistrableDomain() {
domainSetupFor("example.com").notRegistered() domainSetupFor("example.com").notRegistered()
@ -440,27 +416,13 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
+ "' found for domain name '" + domainName + "'"); + "' found for domain name '" + domainName + "'");
} }
void isRejectedWithCauseForbidden(final String type) {
assertThat(validate()).contains(
"'D-???????:null:null.resources.domainName' = '" + domainAsset.getIdentifier() + "' is a forbidden " + type
);
}
void isAccepted() { void isAccepted() {
assertThat(validate()).isEmpty(); assertThat(validate()).isEmpty();
} }
private List<String> validate() { private List<String> validate() {
if ( domainAsset.getBookingItem() != null ) { final var validator = HostingAssetEntityValidatorRegistry.forType(DOMAIN_SETUP);
final var biValidation = HsBookingItemEntityValidatorRegistry.forType(HsBookingItemType.DOMAIN_SETUP) return validator.validateEntity(domainAsset);
.validateEntity(domainAsset.getBookingItem());
if (!biValidation.isEmpty()) {
return biValidation;
}
}
return HostingAssetEntityValidatorRegistry.forType(DOMAIN_SETUP)
.validateEntity(domainAsset);
} }
} }
@ -470,10 +432,7 @@ class HsDomainSetupHostingAssetValidatorUnitTest {
private DomainSetupBuilder domainSetupWithParentAssetFor(final String domainName) { private DomainSetupBuilder domainSetupWithParentAssetFor(final String domainName) {
return new DomainSetupBuilder( return new DomainSetupBuilder(
HsHostingAssetRealEntity.builder() HsHostingAssetRealEntity.builder().type(DOMAIN_SETUP).identifier(Dns.superDomain(domainName).orElseThrow()).build(),
.type(DOMAIN_SETUP)
.identifier(Dns.superDomain(domainName).orElseThrow())
.build(),
domainName); domainName);
} }
} }