From 85f75494ab147f611d719ba89d5dbef63ea905f2 Mon Sep 17 00:00:00 2001 From: gbrodman Date: Tue, 23 Dec 2025 10:38:24 -0500 Subject: [PATCH] Remove implementation of contact flows (#2896) Now that we have transitioned to the minimum dataset, we no longer support any actions on contacts (and by the time this is merged / deployed, all contacts will be deleted). We should just throw an appropriate exception on all contact-related flows. We don't delete the flows themselves, so that we can have an appropriate error message. We also keep all the flows and XML templates around individually for now because we may be required to continue to differentiate the requests in ICANN activity reporting (e.g. srs-cont-create vs srs-cont-delete) --- .../flows/contact/ContactCheckFlow.java | 51 +- .../flows/contact/ContactCreateFlow.java | 81 +--- .../flows/contact/ContactDeleteFlow.java | 87 +--- .../flows/contact/ContactFlowUtils.java | 126 ----- .../flows/contact/ContactInfoFlow.java | 81 +--- .../contact/ContactTransferApproveFlow.java | 83 +--- .../contact/ContactTransferCancelFlow.java | 79 +--- .../contact/ContactTransferQueryFlow.java | 65 +-- .../contact/ContactTransferRejectFlow.java | 76 +-- .../contact/ContactTransferRequestFlow.java | 152 +----- .../flows/contact/ContactUpdateFlow.java | 145 +----- .../flows/contact/ContactsProhibitedFlow.java | 28 ++ .../registry/flows/picker/FlowPicker.java | 1 - .../flows/EppLifecycleContactTest.java | 110 ----- .../registry/flows/EppLifecycleHostTest.java | 17 - .../google/registry/flows/EppTestCase.java | 2 +- .../flows/contact/ContactCheckFlowTest.java | 74 +-- .../flows/contact/ContactCreateFlowTest.java | 129 +----- .../flows/contact/ContactDeleteFlowTest.java | 257 +--------- .../flows/contact/ContactInfoFlowTest.java | 192 +------- .../ContactTransferApproveFlowTest.java | 246 +--------- .../ContactTransferCancelFlowTest.java | 232 +--------- .../contact/ContactTransferFlowTestCase.java | 93 ---- .../contact/ContactTransferQueryFlowTest.java | 198 +------- .../ContactTransferRejectFlowTest.java | 245 +--------- .../ContactTransferRequestFlowTest.java | 294 +----------- .../flows/contact/ContactUpdateFlowTest.java | 437 +----------------- .../registry/flows/contact_create_jd1234.xml | 33 -- .../flows/contact_create_response_jd1234.xml | 18 - .../flows/contact_create_response_sh8013.xml | 18 - .../registry/flows/contact_create_sh8013.xml | 33 -- .../flows/contact_delete_response_sh8013.xml | 11 - .../registry/flows/contact_delete_sh8013.xml | 11 - .../flows/contact_transfer_request.xml | 14 - ...ct_transfer_request_response_alternate.xml | 22 - .../poll_response_domain_transfer_request.xml | 2 +- 36 files changed, 147 insertions(+), 3596 deletions(-) delete mode 100644 core/src/main/java/google/registry/flows/contact/ContactFlowUtils.java create mode 100644 core/src/main/java/google/registry/flows/contact/ContactsProhibitedFlow.java delete mode 100644 core/src/test/java/google/registry/flows/EppLifecycleContactTest.java delete mode 100644 core/src/test/java/google/registry/flows/contact/ContactTransferFlowTestCase.java delete mode 100644 core/src/test/resources/google/registry/flows/contact_create_jd1234.xml delete mode 100644 core/src/test/resources/google/registry/flows/contact_create_response_jd1234.xml delete mode 100644 core/src/test/resources/google/registry/flows/contact_create_response_sh8013.xml delete mode 100644 core/src/test/resources/google/registry/flows/contact_create_sh8013.xml delete mode 100644 core/src/test/resources/google/registry/flows/contact_delete_response_sh8013.xml delete mode 100644 core/src/test/resources/google/registry/flows/contact_delete_sh8013.xml delete mode 100644 core/src/test/resources/google/registry/flows/contact_transfer_request.xml delete mode 100644 core/src/test/resources/google/registry/flows/contact_transfer_request_response_alternate.xml diff --git a/core/src/main/java/google/registry/flows/contact/ContactCheckFlow.java b/core/src/main/java/google/registry/flows/contact/ContactCheckFlow.java index 74f5f535c..6cd35611b 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactCheckFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactCheckFlow.java @@ -14,60 +14,19 @@ package google.registry.flows.contact; -import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; -import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import google.registry.config.RegistryConfig.Config; -import google.registry.flows.EppException; -import google.registry.flows.ExtensionManager; -import google.registry.flows.FlowModule.RegistrarId; -import google.registry.flows.TransactionalFlow; import google.registry.flows.annotations.ReportingSpec; -import google.registry.model.ForeignKeyUtils; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactCommand.Check; -import google.registry.model.eppinput.ResourceCommand; -import google.registry.model.eppoutput.CheckData.ContactCheck; -import google.registry.model.eppoutput.CheckData.ContactCheckData; -import google.registry.model.eppoutput.EppResponse; +import google.registry.flows.exceptions.ContactsProhibitedException; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; -import google.registry.util.Clock; import jakarta.inject.Inject; /** - * An EPP flow that checks whether a contact can be provisioned. + * An EPP flow that is meant to check whether a contact can be provisioned. * - *

This flows can check the existence of multiple contacts simultaneously. - * - * @error {@link google.registry.flows.exceptions.TooManyResourceChecksException} - * @error {@link google.registry.flows.FlowUtils.NotLoggedInException} + * @error {@link ContactsProhibitedException} */ +@Deprecated @ReportingSpec(ActivityReportField.CONTACT_CHECK) -public final class ContactCheckFlow implements TransactionalFlow { - - @Inject ResourceCommand resourceCommand; - @Inject @RegistrarId String registrarId; - @Inject ExtensionManager extensionManager; - @Inject Clock clock; - @Inject @Config("maxChecks") int maxChecks; - @Inject EppResponse.Builder responseBuilder; +public final class ContactCheckFlow extends ContactsProhibitedFlow { @Inject ContactCheckFlow() {} - - @Override - public EppResponse run() throws EppException { - validateRegistrarIsLoggedIn(registrarId); - extensionManager.validate(); // There are no legal extensions for this flow. - ImmutableList targetIds = ((Check) resourceCommand).getTargetIds(); - verifyTargetIdCount(targetIds, maxChecks); - ImmutableSet existingIds = - ForeignKeyUtils.loadKeys(Contact.class, targetIds, clock.nowUtc()).keySet(); - ImmutableList.Builder checks = new ImmutableList.Builder<>(); - for (String id : targetIds) { - boolean unused = !existingIds.contains(id); - checks.add(ContactCheck.create(unused, id, unused ? null : "In use")); - } - return responseBuilder.setResData(ContactCheckData.create(checks.build())).build(); - } } diff --git a/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java b/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java index 364ef2f74..b360c846e 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java @@ -14,94 +14,19 @@ package google.registry.flows.contact; -import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; -import static google.registry.flows.ResourceFlowUtils.verifyResourceDoesNotExist; -import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo; -import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy; -import static google.registry.model.EppResourceUtils.createRepoId; -import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_PROHIBITED; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; -import com.google.common.collect.ImmutableSet; -import google.registry.config.RegistryConfig.Config; -import google.registry.flows.EppException; -import google.registry.flows.ExtensionManager; -import google.registry.flows.FlowModule.RegistrarId; -import google.registry.flows.FlowModule.TargetId; -import google.registry.flows.MutatingFlow; import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.exceptions.ContactsProhibitedException; -import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException; -import google.registry.flows.exceptions.ResourceCreateContentionException; -import google.registry.model.common.FeatureFlag; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactCommand.Create; -import google.registry.model.contact.ContactHistory; -import google.registry.model.domain.metadata.MetadataExtension; -import google.registry.model.eppinput.ResourceCommand; -import google.registry.model.eppoutput.CreateData.ContactCreateData; -import google.registry.model.eppoutput.EppResponse; -import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import jakarta.inject.Inject; -import org.joda.time.DateTime; /** - * An EPP flow that creates a new contact. + * An EPP flow meant to create a new contact. * - * @error {@link google.registry.flows.FlowUtils.NotLoggedInException} * @error {@link ContactsProhibitedException} - * @error {@link ResourceAlreadyExistsForThisClientException} - * @error {@link ResourceCreateContentionException} - * @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException} - * @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException} */ +@Deprecated @ReportingSpec(ActivityReportField.CONTACT_CREATE) -public final class ContactCreateFlow implements MutatingFlow { - - @Inject ResourceCommand resourceCommand; - @Inject ExtensionManager extensionManager; - @Inject @RegistrarId String registrarId; - @Inject @TargetId String targetId; - @Inject ContactHistory.Builder historyBuilder; - @Inject EppResponse.Builder responseBuilder; - @Inject @Config("contactAndHostRoidSuffix") String roidSuffix; +public final class ContactCreateFlow extends ContactsProhibitedFlow { @Inject ContactCreateFlow() {} - - @Override - public EppResponse run() throws EppException { - extensionManager.register(MetadataExtension.class); - validateRegistrarIsLoggedIn(registrarId); - extensionManager.validate(); - if (FeatureFlag.isActiveNow(MINIMUM_DATASET_CONTACTS_PROHIBITED)) { - throw new ContactsProhibitedException(); - } - Create command = (Create) resourceCommand; - DateTime now = tm().getTransactionTime(); - verifyResourceDoesNotExist(Contact.class, targetId, now, registrarId); - Contact newContact = - new Contact.Builder() - .setContactId(targetId) - .setAuthInfo(command.getAuthInfo()) - .setCreationRegistrarId(registrarId) - .setPersistedCurrentSponsorRegistrarId(registrarId) - .setRepoId(createRepoId(tm().allocateId(), roidSuffix)) - .setFaxNumber(command.getFax()) - .setVoiceNumber(command.getVoice()) - .setDisclose(command.getDisclose()) - .setEmailAddress(command.getEmail()) - .setInternationalizedPostalInfo(command.getInternationalizedPostalInfo()) - .setLocalizedPostalInfo(command.getLocalizedPostalInfo()) - .build(); - validateAsciiPostalInfo(newContact.getInternationalizedPostalInfo()); - validateContactAgainstPolicy(newContact); - historyBuilder - .setType(HistoryEntry.Type.CONTACT_CREATE) - .setXmlBytes(null) // We don't want to store contact details in the history entry. - .setContact(newContact); - tm().insertAll(ImmutableSet.of(newContact, historyBuilder.build())); - return responseBuilder - .setResData(ContactCreateData.create(newContact.getContactId(), now)) - .build(); - } } diff --git a/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java b/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java index f25a03e5f..32cc74c90 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java @@ -14,97 +14,20 @@ package google.registry.flows.contact; -import static google.registry.flows.FlowUtils.DELETE_PROHIBITED_STATUSES; -import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; -import static google.registry.flows.ResourceFlowUtils.checkLinkedDomains; -import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; -import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses; -import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo; -import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; -import static google.registry.model.ResourceTransferUtils.denyPendingTransfer; -import static google.registry.model.ResourceTransferUtils.handlePendingTransferOnDelete; -import static google.registry.model.eppoutput.Result.Code.SUCCESS; -import static google.registry.model.transfer.TransferStatus.SERVER_CANCELLED; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; -import com.google.common.collect.ImmutableSet; -import google.registry.flows.EppException; -import google.registry.flows.ExtensionManager; -import google.registry.flows.FlowModule.RegistrarId; -import google.registry.flows.FlowModule.Superuser; -import google.registry.flows.FlowModule.TargetId; -import google.registry.flows.MutatingFlow; import google.registry.flows.annotations.ReportingSpec; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactHistory; -import google.registry.model.domain.metadata.MetadataExtension; -import google.registry.model.eppcommon.AuthInfo; -import google.registry.model.eppcommon.StatusValue; -import google.registry.model.eppcommon.Trid; -import google.registry.model.eppoutput.EppResponse; -import google.registry.model.reporting.HistoryEntry.Type; +import google.registry.flows.exceptions.ContactsProhibitedException; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import jakarta.inject.Inject; -import java.util.Optional; -import org.joda.time.DateTime; /** - * An EPP flow that deletes a contact. + * An EPP flow that is meant to delete a contact. * - *

Contacts that are in use by any domain cannot be deleted. The flow may return immediately if a - * quick smoke check determines that deletion is impossible due to an existing reference. However, a - * successful delete will always be asynchronous, as all existing domains must be checked for - * references to the host before the deletion is allowed to proceed. A poll message will be written - * with the success or failure message when the process is complete. - * - * @error {@link google.registry.flows.FlowUtils.NotLoggedInException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} - * @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException} - * @error {@link google.registry.flows.exceptions.ResourceToDeleteIsReferencedException} + * @error {@link ContactsProhibitedException} */ +@Deprecated @ReportingSpec(ActivityReportField.CONTACT_DELETE) -public final class ContactDeleteFlow implements MutatingFlow { - - @Inject ExtensionManager extensionManager; - @Inject @RegistrarId String registrarId; - @Inject @TargetId String targetId; - @Inject Trid trid; - @Inject @Superuser boolean isSuperuser; - @Inject Optional authInfo; - @Inject ContactHistory.Builder historyBuilder; - @Inject EppResponse.Builder responseBuilder; - +public final class ContactDeleteFlow extends ContactsProhibitedFlow { @Inject ContactDeleteFlow() {} - - @Override - public EppResponse run() throws EppException { - extensionManager.register(MetadataExtension.class); - validateRegistrarIsLoggedIn(registrarId); - extensionManager.validate(); - DateTime now = tm().getTransactionTime(); - checkLinkedDomains(targetId, now, Contact.class); - Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now); - verifyOptionalAuthInfo(authInfo, existingContact); - verifyNoDisallowedStatuses(existingContact, ImmutableSet.of(StatusValue.PENDING_DELETE)); - if (!isSuperuser) { - verifyNoDisallowedStatuses(existingContact, DELETE_PROHIBITED_STATUSES); - verifyResourceOwnership(registrarId, existingContact); - } - // Handle pending transfers on contact deletion. - Contact newContact = - existingContact.getStatusValues().contains(StatusValue.PENDING_TRANSFER) - ? denyPendingTransfer(existingContact, SERVER_CANCELLED, now, registrarId) - : existingContact; - // Wipe out PII on contact deletion. - newContact = - newContact.asBuilder().wipeOut().setStatusValues(null).setDeletionTime(now).build(); - ContactHistory contactHistory = - historyBuilder.setType(Type.CONTACT_DELETE).setContact(newContact).build(); - handlePendingTransferOnDelete(existingContact, newContact, now, contactHistory); - tm().insert(contactHistory); - tm().update(newContact); - return responseBuilder.setResultFromCode(SUCCESS).build(); - } } diff --git a/core/src/main/java/google/registry/flows/contact/ContactFlowUtils.java b/core/src/main/java/google/registry/flows/contact/ContactFlowUtils.java deleted file mode 100644 index b90a130e6..000000000 --- a/core/src/main/java/google/registry/flows/contact/ContactFlowUtils.java +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.flows.contact; - -import static google.registry.model.contact.PostalInfo.Type.INTERNATIONALIZED; - -import com.google.common.base.CharMatcher; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Sets; -import google.registry.flows.EppException; -import google.registry.flows.EppException.ParameterValuePolicyErrorException; -import google.registry.flows.EppException.ParameterValueSyntaxErrorException; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactAddress; -import google.registry.model.contact.PostalInfo; -import google.registry.model.poll.PendingActionNotificationResponse.ContactPendingActionNotificationResponse; -import google.registry.model.poll.PollMessage; -import google.registry.model.reporting.HistoryEntry.HistoryEntryId; -import google.registry.model.transfer.TransferData; -import google.registry.model.transfer.TransferResponse.ContactTransferResponse; -import java.util.Set; -import javax.annotation.Nullable; -import org.joda.time.DateTime; - -/** Static utility functions for contact flows. */ -public class ContactFlowUtils { - /** Check that an internationalized postal info has only ascii characters. */ - static void validateAsciiPostalInfo(@Nullable PostalInfo internationalized) throws EppException { - if (internationalized != null) { - Preconditions.checkState(INTERNATIONALIZED.equals(internationalized.getType())); - ContactAddress address = internationalized.getAddress(); - Set fields = Sets.newHashSet( - internationalized.getName(), - internationalized.getOrg(), - address.getCity(), - address.getCountryCode(), - address.getState(), - address.getZip()); - fields.addAll(address.getStreet()); - for (String field : fields) { - if (field != null && !CharMatcher.ascii().matchesAllOf(field)) { - throw new BadInternationalizedPostalInfoException(); - } - } - } - } - - /** Check contact's state against server policy. */ - static void validateContactAgainstPolicy(Contact contact) throws EppException { - if (contact.getDisclose() != null && !contact.getDisclose().getFlag()) { - throw new DeclineContactDisclosureFieldDisallowedPolicyException(); - } - } - - /** Create a poll message for the gaining client in a transfer. */ - static PollMessage createGainingTransferPollMessage( - String targetId, TransferData transferData, DateTime now, HistoryEntryId contactHistoryId) { - return new PollMessage.OneTime.Builder() - .setRegistrarId(transferData.getGainingRegistrarId()) - .setEventTime(transferData.getPendingTransferExpirationTime()) - .setMsg(transferData.getTransferStatus().getMessage()) - .setResponseData( - ImmutableList.of( - createTransferResponse(targetId, transferData), - ContactPendingActionNotificationResponse.create( - targetId, - transferData.getTransferStatus().isApproved(), - transferData.getTransferRequestTrid(), - now))) - .setContactHistoryId(contactHistoryId) - .build(); - } - - /** Create a poll message for the losing client in a transfer. */ - static PollMessage createLosingTransferPollMessage( - String targetId, TransferData transferData, HistoryEntryId contactHistoryId) { - return new PollMessage.OneTime.Builder() - .setRegistrarId(transferData.getLosingRegistrarId()) - .setEventTime(transferData.getPendingTransferExpirationTime()) - .setMsg(transferData.getTransferStatus().getMessage()) - .setResponseData(ImmutableList.of(createTransferResponse(targetId, transferData))) - .setContactHistoryId(contactHistoryId) - .build(); - } - - /** Create a {@link ContactTransferResponse} off of the info in a {@link TransferData}. */ - static ContactTransferResponse createTransferResponse( - String targetId, TransferData transferData) { - return new ContactTransferResponse.Builder() - .setContactId(targetId) - .setGainingRegistrarId(transferData.getGainingRegistrarId()) - .setLosingRegistrarId(transferData.getLosingRegistrarId()) - .setPendingTransferExpirationTime(transferData.getPendingTransferExpirationTime()) - .setTransferRequestTime(transferData.getTransferRequestTime()) - .setTransferStatus(transferData.getTransferStatus()) - .build(); - } - - /** Declining contact disclosure is disallowed by server policy. */ - static class DeclineContactDisclosureFieldDisallowedPolicyException - extends ParameterValuePolicyErrorException { - public DeclineContactDisclosureFieldDisallowedPolicyException() { - super("Declining contact disclosure is disallowed by server policy."); - } - } - - /** Internationalized postal infos can only contain ASCII characters. */ - static class BadInternationalizedPostalInfoException extends ParameterValueSyntaxErrorException { - public BadInternationalizedPostalInfoException() { - super("Internationalized postal infos can only contain ASCII characters"); - } - } -} diff --git a/core/src/main/java/google/registry/flows/contact/ContactInfoFlow.java b/core/src/main/java/google/registry/flows/contact/ContactInfoFlow.java index 0f5a1f4d2..20ee4afcc 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactInfoFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactInfoFlow.java @@ -14,91 +14,20 @@ package google.registry.flows.contact; -import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; -import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; -import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; -import static google.registry.model.EppResourceUtils.isLinked; -import com.google.common.collect.ImmutableSet; -import google.registry.flows.EppException; -import google.registry.flows.ExtensionManager; -import google.registry.flows.FlowModule.RegistrarId; -import google.registry.flows.FlowModule.Superuser; -import google.registry.flows.FlowModule.TargetId; -import google.registry.flows.TransactionalFlow; import google.registry.flows.annotations.ReportingSpec; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactInfoData; -import google.registry.model.eppcommon.AuthInfo; -import google.registry.model.eppcommon.StatusValue; -import google.registry.model.eppoutput.EppResponse; +import google.registry.flows.exceptions.ContactsProhibitedException; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; -import google.registry.util.Clock; import jakarta.inject.Inject; -import java.util.Optional; -import org.joda.time.DateTime; /** - * An EPP flow that returns information about a contact. + * An EPP flow that is meant to return information about a contact. * - *

The response includes the contact's postal info, phone numbers, emails, the authInfo which can - * be used to request a transfer and the details of the contact's most recent transfer if it has - * ever been transferred. Any registrar can see any contact's information, but the authInfo is only - * visible to the registrar that owns the contact or to a registrar that already supplied it. - * - * @error {@link google.registry.flows.FlowUtils.NotLoggedInException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} + * @error {@link ContactsProhibitedException} */ +@Deprecated @ReportingSpec(ActivityReportField.CONTACT_INFO) -public final class ContactInfoFlow implements TransactionalFlow { - - @Inject ExtensionManager extensionManager; - @Inject Clock clock; - @Inject @RegistrarId String registrarId; - @Inject @TargetId String targetId; - @Inject Optional authInfo; - @Inject @Superuser boolean isSuperuser; - @Inject EppResponse.Builder responseBuilder; - +public final class ContactInfoFlow extends ContactsProhibitedFlow { @Inject ContactInfoFlow() {} - - @Override - public EppResponse run() throws EppException { - DateTime now = clock.nowUtc(); - validateRegistrarIsLoggedIn(registrarId); - extensionManager.validate(); // There are no legal extensions for this flow. - Contact contact = loadAndVerifyExistence(Contact.class, targetId, now); - if (!isSuperuser) { - verifyResourceOwnership(registrarId, contact); - } - boolean includeAuthInfo = - registrarId.equals(contact.getCurrentSponsorRegistrarId()) || authInfo.isPresent(); - ImmutableSet.Builder statusValues = new ImmutableSet.Builder<>(); - statusValues.addAll(contact.getStatusValues()); - if (isLinked(contact.createVKey(), now)) { - statusValues.add(StatusValue.LINKED); - } - return responseBuilder - .setResData( - ContactInfoData.newBuilder() - .setContactId(contact.getContactId()) - .setRepoId(contact.getRepoId()) - .setStatusValues(statusValues.build()) - .setPostalInfos(contact.getPostalInfosAsList()) - .setVoiceNumber(contact.getVoiceNumber()) - .setFaxNumber(contact.getFaxNumber()) - .setEmailAddress(contact.getEmailAddress()) - .setCurrentSponsorRegistrarId(contact.getCurrentSponsorRegistrarId()) - .setCreationRegistrarId(contact.getCreationRegistrarId()) - .setCreationTime(contact.getCreationTime()) - .setLastEppUpdateRegistrarId(contact.getLastEppUpdateRegistrarId()) - .setLastEppUpdateTime(contact.getLastEppUpdateTime()) - .setLastTransferTime(contact.getLastTransferTime()) - .setAuthInfo(includeAuthInfo ? contact.getAuthInfo() : null) - .setDisclose(contact.getDisclose()) - .build()) - .build(); - } } diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java index bf04f6361..9b85caffc 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java @@ -14,92 +14,19 @@ package google.registry.flows.contact; -import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; -import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; -import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer; -import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo; -import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; -import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage; -import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; -import static google.registry.model.ResourceTransferUtils.approvePendingTransfer; -import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_TRANSFER_APPROVE; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; -import com.google.common.collect.ImmutableSet; -import google.registry.flows.EppException; -import google.registry.flows.ExtensionManager; -import google.registry.flows.FlowModule.RegistrarId; -import google.registry.flows.FlowModule.TargetId; -import google.registry.flows.MutatingFlow; import google.registry.flows.annotations.ReportingSpec; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactHistory; -import google.registry.model.domain.metadata.MetadataExtension; -import google.registry.model.eppcommon.AuthInfo; -import google.registry.model.eppinput.ResourceCommand; -import google.registry.model.eppoutput.EppResponse; -import google.registry.model.poll.PollMessage; +import google.registry.flows.exceptions.ContactsProhibitedException; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; -import google.registry.model.transfer.TransferStatus; import jakarta.inject.Inject; -import java.util.Optional; -import org.joda.time.DateTime; /** - * An EPP flow that approves a pending transfer on a contact. + * An EPP flow that is meant to approve a pending transfer on a contact. * - *

The "gaining" registrar requests a transfer from the "losing" (aka current) registrar. The - * losing registrar has a "transfer" time period to respond (by default five days) after which the - * transfer is automatically approved. Within that window, this flow allows the losing client to - * explicitly approve the transfer request, which then becomes effective immediately. - * - * @error {@link google.registry.flows.FlowUtils.NotLoggedInException} - * @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} - * @error {@link google.registry.flows.exceptions.NotPendingTransferException} + * @error {@link ContactsProhibitedException} */ +@Deprecated @ReportingSpec(ActivityReportField.CONTACT_TRANSFER_APPROVE) -public final class ContactTransferApproveFlow implements MutatingFlow { - - @Inject ResourceCommand resourceCommand; - @Inject ExtensionManager extensionManager; - @Inject @RegistrarId String registrarId; - @Inject @TargetId String targetId; - @Inject Optional authInfo; - @Inject ContactHistory.Builder historyBuilder; - @Inject EppResponse.Builder responseBuilder; +public final class ContactTransferApproveFlow extends ContactsProhibitedFlow { @Inject ContactTransferApproveFlow() {} - - /** - * The logic in this flow, which handles client approvals, very closely parallels the logic in - * {@link Contact#cloneProjectedAtTime} which handles implicit server approvals. - */ - @Override - public EppResponse run() throws EppException { - extensionManager.register(MetadataExtension.class); - validateRegistrarIsLoggedIn(registrarId); - extensionManager.validate(); - DateTime now = tm().getTransactionTime(); - Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now); - verifyOptionalAuthInfo(authInfo, existingContact); - verifyHasPendingTransfer(existingContact); - verifyResourceOwnership(registrarId, existingContact); - Contact newContact = - approvePendingTransfer(existingContact, TransferStatus.CLIENT_APPROVED, now); - ContactHistory contactHistory = - historyBuilder.setType(CONTACT_TRANSFER_APPROVE).setContact(newContact).build(); - // Create a poll message for the gaining client. - PollMessage gainingPollMessage = - createGainingTransferPollMessage( - targetId, newContact.getTransferData(), now, contactHistory.getHistoryEntryId()); - tm().insertAll(ImmutableSet.of(contactHistory, gainingPollMessage)); - tm().update(newContact); - // Delete the billing event and poll messages that were written in case the transfer would have - // been implicitly server approved. - tm().delete(existingContact.getTransferData().getServerApproveEntities()); - return responseBuilder - .setResData(createTransferResponse(targetId, newContact.getTransferData())) - .build(); - } } diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java index c126451e9..8f7d5a833 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java @@ -14,88 +14,19 @@ package google.registry.flows.contact; -import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; -import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; -import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer; -import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo; -import static google.registry.flows.ResourceFlowUtils.verifyTransferInitiator; -import static google.registry.flows.contact.ContactFlowUtils.createLosingTransferPollMessage; -import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; -import static google.registry.model.ResourceTransferUtils.denyPendingTransfer; -import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_TRANSFER_CANCEL; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; -import com.google.common.collect.ImmutableSet; -import google.registry.flows.EppException; -import google.registry.flows.ExtensionManager; -import google.registry.flows.FlowModule.RegistrarId; -import google.registry.flows.FlowModule.TargetId; -import google.registry.flows.MutatingFlow; import google.registry.flows.annotations.ReportingSpec; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactHistory; -import google.registry.model.domain.metadata.MetadataExtension; -import google.registry.model.eppcommon.AuthInfo; -import google.registry.model.eppinput.ResourceCommand; -import google.registry.model.eppoutput.EppResponse; -import google.registry.model.poll.PollMessage; +import google.registry.flows.exceptions.ContactsProhibitedException; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; -import google.registry.model.transfer.TransferStatus; import jakarta.inject.Inject; -import java.util.Optional; -import org.joda.time.DateTime; /** - * An EPP flow that cancels a pending transfer on a contact. + * An EPP flow that is meant to cancel a pending transfer on a contact. * - *

The "gaining" registrar requests a transfer from the "losing" (aka current) registrar. The - * losing registrar has a "transfer" time period to respond (by default five days) after which the - * transfer is automatically approved. Within that window, this flow allows the gaining client to - * withdraw the transfer request. - * - * @error {@link google.registry.flows.FlowUtils.NotLoggedInException} - * @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} - * @error {@link google.registry.flows.exceptions.NotPendingTransferException} - * @error {@link google.registry.flows.exceptions.NotTransferInitiatorException} + * @error {@link ContactsProhibitedException} */ +@Deprecated @ReportingSpec(ActivityReportField.CONTACT_TRANSFER_CANCEL) -public final class ContactTransferCancelFlow implements MutatingFlow { - - @Inject ResourceCommand resourceCommand; - @Inject ExtensionManager extensionManager; - @Inject Optional authInfo; - @Inject @RegistrarId String registrarId; - @Inject @TargetId String targetId; - @Inject ContactHistory.Builder historyBuilder; - @Inject EppResponse.Builder responseBuilder; +public final class ContactTransferCancelFlow extends ContactsProhibitedFlow { @Inject ContactTransferCancelFlow() {} - - @Override - public EppResponse run() throws EppException { - extensionManager.register(MetadataExtension.class); - validateRegistrarIsLoggedIn(registrarId); - extensionManager.validate(); - DateTime now = tm().getTransactionTime(); - Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now); - verifyOptionalAuthInfo(authInfo, existingContact); - verifyHasPendingTransfer(existingContact); - verifyTransferInitiator(registrarId, existingContact); - Contact newContact = - denyPendingTransfer(existingContact, TransferStatus.CLIENT_CANCELLED, now, registrarId); - ContactHistory contactHistory = - historyBuilder.setType(CONTACT_TRANSFER_CANCEL).setContact(newContact).build(); - // Create a poll message for the losing client. - PollMessage losingPollMessage = - createLosingTransferPollMessage( - targetId, newContact.getTransferData(), contactHistory.getHistoryEntryId()); - tm().insertAll(ImmutableSet.of(contactHistory, losingPollMessage)); - tm().update(newContact); - // Delete the billing event and poll messages that were written in case the transfer would have - // been implicitly server approved. - tm().delete(existingContact.getTransferData().getServerApproveEntities()); - return responseBuilder - .setResData(createTransferResponse(targetId, newContact.getTransferData())) - .build(); - } } diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferQueryFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferQueryFlow.java index deee73fdd..1894ecd3d 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferQueryFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferQueryFlow.java @@ -14,74 +14,19 @@ package google.registry.flows.contact; -import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; -import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; -import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo; -import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; -import google.registry.flows.EppException; -import google.registry.flows.ExtensionManager; -import google.registry.flows.FlowModule.RegistrarId; -import google.registry.flows.FlowModule.TargetId; -import google.registry.flows.TransactionalFlow; import google.registry.flows.annotations.ReportingSpec; -import google.registry.flows.exceptions.NoTransferHistoryToQueryException; -import google.registry.flows.exceptions.NotAuthorizedToViewTransferException; -import google.registry.model.contact.Contact; -import google.registry.model.eppcommon.AuthInfo; -import google.registry.model.eppoutput.EppResponse; +import google.registry.flows.exceptions.ContactsProhibitedException; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; -import google.registry.util.Clock; import jakarta.inject.Inject; -import java.util.Optional; /** - * An EPP flow that queries a pending transfer on a contact. + * An EPP flow that is meant to query a pending transfer on a contact. * - *

The "gaining" registrar requests a transfer from the "losing" (aka current) registrar. The - * losing registrar has a "transfer" time period to respond (by default five days) after which the - * transfer is automatically approved. This flow can be used by the gaining or losing registrars (or - * anyone with the correct authId) to see the status of a transfer, which may still be pending or - * may have been approved, rejected, cancelled or implicitly approved by virtue of the transfer - * period expiring. - * - * @error {@link google.registry.flows.FlowUtils.NotLoggedInException} - * @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} - * @error {@link google.registry.flows.exceptions.NoTransferHistoryToQueryException} - * @error {@link google.registry.flows.exceptions.NotAuthorizedToViewTransferException} + * @error {@link ContactsProhibitedException} */ +@Deprecated @ReportingSpec(ActivityReportField.CONTACT_TRANSFER_QUERY) -public final class ContactTransferQueryFlow implements TransactionalFlow { - - @Inject ExtensionManager extensionManager; - @Inject Optional authInfo; - @Inject @RegistrarId String registrarId; - @Inject @TargetId String targetId; - @Inject Clock clock; - @Inject EppResponse.Builder responseBuilder; +public final class ContactTransferQueryFlow extends ContactsProhibitedFlow { @Inject ContactTransferQueryFlow() {} - - @Override - public EppResponse run() throws EppException { - validateRegistrarIsLoggedIn(registrarId); - extensionManager.validate(); // There are no legal extensions for this flow. - Contact contact = loadAndVerifyExistence(Contact.class, targetId, clock.nowUtc()); - verifyOptionalAuthInfo(authInfo, contact); - // Most of the fields on the transfer response are required, so there's no way to return valid - // XML if the object has never been transferred (and hence the fields aren't populated). - if (contact.getTransferData().getTransferStatus() == null) { - throw new NoTransferHistoryToQueryException(); - } - // Note that the authorization info on the command (if present) has already been verified. If - // it's present, then the other checks are unnecessary. - if (authInfo.isEmpty() - && !registrarId.equals(contact.getTransferData().getGainingRegistrarId()) - && !registrarId.equals(contact.getTransferData().getLosingRegistrarId())) { - throw new NotAuthorizedToViewTransferException(); - } - return responseBuilder - .setResData(createTransferResponse(targetId, contact.getTransferData())) - .build(); - } } diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java index dddce31da..3eb7d0564 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java @@ -14,85 +14,19 @@ package google.registry.flows.contact; -import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; -import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; -import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer; -import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo; -import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; -import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage; -import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; -import static google.registry.model.ResourceTransferUtils.denyPendingTransfer; -import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_TRANSFER_REJECT; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; -import com.google.common.collect.ImmutableSet; -import google.registry.flows.EppException; -import google.registry.flows.ExtensionManager; -import google.registry.flows.FlowModule.RegistrarId; -import google.registry.flows.FlowModule.TargetId; -import google.registry.flows.MutatingFlow; import google.registry.flows.annotations.ReportingSpec; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactHistory; -import google.registry.model.domain.metadata.MetadataExtension; -import google.registry.model.eppcommon.AuthInfo; -import google.registry.model.eppoutput.EppResponse; -import google.registry.model.poll.PollMessage; +import google.registry.flows.exceptions.ContactsProhibitedException; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; -import google.registry.model.transfer.TransferStatus; import jakarta.inject.Inject; -import java.util.Optional; -import org.joda.time.DateTime; /** - * An EPP flow that rejects a pending transfer on a contact. + * An EPP flow that is meant to reject a pending transfer on a contact. * - *

The "gaining" registrar requests a transfer from the "losing" (aka current) registrar. The - * losing registrar has a "transfer" time period to respond (by default five days) after which the - * transfer is automatically approved. Within that window, this flow allows the losing client to - * reject the transfer request. - * - * @error {@link google.registry.flows.FlowUtils.NotLoggedInException} - * @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} - * @error {@link google.registry.flows.exceptions.NotPendingTransferException} + * @error {@link ContactsProhibitedException} */ +@Deprecated @ReportingSpec(ActivityReportField.CONTACT_TRANSFER_REJECT) -public final class ContactTransferRejectFlow implements MutatingFlow { - - @Inject ExtensionManager extensionManager; - @Inject Optional authInfo; - @Inject @RegistrarId String registrarId; - @Inject @TargetId String targetId; - @Inject ContactHistory.Builder historyBuilder; - @Inject EppResponse.Builder responseBuilder; +public final class ContactTransferRejectFlow extends ContactsProhibitedFlow { @Inject ContactTransferRejectFlow() {} - - @Override - public EppResponse run() throws EppException { - extensionManager.register(MetadataExtension.class); - validateRegistrarIsLoggedIn(registrarId); - extensionManager.validate(); - DateTime now = tm().getTransactionTime(); - Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now); - verifyOptionalAuthInfo(authInfo, existingContact); - verifyHasPendingTransfer(existingContact); - verifyResourceOwnership(registrarId, existingContact); - Contact newContact = - denyPendingTransfer(existingContact, TransferStatus.CLIENT_REJECTED, now, registrarId); - ContactHistory contactHistory = - historyBuilder.setType(CONTACT_TRANSFER_REJECT).setContact(newContact).build(); - PollMessage gainingPollMessage = - createGainingTransferPollMessage( - targetId, newContact.getTransferData(), now, contactHistory.getHistoryEntryId()); - tm().insertAll(ImmutableSet.of(contactHistory, gainingPollMessage)); - tm().update(newContact); - // Delete the billing event and poll messages that were written in case the transfer would have - // been implicitly server approved. - tm().delete(existingContact.getTransferData().getServerApproveEntities()); - return responseBuilder - .setResData(createTransferResponse(targetId, newContact.getTransferData())) - .build(); - } } diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java index af662cc5e..18f1436ce 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java @@ -14,162 +14,20 @@ package google.registry.flows.contact; -import static google.registry.flows.FlowUtils.createHistoryEntryId; -import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; -import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; -import static google.registry.flows.ResourceFlowUtils.verifyAuthInfo; -import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoPresentForResourceTransfer; -import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses; -import static google.registry.flows.contact.ContactFlowUtils.createGainingTransferPollMessage; -import static google.registry.flows.contact.ContactFlowUtils.createLosingTransferPollMessage; -import static google.registry.flows.contact.ContactFlowUtils.createTransferResponse; -import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; -import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_TRANSFER_REQUEST; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; -import com.google.common.collect.ImmutableSet; -import google.registry.config.RegistryConfig.Config; -import google.registry.flows.EppException; -import google.registry.flows.ExtensionManager; -import google.registry.flows.FlowModule.RegistrarId; -import google.registry.flows.FlowModule.TargetId; -import google.registry.flows.MutatingFlow; import google.registry.flows.annotations.ReportingSpec; -import google.registry.flows.exceptions.AlreadyPendingTransferException; -import google.registry.flows.exceptions.ObjectAlreadySponsoredException; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactHistory; -import google.registry.model.domain.metadata.MetadataExtension; -import google.registry.model.eppcommon.AuthInfo; -import google.registry.model.eppcommon.StatusValue; -import google.registry.model.eppcommon.Trid; -import google.registry.model.eppoutput.EppResponse; -import google.registry.model.poll.PollMessage; -import google.registry.model.reporting.HistoryEntry.HistoryEntryId; +import google.registry.flows.exceptions.ContactsProhibitedException; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; -import google.registry.model.transfer.ContactTransferData; -import google.registry.model.transfer.TransferStatus; import jakarta.inject.Inject; -import java.util.Optional; -import org.joda.time.DateTime; -import org.joda.time.Duration; /** - * An EPP flow that requests a transfer on a contact. + * An EPP flow that is meant to request a transfer on a contact. * - *

The "gaining" registrar requests a transfer from the "losing" (aka current) registrar. The - * losing registrar has a "transfer" time period to respond (by default five days) after which the - * transfer is automatically approved. Within that window, the transfer might be approved explicitly - * by the losing registrar or rejected, and the gaining registrar can also cancel the transfer - * request. - * - * @error {@link google.registry.flows.FlowUtils.NotLoggedInException} - * @error {@link google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} - * @error {@link google.registry.flows.exceptions.AlreadyPendingTransferException} - * @error {@link google.registry.flows.exceptions.MissingTransferRequestAuthInfoException} - * @error {@link google.registry.flows.exceptions.ObjectAlreadySponsoredException} - * @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException} + * @error {@link ContactsProhibitedException} */ +@Deprecated @ReportingSpec(ActivityReportField.CONTACT_TRANSFER_REQUEST) -public final class ContactTransferRequestFlow implements MutatingFlow { - - private static final ImmutableSet DISALLOWED_STATUSES = - ImmutableSet.of( - StatusValue.CLIENT_TRANSFER_PROHIBITED, - StatusValue.PENDING_DELETE, - StatusValue.SERVER_TRANSFER_PROHIBITED); - - @Inject ExtensionManager extensionManager; - @Inject Optional authInfo; - @Inject @RegistrarId String gainingClientId; - @Inject @TargetId String targetId; - - @Inject - @Config("contactAutomaticTransferLength") - Duration automaticTransferLength; - - @Inject ContactHistory.Builder historyBuilder; - @Inject Trid trid; - @Inject EppResponse.Builder responseBuilder; - +public final class ContactTransferRequestFlow extends ContactsProhibitedFlow { @Inject ContactTransferRequestFlow() {} - - @Override - public EppResponse run() throws EppException { - extensionManager.register(MetadataExtension.class); - validateRegistrarIsLoggedIn(gainingClientId); - extensionManager.validate(); - DateTime now = tm().getTransactionTime(); - Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now); - verifyAuthInfoPresentForResourceTransfer(authInfo); - verifyAuthInfo(authInfo.get(), existingContact); - // Verify that the resource does not already have a pending transfer. - if (TransferStatus.PENDING.equals(existingContact.getTransferData().getTransferStatus())) { - throw new AlreadyPendingTransferException(targetId); - } - String losingClientId = existingContact.getCurrentSponsorRegistrarId(); - // Verify that this client doesn't already sponsor this resource. - if (gainingClientId.equals(losingClientId)) { - throw new ObjectAlreadySponsoredException(); - } - verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES); - - DateTime transferExpirationTime = now.plus(automaticTransferLength); - ContactTransferData serverApproveTransferData = - new ContactTransferData.Builder() - .setTransferRequestTime(now) - .setTransferRequestTrid(trid) - .setGainingRegistrarId(gainingClientId) - .setLosingRegistrarId(losingClientId) - .setPendingTransferExpirationTime(transferExpirationTime) - .setTransferStatus(TransferStatus.SERVER_APPROVED) - .build(); - HistoryEntryId contactHistoryId = createHistoryEntryId(existingContact); - historyBuilder - .setRevisionId(contactHistoryId.getRevisionId()) - .setType(CONTACT_TRANSFER_REQUEST); - // If the transfer is server approved, this message will be sent to the losing registrar. */ - PollMessage serverApproveLosingPollMessage = - createLosingTransferPollMessage(targetId, serverApproveTransferData, contactHistoryId); - // If the transfer is server approved, this message will be sent to the gaining registrar. */ - PollMessage serverApproveGainingPollMessage = - createGainingTransferPollMessage( - targetId, serverApproveTransferData, now, contactHistoryId); - ContactTransferData pendingTransferData = - serverApproveTransferData - .asBuilder() - .setTransferStatus(TransferStatus.PENDING) - .setServerApproveEntities( - serverApproveGainingPollMessage.getContactRepoId(), - contactHistoryId.getRevisionId(), - ImmutableSet.of( - serverApproveGainingPollMessage.createVKey(), - serverApproveLosingPollMessage.createVKey())) - .build(); - // When a transfer is requested, a poll message is created to notify the losing registrar. - PollMessage requestPollMessage = - createLosingTransferPollMessage(targetId, pendingTransferData, contactHistoryId) - .asBuilder() - .setEventTime(now) // Unlike the serverApprove messages, this applies immediately. - .build(); - Contact newContact = - existingContact - .asBuilder() - .setTransferData(pendingTransferData) - .addStatusValue(StatusValue.PENDING_TRANSFER) - .build(); - tm().update(newContact); - tm().insertAll( - ImmutableSet.of( - historyBuilder.setContact(newContact).build(), - requestPollMessage, - serverApproveGainingPollMessage, - serverApproveLosingPollMessage)); - return responseBuilder - .setResultFromCode(SUCCESS_WITH_ACTION_PENDING) - .setResData(createTransferResponse(targetId, newContact.getTransferData())) - .build(); - } } diff --git a/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java b/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java index afc3c2070..726f11028 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java @@ -14,158 +14,19 @@ package google.registry.flows.contact; -import static com.google.common.collect.Sets.union; -import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn; -import static google.registry.flows.ResourceFlowUtils.checkSameValuesNotAddedAndRemoved; -import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; -import static google.registry.flows.ResourceFlowUtils.verifyAllStatusesAreClientSettable; -import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses; -import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo; -import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; -import static google.registry.flows.contact.ContactFlowUtils.validateAsciiPostalInfo; -import static google.registry.flows.contact.ContactFlowUtils.validateContactAgainstPolicy; -import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_PROHIBITED; -import static google.registry.model.reporting.HistoryEntry.Type.CONTACT_UPDATE; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; -import com.google.common.collect.ImmutableSet; -import google.registry.flows.EppException; -import google.registry.flows.ExtensionManager; -import google.registry.flows.FlowModule.RegistrarId; -import google.registry.flows.FlowModule.Superuser; -import google.registry.flows.FlowModule.TargetId; -import google.registry.flows.MutatingFlow; import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.exceptions.ContactsProhibitedException; -import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException; -import google.registry.model.common.FeatureFlag; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactCommand.Update; -import google.registry.model.contact.ContactCommand.Update.Change; -import google.registry.model.contact.ContactHistory; -import google.registry.model.contact.PostalInfo; -import google.registry.model.domain.metadata.MetadataExtension; -import google.registry.model.eppcommon.AuthInfo; -import google.registry.model.eppcommon.StatusValue; -import google.registry.model.eppinput.ResourceCommand; -import google.registry.model.eppoutput.EppResponse; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import jakarta.inject.Inject; -import java.util.Optional; -import javax.annotation.Nullable; -import org.joda.time.DateTime; /** - * An EPP flow that updates a contact. + * An EPP flow meant to update a contact. * * @error {@link ContactsProhibitedException} - * @error {@link google.registry.flows.FlowUtils.NotLoggedInException} - * @error {@link google.registry.flows.ResourceFlowUtils.AddRemoveSameValueException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException} - * @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} - * @error {@link google.registry.flows.ResourceFlowUtils.StatusNotClientSettableException} - * @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException} - * @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException} - * @error {@link ContactFlowUtils.BadInternationalizedPostalInfoException} - * @error {@link ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException} */ +@Deprecated @ReportingSpec(ActivityReportField.CONTACT_UPDATE) -public final class ContactUpdateFlow implements MutatingFlow { - - /** - * Note that CLIENT_UPDATE_PROHIBITED is intentionally not in this list. This is because it - * requires special checking, since you must be able to clear the status off the object with an - * update. - */ - private static final ImmutableSet DISALLOWED_STATUSES = ImmutableSet.of( - StatusValue.PENDING_DELETE, - StatusValue.SERVER_UPDATE_PROHIBITED); - - @Inject ResourceCommand resourceCommand; - @Inject ExtensionManager extensionManager; - @Inject Optional authInfo; - @Inject @RegistrarId String registrarId; - @Inject @TargetId String targetId; - @Inject @Superuser boolean isSuperuser; - @Inject ContactHistory.Builder historyBuilder; - @Inject EppResponse.Builder responseBuilder; +public final class ContactUpdateFlow extends ContactsProhibitedFlow { @Inject ContactUpdateFlow() {} - - @Override - public EppResponse run() throws EppException { - extensionManager.register(MetadataExtension.class); - validateRegistrarIsLoggedIn(registrarId); - extensionManager.validate(); - if (FeatureFlag.isActiveNow(MINIMUM_DATASET_CONTACTS_PROHIBITED)) { - throw new ContactsProhibitedException(); - } - Update command = (Update) resourceCommand; - DateTime now = tm().getTransactionTime(); - Contact existingContact = loadAndVerifyExistence(Contact.class, targetId, now); - verifyOptionalAuthInfo(authInfo, existingContact); - ImmutableSet statusToRemove = command.getInnerRemove().getStatusValues(); - ImmutableSet statusesToAdd = command.getInnerAdd().getStatusValues(); - if (!isSuperuser) { // The superuser can update any contact and set any status. - verifyResourceOwnership(registrarId, existingContact); - verifyAllStatusesAreClientSettable(union(statusesToAdd, statusToRemove)); - } - verifyNoDisallowedStatuses(existingContact, DISALLOWED_STATUSES); - checkSameValuesNotAddedAndRemoved(statusesToAdd, statusToRemove); - Contact.Builder builder = existingContact.asBuilder(); - Change change = command.getInnerChange(); - // The spec requires the following behaviors: - // * If you update part of a postal info, the fields that you didn't update are unchanged. - // * If you update one postal info but not the other, the other is deleted. - // Therefore, if you want to preserve one postal info and update another you need to send the - // update and also something that technically updates the preserved one, even if it only - // "updates" it by setting just one field to the same value. - PostalInfo internationalized = change.getInternationalizedPostalInfo(); - PostalInfo localized = change.getLocalizedPostalInfo(); - if (internationalized != null) { - builder.overlayInternationalizedPostalInfo(internationalized); - if (localized == null) { - builder.setLocalizedPostalInfo(null); - } - } - if (localized != null) { - builder.overlayLocalizedPostalInfo(localized); - if (internationalized == null) { - builder.setInternationalizedPostalInfo(null); - } - } - Contact newContact = - builder - .setLastEppUpdateTime(now) - .setLastEppUpdateRegistrarId(registrarId) - .setAuthInfo(preferFirst(change.getAuthInfo(), existingContact.getAuthInfo())) - .setDisclose(preferFirst(change.getDisclose(), existingContact.getDisclose())) - .setEmailAddress(preferFirst(change.getEmail(), existingContact.getEmailAddress())) - .setFaxNumber(preferFirst(change.getFax(), existingContact.getFaxNumber())) - .setVoiceNumber(preferFirst(change.getVoice(), existingContact.getVoiceNumber())) - .addStatusValues(statusesToAdd) - .removeStatusValues(statusToRemove) - .build(); - // If the resource is marked with clientUpdateProhibited, and this update did not clear that - // status, then the update must be disallowed (unless a superuser is requesting the change). - if (!isSuperuser - && existingContact.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED) - && newContact.getStatusValues().contains(StatusValue.CLIENT_UPDATE_PROHIBITED)) { - throw new ResourceHasClientUpdateProhibitedException(); - } - validateAsciiPostalInfo(newContact.getInternationalizedPostalInfo()); - validateContactAgainstPolicy(newContact); - historyBuilder - .setType(CONTACT_UPDATE) - .setXmlBytes(null) // We don't want to store contact details in the history entry. - .setContact(newContact); - tm().insert(historyBuilder.build()); - tm().update(newContact); - return responseBuilder.build(); - } - - /** Return the first non-null param, or null if both are null. */ - @Nullable - private static T preferFirst(@Nullable T a, @Nullable T b) { - return a != null ? a : b; - } } diff --git a/core/src/main/java/google/registry/flows/contact/ContactsProhibitedFlow.java b/core/src/main/java/google/registry/flows/contact/ContactsProhibitedFlow.java new file mode 100644 index 000000000..64aaa73be --- /dev/null +++ b/core/src/main/java/google/registry/flows/contact/ContactsProhibitedFlow.java @@ -0,0 +1,28 @@ +// Copyright 2025 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.flows.contact; + +import google.registry.flows.EppException; +import google.registry.flows.Flow; +import google.registry.flows.exceptions.ContactsProhibitedException; +import google.registry.model.eppoutput.EppResponse; + +/** Nomulus follows the Minimum Dataset Requirements, meaning it stores no contact information. */ +public abstract class ContactsProhibitedFlow implements Flow { + @Override + public EppResponse run() throws EppException { + throw new ContactsProhibitedException(); + } +} diff --git a/core/src/main/java/google/registry/flows/picker/FlowPicker.java b/core/src/main/java/google/registry/flows/picker/FlowPicker.java index 4440fa568..e38b0d03d 100644 --- a/core/src/main/java/google/registry/flows/picker/FlowPicker.java +++ b/core/src/main/java/google/registry/flows/picker/FlowPicker.java @@ -135,7 +135,6 @@ public class FlowPicker { return switch (((Poll) innerCommand).getPollOp()) { case ACK -> PollAckFlow.class; case REQUEST -> PollRequestFlow.class; - default -> UnimplementedFlow.class; }; } }; diff --git a/core/src/test/java/google/registry/flows/EppLifecycleContactTest.java b/core/src/test/java/google/registry/flows/EppLifecycleContactTest.java deleted file mode 100644 index e79ed9170..000000000 --- a/core/src/test/java/google/registry/flows/EppLifecycleContactTest.java +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.flows; - -import static google.registry.model.eppoutput.Result.Code.SUCCESS; -import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACK_MESSAGE; -import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_NO_MESSAGES; -import static google.registry.testing.EppMetricSubject.assertThat; - -import com.google.common.collect.ImmutableMap; -import google.registry.persistence.transaction.JpaTestExtensions; -import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -/** Tests for contact lifecycle. */ -class EppLifecycleContactTest extends EppTestCase { - - @RegisterExtension - final JpaIntegrationTestExtension jpa = - new JpaTestExtensions.Builder().withClock(clock).buildIntegrationTestExtension(); - - @Test - void testContactLifecycle() throws Exception { - assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); - assertThatCommand("contact_create_sh8013.xml") - .atTime("2000-06-01T00:00:00Z") - .hasResponse( - "contact_create_response_sh8013.xml", - ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z")); - assertThat(getRecordedEppMetric()) - .hasClientId("NewRegistrar") - .and() - .hasNoTld() - .and() - .hasCommandName("ContactCreate") - .and() - .hasStatus(SUCCESS); - assertThatCommand("contact_info.xml") - .atTime("2000-06-01T00:01:00Z") - .hasResponse("contact_info_from_create_response.xml"); - assertThat(getRecordedEppMetric()) - .hasClientId("NewRegistrar") - .and() - .hasCommandName("ContactInfo") - .and() - .hasStatus(SUCCESS); - assertThatCommand("contact_delete_sh8013.xml") - .hasResponse("contact_delete_response_sh8013.xml"); - assertThat(getRecordedEppMetric()) - .hasClientId("NewRegistrar") - .and() - .hasCommandName("ContactDelete") - .and() - .hasStatus(SUCCESS); - assertThatLogoutSucceeds(); - } - - @Test - void testContactTransferPollMessage() throws Exception { - assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); - assertThatCommand("contact_create_sh8013.xml") - .atTime("2000-06-01T00:00:00Z") - .hasResponse( - "contact_create_response_sh8013.xml", - ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z")); - assertThatLogoutSucceeds(); - - // Initiate a transfer of the newly created contact. - assertThatLoginSucceeds("TheRegistrar", "password2"); - assertThatCommand("contact_transfer_request.xml") - .atTime("2000-06-08T22:00:00Z") - .hasResponse("contact_transfer_request_response_alternate.xml"); - assertThatLogoutSucceeds(); - - // Log back in with the losing registrar, read the poll message, and then ack it. - assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); - assertThatCommand("poll.xml") - .atTime("2000-06-08T22:01:00Z") - .hasResponse("poll_response_contact_transfer.xml"); - assertThat(getRecordedEppMetric()) - .hasClientId("NewRegistrar") - .and() - .hasCommandName("PollRequest") - .and() - .hasStatus(SUCCESS_WITH_ACK_MESSAGE); - assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "6-2000")) - .atTime("2000-06-08T22:02:00Z") - .hasResponse("poll_ack_response_empty.xml"); - assertThat(getRecordedEppMetric()) - .hasClientId("NewRegistrar") - .and() - .hasCommandName("PollAck") - .and() - .hasStatus(SUCCESS_WITH_NO_MESSAGES); - assertThatLogoutSucceeds(); - } -} diff --git a/core/src/test/java/google/registry/flows/EppLifecycleHostTest.java b/core/src/test/java/google/registry/flows/EppLifecycleHostTest.java index f97396af5..ccb5705c7 100644 --- a/core/src/test/java/google/registry/flows/EppLifecycleHostTest.java +++ b/core/src/test/java/google/registry/flows/EppLifecycleHostTest.java @@ -91,14 +91,6 @@ class EppLifecycleHostTest extends EppTestCase { createTld("example"); assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); // Create the fakesite domain. - assertThatCommand("contact_create_sh8013.xml") - .atTime("2000-06-01T00:00:00Z") - .hasResponse( - "contact_create_response_sh8013.xml", - ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z")); - assertThatCommand("contact_create_jd1234.xml") - .atTime("2000-06-01T00:01:00Z") - .hasResponse("contact_create_response_jd1234.xml"); assertThatCommand("domain_create_fakesite_no_nameservers.xml") .atTime("2000-06-01T00:04:00Z") .hasResponse( @@ -142,15 +134,6 @@ class EppLifecycleHostTest extends EppTestCase { assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); - assertThatCommand("contact_create_sh8013.xml") - .atTime("2000-06-01T00:00:00Z") - .hasResponse( - "contact_create_response_sh8013.xml", - ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z")); - assertThatCommand("contact_create_jd1234.xml") - .atTime("2000-06-01T00:01:00Z") - .hasResponse("contact_create_response_jd1234.xml"); - // Create domain example.bar.foo.tld assertThatCommand( "domain_create_no_hosts_or_dsdata.xml", diff --git a/core/src/test/java/google/registry/flows/EppTestCase.java b/core/src/test/java/google/registry/flows/EppTestCase.java index d86f84134..23f6979d6 100644 --- a/core/src/test/java/google/registry/flows/EppTestCase.java +++ b/core/src/test/java/google/registry/flows/EppTestCase.java @@ -223,7 +223,7 @@ public class EppTestCase { return eppMetricBuilder.build(); } - /** Create the two administrative contacts and two hosts. */ + /** Create the two hosts. */ void createHosts() throws Exception { DateTime createTime = DateTime.parse("2000-06-01T00:00:00Z"); assertThatCommand("host_create.xml", ImmutableMap.of("HOSTNAME", "ns1.example.external")) diff --git a/core/src/test/java/google/registry/flows/contact/ContactCheckFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactCheckFlowTest.java index bb95bd53d..d8763dea1 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactCheckFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactCheckFlowTest.java @@ -14,85 +14,25 @@ package google.registry.flows.contact; -import static google.registry.model.eppoutput.CheckData.ContactCheck.create; -import static google.registry.testing.DatabaseHelper.persistActiveContact; -import static google.registry.testing.DatabaseHelper.persistDeletedContact; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; import static org.junit.jupiter.api.Assertions.assertThrows; -import google.registry.flows.EppException; -import google.registry.flows.FlowUtils.NotLoggedInException; -import google.registry.flows.ResourceCheckFlowTestCase; -import google.registry.flows.exceptions.TooManyResourceChecksException; -import google.registry.model.contact.Contact; +import google.registry.flows.FlowTestCase; +import google.registry.flows.exceptions.ContactsProhibitedException; import org.junit.jupiter.api.Test; /** Unit tests for {@link ContactCheckFlow}. */ -class ContactCheckFlowTest extends ResourceCheckFlowTestCase { +class ContactCheckFlowTest extends FlowTestCase { ContactCheckFlowTest() { setEppInput("contact_check.xml"); } @Test - void testNotLoggedIn() { - sessionMetadata.setRegistrarId(null); - EppException thrown = assertThrows(NotLoggedInException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); + void testThrowsException() { + assertAboutEppExceptions() + .that(assertThrows(ContactsProhibitedException.class, this::runFlow)) + .marshalsToXml(); } - @Test - void testNothingExists() throws Exception { - // These ids come from the check xml. - doCheckTest( - create(true, "sh8013", null), - create(true, "sah8013", null), - create(true, "8013sah", null)); - } - - @Test - void testOneExists() throws Exception { - persistActiveContact("sh8013"); - // These ids come from the check xml. - doCheckTest( - create(false, "sh8013", "In use"), - create(true, "sah8013", null), - create(true, "8013sah", null)); - } - - @Test - void testOneExistsButWasDeleted() throws Exception { - persistDeletedContact("sh8013", clock.nowUtc().minusDays(1)); - // These ids come from the check xml. - doCheckTest( - create(true, "sh8013", null), - create(true, "sah8013", null), - create(true, "8013sah", null)); - } - - @Test - void testXmlMatches() throws Exception { - persistActiveContact("sah8013"); - runFlowAssertResponse(loadFile("contact_check_response.xml")); - } - - @Test - void test50IdsAllowed() throws Exception { - // Make sure we don't have a regression that reduces the number of allowed checks. - setEppInput("contact_check_50.xml"); - runFlow(); - } - - @Test - void testTooManyIds() { - setEppInput("contact_check_51.xml"); - EppException thrown = assertThrows(TooManyResourceChecksException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testIcannActivityReportField_getsLogged() throws Exception { - runFlow(); - assertIcannReportingActivityFieldLogged("srs-cont-check"); - } } diff --git a/core/src/test/java/google/registry/flows/contact/ContactCreateFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactCreateFlowTest.java index 4b2232b4c..7ad3517f5 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactCreateFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactCreateFlowTest.java @@ -14,141 +14,24 @@ package google.registry.flows.contact; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_PROHIBITED; -import static google.registry.model.common.FeatureFlag.FeatureStatus.ACTIVE; -import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE; -import static google.registry.testing.ContactSubject.assertAboutContacts; -import static google.registry.testing.DatabaseHelper.assertNoBillingEvents; -import static google.registry.testing.DatabaseHelper.newContact; -import static google.registry.testing.DatabaseHelper.persistActiveContact; -import static google.registry.testing.DatabaseHelper.persistDeletedContact; -import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; -import static google.registry.util.DateTimeUtils.START_OF_TIME; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.google.common.collect.ImmutableSortedMap; -import google.registry.flows.EppException; -import google.registry.flows.FlowUtils.NotLoggedInException; -import google.registry.flows.ResourceFlowTestCase; -import google.registry.flows.contact.ContactFlowUtils.BadInternationalizedPostalInfoException; -import google.registry.flows.contact.ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException; +import google.registry.flows.FlowTestCase; import google.registry.flows.exceptions.ContactsProhibitedException; -import google.registry.flows.exceptions.ResourceAlreadyExistsForThisClientException; -import google.registry.flows.exceptions.ResourceCreateContentionException; -import google.registry.model.common.FeatureFlag; -import google.registry.model.contact.Contact; -import org.joda.time.DateTime; import org.junit.jupiter.api.Test; /** Unit tests for {@link ContactCreateFlow}. */ -class ContactCreateFlowTest extends ResourceFlowTestCase { +class ContactCreateFlowTest extends FlowTestCase { ContactCreateFlowTest() { setEppInput("contact_create.xml"); - clock.setTo(DateTime.parse("1999-04-03T22:00:00.0Z")); - } - - private void doSuccessfulTest() throws Exception { - assertMutatingFlow(true); - runFlowAssertResponse(loadFile("contact_create_response.xml")); - // Check that the contact was created and persisted with a history entry. - Contact contact = reloadResourceByForeignKey(); - assertAboutContacts().that(contact).hasOnlyOneHistoryEntryWhich().hasNoXml(); - assertNoBillingEvents(); - assertLastHistoryContainsResource(contact); } @Test - void testNotLoggedIn() { - sessionMetadata.setRegistrarId(null); - EppException thrown = assertThrows(NotLoggedInException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testDryRun() throws Exception { - dryRunFlowAssertResponse(loadFile("contact_create_response.xml")); - } - - @Test - void testSuccess_neverExisted() throws Exception { - doSuccessfulTest(); - } - - @Test - void testSuccess_existedButWasDeleted() throws Exception { - persistDeletedContact(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1)); - clock.advanceOneMilli(); - doSuccessfulTest(); - } - - @Test - void testFailure_alreadyExists() throws Exception { - persistActiveContact(getUniqueIdFromCommand()); - ResourceAlreadyExistsForThisClientException thrown = - assertThrows(ResourceAlreadyExistsForThisClientException.class, this::runFlow); - assertThat(thrown) - .hasMessageThat() - .contains( - String.format("Object with given ID (%s) already exists", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_minimumDatasetPhase2_cannotCreateContacts() throws Exception { - persistResource( - new FeatureFlag.Builder() - .setFeatureName(MINIMUM_DATASET_CONTACTS_PROHIBITED) - .setStatusMap( - ImmutableSortedMap.of(START_OF_TIME, INACTIVE, clock.nowUtc().minusDays(5), ACTIVE)) - .build()); - EppException thrown = assertThrows(ContactsProhibitedException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_resourceContention() throws Exception { - String targetId = getUniqueIdFromCommand(); - persistResource( - newContact(targetId) - .asBuilder() - .setPersistedCurrentSponsorRegistrarId("NewRegistrar") - .build()); - ResourceCreateContentionException thrown = - assertThrows(ResourceCreateContentionException.class, this::runFlow); - assertThat(thrown) - .hasMessageThat() - .contains(String.format("Object with given ID (%s) already exists", targetId)); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess_nonAsciiInLocAddress() throws Exception { - setEppInput("contact_create_hebrew_loc.xml"); - doSuccessfulTest(); - } - - @Test - void testFailure_nonAsciiInIntAddress() { - setEppInput("contact_create_hebrew_int.xml"); - EppException thrown = - assertThrows(BadInternationalizedPostalInfoException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_declineDisclosure() { - setEppInput("contact_create_decline_disclosure.xml"); - EppException thrown = - assertThrows(DeclineContactDisclosureFieldDisallowedPolicyException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testIcannActivityReportField_getsLogged() throws Exception { - runFlow(); - assertIcannReportingActivityFieldLogged("srs-cont-create"); + void testThrowsException() { + assertAboutEppExceptions() + .that(assertThrows(ContactsProhibitedException.class, this::runFlow)) + .marshalsToXml(); } } diff --git a/core/src/test/java/google/registry/flows/contact/ContactDeleteFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactDeleteFlowTest.java index 71c419704..20298cfad 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactDeleteFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactDeleteFlowTest.java @@ -14,269 +14,24 @@ package google.registry.flows.contact; -import static com.google.common.collect.MoreCollectors.onlyElement; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.ContactSubject.assertAboutContacts; -import static google.registry.testing.DatabaseHelper.assertNoBillingEvents; -import static google.registry.testing.DatabaseHelper.createTld; -import static google.registry.testing.DatabaseHelper.getPollMessages; -import static google.registry.testing.DatabaseHelper.newContact; -import static google.registry.testing.DatabaseHelper.persistActiveContact; -import static google.registry.testing.DatabaseHelper.persistContactWithPendingTransfer; -import static google.registry.testing.DatabaseHelper.persistDeletedContact; -import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Iterables; -import google.registry.flows.EppException; -import google.registry.flows.FlowUtils.NotLoggedInException; -import google.registry.flows.ResourceFlowTestCase; -import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; -import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException; -import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException; -import google.registry.flows.exceptions.ResourceToDeleteIsReferencedException; -import google.registry.model.contact.Contact; -import google.registry.model.eppcommon.StatusValue; -import google.registry.model.eppcommon.Trid; -import google.registry.model.poll.PendingActionNotificationResponse; -import google.registry.model.poll.PollMessage; -import google.registry.model.reporting.HistoryEntry; -import google.registry.model.reporting.HistoryEntry.Type; -import google.registry.model.tld.Tld; -import google.registry.model.transfer.TransferData; -import google.registry.model.transfer.TransferResponse; -import google.registry.model.transfer.TransferStatus; -import google.registry.testing.DatabaseHelper; -import org.joda.time.DateTime; -import org.junit.jupiter.api.BeforeEach; +import google.registry.flows.FlowTestCase; +import google.registry.flows.exceptions.ContactsProhibitedException; import org.junit.jupiter.api.Test; /** Unit tests for {@link ContactDeleteFlow}. */ -class ContactDeleteFlowTest extends ResourceFlowTestCase { +class ContactDeleteFlowTest extends FlowTestCase { - @BeforeEach - void initFlowTest() { + ContactDeleteFlowTest() { setEppInput("contact_delete.xml"); } @Test - void testNotLoggedIn() { - sessionMetadata.setRegistrarId(null); - EppException thrown = assertThrows(NotLoggedInException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testDryRun() throws Exception { - persistActiveContact(getUniqueIdFromCommand()); - dryRunFlowAssertResponse(loadFile("contact_delete_response.xml")); - } - - @Test - void testSuccess() throws Exception { - persistActiveContact(getUniqueIdFromCommand()); - clock.advanceOneMilli(); - assertMutatingFlow(true); - runFlowAssertResponse(loadFile("contact_delete_response.xml")); - assertSqlDeleteSuccess(); - } - - @Test - void testSuccess_pendingTransfer_sql() throws Exception { - DateTime transferRequestTime = clock.nowUtc().minusDays(3); - TransferData oldTransferData = - persistContactWithPendingTransfer( - persistActiveContact(getUniqueIdFromCommand()), - transferRequestTime, - transferRequestTime.plus(Tld.DEFAULT_TRANSFER_GRACE_PERIOD), - clock.nowUtc()) - .getTransferData(); - clock.advanceOneMilli(); - assertMutatingFlow(true); - runFlowAssertResponse(loadFile("contact_delete_response.xml")); - assertSqlDeleteSuccess(Type.CONTACT_DELETE, Type.CONTACT_TRANSFER_REQUEST); - Contact softDeletedContact = reloadResourceByForeignKey(clock.nowUtc().minusMillis(1)); - assertThat(softDeletedContact.getTransferData()) - .isEqualTo( - oldTransferData - .copyConstantFieldsToBuilder() - .setTransferStatus(TransferStatus.SERVER_CANCELLED) - .setPendingTransferExpirationTime(softDeletedContact.getDeletionTime()) - .build()); - PollMessage gainingPollMessage = - Iterables.getOnlyElement(getPollMessages("NewRegistrar", clock.nowUtc())); - assertThat(gainingPollMessage.getEventTime()).isEqualTo(clock.nowUtc()); - assertThat( - gainingPollMessage.getResponseData().stream() - .filter(TransferResponse.class::isInstance) - .map(TransferResponse.class::cast) - .collect(onlyElement()) - .getTransferStatus()) - .isEqualTo(TransferStatus.SERVER_CANCELLED); - PendingActionNotificationResponse panData = - gainingPollMessage.getResponseData().stream() - .filter(PendingActionNotificationResponse.class::isInstance) - .map(PendingActionNotificationResponse.class::cast) - .collect(onlyElement()); - assertThat(panData.getTrid()) - .isEqualTo(Trid.create("transferClient-trid", "transferServer-trid")); - assertThat(panData.getActionResult()).isFalse(); - } - - @Test - void testSuccess_clTridNotSpecified() throws Exception { - setEppInput("contact_delete_no_cltrid.xml"); - persistActiveContact(getUniqueIdFromCommand()); - clock.advanceOneMilli(); - assertMutatingFlow(true); - runFlowAssertResponse(loadFile("contact_delete_response_no_cltrid.xml")); - assertSqlDeleteSuccess(); - } - - @Test - void testFailure_neverExisted() throws Exception { - ResourceDoesNotExistException thrown = - assertThrows(ResourceDoesNotExistException.class, this::runFlow); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_existedButWasDeleted() throws Exception { - persistDeletedContact(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1)); - ResourceDoesNotExistException thrown = - assertThrows(ResourceDoesNotExistException.class, this::runFlow); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_existedButWasClientDeleteProhibited() throws Exception { - doFailingStatusTest( - StatusValue.CLIENT_DELETE_PROHIBITED, ResourceStatusProhibitsOperationException.class); - } - - @Test - void testFailure_existedButWasServerDeleteProhibited() throws Exception { - doFailingStatusTest( - StatusValue.SERVER_DELETE_PROHIBITED, ResourceStatusProhibitsOperationException.class); - } - - @Test - void testFailure_existedButWasPendingDelete() throws Exception { - doFailingStatusTest( - StatusValue.PENDING_DELETE, ResourceStatusProhibitsOperationException.class); - } - - private void doFailingStatusTest(StatusValue statusValue, Class exception) - throws Exception { - persistResource( - newContact(getUniqueIdFromCommand()) - .asBuilder() - .setStatusValues(ImmutableSet.of(statusValue)) - .build()); - EppException thrown = assertThrows(exception, this::runFlow); - assertThat(thrown).hasMessageThat().contains(statusValue.getXmlName()); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess_clientDeleteProhibited_superuser() throws Exception { - persistResource( - persistActiveContact(getUniqueIdFromCommand()) - .asBuilder() - .addStatusValue(StatusValue.CLIENT_DELETE_PROHIBITED) - .build()); - runFlowAssertResponse( - CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("contact_delete_response.xml")); - } - - @Test - void testSuccess_serverDeleteProhibited_superuser() throws Exception { - persistResource( - persistActiveContact(getUniqueIdFromCommand()) - .asBuilder() - .addStatusValue(StatusValue.SERVER_DELETE_PROHIBITED) - .build()); - runFlowAssertResponse( - CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("contact_delete_response.xml")); - } - - @Test - void testFailure_pendingDelete_superuser() throws Exception { - persistResource( - persistActiveContact(getUniqueIdFromCommand()) - .asBuilder() - .addStatusValue(StatusValue.PENDING_DELETE) - .build()); + void testThrowsException() { assertAboutEppExceptions() - .that( - assertThrows( - ResourceStatusProhibitsOperationException.class, - () -> runFlow(CommitMode.LIVE, UserPrivileges.SUPERUSER))) + .that(assertThrows(ContactsProhibitedException.class, this::runFlow)) .marshalsToXml(); } - - @Test - void testFailure_unauthorizedClient() throws Exception { - sessionMetadata.setRegistrarId("NewRegistrar"); - persistActiveContact(getUniqueIdFromCommand()); - EppException thrown = assertThrows(ResourceNotOwnedException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess_superuserUnauthorizedClient() throws Exception { - sessionMetadata.setRegistrarId("NewRegistrar"); - persistActiveContact(getUniqueIdFromCommand()); - clock.advanceOneMilli(); - runFlowAssertResponse( - CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("contact_delete_response.xml")); - assertSqlDeleteSuccess(); - } - - @Test - void testFailure_failfastWhenLinkedToDomain() throws Exception { - createTld("tld"); - persistResource( - DatabaseHelper.newDomain("example.tld", persistActiveContact(getUniqueIdFromCommand()))); - EppException thrown = assertThrows(ResourceToDeleteIsReferencedException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testIcannActivityReportField_getsLogged() throws Exception { - persistActiveContact(getUniqueIdFromCommand()); - clock.advanceOneMilli(); - runFlow(); - assertIcannReportingActivityFieldLogged("srs-cont-delete"); - } - - private void assertSqlDeleteSuccess(HistoryEntry.Type... historyEntryTypes) throws Exception { - assertThat(reloadResourceByForeignKey()).isNull(); - assertAboutContacts() - .that(reloadResourceByForeignKey(clock.nowUtc().minusMillis(1))) - .isNotActiveAt(clock.nowUtc()) - .and() - .hasNullLocalizedPostalInfo() - .and() - .hasNullInternationalizedPostalInfo() - .and() - .hasNullEmailAddress() - .and() - .hasNullVoiceNumber() - .and() - .hasNullFaxNumber() - .and() - .hasExactlyStatusValues(StatusValue.OK) - .and() - .hasOneHistoryEntryEachOfTypes(historyEntryTypes); - assertNoBillingEvents(); - } - - private void assertSqlDeleteSuccess() throws Exception { - assertSqlDeleteSuccess(Type.CONTACT_DELETE); - } } diff --git a/core/src/test/java/google/registry/flows/contact/ContactInfoFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactInfoFlowTest.java index 2a637da85..dcf034c00 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactInfoFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactInfoFlowTest.java @@ -14,202 +14,24 @@ package google.registry.flows.contact; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.model.EppResourceUtils.isDeleted; -import static google.registry.testing.DatabaseHelper.assertNoBillingEvents; -import static google.registry.testing.DatabaseHelper.createTld; -import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import google.registry.flows.EppException; -import google.registry.flows.FlowUtils.NotLoggedInException; -import google.registry.flows.ResourceFlowTestCase; -import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; -import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactAddress; -import google.registry.model.contact.ContactAuthInfo; -import google.registry.model.contact.ContactPhoneNumber; -import google.registry.model.contact.Disclose; -import google.registry.model.contact.PostalInfo; -import google.registry.model.contact.PostalInfo.Type; -import google.registry.model.eppcommon.AuthInfo.PasswordAuth; -import google.registry.model.eppcommon.PresenceMarker; -import google.registry.model.eppcommon.StatusValue; -import google.registry.testing.DatabaseHelper; -import org.joda.time.DateTime; +import google.registry.flows.FlowTestCase; +import google.registry.flows.exceptions.ContactsProhibitedException; import org.junit.jupiter.api.Test; /** Unit tests for {@link ContactInfoFlow}. */ -class ContactInfoFlowTest extends ResourceFlowTestCase { +class ContactInfoFlowTest extends FlowTestCase { ContactInfoFlowTest() { setEppInput("contact_info.xml"); } - private Contact persistContact(boolean active) { - Contact contact = - persistResource( - new Contact.Builder() - .setContactId("sh8013") - .setRepoId("2FF-ROID") - .setDeletionTime(active ? null : clock.nowUtc().minusDays(1)) - .setStatusValues(ImmutableSet.of(StatusValue.CLIENT_DELETE_PROHIBITED)) - .setInternationalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.INTERNATIONALIZED) - .setName("John Doe") - .setOrg("Example Inc.") - .setAddress( - new ContactAddress.Builder() - .setStreet(ImmutableList.of("123 Example Dr.", "Suite 100")) - .setCity("Dulles") - .setState("VA") - .setZip("20166-6503") - .setCountryCode("US") - .build()) - .build()) - .setVoiceNumber( - new ContactPhoneNumber.Builder() - .setPhoneNumber("+1.7035555555") - .setExtension("1234") - .build()) - .setFaxNumber( - new ContactPhoneNumber.Builder().setPhoneNumber("+1.7035555556").build()) - .setEmailAddress("jdoe@example.com") - .setPersistedCurrentSponsorRegistrarId("TheRegistrar") - .setCreationRegistrarId("NewRegistrar") - .setLastEppUpdateRegistrarId("NewRegistrar") - .setCreationTimeForTest(DateTime.parse("1999-04-03T22:00:00.0Z")) - .setLastEppUpdateTime(DateTime.parse("1999-12-03T09:00:00.0Z")) - .setLastTransferTime(DateTime.parse("2000-04-08T09:00:00.0Z")) - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("2fooBAR"))) - .setDisclose( - new Disclose.Builder() - .setFlag(true) - .setVoice(new PresenceMarker()) - .setEmail(new PresenceMarker()) - .build()) - .build()); - assertThat(isDeleted(contact, clock.nowUtc())).isNotEqualTo(active); - return contact; - } - @Test - void testNotLoggedIn() { - sessionMetadata.setRegistrarId(null); - EppException thrown = assertThrows(NotLoggedInException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess() throws Exception { - persistContact(true); - // Check that the persisted contact info was returned. - assertMutatingFlow(false); - runFlowAssertResponse( - loadFile("contact_info_response.xml"), - // We use a different roid scheme than the samples so ignore it. - "epp.response.resData.infData.roid"); - assertNoHistory(); - assertNoBillingEvents(); - } - - @Test - void testSuccess_linked() throws Exception { - createTld("foobar"); - persistResource(DatabaseHelper.newDomain("example.foobar", persistContact(true))); - // Check that the persisted contact info was returned. - assertMutatingFlow(false); - runFlowAssertResponse( - loadFile("contact_info_response_linked.xml"), - // We use a different roid scheme than the samples so ignore it. - "epp.response.resData.infData.roid"); - assertNoHistory(); - assertNoBillingEvents(); - } - - @Test - void testSuccess_owningRegistrarWithoutAuthInfo_seesAuthInfo() throws Exception { - setEppInput("contact_info_no_authinfo.xml"); - persistContact(true); - // Check that the persisted contact info was returned. - assertMutatingFlow(false); - runFlowAssertResponse( - loadFile("contact_info_response.xml"), - // We use a different roid scheme than the samples so ignore it. - "epp.response.resData.infData.roid"); - assertNoHistory(); - assertNoBillingEvents(); - } - - @Test - void testFailure_otherRegistrar_notAuthorized() throws Exception { - setRegistrarIdForFlow("NewRegistrar"); - persistContact(true); - // Check that the persisted contact info was returned. - assertMutatingFlow(false); - ResourceNotOwnedException thrown = assertThrows(ResourceNotOwnedException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess_otherRegistrarWithoutAuthInfoAsSuperuser_doesNotSeeAuthInfo() throws Exception { - setRegistrarIdForFlow("NewRegistrar"); - setEppInput("contact_info_no_authinfo.xml"); - persistContact(true); - // Check that the persisted contact info was returned. - assertMutatingFlow(false); - runFlowAssertResponse( - CommitMode.LIVE, - UserPrivileges.SUPERUSER, - loadFile("contact_info_response_no_authinfo.xml"), - // We use a different roid scheme than the samples so ignore it. - "epp.response.resData.infData.roid"); - assertNoHistory(); - assertNoBillingEvents(); - } - - @Test - void testSuccess_otherRegistrarWithAuthInfoAsSuperuser_seesAuthInfo() throws Exception { - setRegistrarIdForFlow("NewRegistrar"); - persistContact(true); - // Check that the persisted contact info was returned. - assertMutatingFlow(false); - runFlowAssertResponse( - CommitMode.LIVE, - UserPrivileges.SUPERUSER, - loadFile("contact_info_response.xml"), - // We use a different roid scheme than the samples so ignore it. - "epp.response.resData.infData.roid"); - assertNoHistory(); - assertNoBillingEvents(); - } - - @Test - void testFailure_neverExisted() throws Exception { - ResourceDoesNotExistException thrown = - assertThrows(ResourceDoesNotExistException.class, this::runFlow); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_existedButWasDeleted() throws Exception { - persistContact(false); - ResourceDoesNotExistException thrown = - assertThrows(ResourceDoesNotExistException.class, this::runFlow); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testIcannActivityReportField_getsLogged() throws Exception { - persistContact(true); - runFlow(); - assertIcannReportingActivityFieldLogged("srs-cont-info"); + void testThrowsException() { + assertAboutEppExceptions() + .that(assertThrows(ContactsProhibitedException.class, this::runFlow)) + .marshalsToXml(); } } diff --git a/core/src/test/java/google/registry/flows/contact/ContactTransferApproveFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactTransferApproveFlowTest.java index ed2bb584a..b8fd10471 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactTransferApproveFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactTransferApproveFlowTest.java @@ -14,254 +14,24 @@ package google.registry.flows.contact; -import static com.google.common.collect.MoreCollectors.onlyElement; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.ContactSubject.assertAboutContacts; -import static google.registry.testing.DatabaseHelper.assertNoBillingEvents; -import static google.registry.testing.DatabaseHelper.createTld; -import static google.registry.testing.DatabaseHelper.getOnlyPollMessage; -import static google.registry.testing.DatabaseHelper.getPollMessages; -import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; import static org.junit.jupiter.api.Assertions.assertThrows; -import google.registry.flows.EppException; -import google.registry.flows.FlowUtils.NotLoggedInException; -import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException; -import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; -import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException; -import google.registry.flows.exceptions.NotPendingTransferException; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactAuthInfo; -import google.registry.model.eppcommon.AuthInfo.PasswordAuth; -import google.registry.model.eppcommon.Trid; -import google.registry.model.poll.PendingActionNotificationResponse; -import google.registry.model.poll.PollMessage; -import google.registry.model.reporting.HistoryEntry; -import google.registry.model.transfer.TransferData; -import google.registry.model.transfer.TransferResponse; -import google.registry.model.transfer.TransferStatus; -import org.junit.jupiter.api.BeforeEach; +import google.registry.flows.FlowTestCase; +import google.registry.flows.exceptions.ContactsProhibitedException; import org.junit.jupiter.api.Test; /** Unit tests for {@link ContactTransferApproveFlow}. */ -class ContactTransferApproveFlowTest - extends ContactTransferFlowTestCase { +class ContactTransferApproveFlowTest extends FlowTestCase { - @BeforeEach - void setUp() { + ContactTransferApproveFlowTest() { setEppInput("contact_transfer_approve.xml"); - setRegistrarIdForFlow("TheRegistrar"); - setupContactWithPendingTransfer(); - clock.advanceOneMilli(); - createTld("foobar"); - } - - private void doSuccessfulTest(String commandFilename, String expectedXmlFilename) - throws Exception { - setEppInput(commandFilename); - // Look in the future and make sure the poll messages for implicit ack are there. - assertThat(getPollMessages("NewRegistrar", clock.nowUtc().plusMonths(1))) - .hasSize(1); - assertThat(getPollMessages("TheRegistrar", clock.nowUtc().plusMonths(1))) - .hasSize(1); - - // Setup done; run the test. - contact = reloadResourceByForeignKey(); - TransferData originalTransferData = contact.getTransferData(); - assertMutatingFlow(true); - runFlowAssertResponse(loadFile(expectedXmlFilename)); - - // Transfer should have succeeded. Verify correct fields were set. - contact = reloadResourceByForeignKey(); - assertAboutContacts() - .that(contact) - .hasCurrentSponsorRegistrarId("NewRegistrar") - .and() - .hasLastTransferTime(clock.nowUtc()) - .and() - .hasOneHistoryEntryEachOfTypes( - HistoryEntry.Type.CONTACT_TRANSFER_REQUEST, HistoryEntry.Type.CONTACT_TRANSFER_APPROVE); - assertThat(contact.getTransferData()) - .isEqualTo( - originalTransferData.copyConstantFieldsToBuilder() - .setTransferStatus(TransferStatus.CLIENT_APPROVED) - .setPendingTransferExpirationTime(clock.nowUtc()) - .build()); - assertNoBillingEvents(); - // The poll message (in the future) to the losing registrar for implicit ack should be gone. - assertThat(getPollMessages("TheRegistrar", clock.nowUtc().plusMonths(1))).isEmpty(); - // The poll message in the future to the gaining registrar should be gone too, but there - // should be one at the current time to the gaining registrar. - PollMessage gainingPollMessage = getOnlyPollMessage("NewRegistrar"); - assertThat(gainingPollMessage.getEventTime()).isEqualTo(clock.nowUtc()); - assertThat( - gainingPollMessage - .getResponseData() - .stream() - .filter(TransferResponse.class::isInstance) - .map(TransferResponse.class::cast) - .collect(onlyElement()) - .getTransferStatus()) - .isEqualTo(TransferStatus.CLIENT_APPROVED); - PendingActionNotificationResponse panData = - gainingPollMessage - .getResponseData() - .stream() - .filter(PendingActionNotificationResponse.class::isInstance) - .map(PendingActionNotificationResponse.class::cast) - .collect(onlyElement()); - assertThat(panData.getTrid()) - .isEqualTo(Trid.create("transferClient-trid", "transferServer-trid")); - assertThat(panData.getActionResult()).isTrue(); - assertLastHistoryContainsResource(contact); - } - - private void doFailingTest(String commandFilename) throws Exception { - setEppInput(commandFilename); - // Setup done; run the test. - assertMutatingFlow(true); - runFlow(); } @Test - void testNotLoggedIn() { - sessionMetadata.setRegistrarId(null); - EppException thrown = assertThrows(NotLoggedInException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testDryRun() throws Exception { - setEppInput("contact_transfer_approve.xml"); - dryRunFlowAssertResponse(loadFile("contact_transfer_approve_response.xml")); - } - - @Test - void testSuccess() throws Exception { - doSuccessfulTest("contact_transfer_approve.xml", "contact_transfer_approve_response.xml"); - } - - @Test - void testSuccess_withAuthinfo() throws Exception { - doSuccessfulTest("contact_transfer_approve_with_authinfo.xml", - "contact_transfer_approve_response.xml"); - } - - @Test - void testFailure_badContactPassword() { - // Change the contact's password so it does not match the password in the file. - contact = persistResource( - contact.asBuilder() - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("badpassword"))) - .build()); - EppException thrown = - assertThrows( - BadAuthInfoForResourceException.class, - () -> doFailingTest("contact_transfer_approve_with_authinfo.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_neverBeenTransferred() { - changeTransferStatus(null); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_approve.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_clientApproved() { - changeTransferStatus(TransferStatus.CLIENT_APPROVED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_approve.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_clientRejected() { - changeTransferStatus(TransferStatus.CLIENT_REJECTED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_approve.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_clientCancelled() { - changeTransferStatus(TransferStatus.CLIENT_CANCELLED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_approve.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_serverApproved() { - changeTransferStatus(TransferStatus.SERVER_APPROVED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_approve.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_serverCancelled() { - changeTransferStatus(TransferStatus.SERVER_CANCELLED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_approve.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_gainingClient() { - setRegistrarIdForFlow("NewRegistrar"); - EppException thrown = - assertThrows( - ResourceNotOwnedException.class, () -> doFailingTest("contact_transfer_approve.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_unrelatedClient() { - setRegistrarIdForFlow("ClientZ"); - EppException thrown = - assertThrows( - ResourceNotOwnedException.class, () -> doFailingTest("contact_transfer_approve.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_deletedContact() throws Exception { - contact = persistResource( - contact.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); - ResourceDoesNotExistException thrown = - assertThrows( - ResourceDoesNotExistException.class, - () -> doFailingTest("contact_transfer_approve.xml")); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_nonexistentContact() throws Exception { - persistResource(contact.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); - contact = persistResource( - contact.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); - ResourceDoesNotExistException thrown = - assertThrows( - ResourceDoesNotExistException.class, - () -> doFailingTest("contact_transfer_approve.xml")); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testIcannActivityReportField_getsLogged() throws Exception { - runFlow(); - assertIcannReportingActivityFieldLogged("srs-cont-transfer-approve"); + void testThrowsException() { + assertAboutEppExceptions() + .that(assertThrows(ContactsProhibitedException.class, this::runFlow)) + .marshalsToXml(); } } diff --git a/core/src/test/java/google/registry/flows/contact/ContactTransferCancelFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactTransferCancelFlowTest.java index 34cc6feab..97ca53213 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactTransferCancelFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactTransferCancelFlowTest.java @@ -14,240 +14,24 @@ package google.registry.flows.contact; -import static com.google.common.collect.MoreCollectors.onlyElement; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.ContactSubject.assertAboutContacts; -import static google.registry.testing.DatabaseHelper.assertNoBillingEvents; -import static google.registry.testing.DatabaseHelper.getOnlyPollMessage; -import static google.registry.testing.DatabaseHelper.getPollMessages; -import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; import static org.junit.jupiter.api.Assertions.assertThrows; -import google.registry.flows.EppException; -import google.registry.flows.FlowUtils.NotLoggedInException; -import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException; -import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; -import google.registry.flows.exceptions.NotPendingTransferException; -import google.registry.flows.exceptions.NotTransferInitiatorException; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactAuthInfo; -import google.registry.model.eppcommon.AuthInfo.PasswordAuth; -import google.registry.model.poll.PollMessage; -import google.registry.model.reporting.HistoryEntry; -import google.registry.model.transfer.TransferData; -import google.registry.model.transfer.TransferResponse; -import google.registry.model.transfer.TransferStatus; -import org.junit.jupiter.api.BeforeEach; +import google.registry.flows.FlowTestCase; +import google.registry.flows.exceptions.ContactsProhibitedException; import org.junit.jupiter.api.Test; /** Unit tests for {@link ContactTransferCancelFlow}. */ -class ContactTransferCancelFlowTest - extends ContactTransferFlowTestCase { +class ContactTransferCancelFlowTest extends FlowTestCase { - @BeforeEach - void setUp() { - this.setEppInput("contact_transfer_cancel.xml"); - setRegistrarIdForFlow("NewRegistrar"); - setupContactWithPendingTransfer(); - clock.advanceOneMilli(); - } - - private void doSuccessfulTest(String commandFilename, String expectedXmlFilename) - throws Exception { - this.setEppInput(commandFilename); - // Look in the future and make sure the poll messages for implicit ack are there. - assertThat(getPollMessages("NewRegistrar", clock.nowUtc().plusMonths(1))).hasSize(1); - assertThat(getPollMessages("TheRegistrar", clock.nowUtc().plusMonths(1))).hasSize(1); - - // Setup done; run the test. - contact = reloadResourceByForeignKey(); - TransferData originalTransferData = contact.getTransferData(); - assertMutatingFlow(true); - runFlowAssertResponse(loadFile(expectedXmlFilename)); - - // Transfer should have been cancelled. Verify correct fields were set. - contact = reloadResourceByForeignKey(); - assertAboutContacts() - .that(contact) - .hasCurrentSponsorRegistrarId("TheRegistrar") - .and() - .hasLastTransferTimeNotEqualTo(clock.nowUtc()) - .and() - .hasOneHistoryEntryEachOfTypes( - HistoryEntry.Type.CONTACT_TRANSFER_REQUEST, HistoryEntry.Type.CONTACT_TRANSFER_CANCEL); - assertThat(contact.getTransferData()) - .isEqualTo( - originalTransferData.copyConstantFieldsToBuilder() - .setTransferStatus(TransferStatus.CLIENT_CANCELLED) - .setPendingTransferExpirationTime(clock.nowUtc()) - .build()); - assertNoBillingEvents(); - // The poll message (in the future) to the gaining registrar for implicit ack should be gone. - assertThat(getPollMessages("NewRegistrar", clock.nowUtc().plusMonths(1))).isEmpty(); - // The poll message in the future to the losing registrar should be gone too, but there - // should be one at the current time to the losing registrar. - PollMessage losingPollMessage = getOnlyPollMessage("TheRegistrar"); - assertThat(losingPollMessage.getEventTime()).isEqualTo(clock.nowUtc()); - assertThat( - losingPollMessage - .getResponseData() - .stream() - .filter(TransferResponse.class::isInstance) - .map(TransferResponse.class::cast) - .collect(onlyElement()) - .getTransferStatus()) - .isEqualTo(TransferStatus.CLIENT_CANCELLED); - assertLastHistoryContainsResource(contact); - } - - private void doFailingTest(String commandFilename) throws Exception { - this.setEppInput(commandFilename); - // Setup done; run the test. - assertMutatingFlow(true); - runFlow(); - } - - @Test - void testNotLoggedIn() { - sessionMetadata.setRegistrarId(null); - EppException thrown = assertThrows(NotLoggedInException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testDryRun() throws Exception { + ContactTransferCancelFlowTest() { setEppInput("contact_transfer_cancel.xml"); - dryRunFlowAssertResponse(loadFile("contact_transfer_cancel_response.xml")); } @Test - void testSuccess() throws Exception { - doSuccessfulTest("contact_transfer_cancel.xml", "contact_transfer_cancel_response.xml"); - } - - @Test - void testSuccess_withAuthinfo() throws Exception { - doSuccessfulTest("contact_transfer_cancel_with_authinfo.xml", - "contact_transfer_cancel_response.xml"); - } - - @Test - void testFailure_badContactPassword() { - // Change the contact's password so it does not match the password in the file. - contact = - persistResource( - contact - .asBuilder() - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("badpassword"))) - .build()); - EppException thrown = - assertThrows( - BadAuthInfoForResourceException.class, - () -> doFailingTest("contact_transfer_cancel_with_authinfo.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_neverBeenTransferred() { - changeTransferStatus(null); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_cancel.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_clientApproved() { - changeTransferStatus(TransferStatus.CLIENT_APPROVED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_cancel.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_clientRejected() { - changeTransferStatus(TransferStatus.CLIENT_REJECTED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_cancel.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_clientCancelled() { - changeTransferStatus(TransferStatus.CLIENT_CANCELLED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_cancel.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_serverApproved() { - changeTransferStatus(TransferStatus.SERVER_APPROVED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_cancel.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_serverCancelled() { - changeTransferStatus(TransferStatus.SERVER_CANCELLED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_cancel.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_sponsoringClient() { - setRegistrarIdForFlow("TheRegistrar"); - EppException thrown = - assertThrows( - NotTransferInitiatorException.class, - () -> doFailingTest("contact_transfer_cancel.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_unrelatedClient() { - setRegistrarIdForFlow("ClientZ"); - EppException thrown = - assertThrows( - NotTransferInitiatorException.class, - () -> doFailingTest("contact_transfer_cancel.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_deletedContact() throws Exception { - contact = - persistResource(contact.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); - ResourceDoesNotExistException thrown = - assertThrows( - ResourceDoesNotExistException.class, - () -> doFailingTest("contact_transfer_cancel.xml")); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_nonexistentContact() throws Exception { - persistResource(contact.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); - ResourceDoesNotExistException thrown = - assertThrows( - ResourceDoesNotExistException.class, - () -> doFailingTest("contact_transfer_cancel.xml")); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testIcannActivityReportField_getsLogged() throws Exception { - runFlow(); - assertIcannReportingActivityFieldLogged("srs-cont-transfer-cancel"); + void testThrowsException() { + assertAboutEppExceptions() + .that(assertThrows(ContactsProhibitedException.class, this::runFlow)) + .marshalsToXml(); } } diff --git a/core/src/test/java/google/registry/flows/contact/ContactTransferFlowTestCase.java b/core/src/test/java/google/registry/flows/contact/ContactTransferFlowTestCase.java deleted file mode 100644 index d71577ee1..000000000 --- a/core/src/test/java/google/registry/flows/contact/ContactTransferFlowTestCase.java +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2017 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.flows.contact; - -import static com.google.common.base.Preconditions.checkState; -import static google.registry.testing.DatabaseHelper.newContact; -import static google.registry.testing.DatabaseHelper.persistContactWithPendingTransfer; -import static google.registry.testing.DatabaseHelper.persistResource; - -import google.registry.flows.Flow; -import google.registry.flows.ResourceFlowTestCase; -import google.registry.model.EppResource; -import google.registry.model.contact.Contact; -import google.registry.model.tld.Tld; -import google.registry.model.transfer.TransferStatus; -import google.registry.persistence.transaction.JpaTransactionManagerExtension; -import org.joda.time.DateTime; -import org.joda.time.Duration; -import org.junit.jupiter.api.BeforeEach; - -/** - * Base class for contact transfer flow unit tests. - * - * @param the flow type - * @param the resource type - */ -abstract class ContactTransferFlowTestCase - extends ResourceFlowTestCase { - - // Transfer is requested on the 6th and expires on the 11th. - // The "now" of this flow is on the 9th, 3 days in. - - private static final DateTime TRANSFER_REQUEST_TIME = DateTime.parse("2000-06-06T22:00:00.0Z"); - private static final DateTime TRANSFER_EXPIRATION_TIME = - TRANSFER_REQUEST_TIME.plus(Tld.DEFAULT_TRANSFER_GRACE_PERIOD); - private static final Duration TIME_SINCE_REQUEST = Duration.standardDays(3); - - protected Contact contact; - - ContactTransferFlowTestCase() { - checkState(!Tld.DEFAULT_TRANSFER_GRACE_PERIOD.isShorterThan(TIME_SINCE_REQUEST)); - clock.setTo(TRANSFER_REQUEST_TIME.plus(TIME_SINCE_REQUEST)); - } - - @BeforeEach - void beforeEachContactTransferFlowTestCase() { - // Registrar ClientZ is used in tests that need another registrar that definitely doesn't own - // the resources in question. - persistResource( - JpaTransactionManagerExtension.makeRegistrar1() - .asBuilder() - .setRegistrarId("ClientZ") - .build()); - } - - /** Adds a contact that has a pending transfer on it from TheRegistrar to NewRegistrar. */ - void setupContactWithPendingTransfer() { - contact = - persistContactWithPendingTransfer( - newContact("sh8013"), - TRANSFER_REQUEST_TIME, - TRANSFER_EXPIRATION_TIME, - TRANSFER_REQUEST_TIME); - } - - /** Changes the transfer status on the persisted contact. */ - protected void changeTransferStatus(TransferStatus transferStatus) { - contact = persistResource( - contact.asBuilder() - .setTransferData( - contact.getTransferData().asBuilder().setTransferStatus(transferStatus).build()) - .build()); - clock.advanceOneMilli(); - } - - /** Changes the client ID that the flow will run as. */ - @Override - protected void setRegistrarIdForFlow(String registrarId) { - sessionMetadata.setRegistrarId(registrarId); - } -} diff --git a/core/src/test/java/google/registry/flows/contact/ContactTransferQueryFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactTransferQueryFlowTest.java index cd0990f30..916557141 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactTransferQueryFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactTransferQueryFlowTest.java @@ -14,206 +14,24 @@ package google.registry.flows.contact; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.ContactSubject.assertAboutContacts; -import static google.registry.testing.DatabaseHelper.assertNoBillingEvents; -import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; import static org.junit.jupiter.api.Assertions.assertThrows; -import google.registry.flows.EppException; -import google.registry.flows.FlowUtils.NotLoggedInException; -import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException; -import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; -import google.registry.flows.exceptions.NoTransferHistoryToQueryException; -import google.registry.flows.exceptions.NotAuthorizedToViewTransferException; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactAuthInfo; -import google.registry.model.eppcommon.AuthInfo.PasswordAuth; -import google.registry.model.reporting.HistoryEntry; -import google.registry.model.transfer.TransferStatus; -import org.joda.time.DateTime; -import org.junit.jupiter.api.BeforeEach; +import google.registry.flows.FlowTestCase; +import google.registry.flows.exceptions.ContactsProhibitedException; import org.junit.jupiter.api.Test; /** Unit tests for {@link ContactTransferQueryFlow}. */ -class ContactTransferQueryFlowTest - extends ContactTransferFlowTestCase { +class ContactTransferQueryFlowTest extends FlowTestCase { - @BeforeEach - void setUp() { + ContactTransferQueryFlowTest() { setEppInput("contact_transfer_query.xml"); - clock.setTo(DateTime.parse("2000-06-10T22:00:00.0Z")); - setRegistrarIdForFlow("NewRegistrar"); - setupContactWithPendingTransfer(); - } - - private void doSuccessfulTest(String commandFilename, String expectedXmlFilename) - throws Exception { - setEppInput(commandFilename); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); - // Setup done; run the test. - assertMutatingFlow(false); - runFlowAssertResponse(loadFile(expectedXmlFilename)); - assertAboutContacts().that(reloadResourceByForeignKey(clock.nowUtc().minusDays(1))) - .hasOneHistoryEntryEachOfTypes(HistoryEntry.Type.CONTACT_TRANSFER_REQUEST); - assertNoBillingEvents(); - } - - private void doFailingTest(String commandFilename) throws Exception { - setEppInput(commandFilename); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); - // Setup done; run the test. - assertMutatingFlow(false); - runFlow(); } @Test - void testNotLoggedIn() { - sessionMetadata.setRegistrarId(null); - EppException thrown = assertThrows(NotLoggedInException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess() throws Exception { - doSuccessfulTest("contact_transfer_query.xml", "contact_transfer_query_response.xml"); - } - - @Test - void testSuccess_withContactRoid() throws Exception { - doSuccessfulTest("contact_transfer_query_with_roid.xml", "contact_transfer_query_response.xml"); - } - - @Test - void testSuccess_sponsoringClient() throws Exception { - setRegistrarIdForFlow("TheRegistrar"); - doSuccessfulTest("contact_transfer_query.xml", "contact_transfer_query_response.xml"); - } - - @Test - void testSuccess_withAuthinfo() throws Exception { - setRegistrarIdForFlow("ClientZ"); - doSuccessfulTest("contact_transfer_query_with_authinfo.xml", - "contact_transfer_query_response.xml"); - } - - @Test - void testSuccess_clientApproved() throws Exception { - changeTransferStatus(TransferStatus.CLIENT_APPROVED); - doSuccessfulTest("contact_transfer_query.xml", - "contact_transfer_query_response_client_approved.xml"); - } - - @Test - void testSuccess_clientRejected() throws Exception { - changeTransferStatus(TransferStatus.CLIENT_REJECTED); - doSuccessfulTest("contact_transfer_query.xml", - "contact_transfer_query_response_client_rejected.xml"); - } - - @Test - void testSuccess_clientCancelled() throws Exception { - changeTransferStatus(TransferStatus.CLIENT_CANCELLED); - doSuccessfulTest("contact_transfer_query.xml", - "contact_transfer_query_response_client_cancelled.xml"); - } - - @Test - void testSuccess_serverApproved() throws Exception { - changeTransferStatus(TransferStatus.SERVER_APPROVED); - doSuccessfulTest("contact_transfer_query.xml", - "contact_transfer_query_response_server_approved.xml"); - } - - @Test - void testSuccess_serverCancelled() throws Exception { - changeTransferStatus(TransferStatus.SERVER_CANCELLED); - doSuccessfulTest("contact_transfer_query.xml", - "contact_transfer_query_response_server_cancelled.xml"); - } - - @Test - void testFailure_pendingDeleteContact() throws Exception { - changeTransferStatus(TransferStatus.SERVER_CANCELLED); - contact = persistResource( - contact.asBuilder().setDeletionTime(clock.nowUtc().plusDays(1)).build()); - doSuccessfulTest("contact_transfer_query.xml", - "contact_transfer_query_response_server_cancelled.xml"); - } - - @Test - void testFailure_badContactPassword() { - // Change the contact's password so it does not match the password in the file. - contact = - persistResource( - contact - .asBuilder() - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("badpassword"))) - .build()); - EppException thrown = - assertThrows( - BadAuthInfoForResourceException.class, - () -> doFailingTest("contact_transfer_query_with_authinfo.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_badContactRoid() { - // Set the contact to a different ROID, but don't persist it; this is just so the substitution - // code above will write the wrong ROID into the file. - contact = contact.asBuilder().setRepoId("DEADBEEF_TLD-ROID").build(); - EppException thrown = - assertThrows( - BadAuthInfoForResourceException.class, - () -> doFailingTest("contact_transfer_query_with_roid.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_neverBeenTransferred() { - changeTransferStatus(null); - EppException thrown = - assertThrows( - NoTransferHistoryToQueryException.class, - () -> doFailingTest("contact_transfer_query.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_unrelatedClient() { - setRegistrarIdForFlow("ClientZ"); - EppException thrown = - assertThrows( - NotAuthorizedToViewTransferException.class, - () -> doFailingTest("contact_transfer_query.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_deletedContact() throws Exception { - contact = - persistResource(contact.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); - ResourceDoesNotExistException thrown = - assertThrows( - ResourceDoesNotExistException.class, () -> doFailingTest("contact_transfer_query.xml")); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_nonexistentContact() throws Exception { - persistResource(contact.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); - ResourceDoesNotExistException thrown = - assertThrows( - ResourceDoesNotExistException.class, () -> doFailingTest("contact_transfer_query.xml")); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testIcannActivityReportField_getsLogged() throws Exception { - runFlow(); - assertIcannReportingActivityFieldLogged("srs-cont-transfer-query"); + void testThrowsException() { + assertAboutEppExceptions() + .that(assertThrows(ContactsProhibitedException.class, this::runFlow)) + .marshalsToXml(); } } diff --git a/core/src/test/java/google/registry/flows/contact/ContactTransferRejectFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactTransferRejectFlowTest.java index cadb75cd2..53c5c5305 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactTransferRejectFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactTransferRejectFlowTest.java @@ -14,253 +14,24 @@ package google.registry.flows.contact; -import static com.google.common.collect.MoreCollectors.onlyElement; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.ContactSubject.assertAboutContacts; -import static google.registry.testing.DatabaseHelper.assertNoBillingEvents; -import static google.registry.testing.DatabaseHelper.getOnlyPollMessage; -import static google.registry.testing.DatabaseHelper.getPollMessages; -import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; import static org.junit.jupiter.api.Assertions.assertThrows; -import google.registry.flows.EppException; -import google.registry.flows.FlowUtils.NotLoggedInException; -import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException; -import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; -import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException; -import google.registry.flows.exceptions.NotPendingTransferException; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactAuthInfo; -import google.registry.model.eppcommon.AuthInfo.PasswordAuth; -import google.registry.model.eppcommon.Trid; -import google.registry.model.poll.PendingActionNotificationResponse; -import google.registry.model.poll.PollMessage; -import google.registry.model.reporting.HistoryEntry; -import google.registry.model.transfer.TransferData; -import google.registry.model.transfer.TransferResponse; -import google.registry.model.transfer.TransferStatus; -import org.junit.jupiter.api.BeforeEach; +import google.registry.flows.FlowTestCase; +import google.registry.flows.exceptions.ContactsProhibitedException; import org.junit.jupiter.api.Test; /** Unit tests for {@link ContactTransferRejectFlow}. */ -class ContactTransferRejectFlowTest - extends ContactTransferFlowTestCase { +class ContactTransferRejectFlowTest extends FlowTestCase { - @BeforeEach - void setUp() { + ContactTransferRejectFlowTest() { setEppInput("contact_transfer_reject.xml"); - setRegistrarIdForFlow("TheRegistrar"); - setupContactWithPendingTransfer(); - clock.advanceOneMilli(); - } - - private void doSuccessfulTest(String commandFilename, String expectedXmlFilename) - throws Exception { - setEppInput(commandFilename); - // Look in the future and make sure the poll messages for implicit ack are there. - assertThat(getPollMessages("NewRegistrar", clock.nowUtc().plusMonths(1))) - .hasSize(1); - assertThat(getPollMessages("TheRegistrar", clock.nowUtc().plusMonths(1))) - .hasSize(1); - - // Setup done; run the test. - contact = reloadResourceByForeignKey(); - TransferData originalTransferData = contact.getTransferData(); - assertMutatingFlow(true); - runFlowAssertResponse(loadFile(expectedXmlFilename)); - - // Transfer should have failed. Verify correct fields were set. - contact = reloadResourceByForeignKey(); - assertAboutContacts() - .that(contact) - .hasCurrentSponsorRegistrarId("TheRegistrar") - .and() - .hasLastTransferTimeNotEqualTo(clock.nowUtc()) - .and() - .hasOneHistoryEntryEachOfTypes( - HistoryEntry.Type.CONTACT_TRANSFER_REQUEST, HistoryEntry.Type.CONTACT_TRANSFER_REJECT); - assertThat(contact.getTransferData()) - .isEqualTo( - originalTransferData.copyConstantFieldsToBuilder() - .setTransferStatus(TransferStatus.CLIENT_REJECTED) - .setPendingTransferExpirationTime(clock.nowUtc()) - .build()); - // The poll message (in the future) to the losing registrar for implicit ack should be gone. - assertThat(getPollMessages("TheRegistrar", clock.nowUtc().plusMonths(1))) - .isEmpty(); - // The poll message in the future to the gaining registrar should be gone too, but there - // should be one at the current time to the gaining registrar. - PollMessage gainingPollMessage = getOnlyPollMessage("NewRegistrar"); - assertThat(gainingPollMessage.getEventTime()).isEqualTo(clock.nowUtc()); - assertThat( - gainingPollMessage - .getResponseData() - .stream() - .filter(TransferResponse.class::isInstance) - .map(TransferResponse.class::cast) - .collect(onlyElement()) - .getTransferStatus()) - .isEqualTo(TransferStatus.CLIENT_REJECTED); - PendingActionNotificationResponse panData = - gainingPollMessage - .getResponseData() - .stream() - .filter(PendingActionNotificationResponse.class::isInstance) - .map(PendingActionNotificationResponse.class::cast) - .collect(onlyElement()); - assertThat(panData.getTrid()) - .isEqualTo(Trid.create("transferClient-trid", "transferServer-trid")); - assertThat(panData.getActionResult()).isFalse(); - assertNoBillingEvents(); - assertLastHistoryContainsResource(contact); - } - - private void doFailingTest(String commandFilename) throws Exception { - setEppInput(commandFilename); - // Setup done; run the test. - assertMutatingFlow(true); - runFlow(); } @Test - void testNotLoggedIn() { - sessionMetadata.setRegistrarId(null); - EppException thrown = assertThrows(NotLoggedInException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testDryRun() throws Exception { - setEppInput("contact_transfer_reject.xml"); - dryRunFlowAssertResponse(loadFile("contact_transfer_reject_response.xml")); - } - - @Test - void testSuccess() throws Exception { - doSuccessfulTest("contact_transfer_reject.xml", "contact_transfer_reject_response.xml"); - } - - @Test - void testSuccess_domainAuthInfo() throws Exception { - doSuccessfulTest("contact_transfer_reject_with_authinfo.xml", - "contact_transfer_reject_response.xml"); - } - - @Test - void testFailure_badPassword() { - // Change the contact's password so it does not match the password in the file. - contact = - persistResource( - contact - .asBuilder() - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("badpassword"))) - .build()); - EppException thrown = - assertThrows( - BadAuthInfoForResourceException.class, - () -> doFailingTest("contact_transfer_reject_with_authinfo.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_neverBeenTransferred() { - changeTransferStatus(null); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_reject.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_clientApproved() { - changeTransferStatus(TransferStatus.CLIENT_APPROVED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_reject.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_clientRejected() { - changeTransferStatus(TransferStatus.CLIENT_REJECTED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_reject.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_clientCancelled() { - changeTransferStatus(TransferStatus.CLIENT_CANCELLED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_reject.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_serverApproved() { - changeTransferStatus(TransferStatus.SERVER_APPROVED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_reject.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_serverCancelled() { - changeTransferStatus(TransferStatus.SERVER_CANCELLED); - EppException thrown = - assertThrows( - NotPendingTransferException.class, () -> doFailingTest("contact_transfer_reject.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_gainingClient() { - setRegistrarIdForFlow("NewRegistrar"); - EppException thrown = - assertThrows( - ResourceNotOwnedException.class, () -> doFailingTest("contact_transfer_reject.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_unrelatedClient() { - setRegistrarIdForFlow("ClientZ"); - EppException thrown = - assertThrows( - ResourceNotOwnedException.class, () -> doFailingTest("contact_transfer_reject.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_deletedContact() throws Exception { - contact = - persistResource(contact.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); - ResourceDoesNotExistException thrown = - assertThrows( - ResourceDoesNotExistException.class, - () -> doFailingTest("contact_transfer_reject.xml")); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_nonexistentContact() throws Exception { - persistResource(contact.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); - ResourceDoesNotExistException thrown = - assertThrows( - ResourceDoesNotExistException.class, - () -> doFailingTest("contact_transfer_reject.xml")); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testIcannActivityReportField_getsLogged() throws Exception { - runFlow(); - assertIcannReportingActivityFieldLogged("srs-cont-transfer-reject"); + void testThrowsException() { + assertAboutEppExceptions() + .that(assertThrows(ContactsProhibitedException.class, this::runFlow)) + .marshalsToXml(); } } diff --git a/core/src/test/java/google/registry/flows/contact/ContactTransferRequestFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactTransferRequestFlowTest.java index de9ebf8ef..abce25fff 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactTransferRequestFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactTransferRequestFlowTest.java @@ -14,304 +14,24 @@ package google.registry.flows.contact; -import static com.google.common.base.Predicates.equalTo; -import static com.google.common.base.Predicates.not; -import static com.google.common.collect.Iterables.getOnlyElement; -import static com.google.common.collect.MoreCollectors.onlyElement; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.config.RegistryConfig.getContactAutomaticTransferLength; -import static google.registry.testing.ContactSubject.assertAboutContacts; -import static google.registry.testing.DatabaseHelper.assertNoBillingEvents; -import static google.registry.testing.DatabaseHelper.assertPollMessagesEqual; -import static google.registry.testing.DatabaseHelper.deleteResource; -import static google.registry.testing.DatabaseHelper.getPollMessages; -import static google.registry.testing.DatabaseHelper.loadByKeys; -import static google.registry.testing.DatabaseHelper.persistActiveContact; -import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; -import static google.registry.util.CollectionUtils.forceEmptyToNull; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Iterables; -import google.registry.flows.EppException; -import google.registry.flows.FlowUtils.NotLoggedInException; -import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException; -import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; -import google.registry.flows.exceptions.AlreadyPendingTransferException; -import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException; -import google.registry.flows.exceptions.ObjectAlreadySponsoredException; -import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactAuthInfo; -import google.registry.model.eppcommon.AuthInfo.PasswordAuth; -import google.registry.model.eppcommon.StatusValue; -import google.registry.model.eppcommon.Trid; -import google.registry.model.poll.PollMessage; -import google.registry.model.reporting.HistoryEntry; -import google.registry.model.transfer.ContactTransferData; -import google.registry.model.transfer.TransferStatus; -import org.joda.time.DateTime; -import org.junit.jupiter.api.BeforeEach; +import google.registry.flows.FlowTestCase; +import google.registry.flows.exceptions.ContactsProhibitedException; import org.junit.jupiter.api.Test; /** Unit tests for {@link ContactTransferRequestFlow}. */ -class ContactTransferRequestFlowTest - extends ContactTransferFlowTestCase { +class ContactTransferRequestFlowTest extends FlowTestCase { ContactTransferRequestFlowTest() { - // We need the transfer to happen at exactly this time in order for the response to match up. - clock.setTo(DateTime.parse("2000-06-08T22:00:00.0Z")); - } - - @BeforeEach - void beforeEach() { setEppInput("contact_transfer_request.xml"); - setRegistrarIdForFlow("NewRegistrar"); - contact = persistActiveContact("sh8013"); - clock.advanceOneMilli(); - } - - private void doSuccessfulTest(String commandFilename, String expectedXmlFilename) - throws Exception { - setEppInput(commandFilename); - DateTime afterTransfer = clock.nowUtc().plus(getContactAutomaticTransferLength()); - - // Setup done; run the test. - assertMutatingFlow(true); - runFlowAssertResponse(loadFile(expectedXmlFilename)); - - // Transfer should have been requested. Verify correct fields were set. - contact = reloadResourceByForeignKey(); - assertAboutContacts() - .that(contact) - .hasCurrentSponsorRegistrarId("TheRegistrar") - .and() - .hasOnlyOneHistoryEntryWhich() - .hasType(HistoryEntry.Type.CONTACT_TRANSFER_REQUEST); - Trid expectedTrid = - Trid.create( - getClientTrid(), - contact.getTransferData().getTransferRequestTrid().getServerTransactionId()); - assertThat(contact.getTransferData()) - .isEqualTo( - new ContactTransferData.Builder() - .setTransferRequestTrid(expectedTrid) - .setTransferRequestTime(clock.nowUtc()) - .setGainingRegistrarId("NewRegistrar") - .setLosingRegistrarId("TheRegistrar") - .setTransferStatus(TransferStatus.PENDING) - .setPendingTransferExpirationTime(afterTransfer) - // Make the server-approve entities field a no-op comparison; it's easier to - // do this comparison separately below. - .setServerApproveEntities( - contact.getRepoId(), - contact.getTransferData().getHistoryEntryId(), - forceEmptyToNull(contact.getTransferData().getServerApproveEntities())) - .build()); - assertNoBillingEvents(); - assertThat(getPollMessages("TheRegistrar", clock.nowUtc())).hasSize(1); - PollMessage losingRequestMessage = - getOnlyElement(getPollMessages("TheRegistrar", clock.nowUtc())); - - // If we fast forward AUTOMATIC_TRANSFER_DAYS the transfer should have happened. - assertAboutContacts() - .that(contact.cloneProjectedAtTime(afterTransfer)) - .hasCurrentSponsorRegistrarId("NewRegistrar"); - assertThat(getPollMessages("NewRegistrar", afterTransfer)).hasSize(1); - assertThat(getPollMessages("TheRegistrar", afterTransfer)).hasSize(2); - PollMessage gainingApproveMessage = - getOnlyElement(getPollMessages("NewRegistrar", afterTransfer)); - PollMessage losingApproveMessage = - getPollMessages("TheRegistrar", afterTransfer) - .stream() - .filter(not(equalTo(losingRequestMessage))) - .collect(onlyElement()); - - // Check for TransferData server-approve entities containing what we expect: only - // poll messages, the approval notice ones for gaining and losing registrars. - assertPollMessagesEqual( - Iterables.filter( - loadByKeys(contact.getTransferData().getServerApproveEntities()), PollMessage.class), - ImmutableList.of(gainingApproveMessage, losingApproveMessage)); - assertLastHistoryContainsResource(contact); - } - - private void doFailingTest(String commandFilename) throws Exception { - setEppInput(commandFilename); - // Setup done; run the test. - assertMutatingFlow(true); - runFlow(); } @Test - void testNotLoggedIn() { - sessionMetadata.setRegistrarId(null); - EppException thrown = assertThrows(NotLoggedInException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testDryRun() throws Exception { - setEppInput("contact_transfer_request.xml"); - dryRunFlowAssertResponse(loadFile("contact_transfer_request_response.xml")); - } - - @Test - void testSuccess() throws Exception { - doSuccessfulTest("contact_transfer_request.xml", "contact_transfer_request_response.xml"); - } - - @Test - void testFailure_noAuthInfo() { - EppException thrown = - assertThrows( - MissingTransferRequestAuthInfoException.class, - () -> doFailingTest("contact_transfer_request_no_authinfo.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_badPassword() { - // Change the contact's password so it does not match the password in the file. - contact = - persistResource( - contact - .asBuilder() - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("badpassword"))) - .build()); - EppException thrown = - assertThrows( - BadAuthInfoForResourceException.class, - () -> doFailingTest("contact_transfer_request.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess_clientApproved() throws Exception { - changeTransferStatus(TransferStatus.CLIENT_APPROVED); - doSuccessfulTest("contact_transfer_request.xml", "contact_transfer_request_response.xml"); - } - - @Test - void testSuccess_clientRejected() throws Exception { - changeTransferStatus(TransferStatus.CLIENT_REJECTED); - doSuccessfulTest("contact_transfer_request.xml", "contact_transfer_request_response.xml"); - } - - @Test - void testSuccess_clientCancelled() throws Exception { - changeTransferStatus(TransferStatus.CLIENT_CANCELLED); - doSuccessfulTest("contact_transfer_request.xml", "contact_transfer_request_response.xml"); - } - - @Test - void testSuccess_serverApproved() throws Exception { - changeTransferStatus(TransferStatus.SERVER_APPROVED); - doSuccessfulTest("contact_transfer_request.xml", "contact_transfer_request_response.xml"); - } - - @Test - void testSuccess_serverCancelled() throws Exception { - changeTransferStatus(TransferStatus.SERVER_CANCELLED); - doSuccessfulTest("contact_transfer_request.xml", "contact_transfer_request_response.xml"); - } - - @Test - void testFailure_pending() { - contact = - persistResource( - contact - .asBuilder() - .setTransferData( - contact - .getTransferData() - .asBuilder() - .setTransferStatus(TransferStatus.PENDING) - .setPendingTransferExpirationTime(clock.nowUtc().plusDays(1)) - .build()) - .build()); - EppException thrown = - assertThrows( - AlreadyPendingTransferException.class, - () -> doFailingTest("contact_transfer_request.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_sponsoringClient() { - setRegistrarIdForFlow("TheRegistrar"); - EppException thrown = - assertThrows( - ObjectAlreadySponsoredException.class, - () -> doFailingTest("contact_transfer_request.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_deletedContact() throws Exception { - contact = - persistResource(contact.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); - ResourceDoesNotExistException thrown = - assertThrows( - ResourceDoesNotExistException.class, - () -> doFailingTest("contact_transfer_request.xml")); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_nonexistentContact() throws Exception { - deleteResource(contact); - ResourceDoesNotExistException thrown = - assertThrows( - ResourceDoesNotExistException.class, - () -> doFailingTest("contact_transfer_request.xml")); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_clientTransferProhibited() { - contact = - persistResource( - contact.asBuilder().addStatusValue(StatusValue.CLIENT_TRANSFER_PROHIBITED).build()); - ResourceStatusProhibitsOperationException thrown = - assertThrows( - ResourceStatusProhibitsOperationException.class, - () -> doFailingTest("contact_transfer_request.xml")); - assertThat(thrown).hasMessageThat().contains("clientTransferProhibited"); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_serverTransferProhibited() { - contact = - persistResource( - contact.asBuilder().addStatusValue(StatusValue.SERVER_TRANSFER_PROHIBITED).build()); - ResourceStatusProhibitsOperationException thrown = - assertThrows( - ResourceStatusProhibitsOperationException.class, - () -> doFailingTest("contact_transfer_request.xml")); - assertThat(thrown).hasMessageThat().contains("serverTransferProhibited"); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_pendingDelete() { - contact = - persistResource(contact.asBuilder().addStatusValue(StatusValue.PENDING_DELETE).build()); - ResourceStatusProhibitsOperationException thrown = - assertThrows( - ResourceStatusProhibitsOperationException.class, - () -> doFailingTest("contact_transfer_request.xml")); - assertThat(thrown).hasMessageThat().contains("pendingDelete"); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testIcannActivityReportField_getsLogged() throws Exception { - runFlow(); - assertIcannReportingActivityFieldLogged("srs-cont-transfer-request"); + void testThrowsException() { + assertAboutEppExceptions() + .that(assertThrows(ContactsProhibitedException.class, this::runFlow)) + .marshalsToXml(); } } diff --git a/core/src/test/java/google/registry/flows/contact/ContactUpdateFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactUpdateFlowTest.java index 81b92eced..5ad8842a5 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactUpdateFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactUpdateFlowTest.java @@ -14,449 +14,24 @@ package google.registry.flows.contact; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_PROHIBITED; -import static google.registry.model.common.FeatureFlag.FeatureStatus.ACTIVE; -import static google.registry.model.common.FeatureFlag.FeatureStatus.INACTIVE; -import static google.registry.testing.ContactSubject.assertAboutContacts; -import static google.registry.testing.DatabaseHelper.assertNoBillingEvents; -import static google.registry.testing.DatabaseHelper.newContact; -import static google.registry.testing.DatabaseHelper.persistActiveContact; -import static google.registry.testing.DatabaseHelper.persistDeletedContact; -import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; -import static google.registry.util.DateTimeUtils.START_OF_TIME; import static org.junit.jupiter.api.Assertions.assertThrows; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedMap; -import google.registry.flows.EppException; -import google.registry.flows.FlowUtils.NotLoggedInException; -import google.registry.flows.ResourceFlowTestCase; -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.contact.ContactFlowUtils.BadInternationalizedPostalInfoException; -import google.registry.flows.contact.ContactFlowUtils.DeclineContactDisclosureFieldDisallowedPolicyException; +import google.registry.flows.FlowTestCase; import google.registry.flows.exceptions.ContactsProhibitedException; -import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException; -import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException; -import google.registry.model.common.FeatureFlag; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactAddress; -import google.registry.model.contact.PostalInfo; -import google.registry.model.contact.PostalInfo.Type; -import google.registry.model.eppcommon.StatusValue; import org.junit.jupiter.api.Test; /** Unit tests for {@link ContactUpdateFlow}. */ -class ContactUpdateFlowTest extends ResourceFlowTestCase { +class ContactUpdateFlowTest extends FlowTestCase { ContactUpdateFlowTest() { setEppInput("contact_update.xml"); } - private void doSuccessfulTest() throws Exception { - clock.advanceOneMilli(); - assertMutatingFlow(true); - runFlowAssertResponse(loadFile("generic_success_response.xml")); - Contact contact = reloadResourceByForeignKey(); - // Check that the contact was updated. This value came from the xml. - assertAboutContacts() - .that(contact) - .hasAuthInfoPwd("2fooBAR") - .and() - .hasOnlyOneHistoryEntryWhich() - .hasNoXml(); - assertNoBillingEvents(); - assertLastHistoryContainsResource(contact); - } - @Test - void testNotLoggedIn() { - sessionMetadata.setRegistrarId(null); - EppException thrown = assertThrows(NotLoggedInException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testDryRun() throws Exception { - persistActiveContact(getUniqueIdFromCommand()); - dryRunFlowAssertResponse(loadFile("generic_success_response.xml")); - } - - @Test - void testSuccess() throws Exception { - persistActiveContact(getUniqueIdFromCommand()); - doSuccessfulTest(); - } - - @Test - void testFailure_minimumDatasetPhase2_cannotUpdateContacts() throws Exception { - persistResource( - new FeatureFlag.Builder() - .setFeatureName(MINIMUM_DATASET_CONTACTS_PROHIBITED) - .setStatusMap( - ImmutableSortedMap.of(START_OF_TIME, INACTIVE, clock.nowUtc().minusDays(5), ACTIVE)) - .build()); - EppException thrown = assertThrows(ContactsProhibitedException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess_updatingInternationalizedPostalInfoDeletesLocalized() throws Exception { - Contact contact = - persistResource( - newContact(getUniqueIdFromCommand()) - .asBuilder() - .setLocalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.LOCALIZED) - .setAddress( - new ContactAddress.Builder() - .setStreet(ImmutableList.of("111 8th Ave", "4th Floor")) - .setCity("New York") - .setState("NY") - .setZip("10011") - .setCountryCode("US") - .build()) - .build()) - .build()); - clock.advanceOneMilli(); - // The test xml updates the internationalized postal info and should therefore implicitly delete - // the localized one since they are treated as a pair for update purposes. - assertAboutContacts().that(contact) - .hasNonNullLocalizedPostalInfo().and() - .hasNullInternationalizedPostalInfo(); - - runFlowAssertResponse(loadFile("generic_success_response.xml")); - assertAboutContacts().that(reloadResourceByForeignKey()) - .hasNullLocalizedPostalInfo().and() - .hasInternationalizedPostalInfo(new PostalInfo.Builder() - .setType(Type.INTERNATIONALIZED) - .setAddress(new ContactAddress.Builder() - .setStreet(ImmutableList.of("124 Example Dr.", "Suite 200")) - .setCity("Dulles") - .setState("VA") - .setZip("20166-6503") - .setCountryCode("US") - .build()) - .build()); - } - - @Test - void testSuccess_updatingLocalizedPostalInfoDeletesInternationalized() throws Exception { - setEppInput("contact_update_localized.xml"); - Contact contact = - persistResource( - newContact(getUniqueIdFromCommand()) - .asBuilder() - .setInternationalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.INTERNATIONALIZED) - .setAddress( - new ContactAddress.Builder() - .setStreet(ImmutableList.of("111 8th Ave", "4th Floor")) - .setCity("New York") - .setState("NY") - .setZip("10011") - .setCountryCode("US") - .build()) - .build()) - .build()); - clock.advanceOneMilli(); - // The test xml updates the localized postal info and should therefore implicitly delete - // the internationalized one since they are treated as a pair for update purposes. - assertAboutContacts().that(contact) - .hasNonNullInternationalizedPostalInfo().and() - .hasNullLocalizedPostalInfo(); - - runFlowAssertResponse(loadFile("generic_success_response.xml")); - assertAboutContacts().that(reloadResourceByForeignKey()) - .hasNullInternationalizedPostalInfo().and() - .hasLocalizedPostalInfo(new PostalInfo.Builder() - .setType(Type.LOCALIZED) - .setAddress(new ContactAddress.Builder() - .setStreet(ImmutableList.of("124 Example Dr.", "Suite 200")) - .setCity("Dulles") - .setState("VA") - .setZip("20166-6503") - .setCountryCode("US") - .build()) - .build()); - } - - @Test - void testSuccess_partialPostalInfoUpdate() throws Exception { - setEppInput("contact_update_partial_postalinfo.xml"); - persistResource( - newContact(getUniqueIdFromCommand()) - .asBuilder() - .setLocalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.LOCALIZED) - .setName("A. Person") - .setOrg("Company Inc.") - .setAddress( - new ContactAddress.Builder() - .setStreet(ImmutableList.of("123 4th st", "5th Floor")) - .setCity("City") - .setState("AB") - .setZip("12345") - .setCountryCode("US") - .build()) - .build()) - .build()); - clock.advanceOneMilli(); - // The test xml updates the address of the postal info and should leave the name untouched. - runFlowAssertResponse(loadFile("generic_success_response.xml")); - assertAboutContacts().that(reloadResourceByForeignKey()).hasLocalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.LOCALIZED) - .setName("A. Person") - .setOrg("Company Inc.") - .setAddress(new ContactAddress.Builder() - .setStreet(ImmutableList.of("456 5th st")) - .setCity("Place") - .setState("CD") - .setZip("54321") - .setCountryCode("US") - .build()) - .build()); - } - - @Test - void testSuccess_updateOnePostalInfo_touchOtherPostalInfoPreservesIt() throws Exception { - setEppInput("contact_update_partial_postalinfo_preserve_int.xml"); - persistResource( - newContact(getUniqueIdFromCommand()) - .asBuilder() - .setLocalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.LOCALIZED) - .setName("A. Person") - .setOrg("Company Inc.") - .setAddress( - new ContactAddress.Builder() - .setStreet(ImmutableList.of("123 4th st", "5th Floor")) - .setCity("City") - .setState("AB") - .setZip("12345") - .setCountryCode("US") - .build()) - .build()) - .setInternationalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.INTERNATIONALIZED) - .setName("B. Person") - .setOrg("Company Co.") - .setAddress( - new ContactAddress.Builder() - .setStreet(ImmutableList.of("100 200th Dr.", "6th Floor")) - .setCity("Town") - .setState("CD") - .setZip("67890") - .setCountryCode("US") - .build()) - .build()) - .build()); - clock.advanceOneMilli(); - // The test xml updates the address of the localized postal info. It also sets the name of the - // internationalized postal info to the same value it previously had, which causes it to be - // preserved. If the xml had not mentioned the internationalized one at all it would have been - // deleted. - runFlowAssertResponse(loadFile("generic_success_response.xml")); - assertAboutContacts().that(reloadResourceByForeignKey()) - .hasLocalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.LOCALIZED) - .setName("A. Person") - .setOrg("Company Inc.") - .setAddress(new ContactAddress.Builder() - .setStreet(ImmutableList.of("456 5th st")) - .setCity("Place") - .setState("CD") - .setZip("54321") - .setCountryCode("US") - .build()) - .build()) - .and() - .hasInternationalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.INTERNATIONALIZED) - .setName("B. Person") - .setOrg("Company Co.") - .setAddress(new ContactAddress.Builder() - .setStreet(ImmutableList.of("100 200th Dr.", "6th Floor")) - .setCity("Town") - .setState("CD") - .setZip("67890") - .setCountryCode("US") - .build()) - .build()); - } - - @Test - void testFailure_neverExisted() throws Exception { - ResourceDoesNotExistException thrown = - assertThrows(ResourceDoesNotExistException.class, this::runFlow); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_existedButWasDeleted() throws Exception { - persistDeletedContact(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1)); - ResourceDoesNotExistException thrown = - assertThrows(ResourceDoesNotExistException.class, this::runFlow); - assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_statusValueNotClientSettable() throws Exception { - setEppInput("contact_update_prohibited_status.xml"); - persistActiveContact(getUniqueIdFromCommand()); - EppException thrown = assertThrows(StatusNotClientSettableException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess_superuserStatusValueNotClientSettable() throws Exception { - setEppInput("contact_update_prohibited_status.xml"); - persistActiveContact(getUniqueIdFromCommand()); - clock.advanceOneMilli(); - runFlowAssertResponse( - CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml")); - } - - @Test - void testFailure_unauthorizedClient() throws Exception { - sessionMetadata.setRegistrarId("NewRegistrar"); - persistActiveContact(getUniqueIdFromCommand()); - EppException thrown = assertThrows(ResourceNotOwnedException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess_superuserUnauthorizedClient() throws Exception { - sessionMetadata.setRegistrarId("NewRegistrar"); - persistActiveContact(getUniqueIdFromCommand()); - clock.advanceOneMilli(); - runFlowAssertResponse( - CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml")); - } - - @Test - void testSuccess_clientUpdateProhibited_removed() throws Exception { - setEppInput("contact_update_remove_client_update_prohibited.xml"); - persistResource( - newContact(getUniqueIdFromCommand()) - .asBuilder() - .setStatusValues(ImmutableSet.of(StatusValue.CLIENT_UPDATE_PROHIBITED)) - .build()); - doSuccessfulTest(); - assertAboutContacts() - .that(reloadResourceByForeignKey()) - .doesNotHaveStatusValue(StatusValue.CLIENT_UPDATE_PROHIBITED); - } - - @Test - void testSuccess_superuserClientUpdateProhibited_notRemoved() throws Exception { - setEppInput("contact_update_prohibited_status.xml"); - persistResource( - newContact(getUniqueIdFromCommand()) - .asBuilder() - .setStatusValues(ImmutableSet.of(StatusValue.CLIENT_UPDATE_PROHIBITED)) - .build()); - clock.advanceOneMilli(); - runFlowAssertResponse( - CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml")); - assertAboutContacts() - .that(reloadResourceByForeignKey()) - .hasStatusValue(StatusValue.CLIENT_UPDATE_PROHIBITED) - .and() - .hasStatusValue(StatusValue.SERVER_DELETE_PROHIBITED); - } - - @Test - void testFailure_clientUpdateProhibited_notRemoved() throws Exception { - persistResource( - newContact(getUniqueIdFromCommand()) - .asBuilder() - .setStatusValues(ImmutableSet.of(StatusValue.CLIENT_UPDATE_PROHIBITED)) - .build()); - EppException thrown = - assertThrows(ResourceHasClientUpdateProhibitedException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_serverUpdateProhibited() throws Exception { - persistResource( - newContact(getUniqueIdFromCommand()) - .asBuilder() - .setStatusValues(ImmutableSet.of(StatusValue.SERVER_UPDATE_PROHIBITED)) - .build()); - ResourceStatusProhibitsOperationException thrown = - assertThrows(ResourceStatusProhibitsOperationException.class, this::runFlow); - assertThat(thrown).hasMessageThat().contains("serverUpdateProhibited"); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_pendingDeleteProhibited() throws Exception { - persistResource( - newContact(getUniqueIdFromCommand()) - .asBuilder() - .setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE)) - .build()); - ResourceStatusProhibitsOperationException thrown = - assertThrows(ResourceStatusProhibitsOperationException.class, this::runFlow); - assertThat(thrown).hasMessageThat().contains("pendingDelete"); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testSuccess_nonAsciiInLocAddress() throws Exception { - setEppInput("contact_update_hebrew_loc.xml"); - persistActiveContact(getUniqueIdFromCommand()); - doSuccessfulTest(); - } - - @Test - void testFailure_nonAsciiInIntAddress() throws Exception { - setEppInput("contact_update_hebrew_int.xml"); - persistActiveContact(getUniqueIdFromCommand()); - EppException thrown = - assertThrows(BadInternationalizedPostalInfoException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_declineDisclosure() throws Exception { - setEppInput("contact_update_decline_disclosure.xml"); - persistActiveContact(getUniqueIdFromCommand()); - EppException thrown = - assertThrows(DeclineContactDisclosureFieldDisallowedPolicyException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_addRemoveSameValue() throws Exception { - setEppInput("contact_update_add_remove_same.xml"); - persistActiveContact(getUniqueIdFromCommand()); - EppException thrown = assertThrows(AddRemoveSameValueException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testIcannActivityReportField_getsLogged() throws Exception { - persistActiveContact(getUniqueIdFromCommand()); - clock.advanceOneMilli(); - runFlow(); - assertIcannReportingActivityFieldLogged("srs-cont-update"); + void testThrowsException() { + assertAboutEppExceptions() + .that(assertThrows(ContactsProhibitedException.class, this::runFlow)) + .marshalsToXml(); } } diff --git a/core/src/test/resources/google/registry/flows/contact_create_jd1234.xml b/core/src/test/resources/google/registry/flows/contact_create_jd1234.xml deleted file mode 100644 index 50ef7ed53..000000000 --- a/core/src/test/resources/google/registry/flows/contact_create_jd1234.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - jd1234 - - John Doe - Example Inc. - - 123 Example Dr. - Suite 100 - Dulles - VA - 20166-6503 - US - - - +1.7035555555 - +1.7035555556 - jdoe@example.com - - 2fooBAR - - - - - - - - ABC-12345 - - diff --git a/core/src/test/resources/google/registry/flows/contact_create_response_jd1234.xml b/core/src/test/resources/google/registry/flows/contact_create_response_jd1234.xml deleted file mode 100644 index 6bbe3cdbf..000000000 --- a/core/src/test/resources/google/registry/flows/contact_create_response_jd1234.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - Command completed successfully - - - - jd1234 - 2000-06-01T00:01:00.0Z - - - - ABC-12345 - server-trid - - - diff --git a/core/src/test/resources/google/registry/flows/contact_create_response_sh8013.xml b/core/src/test/resources/google/registry/flows/contact_create_response_sh8013.xml deleted file mode 100644 index 65a59199d..000000000 --- a/core/src/test/resources/google/registry/flows/contact_create_response_sh8013.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - Command completed successfully - - - - sh8013 - %CRDATE% - - - - ABC-12345 - server-trid - - - diff --git a/core/src/test/resources/google/registry/flows/contact_create_sh8013.xml b/core/src/test/resources/google/registry/flows/contact_create_sh8013.xml deleted file mode 100644 index 231a1f5b6..000000000 --- a/core/src/test/resources/google/registry/flows/contact_create_sh8013.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - sh8013 - - John Doe - Example Inc. - - 123 Example Dr. - Suite 100 - Dulles - VA - 20166-6503 - US - - - +1.7035555555 - +1.7035555556 - jdoe@example.com - - 2fooBAR - - - - - - - - ABC-12345 - - diff --git a/core/src/test/resources/google/registry/flows/contact_delete_response_sh8013.xml b/core/src/test/resources/google/registry/flows/contact_delete_response_sh8013.xml deleted file mode 100644 index ab613d34f..000000000 --- a/core/src/test/resources/google/registry/flows/contact_delete_response_sh8013.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - Command completed successfully - - - ABC-12345 - server-trid - - - diff --git a/core/src/test/resources/google/registry/flows/contact_delete_sh8013.xml b/core/src/test/resources/google/registry/flows/contact_delete_sh8013.xml deleted file mode 100644 index 71e444008..000000000 --- a/core/src/test/resources/google/registry/flows/contact_delete_sh8013.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - sh8013 - - - ABC-12345 - - diff --git a/core/src/test/resources/google/registry/flows/contact_transfer_request.xml b/core/src/test/resources/google/registry/flows/contact_transfer_request.xml deleted file mode 100644 index dddbf6786..000000000 --- a/core/src/test/resources/google/registry/flows/contact_transfer_request.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - sh8013 - - 2fooBAR - - - - ABC-12345 - - diff --git a/core/src/test/resources/google/registry/flows/contact_transfer_request_response_alternate.xml b/core/src/test/resources/google/registry/flows/contact_transfer_request_response_alternate.xml deleted file mode 100644 index eee999ae0..000000000 --- a/core/src/test/resources/google/registry/flows/contact_transfer_request_response_alternate.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - Command completed successfully; action pending - - - - sh8013 - pending - TheRegistrar - 2000-06-08T22:00:00.0Z - NewRegistrar - 2000-06-13T22:00:00.0Z - - - - ABC-12345 - server-trid - - - diff --git a/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_request.xml b/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_request.xml index 35ae1cf8c..e328be4af 100644 --- a/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_request.xml +++ b/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_request.xml @@ -20,7 +20,7 @@ ABC-12345 - BYiJH5vHRRW6EuYXo/Kdsg==-23 + server-trid