mirror of
https://github.com/google/nomulus.git
synced 2025-05-17 01:47:14 +02:00
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:
parent
139c8e190d
commit
f56355c9e8
4 changed files with 59 additions and 0 deletions
|
@ -582,6 +582,7 @@ An EPP flow that creates a new domain resource.
|
||||||
* 2305
|
* 2305
|
||||||
* The allocation token was already redeemed.
|
* The allocation token was already redeemed.
|
||||||
* 2306
|
* 2306
|
||||||
|
* Anchor tenant domain create is for the wrong number of years.
|
||||||
* The provided mark is not yet valid.
|
* The provided mark is not yet valid.
|
||||||
* The provided mark has expired.
|
* The provided mark has expired.
|
||||||
* Domain names can only contain a-z, 0-9, '.' and '-'.
|
* Domain names can only contain a-z, 0-9, '.' and '-'.
|
||||||
|
|
|
@ -56,6 +56,7 @@ import com.googlecode.objectify.Key;
|
||||||
import google.registry.dns.DnsQueue;
|
import google.registry.dns.DnsQueue;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.EppException.CommandUseErrorException;
|
import google.registry.flows.EppException.CommandUseErrorException;
|
||||||
|
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
||||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
import google.registry.flows.FlowModule.ClientId;
|
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.exceptions.ResourceAlreadyExistsException}
|
||||||
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
|
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
|
||||||
* @error {@link google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException}
|
* @error {@link google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException}
|
||||||
|
* @error {@link DomainCreateFlow.AnchorTenantCreatePeriodException}
|
||||||
* @error {@link DomainCreateFlow.DomainHasOpenApplicationsException}
|
* @error {@link DomainCreateFlow.DomainHasOpenApplicationsException}
|
||||||
* @error {@link DomainCreateFlow.MustHaveSignedMarksInCurrentPhaseException}
|
* @error {@link DomainCreateFlow.MustHaveSignedMarksInCurrentPhaseException}
|
||||||
* @error {@link DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException}
|
* @error {@link DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException}
|
||||||
|
@ -184,6 +186,9 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||||
private static final ImmutableSet<TldState> SUNRISE_STATES =
|
private static final ImmutableSet<TldState> SUNRISE_STATES =
|
||||||
Sets.immutableEnumSet(TldState.SUNRISE, TldState.SUNRUSH);
|
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 ExtensionManager extensionManager;
|
||||||
@Inject EppInput eppInput;
|
@Inject EppInput eppInput;
|
||||||
@Inject AuthInfo authInfo;
|
@Inject AuthInfo authInfo;
|
||||||
|
@ -229,6 +234,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
TldState tldState = registry.getTldState(now);
|
TldState tldState = registry.getTldState(now);
|
||||||
boolean isAnchorTenant = isAnchorTenant(domainName);
|
boolean isAnchorTenant = isAnchorTenant(domainName);
|
||||||
|
verifyAnchorTenantValidPeriod(isAnchorTenant, years);
|
||||||
Optional<LaunchCreateExtension> launchCreate =
|
Optional<LaunchCreateExtension> launchCreate =
|
||||||
eppInput.getSingleExtension(LaunchCreateExtension.class);
|
eppInput.getSingleExtension(LaunchCreateExtension.class);
|
||||||
boolean hasSignedMarks =
|
boolean hasSignedMarks =
|
||||||
|
@ -374,6 +380,17 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||||
|| (metadataExtension.isPresent() && metadataExtension.get().getIsAnchorTenant());
|
|| (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. */
|
/** Prohibit creating a domain if there is an open application for the same name. */
|
||||||
private void verifyNoOpenApplications(DateTime now) throws DomainHasOpenApplicationsException {
|
private void verifyNoOpenApplications(DateTime now) throws DomainHasOpenApplicationsException {
|
||||||
for (DomainApplication application : loadActiveApplicationsByDomainName(targetId, now)) {
|
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");
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ import google.registry.flows.EppException.UnimplementedExtensionException;
|
||||||
import google.registry.flows.EppRequestSource;
|
import google.registry.flows.EppRequestSource;
|
||||||
import google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException;
|
import google.registry.flows.ExtensionManager.UndeclaredServiceExtensionException;
|
||||||
import google.registry.flows.ResourceFlowTestCase;
|
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.DomainHasOpenApplicationsException;
|
||||||
import google.registry.flows.domain.DomainCreateFlow.MustHaveSignedMarksInCurrentPhaseException;
|
import google.registry.flows.domain.DomainCreateFlow.MustHaveSignedMarksInCurrentPhaseException;
|
||||||
import google.registry.flows.domain.DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException;
|
import google.registry.flows.domain.DomainCreateFlow.NoGeneralRegistrationsInCurrentPhaseException;
|
||||||
|
@ -1059,6 +1060,14 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
||||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
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
|
@Test
|
||||||
public void testSuccess_anchorTenantViaAuthCode_matchingLrpToken() throws Exception {
|
public void testSuccess_anchorTenantViaAuthCode_matchingLrpToken() throws Exception {
|
||||||
// This is definitely a corner case, as (without superuser) anchor tenants may only register
|
// This is definitely a corner case, as (without superuser) anchor tenants may only register
|
||||||
|
|
22
javatests/google/registry/flows/domain/testdata/domain_create_anchor_authcode_invalid_years.xml
vendored
Normal file
22
javatests/google/registry/flows/domain/testdata/domain_create_anchor_authcode_invalid_years.xml
vendored
Normal 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>
|
Loading…
Add table
Add a link
Reference in a new issue