mirror of
https://github.com/google/nomulus
synced 2026-09-12 02:56:26 +00:00
Don't apply non-premium default tokens to premium names (#2007)
* Don't apply non-premium default tokens to premium names * Add test for renew * Remove premium check from try/catch block * Add check in validateToken * Update docs * Add validateForPremiums * Better method name * Shorten error message to fit as reason * Add missing extension catch * Remove extra javadoc * Fix merge conflicts and change error message * Update flow docs
This commit is contained in:
@@ -50,6 +50,7 @@ import google.registry.flows.annotations.ReportingSpec;
|
||||
import google.registry.flows.custom.DomainCheckFlowCustomLogic;
|
||||
import google.registry.flows.custom.DomainCheckFlowCustomLogic.BeforeResponseParameters;
|
||||
import google.registry.flows.custom.DomainCheckFlowCustomLogic.BeforeResponseReturnData;
|
||||
import google.registry.flows.domain.DomainPricingLogic.AllocationTokenInvalidForPremiumNameException;
|
||||
import google.registry.flows.domain.token.AllocationTokenDomainCheckResults;
|
||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils;
|
||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException;
|
||||
@@ -81,6 +82,7 @@ import google.registry.model.tld.Tld;
|
||||
import google.registry.model.tld.Tld.TldState;
|
||||
import google.registry.model.tld.label.ReservationType;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.pricing.PricingEngineProxy;
|
||||
import google.registry.util.Clock;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
@@ -291,6 +293,7 @@ public final class DomainCheckFlow implements Flow {
|
||||
allocationToken.get(),
|
||||
feeCheckItem.getCommandName(),
|
||||
registrarId,
|
||||
PricingEngineProxy.isDomainPremium(domainName, now),
|
||||
now);
|
||||
}
|
||||
handleFeeRequest(
|
||||
@@ -305,7 +308,8 @@ public final class DomainCheckFlow implements Flow {
|
||||
availableDomains.contains(domainName),
|
||||
recurrences.getOrDefault(domainName, null));
|
||||
responseItems.add(builder.setDomainNameIfSupported(domainName).build());
|
||||
} catch (AllocationTokenNotValidForCommandException
|
||||
} catch (AllocationTokenInvalidForPremiumNameException
|
||||
| AllocationTokenNotValidForCommandException
|
||||
| AllocationTokenNotValidForDomainException
|
||||
| AllocationTokenNotValidForRegistrarException
|
||||
| AllocationTokenNotValidForTldException
|
||||
|
||||
@@ -74,6 +74,7 @@ import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
|
||||
import google.registry.flows.EppException.RequiredParameterMissingException;
|
||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||
import google.registry.flows.EppException.UnimplementedOptionException;
|
||||
import google.registry.flows.domain.DomainPricingLogic.AllocationTokenInvalidForPremiumNameException;
|
||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils;
|
||||
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
|
||||
import google.registry.model.EppResource;
|
||||
@@ -1217,8 +1218,15 @@ public class DomainFlowUtils {
|
||||
for (Optional<AllocationToken> token : tokenList) {
|
||||
try {
|
||||
AllocationTokenFlowUtils.validateToken(
|
||||
InternetDomainName.from(domainName), token.get(), commandName, registrarId, now);
|
||||
} catch (AssociationProhibitsOperationException | StatusProhibitsOperationException e) {
|
||||
InternetDomainName.from(domainName),
|
||||
token.get(),
|
||||
commandName,
|
||||
registrarId,
|
||||
isDomainPremium(domainName, now),
|
||||
now);
|
||||
} catch (AssociationProhibitsOperationException
|
||||
| StatusProhibitsOperationException
|
||||
| AllocationTokenInvalidForPremiumNameException e) {
|
||||
// Allocation token was not valid for this registration, continue to check the next token in
|
||||
// the list
|
||||
continue;
|
||||
|
||||
@@ -16,6 +16,7 @@ package google.registry.flows.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.flows.domain.DomainFlowUtils.zeroInCurrency;
|
||||
import static google.registry.flows.domain.token.AllocationTokenFlowUtils.validateTokenForPossiblePremiumName;
|
||||
import static google.registry.pricing.PricingEngineProxy.getPricesForDomainName;
|
||||
import static google.registry.util.DomainNameUtils.getTldFromDomainName;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
|
||||
@@ -257,12 +258,7 @@ public final class DomainPricingLogic {
|
||||
private Money getDomainCostWithDiscount(
|
||||
boolean isPremium, int years, Optional<AllocationToken> allocationToken, Money oneYearCost)
|
||||
throws AllocationTokenInvalidForPremiumNameException {
|
||||
if (allocationToken.isPresent()
|
||||
&& allocationToken.get().getDiscountFraction() != 0.0
|
||||
&& isPremium
|
||||
&& !allocationToken.get().shouldDiscountPremiums()) {
|
||||
throw new AllocationTokenInvalidForPremiumNameException();
|
||||
}
|
||||
validateTokenForPossiblePremiumName(allocationToken, isPremium);
|
||||
Money totalDomainFlowCost = oneYearCost.multipliedBy(years);
|
||||
|
||||
// Apply the allocation token discount, if applicable.
|
||||
@@ -281,8 +277,8 @@ public final class DomainPricingLogic {
|
||||
/** An allocation token was provided that is invalid for premium domains. */
|
||||
public static class AllocationTokenInvalidForPremiumNameException
|
||||
extends CommandUseErrorException {
|
||||
AllocationTokenInvalidForPremiumNameException() {
|
||||
super("A nonzero discount code cannot be applied to premium domains");
|
||||
public AllocationTokenInvalidForPremiumNameException() {
|
||||
super("Token not valid for premium name");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+50
-25
@@ -16,6 +16,7 @@ package google.registry.flows.domain.token;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.pricing.PricingEngineProxy.isDomainPremium;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -26,6 +27,7 @@ import google.registry.flows.EppException;
|
||||
import google.registry.flows.EppException.AssociationProhibitsOperationException;
|
||||
import google.registry.flows.EppException.AuthorizationErrorException;
|
||||
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||
import google.registry.flows.domain.DomainPricingLogic.AllocationTokenInvalidForPremiumNameException;
|
||||
import google.registry.model.billing.BillingBase.RenewalPriceBehavior;
|
||||
import google.registry.model.billing.BillingRecurrence;
|
||||
import google.registry.model.domain.Domain;
|
||||
@@ -79,7 +81,13 @@ public class AllocationTokenFlowUtils {
|
||||
ImmutableMap.Builder<InternetDomainName, String> resultsBuilder = new ImmutableMap.Builder<>();
|
||||
for (InternetDomainName domainName : domainNames) {
|
||||
try {
|
||||
validateToken(domainName, tokenEntity, CommandName.CREATE, registrarId, now);
|
||||
validateToken(
|
||||
domainName,
|
||||
tokenEntity,
|
||||
CommandName.CREATE,
|
||||
registrarId,
|
||||
isDomainPremium(domainName.toString(), now),
|
||||
now);
|
||||
validDomainNames.add(domainName);
|
||||
} catch (EppException e) {
|
||||
resultsBuilder.put(domainName, e.getMessage());
|
||||
@@ -105,7 +113,7 @@ public class AllocationTokenFlowUtils {
|
||||
/**
|
||||
* Validates a given token. The token could be invalid if it has allowed client IDs or TLDs that
|
||||
* do not include this client ID / TLD, or if the token has a promotion that is not currently
|
||||
* running.
|
||||
* running, or the token is not valid for a premium name when necessary.
|
||||
*
|
||||
* @throws EppException if the token is invalid in any way
|
||||
*/
|
||||
@@ -114,33 +122,48 @@ public class AllocationTokenFlowUtils {
|
||||
AllocationToken token,
|
||||
CommandName commandName,
|
||||
String registrarId,
|
||||
boolean isPremium,
|
||||
DateTime now)
|
||||
throws EppException {
|
||||
|
||||
// Only tokens with default behavior require validation
|
||||
if (TokenBehavior.DEFAULT.equals(token.getTokenBehavior())) {
|
||||
if (!token.getAllowedEppActions().isEmpty()
|
||||
&& !token.getAllowedEppActions().contains(commandName)) {
|
||||
throw new AllocationTokenNotValidForCommandException();
|
||||
}
|
||||
if (!token.getAllowedRegistrarIds().isEmpty()
|
||||
&& !token.getAllowedRegistrarIds().contains(registrarId)) {
|
||||
throw new AllocationTokenNotValidForRegistrarException();
|
||||
}
|
||||
if (!token.getAllowedTlds().isEmpty()
|
||||
&& !token.getAllowedTlds().contains(domainName.parent().toString())) {
|
||||
throw new AllocationTokenNotValidForTldException();
|
||||
}
|
||||
if (token.getDomainName().isPresent()
|
||||
&& !token.getDomainName().get().equals(domainName.toString())) {
|
||||
throw new AllocationTokenNotValidForDomainException();
|
||||
}
|
||||
// Tokens without status transitions will just have a single-entry NOT_STARTED map, so only
|
||||
// check the status transitions map if it's non-trivial.
|
||||
if (token.getTokenStatusTransitions().size() > 1
|
||||
&& !TokenStatus.VALID.equals(token.getTokenStatusTransitions().getValueAtTime(now))) {
|
||||
throw new AllocationTokenNotInPromotionException();
|
||||
}
|
||||
if (!TokenBehavior.DEFAULT.equals(token.getTokenBehavior())) {
|
||||
return;
|
||||
}
|
||||
validateTokenForPossiblePremiumName(Optional.of(token), isPremium);
|
||||
if (!token.getAllowedEppActions().isEmpty()
|
||||
&& !token.getAllowedEppActions().contains(commandName)) {
|
||||
throw new AllocationTokenNotValidForCommandException();
|
||||
}
|
||||
if (!token.getAllowedRegistrarIds().isEmpty()
|
||||
&& !token.getAllowedRegistrarIds().contains(registrarId)) {
|
||||
throw new AllocationTokenNotValidForRegistrarException();
|
||||
}
|
||||
if (!token.getAllowedTlds().isEmpty()
|
||||
&& !token.getAllowedTlds().contains(domainName.parent().toString())) {
|
||||
throw new AllocationTokenNotValidForTldException();
|
||||
}
|
||||
if (token.getDomainName().isPresent()
|
||||
&& !token.getDomainName().get().equals(domainName.toString())) {
|
||||
throw new AllocationTokenNotValidForDomainException();
|
||||
}
|
||||
// Tokens without status transitions will just have a single-entry NOT_STARTED map, so only
|
||||
// check the status transitions map if it's non-trivial.
|
||||
if (token.getTokenStatusTransitions().size() > 1
|
||||
&& !TokenStatus.VALID.equals(token.getTokenStatusTransitions().getValueAtTime(now))) {
|
||||
throw new AllocationTokenNotInPromotionException();
|
||||
}
|
||||
}
|
||||
|
||||
/** Validates that the given token is valid for a premium name if the name is premium. */
|
||||
public static void validateTokenForPossiblePremiumName(
|
||||
Optional<AllocationToken> token, boolean isPremium)
|
||||
throws AllocationTokenInvalidForPremiumNameException {
|
||||
if (token.isPresent()
|
||||
&& token.get().getDiscountFraction() != 0.0
|
||||
&& isPremium
|
||||
&& !token.get().shouldDiscountPremiums()) {
|
||||
throw new AllocationTokenInvalidForPremiumNameException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +210,7 @@ public class AllocationTokenFlowUtils {
|
||||
tokenEntity,
|
||||
CommandName.CREATE,
|
||||
registrarId,
|
||||
isDomainPremium(command.getDomainName(), now),
|
||||
now);
|
||||
return Optional.of(tokenCustomLogic.validateToken(command, tokenEntity, tld, registrarId, now));
|
||||
}
|
||||
@@ -209,6 +233,7 @@ public class AllocationTokenFlowUtils {
|
||||
tokenEntity,
|
||||
commandName,
|
||||
registrarId,
|
||||
isDomainPremium(existingDomain.getDomainName(), now),
|
||||
now);
|
||||
return Optional.of(
|
||||
tokenCustomLogic.validateToken(existingDomain, tokenEntity, tld, registrarId, now));
|
||||
|
||||
Reference in New Issue
Block a user