diff --git a/docs/flows.md b/docs/flows.md index 4e7fa793a..ce34c767a 100644 --- a/docs/flows.md +++ b/docs/flows.md @@ -275,6 +275,11 @@ the domain to convert to a normal create and be billed for accordingly. * Linked resource in pending delete prohibits operation. * Nameservers are not whitelisted for this TLD. * Nameservers not specified for domain on TLD with nameserver whitelist. + * Nameservers are not whitelisted for this domain. + * Nameservers not specified for domain with nameserver-restricted + reservation. + * Requested domain does not have nameserver-restricted reservation for a + TLD that requires such a reservation to create domains. * Registrant is not whitelisted for this TLD. * 2306 * Cannot add and remove the same value. @@ -759,6 +764,12 @@ application. Updates cannot change the domain name that is being applied for. clear that status. * Resource status prohibits this operation. * Nameservers are not whitelisted for this TLD. + * Nameservers not specified for domain on TLD with nameserver whitelist. + * Nameservers are not whitelisted for this domain. + * Nameservers not specified for domain with nameserver-restricted + reservation. + * Requested domain does not have nameserver-restricted reservation for a + TLD that requires such a reservation to create domains. * Registrant is not whitelisted for this TLD. * Application status prohibits this domain update. * 2306 diff --git a/java/google/registry/flows/domain/DomainApplicationUpdateFlow.java b/java/google/registry/flows/domain/DomainApplicationUpdateFlow.java index b7003cf90..dd5e5fa89 100644 --- a/java/google/registry/flows/domain/DomainApplicationUpdateFlow.java +++ b/java/google/registry/flows/domain/DomainApplicationUpdateFlow.java @@ -29,8 +29,10 @@ import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToT import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences; import static google.registry.flows.domain.DomainFlowUtils.updateDsData; import static google.registry.flows.domain.DomainFlowUtils.validateContactsHaveTypes; +import static google.registry.flows.domain.DomainFlowUtils.validateDomainAllowedOnCreateRestrictedTld; import static google.registry.flows.domain.DomainFlowUtils.validateDsData; import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; +import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnDomain; import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnTld; import static google.registry.flows.domain.DomainFlowUtils.validateNameserversCountForTld; import static google.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts; @@ -41,6 +43,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNot import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete; import static google.registry.model.EppResourceUtils.loadDomainApplication; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.util.CollectionUtils.nullToEmpty; import com.google.common.base.Optional; import com.google.common.collect.ImmutableSet; @@ -56,7 +59,6 @@ import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForNonFreeOperationException; -import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForTldException; import google.registry.model.ImmutableObject; import google.registry.model.domain.DomainApplication; import google.registry.model.domain.DomainCommand.Update; @@ -99,7 +101,11 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.MissingAdminContactException} * @error {@link DomainFlowUtils.MissingContactTypeException} * @error {@link DomainFlowUtils.MissingTechnicalContactException} - * @error {@link NameserversNotAllowedForTldException} + * @error {@link DomainFlowUtils.NameserversNotAllowedForTldException} + * @error {@link DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException} + * @error {@link DomainFlowUtils.NameserversNotAllowedForDomainException} + * @error {@link DomainFlowUtils.NameserversNotSpecifiedForNameserverRestrictedDomainException} + * @error {@link DomainFlowUtils.DomainNotAllowedForTldWithCreateRestrictionException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException} * @error {@link DomainFlowUtils.RegistrantNotAllowedException} * @error {@link DomainFlowUtils.SecDnsAllUsageException} @@ -179,8 +185,9 @@ public class DomainApplicationUpdateFlow implements TransactionalFlow { throw new ApplicationStatusProhibitsUpdateException( existingApplication.getApplicationStatus()); } + Registry registry = Registry.get(tld); FeesAndCredits feesAndCredits = - pricingLogic.getApplicationUpdatePrice(Registry.get(tld), existingApplication, now); + pricingLogic.getApplicationUpdatePrice(registry, existingApplication, now); FeeUpdateCommandExtension feeUpdate = eppInput.getSingleExtension(FeeUpdateCommandExtension.class); // If the fee extension is present, validate it (even if the cost is zero, to check for price @@ -201,6 +208,13 @@ public class DomainApplicationUpdateFlow implements TransactionalFlow { validateRegistrantAllowedOnTld(tld, command.getInnerChange().getRegistrantContactId()); validateNameserversAllowedOnTld( tld, add.getNameserverFullyQualifiedHostNames()); + InternetDomainName domainName = + InternetDomainName.from(existingApplication.getFullyQualifiedDomainName()); + if (registry.getDomainCreateRestricted()) { + validateDomainAllowedOnCreateRestrictedTld(domainName); + } + validateNameserversAllowedOnDomain( + domainName, nullToEmpty(add.getNameserverFullyQualifiedHostNames())); } private HistoryEntry buildHistory(DomainApplication existingApplication, DateTime now) { diff --git a/java/google/registry/flows/domain/DomainFlowUtils.java b/java/google/registry/flows/domain/DomainFlowUtils.java index 53a532d70..5727a86fd 100644 --- a/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/java/google/registry/flows/domain/DomainFlowUtils.java @@ -375,7 +375,8 @@ public class DomainFlowUtils { } /** Validates if the requested domain can be reated on a domain create restricted TLD. */ - static void validateDomainCreateAllowed(InternetDomainName domainName) throws EppException { + static void validateDomainAllowedOnCreateRestrictedTld(InternetDomainName domainName) + throws EppException { ImmutableSet reservationTypes = getReservationTypes(domainName); if (!reservationTypes.contains(NAMESERVER_RESTRICTED)) { throw new DomainNotAllowedForTldWithCreateRestrictionException(domainName.toString()); @@ -782,7 +783,7 @@ public class DomainFlowUtils { validateNameserversCountForTld(tld, domainName, fullyQualifiedHostNames.size()); validateNameserversAllowedOnTld(tld, fullyQualifiedHostNames); if (registry.getDomainCreateRestricted()) { - validateDomainCreateAllowed(domainName); + validateDomainAllowedOnCreateRestrictedTld(domainName); } validateNameserversAllowedOnDomain(domainName, fullyQualifiedHostNames); } diff --git a/java/google/registry/flows/domain/DomainUpdateFlow.java b/java/google/registry/flows/domain/DomainUpdateFlow.java index 3365b0a7c..961b2fd06 100644 --- a/java/google/registry/flows/domain/DomainUpdateFlow.java +++ b/java/google/registry/flows/domain/DomainUpdateFlow.java @@ -29,8 +29,10 @@ import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToT import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences; import static google.registry.flows.domain.DomainFlowUtils.updateDsData; import static google.registry.flows.domain.DomainFlowUtils.validateContactsHaveTypes; +import static google.registry.flows.domain.DomainFlowUtils.validateDomainAllowedOnCreateRestrictedTld; import static google.registry.flows.domain.DomainFlowUtils.validateDsData; import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; +import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnDomain; import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnTld; import static google.registry.flows.domain.DomainFlowUtils.validateNameserversCountForTld; import static google.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts; @@ -39,6 +41,7 @@ import static google.registry.flows.domain.DomainFlowUtils.validateRequiredConta import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited; import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.DateTimeUtils.earliestOf; import com.google.common.base.Optional; @@ -116,6 +119,9 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.MissingTechnicalContactException} * @error {@link DomainFlowUtils.NameserversNotAllowedForTldException} * @error {@link DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException} + * @error {@link DomainFlowUtils.NameserversNotAllowedForDomainException} + * @error {@link DomainFlowUtils.NameserversNotSpecifiedForNameserverRestrictedDomainException} + * @error {@link DomainFlowUtils.DomainNotAllowedForTldWithCreateRestrictionException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException} * @error {@link DomainFlowUtils.RegistrantNotAllowedException} * @error {@link DomainFlowUtils.SecDnsAllUsageException} @@ -209,13 +215,14 @@ public final class DomainUpdateFlow implements TransactionalFlow { verifyAllStatusesAreClientSettable(union(add.getStatusValues(), remove.getStatusValues())); } String tld = existingDomain.getTld(); + Registry registry = Registry.get(tld); checkAllowedAccessToTld(clientId, tld); FeeTransformCommandExtension feeUpdate = eppInput.getSingleExtension(FeeUpdateCommandExtension.class); // If the fee extension is present, validate it (even if the cost is zero, to check for price // mismatches). Don't rely on the the validateFeeChallenge check for feeUpdate nullness, because // it throws an error if the name is premium, and we don't want to do that here. - FeesAndCredits feesAndCredits = pricingLogic.getUpdatePrice(Registry.get(tld), targetId, now); + FeesAndCredits feesAndCredits = pricingLogic.getUpdatePrice(registry, targetId, now); if (feeUpdate != null) { validateFeeChallenge(targetId, existingDomain.getTld(), now, feeUpdate, feesAndCredits); } else if (!feesAndCredits.getTotalCost().isZero()) { @@ -231,6 +238,13 @@ public final class DomainUpdateFlow implements TransactionalFlow { validateRegistrantAllowedOnTld(tld, command.getInnerChange().getRegistrantContactId()); validateNameserversAllowedOnTld( tld, add.getNameserverFullyQualifiedHostNames()); + InternetDomainName domainName = + InternetDomainName.from(existingDomain.getFullyQualifiedDomainName()); + if (registry.getDomainCreateRestricted()) { + validateDomainAllowedOnCreateRestrictedTld(domainName); + } + validateNameserversAllowedOnDomain( + domainName, nullToEmpty(add.getNameserverFullyQualifiedHostNames())); } private HistoryEntry buildHistoryEntry(DomainResource existingDomain, DateTime now) { diff --git a/javatests/google/registry/flows/domain/DomainApplicationUpdateFlowTest.java b/javatests/google/registry/flows/domain/DomainApplicationUpdateFlowTest.java index acd16fd19..0e7f61efe 100644 --- a/javatests/google/registry/flows/domain/DomainApplicationUpdateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainApplicationUpdateFlowTest.java @@ -24,6 +24,7 @@ import static google.registry.testing.DatastoreHelper.generateNewDomainRoid; import static google.registry.testing.DatastoreHelper.newDomainApplication; import static google.registry.testing.DatastoreHelper.persistActiveContact; import static google.registry.testing.DatastoreHelper.persistActiveHost; +import static google.registry.testing.DatastoreHelper.persistReservedList; import static google.registry.testing.DatastoreHelper.persistResource; import static google.registry.testing.DomainApplicationSubject.assertAboutApplications; import static google.registry.util.DateTimeUtils.START_OF_TIME; @@ -39,6 +40,7 @@ import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException; import google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException; import google.registry.flows.domain.DomainApplicationUpdateFlow.ApplicationStatusProhibitsUpdateException; import google.registry.flows.domain.DomainFlowUtils.ApplicationDomainNameMismatchException; +import google.registry.flows.domain.DomainFlowUtils.DomainNotAllowedForTldWithCreateRestrictionException; import google.registry.flows.domain.DomainFlowUtils.DuplicateContactForRoleException; import google.registry.flows.domain.DomainFlowUtils.EmptySecDnsUpdateException; import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException; @@ -47,7 +49,10 @@ import google.registry.flows.domain.DomainFlowUtils.MaxSigLifeChangeNotSupported import google.registry.flows.domain.DomainFlowUtils.MissingAdminContactException; import google.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; import google.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException; +import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForDomainException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForTldException; +import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForNameserverRestrictedDomainException; +import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException; import google.registry.flows.domain.DomainFlowUtils.SecDnsAllUsageException; @@ -671,6 +676,241 @@ public class DomainApplicationUpdateFlowTest doSuccessfulTest(); } + @Test + public void testFailure_tldWithNameserverWhitelist_removeLastNameserver() throws Exception { + setEppInput("domain_update_sunrise_remove_nameserver.xml"); + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setAllowedFullyQualifiedHostNames( + ImmutableSet.of("ns1.example.tld", "ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + thrown.expect(NameserversNotSpecifiedForTldWithNameserverWhitelistException.class); + runFlow(); + } + + @Test + public void testSuccess_tldWithNameserverWhitelist_removeNameserver() throws Exception { + setEppInput("domain_update_sunrise_remove_nameserver.xml"); + persistReferencedEntities(); + persistApplication(); + persistResource( + reloadDomainApplication() + .asBuilder() + .addNameservers( + ImmutableSet.of( + Key.create( + loadByForeignKey(HostResource.class, "ns2.example.tld", clock.nowUtc())))) + .build()); + persistResource( + Registry.get("tld") + .asBuilder() + .setAllowedFullyQualifiedHostNames( + ImmutableSet.of("ns1.example.tld", "ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + doSuccessfulTest(); + } + + @Test + public void testSuccess_domainNameserverRestricted_addedNameserverAllowed() throws Exception { + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setReservedLists( + persistReservedList( + "reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + doSuccessfulTest(); + } + + @Test + public void testFailure_domainNameserverRestricted_addedNameserverDisallowed() throws Exception { + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setReservedLists( + persistReservedList( + "reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns3.example.tld")) + .build()); + clock.advanceOneMilli(); + thrown.expect(NameserversNotAllowedForDomainException.class, "ns2.example.tld"); + runFlow(); + } + + @Test + public void testFailure_domainNameserverRestricted_removeLastNameserver() throws Exception { + setEppInput("domain_update_sunrise_remove_nameserver.xml"); + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setReservedLists( + persistReservedList( + "reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + thrown.expect(NameserversNotSpecifiedForNameserverRestrictedDomainException.class); + runFlow(); + } + + @Test + public void testSuccess_domainNameserverRestricted_removeNameservers() throws Exception { + setEppInput("domain_update_sunrise_remove_nameserver.xml"); + persistReferencedEntities(); + persistApplication(); + persistResource( + reloadDomainApplication() + .asBuilder() + .addNameservers( + ImmutableSet.of( + Key.create( + loadByForeignKey(HostResource.class, "ns2.example.tld", clock.nowUtc())))) + .build()); + persistResource( + Registry.get("tld") + .asBuilder() + .setReservedLists( + persistReservedList( + "reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + doSuccessfulTest(); + } + + @Test + public void testSuccess_domainCreateRestricted_addedNameserverAllowed() throws Exception { + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setDomainCreateRestricted(true) + .setReservedLists( + persistReservedList( + "reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + doSuccessfulTest(); + } + + @Test + public void testSuccess_addedNameserversAllowedInTldAndDomainNameserversWhitelists() + throws Exception { + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setAllowedFullyQualifiedHostNames( + ImmutableSet.of("ns1.example.tld", "ns2.example.tld")) + .setReservedLists( + persistReservedList( + "reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + doSuccessfulTest(); + } + + @Test + public void testFailure_addedNameserversAllowedInTld_disallowedInDomainNameserversWhitelists() + throws Exception { + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setAllowedFullyQualifiedHostNames( + ImmutableSet.of("ns1.example.tld", "ns2.example.tld")) + .setReservedLists( + persistReservedList( + "reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns3.example.tld")) + .build()); + clock.advanceOneMilli(); + thrown.expect(NameserversNotAllowedForDomainException.class, "ns2.example.tld"); + runFlow(); + } + + @Test + public void testFailure_addedNameserversDisallowedInTld_AllowedInDomainNameserversWhitelists() + throws Exception { + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setAllowedFullyQualifiedHostNames( + ImmutableSet.of("ns1.example.tld", "ns3.example.tld")) + .setReservedLists( + persistReservedList( + "reserved", "example,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + thrown.expect(NameserversNotAllowedForTldException.class, "ns2.example.tld"); + runFlow(); + } + + @Test + public void testFailure_tldNameserversAllowed_domainCreateRestricted_domainNotReserved() + throws Exception { + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setDomainCreateRestricted(true) + .setAllowedFullyQualifiedHostNames( + ImmutableSet.of("ns1.example.tld", "ns2.example.tld")) + .setReservedLists( + persistReservedList( + "reserved", "lol,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + thrown.expect(DomainNotAllowedForTldWithCreateRestrictionException.class); + runFlow(); + } + + @Test + public void testFailure_domainCreateRestricted_domainNotReserved() throws Exception { + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setDomainCreateRestricted(true) + .setReservedLists( + persistReservedList( + "reserved", "lol,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + thrown.expect(DomainNotAllowedForTldWithCreateRestrictionException.class); + runFlow(); + } + + @Test + public void testSuccess_domainCreateNotRestricted_domainNotReserved() throws Exception { + persistReferencedEntities(); + persistApplication(); + persistResource( + Registry.get("tld") + .asBuilder() + .setReservedLists( + persistReservedList( + "reserved", "lol,NAMESERVER_RESTRICTED,ns1.example.tld:ns2.example.tld")) + .build()); + clock.advanceOneMilli(); + doSuccessfulTest(); + } + @Test public void testFailure_customPricingLogic_feeMismatch() throws Exception { persistReferencedEntities(); diff --git a/javatests/google/registry/flows/domain/DomainUpdateFlowTest.java b/javatests/google/registry/flows/domain/DomainUpdateFlowTest.java index ec9f7b9b8..1093d755b 100644 --- a/javatests/google/registry/flows/domain/DomainUpdateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainUpdateFlowTest.java @@ -29,6 +29,7 @@ import static google.registry.testing.DatastoreHelper.persistActiveDomain; import static google.registry.testing.DatastoreHelper.persistActiveHost; import static google.registry.testing.DatastoreHelper.persistActiveSubordinateHost; import static google.registry.testing.DatastoreHelper.persistDeletedDomain; +import static google.registry.testing.DatastoreHelper.persistReservedList; import static google.registry.testing.DatastoreHelper.persistResource; import static google.registry.testing.DomainResourceSubject.assertAboutDomains; import static google.registry.testing.HistoryEntrySubject.assertAboutHistoryEntries; @@ -46,6 +47,7 @@ import google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException; import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException; import google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException; +import google.registry.flows.domain.DomainFlowUtils.DomainNotAllowedForTldWithCreateRestrictionException; import google.registry.flows.domain.DomainFlowUtils.DuplicateContactForRoleException; import google.registry.flows.domain.DomainFlowUtils.EmptySecDnsUpdateException; import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException; @@ -56,7 +58,9 @@ import google.registry.flows.domain.DomainFlowUtils.MaxSigLifeChangeNotSupported import google.registry.flows.domain.DomainFlowUtils.MissingAdminContactException; import google.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; import google.registry.flows.domain.DomainFlowUtils.MissingTechnicalContactException; +import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForDomainException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForTldException; +import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForNameserverRestrictedDomainException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException; @@ -1145,7 +1149,7 @@ public class DomainUpdateFlowTest extends ResourceFlowTestCase + + + + example.tld + + mak21 + Payment overdue. + + + + ns1.example.tld + + sh8013 + + + + sh8013 + + 2BARfoo + + + + + + + sunrise + 1-TLD + + + ABC-12345 + +