diff --git a/java/google/registry/flows/ResourceFlowUtils.java b/java/google/registry/flows/ResourceFlowUtils.java index f0f5a3669..943e24c94 100644 --- a/java/google/registry/flows/ResourceFlowUtils.java +++ b/java/google/registry/flows/ResourceFlowUtils.java @@ -14,6 +14,7 @@ package google.registry.flows; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.Iterables.tryFind; @@ -214,6 +215,7 @@ public final class ResourceFlowUtils { */ public static TransferData createResolvedTransferData( TransferData oldTransferData, TransferStatus transferStatus, DateTime now) { + checkArgument(!oldTransferData.equals(TransferData.EMPTY), "No old transfer to resolve."); return oldTransferData.asBuilder() .setExtendedRegistrationYears(null) .setServerApproveEntities(null) @@ -238,6 +240,9 @@ public final class ResourceFlowUtils { R extends EppResource & ResourceWithTransferData, B extends EppResource.Builder & BuilderWithTransferData> B resolvePendingTransfer( R resource, TransferStatus transferStatus, DateTime now) { + checkState( + resource.getStatusValues().contains(StatusValue.PENDING_TRANSFER), + "Resource is not in pending transfer status."); return ((B) resource.asBuilder()) .removeStatusValue(StatusValue.PENDING_TRANSFER) .setTransferData( diff --git a/java/google/registry/flows/async/DeleteContactsAndHostsAction.java b/java/google/registry/flows/async/DeleteContactsAndHostsAction.java index 6b8f11c5d..8b934f348 100644 --- a/java/google/registry/flows/async/DeleteContactsAndHostsAction.java +++ b/java/google/registry/flows/async/DeleteContactsAndHostsAction.java @@ -63,6 +63,7 @@ import google.registry.model.ImmutableObject; import google.registry.model.annotations.ExternalMessagingName; import google.registry.model.contact.ContactResource; import google.registry.model.domain.DomainBase; +import google.registry.model.eppcommon.StatusValue; import google.registry.model.host.HostResource; import google.registry.model.poll.PollMessage; import google.registry.model.reporting.HistoryEntry; @@ -317,10 +318,12 @@ public class DeleteContactsAndHostsAction implements Runnable { EppResource.Builder resourceToSaveBuilder; if (resource instanceof ContactResource) { ContactResource contact = (ContactResource) resource; - resourceToSaveBuilder = contact.asBuilder() - .setTransferData(createResolvedTransferData( - contact.getTransferData(), TransferStatus.SERVER_CANCELLED, now)) - .wipeOut(); + ContactResource.Builder contactToSaveBuilder = contact.asBuilder(); + if (contact.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) { + contactToSaveBuilder = contactToSaveBuilder.setTransferData(createResolvedTransferData( + contact.getTransferData(), TransferStatus.SERVER_CANCELLED, now)); + } + resourceToSaveBuilder = contactToSaveBuilder.wipeOut(); } else { resourceToSaveBuilder = resource.asBuilder(); } diff --git a/java/google/registry/flows/domain/DomainDeleteFlow.java b/java/google/registry/flows/domain/DomainDeleteFlow.java index bf4316f9c..2313d83b7 100644 --- a/java/google/registry/flows/domain/DomainDeleteFlow.java +++ b/java/google/registry/flows/domain/DomainDeleteFlow.java @@ -131,9 +131,10 @@ public final class DomainDeleteFlow implements TransactionalFlow { AfterValidationParameters.newBuilder().setExistingDomain(existingDomain).build()); ImmutableSet.Builder entitiesToSave = new ImmutableSet.Builder<>(); HistoryEntry historyEntry = buildHistoryEntry(existingDomain, now); - Builder builder = - ResourceFlowUtils.resolvePendingTransfer( - existingDomain, TransferStatus.SERVER_CANCELLED, now); + Builder builder = existingDomain.getStatusValues().contains(StatusValue.PENDING_TRANSFER) + ? ResourceFlowUtils.resolvePendingTransfer( + existingDomain, TransferStatus.SERVER_CANCELLED, now) + : existingDomain.asBuilder(); builder.setDeletionTime(now).setStatusValues(null); // If the domain is in the Add Grace Period, we delete it immediately, which is already // reflected in the builder we just prepared. Otherwise we give it a PENDING_DELETE status. diff --git a/javatests/google/registry/flows/async/DeleteContactsAndHostsActionTest.java b/javatests/google/registry/flows/async/DeleteContactsAndHostsActionTest.java index 445f3ba55..557550bfd 100644 --- a/javatests/google/registry/flows/async/DeleteContactsAndHostsActionTest.java +++ b/javatests/google/registry/flows/async/DeleteContactsAndHostsActionTest.java @@ -75,6 +75,7 @@ import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage.OneTime; import google.registry.model.registry.Registry; import google.registry.model.reporting.HistoryEntry; +import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferResponse; import google.registry.testing.ExceptionRule; import google.registry.testing.FakeClock; @@ -196,6 +197,16 @@ public class DeleteContactsAndHostsActionTest assertNoTasksEnqueued(QUEUE_ASYNC_DELETE); } + @Test + public void testSuccess_contactWithoutPendingTransfer_isDeletedAndHasNoTransferData() + throws Exception { + ContactResource contact = persistContactPendingDelete("blah8221"); + enqueuer.enqueueAsyncDelete(contact, "TheRegistrar", false); + runMapreduce(); + ContactResource contactAfterDeletion = ofy().load().entity(contact).now(); + assertThat(contactAfterDeletion.getTransferData()).isEqualTo(TransferData.EMPTY); + } + @Test public void testSuccess_contactWithPendingTransfer_getsDeleted() throws Exception { DateTime transferRequestTime = clock.nowUtc().minusDays(3); diff --git a/javatests/google/registry/flows/domain/DomainDeleteFlowTest.java b/javatests/google/registry/flows/domain/DomainDeleteFlowTest.java index 4d456f643..6f75e7df4 100644 --- a/javatests/google/registry/flows/domain/DomainDeleteFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainDeleteFlowTest.java @@ -480,6 +480,16 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase