Always validate domain name on allocation token (#498)

* Always validate domain name on allocation token

This is in response to a client-reported error, where they accidentally sent the
wrong domain name on a domain create that included an allocation token. What
should have happened (and that now happens as of this commit) is an error being
thrown that the allocation token does not match the domain name being created.
What happened instead was that, since the incorrectly submitted domain name was
not reserved, the create succeeded (as it would for all creates of unreserved
domains in GA) and the allocation token was redeemed, which is not what you'd
expect.

* Fix tests to reflect changed check behavior
This commit is contained in:
Ben McIlwain 2020-02-27 16:48:37 -05:00 committed by GitHub
parent 429bc8e6d2
commit 9283cd263f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 105 additions and 38 deletions

View file

@ -186,7 +186,7 @@ public class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFl
.build());
doCheckTest(
create(false, "example1.tld", "In use"),
create(true, "example2.tld", null),
create(false, "example2.tld", "Alloc token invalid for domain"),
create(false, "reserved.tld", "Reserved"),
create(true, "specificuse.tld", null));
}
@ -203,7 +203,7 @@ public class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFl
.build());
doCheckTest(
create(false, "example1.tld", "In use"),
create(true, "example2.tld", null),
create(false, "example2.tld", "Alloc token invalid for domain"),
create(false, "reserved.tld", "Reserved"),
create(false, "specificuse.tld", "Allocation token required"));
}
@ -224,8 +224,8 @@ public class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFl
.build())
.build());
doCheckTest(
create(true, "example1.tld", null),
create(true, "example2.tld", null),
create(false, "example1.tld", "Alloc token invalid for domain"),
create(false, "example2.tld", "Alloc token invalid for domain"),
create(false, "reserved.tld", "Reserved"),
create(true, "specificuse.tld", null));
}
@ -246,8 +246,8 @@ public class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFl
.build())
.build());
doCheckTest(
create(false, "example1.tld", "Alloc token not in promo period"),
create(false, "example2.tld", "Alloc token not in promo period"),
create(false, "example1.tld", "Alloc token invalid for domain"),
create(false, "example2.tld", "Alloc token invalid for domain"),
create(false, "reserved.tld", "Reserved"),
create(false, "specificuse.tld", "Alloc token not in promo period"));
}

View file

@ -131,6 +131,7 @@ import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeExcep
import google.registry.flows.domain.DomainFlowUtils.UnsupportedMarkTypeException;
import google.registry.flows.domain.DomainPricingLogic.AllocationTokenInvalidForPremiumNameException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForDomainException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException;
@ -440,6 +441,44 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
public void testFailure_reservedDomainCreate_allocationTokenIsForADifferentDomain() {
// Try to register a reserved domain name with an allocation token valid for a different domain
// name.
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "resdom.tld"));
persistContactsAndHosts();
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setDomainName("otherdomain.tld")
.build());
clock.advanceOneMilli();
EppException thrown =
assertThrows(AllocationTokenNotValidForDomainException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
assertAllocationTokenWasNotRedeemed("abc123");
}
@Test
public void testFailure_nonreservedDomainCreate_allocationTokenIsForADifferentDomain() {
// Try to register a non-reserved domain name with an allocation token valid for a different
// domain name.
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld"));
persistContactsAndHosts();
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(SINGLE_USE)
.setDomainName("otherdomain.tld")
.build());
clock.advanceOneMilli();
EppException thrown =
assertThrows(AllocationTokenNotValidForDomainException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
assertAllocationTokenWasNotRedeemed("abc123");
}
@Test
public void testFailure_alreadyRedemeedAllocationToken() {
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld"));
@ -1212,6 +1251,12 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
.isEqualTo(Key.create(getHistoryEntries(reloadResourceByForeignKey()).get(0)));
}
private void assertAllocationTokenWasNotRedeemed(String token) {
AllocationToken reloadedToken =
ofy().load().key(Key.create(AllocationToken.class, token)).now();
assertThat(reloadedToken.isRedeemed()).isFalse();
}
@Test
public void testSuccess_allocationTokenPromotion() throws Exception {
// A discount of 0.5 means that the first-year cost (13) is cut in half, so a discount of 6.5