diff --git a/java/google/registry/flows/domain/BaseDomainCreateFlow.java b/java/google/registry/flows/domain/BaseDomainCreateFlow.java index 6c891b2f1..6a5252842 100644 --- a/java/google/registry/flows/domain/BaseDomainCreateFlow.java +++ b/java/google/registry/flows/domain/BaseDomainCreateFlow.java @@ -41,6 +41,7 @@ import static google.registry.util.CollectionUtils.nullToEmpty; import com.google.common.base.Optional; import com.google.common.net.InternetDomainName; +import com.googlecode.objectify.Key; import com.googlecode.objectify.Work; import google.registry.flows.EppException; import google.registry.flows.EppException.ParameterValuePolicyErrorException; @@ -49,10 +50,12 @@ import google.registry.flows.EppException.ParameterValueSyntaxErrorException; import google.registry.flows.EppException.StatusProhibitsOperationException; import google.registry.flows.EppException.UnimplementedOptionException; import google.registry.flows.ResourceCreateFlow; +import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException; import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase.Builder; import google.registry.model.domain.DomainCommand.Create; import google.registry.model.domain.DomainResource; +import google.registry.model.domain.LrpToken; import google.registry.model.domain.fee.FeeTransformCommandExtension; import google.registry.model.domain.launch.LaunchCreateExtension; import google.registry.model.domain.launch.LaunchNotice; @@ -90,6 +93,7 @@ public abstract class BaseDomainCreateFlow lrpToken; @Override public final void initResourceCreateOrMutateFlow() throws EppException { @@ -183,6 +187,13 @@ public abstract class BaseDomainCreateFlowabsent(); // Superusers can create reserved domains, force creations on domains that require a claims // notice without specifying a claims key, and override blocks on registering premium domains. if (!isSuperuser) { @@ -191,6 +202,9 @@ public abstract class BaseDomainCreateFlow getFeeClass(String domainName, DateTime date) { return getPricesForDomainName(domainName, date).getFeeClass(); } + + /** + * Checks whether a {@link Create} command has a valid {@link LrpToken} for a particular TLD, and + * return that token (wrapped in an {@link Optional}) if one exists. + * + *

This method has no knowledge of whether or not an auth code (interpreted here as an LRP + * token) has already been checked against the reserved list for QLP (anchor tenant), as auth + * codes are used for both types of registrations. + */ + public static Optional getMatchingLrpToken(Create createCommand) { + // Note that until the actual per-TLD logic is built out, what's being done here is a basic + // domain-name-to-assignee match. + String lrpToken = createCommand.getAuthInfo().getPw().getValue(); + LrpToken token = ofy().load().key(Key.create(LrpToken.class, lrpToken)).now(); + if (token != null) { + if (token.getAssignee().equalsIgnoreCase(createCommand.getFullyQualifiedDomainName()) + && token.getRedemptionHistoryEntry() == null) { + return Optional.of(token); + } + } + return Optional.absent(); + } } diff --git a/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java b/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java index 62917448f..d787a6492 100644 --- a/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java @@ -39,10 +39,12 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; +import com.googlecode.objectify.Key; import google.registry.flows.EppException.UnimplementedExtensionException; import google.registry.flows.ResourceCreateFlow.ResourceAlreadyExistsException; import google.registry.flows.ResourceFlow.BadCommandForRegistryPhaseException; import google.registry.flows.ResourceFlowTestCase; +import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException; import google.registry.flows.domain.BaseDomainCreateFlow.AcceptedTooLongAgoException; import google.registry.flows.domain.BaseDomainCreateFlow.ClaimsPeriodEndedException; import google.registry.flows.domain.BaseDomainCreateFlow.ExpiredClaimException; @@ -100,6 +102,7 @@ import google.registry.flows.domain.DomainFlowUtils.TrailingDashException; import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException; import google.registry.model.domain.DomainApplication; import google.registry.model.domain.GracePeriod; +import google.registry.model.domain.LrpToken; import google.registry.model.domain.launch.ApplicationStatus; import google.registry.model.domain.launch.LaunchNotice; import google.registry.model.domain.launch.LaunchPhase; @@ -867,6 +870,127 @@ public class DomainApplicationCreateFlowTest doSuccessfulTest("domain_create_landrush_response.xml", false, 2); } + @Test + public void testSuccess_landrushLrpApplication() throws Exception { + createTld("tld", TldState.LANDRUSH); + persistResource(Registry.get("tld").asBuilder() + .setLrpTldStates(ImmutableSet.of(TldState.LANDRUSH)) + .build()); + LrpToken token = persistResource(new LrpToken.Builder() + .setToken("lrptokentest") + .setAssignee("test-validate.tld") + .build()); + setEppInput("domain_create_landrush_lrp.xml"); + persistContactsAndHosts(); + clock.advanceOneMilli(); + doSuccessfulTest("domain_create_landrush_response.xml", false); + assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNotNull(); + } + + @Test + public void testSuccess_landrush_duringLrpWithMissingToken() throws Exception { + createTld("tld", TldState.LANDRUSH); + persistResource(Registry.get("tld").asBuilder() + .setLrpTldStates(ImmutableSet.of(TldState.LANDRUSH)) + .build()); + setEppInput("domain_create_landrush.xml"); + persistContactsAndHosts(); + clock.advanceOneMilli(); + doSuccessfulTest("domain_create_landrush_response.xml", false); + } + + @Test + public void testSuccess_landrushLrpApplication_superuser() throws Exception { + // Using an LRP token as superuser should still mark the token as redeemed (i.e. same effect + // as non-superuser). + createTld("tld", TldState.LANDRUSH); + persistResource(Registry.get("tld").asBuilder() + .setLrpTldStates(ImmutableSet.of(TldState.LANDRUSH)) + .build()); + LrpToken token = persistResource(new LrpToken.Builder() + .setToken("lrptokentest") + .setAssignee("test-validate.tld") + .build()); + setEppInput("domain_create_landrush_lrp.xml"); + persistContactsAndHosts(); + clock.advanceOneMilli(); + runSuperuserFlow("domain_create_landrush_response.xml"); + assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNotNull(); + } + + @Test + public void testFailure_landrushLrpApplication_badToken() throws Exception { + thrown.expect(BadAuthInfoForResourceException.class); + createTld("tld", TldState.LANDRUSH); + persistResource(Registry.get("tld").asBuilder() + .setLrpTldStates(ImmutableSet.of(TldState.LANDRUSH)) + .build()); + persistResource(new LrpToken.Builder() + .setToken("lrptokentest2") + .setAssignee("test-validate.tld") + .build()); + setEppInput("domain_create_landrush_lrp.xml"); + persistContactsAndHosts(); + clock.advanceOneMilli(); + runFlow(); + } + + @Test + public void testFailure_landrushLrpApplication_usedToken() throws Exception { + thrown.expect(BadAuthInfoForResourceException.class); + createTld("tld", TldState.LANDRUSH); + persistResource(Registry.get("tld").asBuilder() + .setLrpTldStates(ImmutableSet.of(TldState.LANDRUSH)) + .build()); + persistResource(new LrpToken.Builder() + .setToken("lrptokentest") + .setAssignee("test-validate.tld") + .setRedemptionHistoryEntry(Key.create(HistoryEntry.class, "1")) // as long as it's not null + .build()); + setEppInput("domain_create_landrush_lrp.xml"); + persistContactsAndHosts(); + clock.advanceOneMilli(); + runFlow(); + } + + @Test + public void testSuccess_landrushApplicationWithLrpToken_notInLrp() throws Exception { + createTld("tld", TldState.LANDRUSH); + LrpToken token = persistResource(new LrpToken.Builder() + .setToken("lrptokentest") + .setAssignee("test-validate.tld") + .build()); + setEppInput("domain_create_landrush_lrp.xml"); + persistContactsAndHosts(); + clock.advanceOneMilli(); + // Application should continue as normal, since the LRP token will just be ignored + doSuccessfulTest("domain_create_landrush_response.xml", false); + // Token should not be marked as used, since this isn't an LRP state + assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNull(); + } + + @Test + public void testSuccess_landrushApplicationWithLrpToken_differentLrpState() throws Exception { + createTld("tld"); + persistResource(Registry.get("tld").asBuilder() + .setLrpTldStates(ImmutableSet.of(TldState.SUNRISE)) + .setTldStateTransitions(ImmutableSortedMap.of( + START_OF_TIME, TldState.SUNRISE, + clock.nowUtc(), TldState.LANDRUSH)) + .build()); + LrpToken token = persistResource(new LrpToken.Builder() + .setToken("lrptokentest") + .setAssignee("test-validate.tld") + .build()); + setEppInput("domain_create_landrush_lrp.xml"); + persistContactsAndHosts(); + clock.advanceOneMilli(); + // Application should continue as normal, since the LRP token will just be ignored + doSuccessfulTest("domain_create_landrush_response.xml", false); + // Token should not be marked as used, since this isn't an LRP state + assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry()).isNull(); + } + @Test public void testFailure_landrushWithPeriodInMonths() throws Exception { thrown.expect(BadPeriodUnitException.class); diff --git a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java index c5aa23f39..9111e46d5 100644 --- a/javatests/google/registry/flows/domain/DomainCreateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainCreateFlowTest.java @@ -17,6 +17,7 @@ package google.registry.flows.domain; import static com.google.common.io.BaseEncoding.base16; import static com.google.common.truth.Truth.assertThat; import static google.registry.model.domain.fee.Fee.FEE_EXTENSION_URIS; +import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.pricing.PricingEngineProxy.getPricesForDomainName; import static google.registry.testing.DatastoreHelper.assertBillingEvents; import static google.registry.testing.DatastoreHelper.createTld; @@ -102,6 +103,7 @@ import google.registry.model.billing.BillingEvent.Flag; import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.domain.DomainResource; import google.registry.model.domain.GracePeriod; +import google.registry.model.domain.LrpToken; import google.registry.model.domain.launch.ApplicationStatus; import google.registry.model.domain.launch.LaunchNotice; import google.registry.model.domain.rgp.GracePeriodStatus; @@ -785,6 +787,34 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase + + + Command completed successfully + + + + anchor.tld + 1999-04-03T22:00:00Z + 2001-04-03T22:00:00Z + + + + ABC-12345 + server-trid + + + diff --git a/javatests/google/registry/flows/domain/testdata/domain_create_landrush.xml b/javatests/google/registry/flows/domain/testdata/domain_create_landrush.xml index b6b7f5192..e89c8df2c 100644 --- a/javatests/google/registry/flows/domain/testdata/domain_create_landrush.xml +++ b/javatests/google/registry/flows/domain/testdata/domain_create_landrush.xml @@ -13,7 +13,7 @@ sh8013 sh8013 - 2fooBAR + diff --git a/javatests/google/registry/flows/domain/testdata/domain_create_landrush_lrp.xml b/javatests/google/registry/flows/domain/testdata/domain_create_landrush_lrp.xml new file mode 100644 index 000000000..63522eeb3 --- /dev/null +++ b/javatests/google/registry/flows/domain/testdata/domain_create_landrush_lrp.xml @@ -0,0 +1,28 @@ + + + + + + test-validate.tld + + ns1.example.net + ns2.example.net + + jd1234 + sh8013 + sh8013 + + lrptokentest + + + + + + landrush + + + ABC-12345 + +