From 4b99fae1dd68b5326083517a8e685fa48d006625 Mon Sep 17 00:00:00 2001 From: mcilwain Date: Thu, 19 Jul 2018 11:57:04 -0700 Subject: [PATCH] Properly handle NAME_COLLISION domains in start-date sunrise Domains that are reserved with type NAME_COLLISION can be registered defensively during sunrise only, but DNS can never resolve for them. Correspondingly, we need to apply the SERVER_HOLD status for such registrations. We also send the registrar a poll message informing them of this act. This brings us up to feature parity with end-date sunrise (implemented in DomainAllocateFlow), which already has all of this handling. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=205277728 --- .../flows/domain/DomainAllocateFlow.java | 6 +- .../flows/domain/DomainCreateFlow.java | 41 +++++- .../flows/domain/DomainFlowUtils.java | 6 + .../flows/domain/DomainCreateFlowTest.java | 134 ++++++++++++++---- ...reate_registration_encoded_signed_mark.xml | 2 +- ...eate_response_encoded_signed_mark_name.xml | 2 +- 6 files changed, 153 insertions(+), 38 deletions(-) diff --git a/java/google/registry/flows/domain/DomainAllocateFlow.java b/java/google/registry/flows/domain/DomainAllocateFlow.java index e44b6e2d9..050b24203 100644 --- a/java/google/registry/flows/domain/DomainAllocateFlow.java +++ b/java/google/registry/flows/domain/DomainAllocateFlow.java @@ -17,6 +17,7 @@ package google.registry.flows.domain; import static com.google.common.collect.MoreCollectors.onlyElement; import static google.registry.flows.FlowUtils.validateClientIsLoggedIn; import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist; +import static google.registry.flows.domain.DomainFlowUtils.COLLISION_MESSAGE; import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences; import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse; import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes; @@ -113,11 +114,6 @@ import org.joda.time.Duration; @ReportingSpec(ActivityReportField.DOMAIN_CREATE) // Allocates are special domain creates. public class DomainAllocateFlow implements TransactionalFlow { - private static final String COLLISION_MESSAGE = - "Domain on the name collision list was allocated. But by policy, the domain will not be " - + "delegated. Please visit https://www.icann.org/namecollision for more information on name " - + "collision."; - @Inject ExtensionManager extensionManager; @Inject AuthInfo authInfo; @Inject ResourceCommand resourceCommand; diff --git a/java/google/registry/flows/domain/DomainCreateFlow.java b/java/google/registry/flows/domain/DomainCreateFlow.java index d873fcfab..58b927ade 100644 --- a/java/google/registry/flows/domain/DomainCreateFlow.java +++ b/java/google/registry/flows/domain/DomainCreateFlow.java @@ -17,9 +17,11 @@ package google.registry.flows.domain; import static google.registry.flows.FlowUtils.persistEntityChanges; import static google.registry.flows.FlowUtils.validateClientIsLoggedIn; import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist; +import static google.registry.flows.domain.DomainFlowUtils.COLLISION_MESSAGE; import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences; import static google.registry.flows.domain.DomainFlowUtils.createFeeCreateResponse; +import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes; import static google.registry.flows.domain.DomainFlowUtils.prepareMarkedLrpTokenEntity; import static google.registry.flows.domain.DomainFlowUtils.validateCreateCommandContactsAndNameservers; import static google.registry.flows.domain.DomainFlowUtils.validateDomainAllowedOnCreateRestrictedTld; @@ -38,6 +40,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNo import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive; import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; import static google.registry.model.EppResourceUtils.createDomainRepoId; +import static google.registry.model.eppcommon.StatusValue.SERVER_HOLD; import static google.registry.model.eppcommon.StatusValue.SERVER_TRANSFER_PROHIBITED; import static google.registry.model.eppcommon.StatusValue.SERVER_UPDATE_PROHIBITED; import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName; @@ -46,6 +49,7 @@ import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABIL import static google.registry.model.registry.Registry.TldState.START_DATE_SUNRISE; import static google.registry.model.registry.Registry.TldState.SUNRISE; import static google.registry.model.registry.Registry.TldState.SUNRUSH; +import static google.registry.model.registry.label.ReservationType.NAME_COLLISION; import static google.registry.model.registry.label.ReservedList.matchesAnchorTenantReservation; import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.leapSafeAddYears; @@ -74,7 +78,6 @@ import google.registry.flows.domain.token.AllocationTokenFlowUtils; import google.registry.model.ImmutableObject; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.Flag; -import google.registry.model.billing.BillingEvent.OneTime; import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Recurring; import google.registry.model.domain.DomainApplication; @@ -92,6 +95,7 @@ import google.registry.model.domain.secdns.SecDnsCreateExtension; import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationTokenExtension; import google.registry.model.eppcommon.AuthInfo; +import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppinput.EppInput; import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppoutput.CreateData.DomainCreateData; @@ -99,6 +103,7 @@ import google.registry.model.eppoutput.EppResponse; import google.registry.model.index.EppResourceIndex; import google.registry.model.index.ForeignKeyIndex; import google.registry.model.ofy.ObjectifyService; +import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage.Autorenew; import google.registry.model.registry.Registry; @@ -326,6 +331,17 @@ public class DomainCreateFlow implements TransactionalFlow { if (!feesAndCredits.getEapCost().isZero()) { entitiesToSave.add(createEapBillingEvent(feesAndCredits, createBillingEvent)); } + + ImmutableSet.Builder statuses = new ImmutableSet.Builder<>(); + if (registry.getDomainCreateRestricted()) { + statuses.add(SERVER_UPDATE_PROHIBITED, SERVER_TRANSFER_PROHIBITED); + } + if (getReservationTypes(domainName).contains(NAME_COLLISION)) { + statuses.add(SERVER_HOLD); + entitiesToSave.add( + createNameCollisionOneTimePollMessage(targetId, historyEntry, clientId, now)); + } + DomainResource newDomain = new DomainResource.Builder() .setCreationClientId(clientId) @@ -342,10 +358,7 @@ public class DomainCreateFlow implements TransactionalFlow { .setAuthInfo(command.getAuthInfo()) .setFullyQualifiedDomainName(targetId) .setNameservers(command.getNameservers()) - .setStatusValues( - registry.getDomainCreateRestricted() - ? ImmutableSet.of(SERVER_UPDATE_PROHIBITED, SERVER_TRANSFER_PROHIBITED) - : ImmutableSet.of()) + .setStatusValues(statuses.build()) .setContacts(command.getContacts()) .addGracePeriod(GracePeriod.forBillingEvent(GracePeriodStatus.ADD, createBillingEvent)) .build(); @@ -499,7 +512,7 @@ public class DomainCreateFlow implements TransactionalFlow { .build(); } - private OneTime createOneTimeBillingEvent( + private BillingEvent.OneTime createOneTimeBillingEvent( Registry registry, boolean isAnchorTenant, boolean isSunriseCreate, @@ -556,7 +569,7 @@ public class DomainCreateFlow implements TransactionalFlow { .build(); } - private static OneTime createEapBillingEvent( + private static BillingEvent.OneTime createEapBillingEvent( FeesAndCredits feesAndCredits, BillingEvent.OneTime createBillingEvent) { return new BillingEvent.OneTime.Builder() .setReason(Reason.FEE_EARLY_ACCESS) @@ -571,6 +584,20 @@ public class DomainCreateFlow implements TransactionalFlow { .build(); } + private static PollMessage.OneTime createNameCollisionOneTimePollMessage( + String fullyQualifiedDomainName, HistoryEntry historyEntry, String clientId, DateTime now) { + return new PollMessage.OneTime.Builder() + .setClientId(clientId) + .setEventTime(now) + .setMsg(COLLISION_MESSAGE) // Remind the registrar of the name collision policy. + .setResponseData( + ImmutableList.of( + DomainPendingActionNotificationResponse.create( + fullyQualifiedDomainName, true, historyEntry.getTrid(), now))) + .setParent(historyEntry) + .build(); + } + private boolean isLrpCreate(Registry registry, boolean isAnchorTenant, DateTime now) { return registry.getLrpPeriod().contains(now) && !isAnchorTenant; } diff --git a/java/google/registry/flows/domain/DomainFlowUtils.java b/java/google/registry/flows/domain/DomainFlowUtils.java index fd3bc3ffd..2c57be8dd 100644 --- a/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/java/google/registry/flows/domain/DomainFlowUtils.java @@ -149,6 +149,12 @@ public class DomainFlowUtils { ReservationType.NAME_COLLISION, ReservationType.MISTAKEN_PREMIUM); + /** Warning message for allocation of collision domains in sunrise. */ + public static final String COLLISION_MESSAGE = + "Domain on the name collision list was allocated. But by policy, the domain will not be " + + "delegated. Please visit https://www.icann.org/namecollision for more information on " + + "name collision."; + /** Non-sunrise tld states. */ private static final ImmutableSet DISALLOWED_TLD_STATES_FOR_APPLICATION_FLOWS = Sets.immutableEnumSet( diff --git a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java index 9fc2e8ea1..64e139284 100644 --- a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java @@ -21,6 +21,7 @@ import static google.registry.flows.FlowTestCase.UserPrivileges.SUPERUSER; import static google.registry.model.billing.BillingEvent.Flag.ANCHOR_TENANT; import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS; import static google.registry.model.eppcommon.StatusValue.OK; +import static google.registry.model.eppcommon.StatusValue.SERVER_HOLD; import static google.registry.model.eppcommon.StatusValue.SERVER_TRANSFER_PROHIBITED; import static google.registry.model.eppcommon.StatusValue.SERVER_UPDATE_PROHIBITED; import static google.registry.model.ofy.ObjectifyService.ofy; @@ -59,6 +60,7 @@ import static org.joda.money.CurrencyUnit.EUR; import static org.joda.money.CurrencyUnit.USD; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; @@ -144,6 +146,7 @@ import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.secdns.DelegationSignerData; import google.registry.model.domain.token.AllocationToken; import google.registry.model.eppcommon.StatusValue; +import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; import google.registry.model.poll.PollMessage; import google.registry.model.registrar.Registrar; import google.registry.model.registrar.Registrar.State; @@ -184,7 +187,9 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase - %NAME% + %DOMAIN% 2 ns1.example.net diff --git a/javatests/google/registry/flows/domain/testdata/domain_create_response_encoded_signed_mark_name.xml b/javatests/google/registry/flows/domain/testdata/domain_create_response_encoded_signed_mark_name.xml index 5ca7ab1c8..ee99da762 100644 --- a/javatests/google/registry/flows/domain/testdata/domain_create_response_encoded_signed_mark_name.xml +++ b/javatests/google/registry/flows/domain/testdata/domain_create_response_encoded_signed_mark_name.xml @@ -5,7 +5,7 @@ - test-validate.tld + %DOMAIN% 2014-09-09T09:09:09Z 2016-09-09T09:09:09Z