Allow incorrect fee extensions on domain creates with default tokens (#1927)

* Modify fee extension to accept larger costs on creates with default tokens

* Add tests

* Add some comments to tests
This commit is contained in:
sarahcaseybot 2023-02-28 14:24:03 -05:00 committed by GitHub
parent c07728dab8
commit 9a212314ca
8 changed files with 189 additions and 16 deletions

View file

@ -280,8 +280,12 @@ public final class DomainCreateFlow implements TransactionalFlow {
registrarId,
now,
eppInput.getSingleExtension(AllocationTokenExtension.class));
boolean defaultTokenUsed = false;
if (!allocationToken.isPresent() && !registry.getDefaultPromoTokens().isEmpty()) {
allocationToken = checkForDefaultToken(registry, command);
if (allocationToken.isPresent()) {
defaultTokenUsed = true;
}
}
boolean isAnchorTenant =
isAnchorTenant(
@ -340,7 +344,7 @@ public final class DomainCreateFlow implements TransactionalFlow {
FeesAndCredits feesAndCredits =
pricingLogic.getCreatePrice(
registry, targetId, now, years, isAnchorTenant, allocationToken);
validateFeeChallenge(feeCreate, feesAndCredits);
validateFeeChallenge(feeCreate, feesAndCredits, defaultTokenUsed);
Optional<SecDnsCreateExtension> secDnsCreate =
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
DateTime registrationExpirationTime = leapSafeAddYears(now, years);

View file

@ -778,12 +778,13 @@ public class DomainFlowUtils {
*/
public static void validateFeeChallenge(
final Optional<? extends FeeTransformCommandExtension> feeCommand,
FeesAndCredits feesAndCredits)
FeesAndCredits feesAndCredits,
boolean defaultTokenUsed)
throws EppException {
if (feesAndCredits.hasAnyPremiumFees() && !feeCommand.isPresent()) {
throw new FeesRequiredForPremiumNameException();
}
validateFeesAckedIfPresent(feeCommand, feesAndCredits);
validateFeesAckedIfPresent(feeCommand, feesAndCredits, defaultTokenUsed);
}
/**
@ -795,7 +796,8 @@ public class DomainFlowUtils {
*/
public static void validateFeesAckedIfPresent(
final Optional<? extends FeeTransformCommandExtension> feeCommand,
FeesAndCredits feesAndCredits)
FeesAndCredits feesAndCredits,
boolean defaultTokenUsed)
throws EppException {
// Check for the case where a fee command extension was required but not provided.
// This only happens when the total fees are non-zero and include custom fees requiring the
@ -856,7 +858,9 @@ public class DomainFlowUtils {
// Checking if total amount is expected. Extra fees that we are not expecting may be passed in.
// Or if there is only a single fee type expected.
if (!feeTotal.equals(feesAndCredits.getTotalCost())) {
throw new FeesMismatchException(feesAndCredits.getTotalCost());
if (!defaultTokenUsed || feeTotal.isLessThan(feesAndCredits.getTotalCost())) {
throw new FeesMismatchException(feesAndCredits.getTotalCost());
}
}
}

View file

@ -199,7 +199,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
now,
years,
existingRecurringBillingEvent);
validateFeeChallenge(feeRenew, feesAndCredits);
validateFeeChallenge(feeRenew, feesAndCredits, false);
flowCustomLogic.afterValidation(
AfterValidationParameters.newBuilder()
.setExistingDomain(existingDomain)

View file

@ -226,7 +226,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
if (!existingDomain.getGracePeriodStatuses().contains(GracePeriodStatus.REDEMPTION)) {
throw new DomainNotEligibleForRestoreException();
}
validateFeeChallenge(feeUpdate, feesAndCredits);
validateFeeChallenge(feeUpdate, feesAndCredits, false);
}
private static Domain performRestore(

View file

@ -210,7 +210,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
}
if (feesAndCredits.isPresent()) {
validateFeeChallenge(feeTransfer, feesAndCredits.get());
validateFeeChallenge(feeTransfer, feesAndCredits.get(), false);
}
HistoryEntryId domainHistoryId = createHistoryEntryId(existingDomain);
historyBuilder

View file

@ -231,7 +231,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
Optional<FeeUpdateCommandExtension> feeUpdate =
eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
FeesAndCredits feesAndCredits = pricingLogic.getUpdatePrice(registry, targetId, now);
validateFeesAckedIfPresent(feeUpdate, feesAndCredits);
validateFeesAckedIfPresent(feeUpdate, feesAndCredits, false);
verifyNotInPendingDelete(
add.getContacts(),
command.getInnerChange().getRegistrant(),

View file

@ -703,7 +703,9 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6", "CURRENCY", "USD"));
persistContactsAndHosts();
doSuccessfulTest(
"tld", "domain_create_response_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
"tld",
"domain_create_response_fee.xml",
ImmutableMap.of("FEE_VERSION", "0.6", "FEE", "26.00"));
}
@Test
@ -711,7 +713,9 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11", "CURRENCY", "USD"));
persistContactsAndHosts();
doSuccessfulTest(
"tld", "domain_create_response_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
"tld",
"domain_create_response_fee.xml",
ImmutableMap.of("FEE_VERSION", "0.11", "FEE", "26.00"));
}
@Test
@ -719,7 +723,9 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12", "CURRENCY", "USD"));
persistContactsAndHosts();
doSuccessfulTest(
"tld", "domain_create_response_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12"));
"tld",
"domain_create_response_fee.xml",
ImmutableMap.of("FEE_VERSION", "0.12", "FEE", "26.00"));
}
@Test
@ -727,7 +733,9 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
setEppInput("domain_create_fee_defaults.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
persistContactsAndHosts();
doSuccessfulTest(
"tld", "domain_create_response_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6"));
"tld",
"domain_create_response_fee.xml",
ImmutableMap.of("FEE_VERSION", "0.6", "FEE", "26.00"));
}
@Test
@ -735,7 +743,9 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
setEppInput("domain_create_fee_defaults.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistContactsAndHosts();
doSuccessfulTest(
"tld", "domain_create_response_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
"tld",
"domain_create_response_fee.xml",
ImmutableMap.of("FEE_VERSION", "0.11", "FEE", "26.00"));
}
@Test
@ -743,7 +753,9 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
setEppInput("domain_create_fee_defaults.xml", ImmutableMap.of("FEE_VERSION", "0.12"));
persistContactsAndHosts();
doSuccessfulTest(
"tld", "domain_create_response_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12"));
"tld",
"domain_create_response_fee.xml",
ImmutableMap.of("FEE_VERSION", "0.12", "FEE", "26.00"));
}
@Test
@ -1111,6 +1123,57 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testSuccess_wrongFeeAmountTooHigh_defaultToken_v06() throws Exception {
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("tld"))
.setDiscountFraction(0.5)
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 8))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6", "CURRENCY", "USD"));
persistContactsAndHosts();
// $12 is equal to 50% off the first year registration and 0% 0ff the 2nd year
runFlowAssertResponse(
loadFile(
"domain_create_response_fee.xml",
ImmutableMap.of("FEE_VERSION", "0.6", "FEE", "12.00")));
}
@Test
void testFailure_wrongFeeAmountTooLow_defaultToken_v06() throws Exception {
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("tld"))
.setDiscountFraction(0.5)
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 100))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6", "CURRENCY", "USD"));
persistContactsAndHosts();
EppException thrown = assertThrows(FeesMismatchException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_wrongFeeAmount_v11() {
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11", "CURRENCY", "USD"));
@ -1121,6 +1184,57 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testSuccess_wrongFeeAmountTooHigh_defaultToken_v11() throws Exception {
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("tld"))
.setDiscountFraction(0.5)
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 8))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11", "CURRENCY", "USD"));
persistContactsAndHosts();
// $12 is equal to 50% off the first year registration and 0% 0ff the 2nd year
runFlowAssertResponse(
loadFile(
"domain_create_response_fee.xml",
ImmutableMap.of("FEE_VERSION", "0.11", "FEE", "12.00")));
}
@Test
void testFailure_wrongFeeAmountTooLow_defaultToken_v11() throws Exception {
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("tld"))
.setDiscountFraction(0.5)
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 100))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11", "CURRENCY", "USD"));
persistContactsAndHosts();
EppException thrown = assertThrows(FeesMismatchException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_wrongFeeAmount_v12() {
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12", "CURRENCY", "USD"));
@ -1131,6 +1245,57 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testSuccess_wrongFeeAmountTooHigh_defaultToken_v12() throws Exception {
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("tld"))
.setDiscountFraction(0.5)
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 8))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12", "CURRENCY", "USD"));
persistContactsAndHosts();
// $12 is equal to 50% off the first year registration and 0% 0ff the 2nd year
runFlowAssertResponse(
loadFile(
"domain_create_response_fee.xml",
ImmutableMap.of("FEE_VERSION", "0.12", "FEE", "12.00")));
}
@Test
void testFailure_wrongFeeAmountTooLow_defaultToken_v12() throws Exception {
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("tld"))
.setDiscountFraction(0.5)
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.setCreateBillingCost(Money.of(USD, 100))
.build());
// Expects fee of $26
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.12", "CURRENCY", "USD"));
persistContactsAndHosts();
EppException thrown = assertThrows(FeesMismatchException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
void testFailure_wrongCurrency_v06() {
setEppInput("domain_create_fee.xml", ImmutableMap.of("FEE_VERSION", "0.6", "CURRENCY", "EUR"));

View file

@ -14,7 +14,7 @@
<extension>
<fee:creData xmlns:fee="urn:ietf:params:xml:ns:fee-%FEE_VERSION%">
<fee:currency>USD</fee:currency>
<fee:fee description="create">26.00</fee:fee>
<fee:fee description="create">%FEE%</fee:fee>
</fee:creData>
</extension>
<trID>