Deny non-active registrars access to non-free EPP commands

Registrars that are PENDING or SUSPENDED should not have access to
EPP commands that cost money, as in either case it's not likely we'd
actually be able to get payment from said registrar. For this reason
we already prevented access to the domain create flow for non-active
registrars. This commit extends that to other commands that cost
money, including renewals, restores, and transfer requests.

Note that implicit autorenews will still occur for suspended
registrars, as in our point-in-time data model there's no good way
to prevent them. So when a registrar is suspended for non-payment,
the game plan is to get all of their domains transferred out to a
registrar that will pay as soon as possible.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=223173677
This commit is contained in:
mcilwain 2018-11-28 08:41:05 -08:00 committed by jianglai
parent dbdc69916a
commit 11da64bee2
13 changed files with 172 additions and 15 deletions

View file

@ -231,6 +231,8 @@ An EPP flow that updates a contact.
An EPP flow that allocates a new domain resource from a domain application. An EPP flow that allocates a new domain resource from a domain application.
Note that this flow is only run by superusers.
### Errors ### Errors
@ -295,7 +297,7 @@ An EPP flow that creates a new application for a domain resource.
* Specified extension is not implemented. * Specified extension is not implemented.
* 2201 * 2201
* Registrar is not authorized to access this TLD. * Registrar is not authorized to access this TLD.
* Registrar must be active in order to create domains or applications. * Registrar must be active in order to perform this operation.
* 2302 * 2302
* Resource with this id already exists. * Resource with this id already exists.
* This name has already been claimed by a sunrise applicant. * This name has already been claimed by a sunrise applicant.
@ -556,7 +558,7 @@ An EPP flow that creates a new domain resource.
* 2201 * 2201
* Only a tool can pass a metadata extension. * Only a tool can pass a metadata extension.
* Registrar is not authorized to access this TLD. * Registrar is not authorized to access this TLD.
* Registrar must be active in order to create domains or applications. * Registrar must be active in order to perform this operation.
* 2302 * 2302
* Resource with this id already exists. * Resource with this id already exists.
* 2303 * 2303
@ -689,6 +691,7 @@ comes in at the exact millisecond that the domain would have expired.
* 2201 * 2201
* The specified resource belongs to another client. * The specified resource belongs to another client.
* Registrar is not authorized to access this TLD. * Registrar is not authorized to access this TLD.
* Registrar must be active in order to perform this operation.
* 2303 * 2303
* Resource with this id does not exist. * Resource with this id does not exist.
* 2304 * 2304
@ -745,6 +748,7 @@ regardless of what the original expiration time was.
* 2201 * 2201
* The specified resource belongs to another client. * The specified resource belongs to another client.
* Registrar is not authorized to access this TLD. * Registrar is not authorized to access this TLD.
* Registrar must be active in order to perform this operation.
* 2303 * 2303
* Resource with this id does not exist. * Resource with this id does not exist.
* 2304 * 2304
@ -907,6 +911,7 @@ new ones with the correct approval time).
* 2201 * 2201
* Authorization info is required to request a transfer. * Authorization info is required to request a transfer.
* Registrar is not authorized to access this TLD. * Registrar is not authorized to access this TLD.
* Registrar must be active in order to perform this operation.
* 2202 * 2202
* Authorization information for accessing resource is invalid. * Authorization information for accessing resource is invalid.
* 2300 * 2300

View file

