diff --git a/docs/flows.md b/docs/flows.md index 263075e55..71a78c2fa 100644 --- a/docs/flows.md +++ b/docs/flows.md @@ -582,6 +582,7 @@ An EPP flow that creates a new domain resource. * 2305 * The allocation token was already redeemed. * 2306 + * Anchor tenant domain create is for the wrong number of years. * The provided mark is not yet valid. * The provided mark has expired. * Domain names can only contain a-z, 0-9, '.' and '-'. diff --git a/java/google/registry/flows/domain/DomainCreateFlow.java b/java/google/registry/flows/domain/DomainCreateFlow.java index a3bbcde66..dab9a7a03 100644 --- a/java/google/registry/flows/domain/DomainCreateFlow.java +++ b/java/google/registry/flows/domain/DomainCreateFlow.java @@ -56,6 +56,7 @@ import com.googlecode.objectify.Key; import google.registry.dns.DnsQueue; import google.registry.flows.EppException; import google.registry.flows.EppException.CommandUseErrorException; +import google.registry.flows.EppException.ParameterValuePolicyErrorException; import google.registry.flows.EppException.StatusProhibitsOperationException; import google.registry.flows.ExtensionManager; import google.registry.flows.FlowModule.ClientId; @@ -120,6 +121,7 @@ import org.joda.time.Duration; * @error {@link google.registry.flows.exceptions.ResourceAlreadyExistsException} * @error {@link google.registry.flows.EppException.UnimplementedExtensionException} * @error {@link google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException} + * @error {@link DomainCreateFlow.AnchorTenantCreatePeriodException} * @error {@link DomainCreateFlow.DomainHasOpenApplicationsException} * @error {@link DomainCreateFlow.MustHaveSignedMarksInCurrentPhaseException} * @error {@link DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException} @@ -184,6 +186,9 @@ public class DomainCreateFlow implements TransactionalFlow { private static final ImmutableSet SUNRISE_STATES = Sets.immutableEnumSet(TldState.SUNRISE, TldState.SUNRUSH); + /** Anchor tenant creates should always be for 2 years, since they get 2 years free. */ + private static final int ANCHOR_TENANT_CREATE_VALID_YEARS = 2; + @Inject ExtensionManager extensionManager; @Inject EppInput eppInput; @Inject AuthInfo authInfo; @@ -229,6 +234,7 @@ public class DomainCreateFlow implements TransactionalFlow { } TldState tldState = registry.getTldState(now); boolean isAnchorTenant = isAnchorTenant(domainName); + verifyAnchorTenantValidPeriod(isAnchorTenant, years); Optional launchCreate = eppInput.getSingleExtension(LaunchCreateExtension.class); boolean hasSignedMarks = @@ -374,6 +380,17 @@ public class DomainCreateFlow implements TransactionalFlow { || (metadataExtension.isPresent() && metadataExtension.get().getIsAnchorTenant()); } + /** + * Verifies anchor tenant creates are only done for {@value ANCHOR_TENANT_CREATE_VALID_YEARS} year + * periods, as anchor tenants get exactly that many years of free registration. + */ + static void verifyAnchorTenantValidPeriod(boolean isAnchorTenant, int registrationYears) + throws EppException { + if (isAnchorTenant && registrationYears != ANCHOR_TENANT_CREATE_VALID_YEARS) { + throw new AnchorTenantCreatePeriodException(registrationYears); + } + } + /** Prohibit creating a domain if there is an open application for the same name. */ private void verifyNoOpenApplications(DateTime now) throws DomainHasOpenApplicationsException { for (DomainApplication application : loadActiveApplicationsByDomainName(targetId, now)) { @@ -557,4 +574,14 @@ public class DomainCreateFlow implements TransactionalFlow { super("The current registry phase requires a signed mark for registrations"); } } + + /** Anchor tenant domain create is for the wrong number of years. */ + static class AnchorTenantCreatePeriodException extends ParameterValuePolicyErrorException { + public AnchorTenantCreatePeriodException(int invalidYears) { + super( + String.format( + "Anchor tenant domain creates must be for a period of %s years, got %s instead.", + ANCHOR_TENANT_CREATE_VALID_YEARS, invalidYears)); + } + } } diff --git a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java index 5d989acd0..c222ca42b 100644 --- a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java @@ -65,6 +65,7 @@ import google.registry.flows.EppException.UnimplementedExtensionException; import google.registry.flows.EppRequestSource; import google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException; import google.registry.flows.ResourceFlowTestCase; +import google.registry.flows.domain.DomainCreateFlow.AnchorTenantCreatePeriodException; import google.registry.flows.domain.DomainCreateFlow.DomainHasOpenApplicationsException; import google.registry.flows.domain.DomainCreateFlow.MustHaveSignedMarksInCurrentPhaseException; import google.registry.flows.domain.DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException; @@ -1059,6 +1060,14 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase + + + + anchor.tld + 1 + + ns1.example.net + ns2.example.net + + jd1234 + sh8013 + sh8013 + + 2fooBAR + + + + ABC-12345 + +