From 844b5ab7136d238f1dabfee29ba06e7f1aa33e1d Mon Sep 17 00:00:00 2001 From: Ben McIlwain Date: Tue, 20 Apr 2021 15:22:49 -0400 Subject: [PATCH] Send an immediate poll message for superuser domain deletes (#1096) * Send an immediate poll message for superuser domain deletes This poll message is in addition to the normal poll message that is sent when the domain's deletion is effective (typically 35 days later). It's needed because, in the event of a superuser deletion, the owning registrar won't otherwise necessarily know it's happening. Note that, in the case of a --immediate superuser deletion, the normal poll message is already being sent immediately, so this additional poll message is not necessary. --- .../flows/domain/DomainDeleteFlow.java | 23 +++++++++- .../flows/domain/DomainDeleteFlowTest.java | 45 +++++++++++++++---- .../registry/testing/DatabaseHelper.java | 8 ++-- 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java index 0a3da5183..f9d068f90 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java @@ -208,13 +208,21 @@ public final class DomainDeleteFlow implements TransactionalFlow { // Enqueue the deletion poll message if the delete is asynchronous or if requested by a // superuser (i.e. the registrar didn't request this delete and thus should be notified even if // it is synchronous). - if (!durationUntilDelete.equals(Duration.ZERO) || isSuperuser) { + if (durationUntilDelete.isLongerThan(Duration.ZERO) || isSuperuser) { PollMessage.OneTime deletePollMessage = createDeletePollMessage(existingDomain, historyEntry, deletionTime); entitiesToSave.add(deletePollMessage); builder.setDeletePollMessage(deletePollMessage.createVKey()); } + // Send a second poll message immediately if the domain is being deleted asynchronously by a + // registrar other than the sponsoring registrar (which will necessarily be a superuser). + if (durationUntilDelete.isLongerThan(Duration.ZERO) + && !clientId.equals(existingDomain.getPersistedCurrentSponsorClientId())) { + entitiesToSave.add( + createImmediateDeletePollMessage(existingDomain, historyEntry, now, deletionTime)); + } + // Cancel any grace periods that were still active, and set the expiration time accordingly. DateTime newExpirationTime = existingDomain.getRegistrationExpirationTime(); for (GracePeriod gracePeriod : existingDomain.getGracePeriods()) { @@ -346,6 +354,19 @@ public final class DomainDeleteFlow implements TransactionalFlow { .build(); } + private PollMessage.OneTime createImmediateDeletePollMessage( + DomainBase existingDomain, HistoryEntry historyEntry, DateTime now, DateTime deletionTime) { + return new PollMessage.OneTime.Builder() + .setClientId(existingDomain.getPersistedCurrentSponsorClientId()) + .setEventTime(now) + .setParent(historyEntry) + .setMsg( + String.format( + "Domain %s was deleted by registry administrator with final deletion effective: %s", + existingDomain.getDomainName(), deletionTime)) + .build(); + } + @Nullable private ImmutableList getResponseExtensions( DomainBase existingDomain, DateTime now) { diff --git a/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java index 8d8ff6d0b..6cadf91cd 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java @@ -59,6 +59,7 @@ import static org.joda.time.Duration.standardDays; import static org.joda.time.Duration.standardSeconds; import static org.junit.jupiter.api.Assertions.assertThrows; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; @@ -87,6 +88,7 @@ import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.Trid; import google.registry.model.host.HostResource; import google.registry.model.poll.PendingActionNotificationResponse; +import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; import google.registry.model.poll.PollMessage; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldType; @@ -328,12 +330,12 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase substitutions) @@ -355,7 +357,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase getPollMessages(String clientId, DateTime now) { + public static ImmutableList getPollMessages(String clientId, DateTime beforeOrAt) { return transactIfJpaTm( () -> tm().loadAllOf(PollMessage.class).stream() .filter(pollMessage -> pollMessage.getClientId().equals(clientId)) - .filter( - pollMessage -> - pollMessage.getEventTime().isEqual(now) - || pollMessage.getEventTime().isBefore(now)) + .filter(pollMessage -> isBeforeOrAt(pollMessage.getEventTime(), beforeOrAt)) .collect(toImmutableList())); }