@ -98,6 +98,8 @@ import org.joda.time.Duration;
/** /**
* An EPP flow that allocates a new domain resource from a domain application. * An EPP flow that allocates a new domain resource from a domain application.
* *
* <p>Note that this flow is only run by superusers.
*
* @error {@link google.registry.flows.exceptions.ResourceAlreadyExistsException} * @error {@link google.registry.flows.exceptions.ResourceAlreadyExistsException}
* @error {@link DomainAllocateFlow.HasFinalStatusException} * @error {@link DomainAllocateFlow.HasFinalStatusException}
* @error {@link DomainAllocateFlow.MissingApplicationException} * @error {@link DomainAllocateFlow.MissingApplicationException}

View file

@ -147,7 +147,7 @@ import org.joda.time.DateTime;
* @error {@link DomainFlowUtils.NotAuthorizedForTldException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link DomainFlowUtils.PremiumNameBlockedException} * @error {@link DomainFlowUtils.PremiumNameBlockedException}
* @error {@link DomainFlowUtils.RegistrantNotAllowedException} * @error {@link DomainFlowUtils.RegistrantNotAllowedException}
* @error {@link DomainFlowUtils.RegistrarMustBeActiveToCreateDomainsException} * @error {@link DomainFlowUtils.RegistrarMustBeActiveForThisOperationException}
* @error {@link DomainFlowTmchUtils.SignedMarksMustBeEncodedException} * @error {@link DomainFlowTmchUtils.SignedMarksMustBeEncodedException}
* @error {@link DomainFlowTmchUtils.SignedMarkCertificateExpiredException} * @error {@link DomainFlowTmchUtils.SignedMarkCertificateExpiredException}
* @error {@link DomainFlowTmchUtils.SignedMarkCertificateInvalidException} * @error {@link DomainFlowTmchUtils.SignedMarkCertificateInvalidException}

View file

@ -179,7 +179,7 @@ import org.joda.time.Duration;
* @error {@link DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException} * @error {@link DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverWhitelistException}
* @error {@link DomainFlowUtils.PremiumNameBlockedException} * @error {@link DomainFlowUtils.PremiumNameBlockedException}
* @error {@link DomainFlowUtils.RegistrantNotAllowedException} * @error {@link DomainFlowUtils.RegistrantNotAllowedException}
* @error {@link DomainFlowUtils.RegistrarMustBeActiveToCreateDomainsException} * @error {@link DomainFlowUtils.RegistrarMustBeActiveForThisOperationException}
* @error {@link DomainFlowUtils.TldDoesNotExistException} * @error {@link DomainFlowUtils.TldDoesNotExistException}
* @error {@link DomainFlowUtils.TooManyDsRecordsException} * @error {@link DomainFlowUtils.TooManyDsRecordsException}
* @error {@link DomainFlowUtils.TooManyNameserversException} * @error {@link DomainFlowUtils.TooManyNameserversException}

View file

@ -892,13 +892,14 @@ public class DomainFlowUtils {
/** /**
* Check that the registrar with the given client ID is active. * Check that the registrar with the given client ID is active.
* *
* <p>Non-active registrars are not allowed to create domain applications or domain resources. * <p>Non-active registrars are not allowed to run operations that cost money, like domain creates
* or renews.
*/ */
static void verifyRegistrarIsActive(String clientId) static void verifyRegistrarIsActive(String clientId)
throws RegistrarMustBeActiveToCreateDomainsException { throws RegistrarMustBeActiveForThisOperationException {
Registrar registrar = Registrar.loadByClientIdCached(clientId).get(); Registrar registrar = Registrar.loadByClientIdCached(clientId).get();
if (registrar.getState() != State.ACTIVE) { if (registrar.getState() != State.ACTIVE) {
throw new RegistrarMustBeActiveToCreateDomainsException(); throw new RegistrarMustBeActiveForThisOperationException();
} }
} }
@ -1606,10 +1607,10 @@ public class DomainFlowUtils {
} }
} }
/** Registrar must be active in order to create domains or applications. */ /** Registrar must be active in order to perform this operation. */
static class RegistrarMustBeActiveToCreateDomainsException extends AuthorizationErrorException { static class RegistrarMustBeActiveForThisOperationException extends AuthorizationErrorException {
public RegistrarMustBeActiveToCreateDomainsException() { public RegistrarMustBeActiveForThisOperationException() {
super("Registrar must be active in order to create domains or applications"); super("Registrar must be active in order to perform this operation");
} }
} }
} }

View file

