Restrict domain transfer periods to 1 year

It turns out that this ICANN policy appears to prohibit transfers with
registration extensions other than 1 year (section A.8):
https://www.icann.org/resources/pages/policy-2012-03-07-en

This is backed up by the practical fact that we've never seen a registrar
request a transfer for any period other than one year.

And removing the support for multi-year transfers vastly simplifies
transfer logic and eliminates a bunch of annoying corner cases.  Users
still can achieve the same thing by doing a 1-year transfer plus a
manual renewal afterwards for the remainder of the desired extension.

This change leaves in place lots of infrastructure to support multi-year
transfers that is now obsolete (e.g. TransferData.extendedRegistrationYears).
This should all be cleaned up, but it's a lower priority than fixing the
gap itself and insulating ourselves against needing to handle any real
multi-year transfer case.  Once this CL goes in, we can start ignoring
extendedRegistrationYears entirely because it'll always be 1 year, which
makes the cleanup process easier.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=150212864
This commit is contained in:
nickfelt 2017-03-15 10:56:18 -07:00 committed by Ben McIlwain
parent 852f1afb6c
commit f28104ad03
13 changed files with 97 additions and 42 deletions

View file

@ -44,6 +44,7 @@ import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow;
import google.registry.flows.exceptions.AlreadyPendingTransferException;
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
import google.registry.flows.exceptions.TransferPeriodMustBeOneYearException;
import google.registry.model.domain.DomainCommand.Transfer;
import google.registry.model.domain.DomainResource;
import google.registry.model.domain.Period;
@ -89,6 +90,7 @@ import org.joda.time.DateTime;
* @error {@link google.registry.flows.exceptions.MissingTransferRequestAuthInfoException}
* @error {@link google.registry.flows.exceptions.ObjectAlreadySponsoredException}
* @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException}
* @error {@link google.registry.flows.exceptions.TransferPeriodMustBeOneYearException}
* @error {@link DomainFlowUtils.BadPeriodUnitException}
* @error {@link DomainFlowUtils.CurrencyUnitMismatchException}
* @error {@link DomainFlowUtils.CurrencyValueScaleException}
@ -216,12 +218,39 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
throw new ObjectAlreadySponsoredException();
}
checkAllowedAccessToTld(gainingClientId, existingDomain.getTld());
verifyUnitIsYears(period);
verifyTransferPeriodIsOneYear(period);
if (!isSuperuser) {
verifyPremiumNameIsNotBlocked(targetId, now, gainingClientId);
}
}
/**
* Verify that the transfer period is one year.
*
* <p>Restricting transfers to one year is seemingly required by ICANN's <a
* href="https://www.icann.org/resources/pages/policy-2012-03-07-en">Policy on Transfer of
* Registrations between Registrars</a>, section A.8. It states that "the completion by Registry
* Operator of a holder-authorized transfer under this Part A shall result in a one-year extension
* of the existing registration, provided that in no event shall the total unexpired term of a
* registration exceed ten (10) years."
*
* <p>Even if not required, this policy is desirable because it dramatically simplifies the logic
* in transfer flows. Registrars appear to never request 2+ year transfers in practice, and they
* can always decompose an multi-year transfer into a 1-year transfer followed by a manual renewal
* afterwards. The <a href="https://tools.ietf.org/html/rfc5731#section-3.2.4">EPP Domain RFC,
* section 3.2.4</a> says about EPP transfer periods that "the number of units available MAY be
* subject to limits imposed by the server" so we're just limiting the units to one.
*
* <p>Note that clients can omit the period element from the transfer EPP entirely, but then it
* will simply default to one year.
*/
private static void verifyTransferPeriodIsOneYear(Period period) throws EppException {
verifyUnitIsYears(period);
if (period.getValue() != 1) {
throw new TransferPeriodMustBeOneYearException();
}
}
private HistoryEntry buildHistory(Period period, DomainResource existingResource, DateTime now) {
return historyBuilder
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST)