Enforce anchor tenant domain create period

This verifies anchor tenant creates by registrars are for exactly 2 years, to simplify billing down the line (anchor tenants get 2 years of free domain creates).

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=193931858
This commit is contained in:
larryruili 2018-04-23 09:01:25 -07:00 committed by jianglai
parent 139c8e190d
commit f56355c9e8
4 changed files with 59 additions and 0 deletions

View file

@ -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 '-'.

View file

@ -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<TldState> 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<LaunchCreateExtension> 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));
}
}
}

View file

@ -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<DomainCreateFlow,
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_anchorTenantViaAuthCode_notTwoYearPeriod() throws Exception {
setEppInput("domain_create_anchor_authcode_invalid_years.xml");
persistContactsAndHosts();
EppException thrown = assertThrows(AnchorTenantCreatePeriodException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testSuccess_anchorTenantViaAuthCode_matchingLrpToken() throws Exception {
// This is definitely a corner case, as (without superuser) anchor tenants may only register

View file

@ -0,0 +1,22 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<create>
<domain:create
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>anchor.tld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:ns>
<domain:hostObj>ns1.example.net</domain:hostObj>
<domain:hostObj>ns2.example.net</domain:hostObj>
</domain:ns>
<domain:registrant>jd1234</domain:registrant>
<domain:contact type="admin">sh8013</domain:contact>
<domain:contact type="tech">sh8013</domain:contact>
<domain:authInfo>
<domain:pw>2fooBAR</domain:pw>
</domain:authInfo>
</domain:create>
</create>
<clTRID>ABC-12345</clTRID>
</command>
</epp>