@ -26,6 +26,7 @@ import static google.registry.flows.domain.DomainFlowUtils.newAutorenewPollMessa
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime; import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.flows.domain.DomainFlowUtils.validateRegistrationPeriod; import static google.registry.flows.domain.DomainFlowUtils.validateRegistrationPeriod;
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.util.DateTimeUtils.leapSafeAddYears; import static google.registry.util.DateTimeUtils.leapSafeAddYears;
@ -101,6 +102,7 @@ import org.joda.time.Duration;
* @error {@link DomainFlowUtils.FeesMismatchException} * @error {@link DomainFlowUtils.FeesMismatchException}
* @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException} * @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link DomainFlowUtils.RegistrarMustBeActiveForThisOperationException}
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
* @error {@link DomainRenewFlow.IncorrectCurrentExpirationDateException} * @error {@link DomainRenewFlow.IncorrectCurrentExpirationDateException}
*/ */
@ -133,6 +135,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
flowCustomLogic.beforeValidation(); flowCustomLogic.beforeValidation();
extensionManager.validate(); extensionManager.validate();
validateClientIsLoggedIn(clientId); validateClientIsLoggedIn(clientId);
verifyRegistrarIsActive(clientId);
DateTime now = ofy().getTransactionTime(); DateTime now = ofy().getTransactionTime();
Renew command = (Renew) resourceCommand; Renew command = (Renew) resourceCommand;
// Loads the target resource if it exists // Loads the target resource if it exists

View file

@ -25,6 +25,7 @@ import static google.registry.flows.domain.DomainFlowUtils.newAutorenewPollMessa
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.flows.domain.DomainFlowUtils.verifyNotReserved; import static google.registry.flows.domain.DomainFlowUtils.verifyNotReserved;
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked; import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.END_OF_TIME;
@ -101,6 +102,7 @@ import org.joda.time.DateTime;
* @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException} * @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link DomainFlowUtils.PremiumNameBlockedException} * @error {@link DomainFlowUtils.PremiumNameBlockedException}
* @error {@link DomainFlowUtils.RegistrarMustBeActiveForThisOperationException}
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
* @error {@link DomainRestoreRequestFlow.DomainNotEligibleForRestoreException} * @error {@link DomainRestoreRequestFlow.DomainNotEligibleForRestoreException}
* @error {@link DomainRestoreRequestFlow.RestoreCommandIncludesChangesException} * @error {@link DomainRestoreRequestFlow.RestoreCommandIncludesChangesException}
@ -129,6 +131,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
RgpUpdateExtension.class); RgpUpdateExtension.class);
extensionManager.validate(); extensionManager.validate();
validateClientIsLoggedIn(clientId); validateClientIsLoggedIn(clientId);
verifyRegistrarIsActive(clientId);
Update command = (Update) resourceCommand; Update command = (Update) resourceCommand;
DateTime now = ofy().getTransactionTime(); DateTime now = ofy().getTransactionTime();
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now); DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);

View file

@ -23,6 +23,7 @@ import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToT
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime; import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge; import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked; import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
import static google.registry.flows.domain.DomainFlowUtils.verifyRegistrarIsActive;
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
import static google.registry.flows.domain.DomainTransferUtils.createLosingTransferPollMessage; import static google.registry.flows.domain.DomainTransferUtils.createLosingTransferPollMessage;
import static google.registry.flows.domain.DomainTransferUtils.createPendingTransferData; import static google.registry.flows.domain.DomainTransferUtils.createPendingTransferData;
@ -107,6 +108,7 @@ import org.joda.time.DateTime;
* @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException} * @error {@link DomainFlowUtils.FeesRequiredForPremiumNameException}
* @error {@link DomainFlowUtils.NotAuthorizedForTldException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException}
* @error {@link DomainFlowUtils.PremiumNameBlockedException} * @error {@link DomainFlowUtils.PremiumNameBlockedException}
* @error {@link DomainFlowUtils.RegistrarMustBeActiveForThisOperationException}
* @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException}
*/ */
@ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_REQUEST) @ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_REQUEST)
@ -139,6 +141,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
MetadataExtension.class); MetadataExtension.class);
extensionManager.validate(); extensionManager.validate();
validateClientIsLoggedIn(gainingClientId); validateClientIsLoggedIn(gainingClientId);
verifyRegistrarIsActive(gainingClientId);
DateTime now = ofy().getTransactionTime(); DateTime now = ofy().getTransactionTime();
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now); DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
Optional<DomainTransferRequestSuperuserExtension> superuserExtension = Optional<DomainTransferRequestSuperuserExtension> superuserExtension =

View file

