From 37440d6b2928886c936689ab6e84bba7450f19ca Mon Sep 17 00:00:00 2001 From: jianglai Date: Tue, 21 Mar 2017 11:50:13 -0700 Subject: [PATCH] Add nameserver validation in domain update related flows When updating domains, make sure that if the domains are nameserver restricted, the updated nameservers set on the domains are still consistent with the restriction. When updating domains of a domain created restricted TLD, validate if the domain is still on the reserved list with nameserver restricted reservation. If it is not, there's likely some conflicting states of the domain that needs to be reconciled (e. g.the domain is removed from the reserved list after being created). Throws an exception in this case. Also added missing tests for TLDs with nameserver whitelist. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=150781935 --- docs/flows.md | 11 + .../domain/DomainApplicationUpdateFlow.java | 20 +- .../flows/domain/DomainFlowUtils.java | 5 +- .../flows/domain/DomainUpdateFlow.java | 16 +- .../DomainApplicationUpdateFlowTest.java | 240 ++++++++++++++++++ .../flows/domain/DomainUpdateFlowTest.java | 198 ++++++++++++++- ...omain_update_sunrise_remove_nameserver.xml | 35 +++ 7 files changed, 517 insertions(+), 8 deletions(-) create mode 100644 javatests/google/registry/flows/domain/testdata/domain_update_sunrise_remove_nameserver.xml 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 + +