@ -100,7 +100,7 @@ import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTl
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException; import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException;
import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException; import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException;
import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveToCreateDomainsException; import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveForThisOperationException;
import google.registry.flows.domain.DomainFlowUtils.TldDoesNotExistException; import google.registry.flows.domain.DomainFlowUtils.TldDoesNotExistException;
import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException; import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException; import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
@ -771,7 +771,24 @@ public class DomainApplicationCreateFlowTest
.build()); .build());
clock.advanceOneMilli(); clock.advanceOneMilli();
EppException thrown = EppException thrown =
assertThrows(RegistrarMustBeActiveToCreateDomainsException.class, this::runFlow); assertThrows(RegistrarMustBeActiveForThisOperationException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_pendingRegistrarCantCreateDomainApplication() {
setEppInput("domain_create_sunrise_encoded_signed_mark.xml");
persistContactsAndHosts();
clock.advanceOneMilli();
persistResource(
Registrar.loadByClientId("TheRegistrar")
.get()
.asBuilder()
.setState(State.PENDING)
.build());
clock.advanceOneMilli();
EppException thrown =
assertThrows(RegistrarMustBeActiveForThisOperationException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }

View file

@ -121,7 +121,7 @@ import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTl
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException; import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException;
import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException; import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException;
import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveToCreateDomainsException; import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveForThisOperationException;
import google.registry.flows.domain.DomainFlowUtils.TldDoesNotExistException; import google.registry.flows.domain.DomainFlowUtils.TldDoesNotExistException;
import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException; import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException;
import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException; import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException;
@ -1618,7 +1618,21 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
.setState(State.SUSPENDED) .setState(State.SUSPENDED)
.build()); .build());
EppException thrown = EppException thrown =
assertThrows(RegistrarMustBeActiveToCreateDomainsException.class, this::runFlow); assertThrows(RegistrarMustBeActiveForThisOperationException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_pendingRegistrarCantCreateDomain() {
persistContactsAndHosts();
persistResource(
Registrar.loadByClientId("TheRegistrar")
.get()
.asBuilder()
.setState(State.PENDING)
.build());
EppException thrown =
assertThrows(RegistrarMustBeActiveForThisOperationException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }

View file

@ -49,6 +49,7 @@ import google.registry.flows.domain.DomainFlowUtils.ExceedsMaxRegistrationYearsE
import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException; import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException;
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForPremiumNameException; import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForPremiumNameException;
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveForThisOperationException;
import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException; import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException;
import google.registry.flows.domain.DomainRenewFlow.IncorrectCurrentExpirationDateException; import google.registry.flows.domain.DomainRenewFlow.IncorrectCurrentExpirationDateException;
import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException; import google.registry.flows.exceptions.ResourceStatusProhibitsOperationException;
@ -60,6 +61,8 @@ import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.StatusValue;
import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.Registrar.State;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.model.reporting.DomainTransactionRecord; import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField; import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
@ -374,6 +377,32 @@ public class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, D
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test
public void testFailure_suspendedRegistrarCantRenewDomain() {
persistResource(
Registrar.loadByClientId("TheRegistrar")
.get()
.asBuilder()
.setState(State.SUSPENDED)
.build());
EppException thrown =
assertThrows(RegistrarMustBeActiveForThisOperationException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_pendingRegistrarCantRenewDomain() {
persistResource(
Registrar.loadByClientId("TheRegistrar")
.get()
.asBuilder()
.setState(State.PENDING)
.build());
EppException thrown =
assertThrows(RegistrarMustBeActiveForThisOperationException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test @Test
public void testSuccess_nonDefaultRenewGracePeriod() throws Exception { public void testSuccess_nonDefaultRenewGracePeriod() throws Exception {
persistResource( persistResource(

View file

@ -51,6 +51,7 @@ import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException;
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForPremiumNameException; import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForPremiumNameException;
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException; import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException;
import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveForThisOperationException;
import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException; import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException;
import google.registry.flows.domain.DomainRestoreRequestFlow.DomainNotEligibleForRestoreException; import google.registry.flows.domain.DomainRestoreRequestFlow.DomainNotEligibleForRestoreException;
import google.registry.flows.domain.DomainRestoreRequestFlow.RestoreCommandIncludesChangesException; import google.registry.flows.domain.DomainRestoreRequestFlow.RestoreCommandIncludesChangesException;
@ -62,6 +63,8 @@ import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.StatusValue;
import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.Registrar.State;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.model.reporting.DomainTransactionRecord; import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField; import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
@ -349,6 +352,33 @@ public class DomainRestoreRequestFlowTest
ResourceDoesNotExistException thrown = ResourceDoesNotExistException thrown =
assertThrows(ResourceDoesNotExistException.class, this::runFlow); assertThrows(ResourceDoesNotExistException.class, this::runFlow);
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_suspendedRegistrarCantRestoreDomain() {
persistResource(
Registrar.loadByClientId("TheRegistrar")
.get()
.asBuilder()
.setState(State.SUSPENDED)
.build());
EppException thrown =
assertThrows(RegistrarMustBeActiveForThisOperationException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_pendingRegistrarCantRestoreDomain() {
persistResource(
Registrar.loadByClientId("TheRegistrar")
.get()
.asBuilder()
.setState(State.PENDING)
.build());
EppException thrown =
assertThrows(RegistrarMustBeActiveForThisOperationException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @Test

View file

@ -67,6 +67,7 @@ import google.registry.flows.domain.DomainFlowUtils.FeesMismatchException;
import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForPremiumNameException; import google.registry.flows.domain.DomainFlowUtils.FeesRequiredForPremiumNameException;
import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException;
import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException; import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException;
import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveForThisOperationException;
import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException; import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException;
import google.registry.flows.exceptions.AlreadyPendingTransferException; import google.registry.flows.exceptions.AlreadyPendingTransferException;
import google.registry.flows.exceptions.InvalidTransferPeriodValueException; import google.registry.flows.exceptions.InvalidTransferPeriodValueException;
@ -89,6 +90,8 @@ import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid; import google.registry.model.eppcommon.Trid;
import google.registry.model.poll.PendingActionNotificationResponse; import google.registry.model.poll.PendingActionNotificationResponse;
import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage;
import google.registry.model.registrar.Registrar;
import google.registry.model.registrar.Registrar.State;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.model.reporting.DomainTransactionRecord; import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
@ -775,6 +778,40 @@ public class DomainTransferRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test
public void testFailure_suspendedRegistrarCantTransferDomain() {
setupDomain("example", "tld");
clock.advanceOneMilli();
persistResource(
Registrar.loadByClientId("NewRegistrar")
.get()
.asBuilder()
.setState(State.SUSPENDED)
.build());
EppException thrown =
assertThrows(
RegistrarMustBeActiveForThisOperationException.class,
() -> doFailingTest("domain_transfer_request.xml"));
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_pendingRegistrarCantTransferDomain() {
setupDomain("example", "tld");
clock.advanceOneMilli();
persistResource(
Registrar.loadByClientId("NewRegistrar")
.get()
.asBuilder()
.setState(State.PENDING)
.build());
EppException thrown =
assertThrows(
RegistrarMustBeActiveForThisOperationException.class,
() -> doFailingTest("domain_transfer_request.xml"));
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test @Test
public void testSuccess_nonDefaultAutomaticTransferLength() throws Exception { public void testSuccess_nonDefaultAutomaticTransferLength() throws Exception {
setupDomain("example", "tld"); setupDomain("example", "tld");
@ -805,6 +842,19 @@ public class DomainTransferRequestFlowTest
"domain_transfer_request_missing_period.xml", "domain_transfer_request_response.xml"); "domain_transfer_request_missing_period.xml", "domain_transfer_request_response.xml");
} }
@Test
public void testSuccess_canTransferAwayFromSuspendedRegistrar() throws Exception {
setupDomain("example", "tld");
clock.advanceOneMilli();
persistResource(
Registrar.loadByClientId("TheRegistrar")
.get()
.asBuilder()
.setState(State.SUSPENDED)
.build());
doSuccessfulTest("domain_transfer_request.xml", "domain_transfer_request_response.xml");
}
@Test @Test
public void testFailure_multiYearPeriod() { public void testFailure_multiYearPeriod() {
setupDomain("example", "tld"); setupDomain("example", "tld");