mirror of
https://github.com/google/nomulus.git
synced 2025-05-14 00:17:20 +02:00
Validate on-load that an AllocationToken can be used
Check the timing (that is, whether or not we're in a promotion), the allowed registrar client IDs, and the allowed TLDs. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=246824080
This commit is contained in:
parent
1480181fe1
commit
df7e9a1225
9 changed files with 344 additions and 55 deletions
|
@ -344,6 +344,7 @@ An EPP flow that creates a new domain resource.
|
||||||
* 2303
|
* 2303
|
||||||
* Resource linked to this domain does not exist.
|
* Resource linked to this domain does not exist.
|
||||||
* 2304
|
* 2304
|
||||||
|
* The allocation token is not currently valid.
|
||||||
* The claims period for this TLD has ended.
|
* The claims period for this TLD has ended.
|
||||||
* Requested domain is reserved.
|
* Requested domain is reserved.
|
||||||
* Linked resource in pending delete prohibits operation.
|
* Linked resource in pending delete prohibits operation.
|
||||||
|
@ -355,6 +356,8 @@ An EPP flow that creates a new domain resource.
|
||||||
* Registrant is not whitelisted for this TLD.
|
* Registrant is not whitelisted for this TLD.
|
||||||
* Requested domain does not require a claims notice.
|
* Requested domain does not require a claims notice.
|
||||||
* 2305
|
* 2305
|
||||||
|
* The allocation token is not valid for this registrar.
|
||||||
|
* The allocation token is not valid for this TLD.
|
||||||
* 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.
|
* Anchor tenant domain create is for the wrong number of years.
|
||||||
|
|
|
@ -114,6 +114,9 @@ import org.joda.time.Duration;
|
||||||
/**
|
/**
|
||||||
* An EPP flow that creates a new domain resource.
|
* An EPP flow that creates a new domain resource.
|
||||||
*
|
*
|
||||||
|
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException}
|
||||||
|
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException}
|
||||||
|
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException}
|
||||||
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException}
|
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException}
|
||||||
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException}
|
* @error {@link google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException}
|
||||||
* @error {@link google.registry.flows.exceptions.OnlyToolCanPassMetadataException}
|
* @error {@link google.registry.flows.exceptions.OnlyToolCanPassMetadataException}
|
||||||
|
@ -445,7 +448,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||||
eppInput.getSingleExtension(AllocationTokenExtension.class);
|
eppInput.getSingleExtension(AllocationTokenExtension.class);
|
||||||
return Optional.ofNullable(
|
return Optional.ofNullable(
|
||||||
extension.isPresent()
|
extension.isPresent()
|
||||||
? allocationTokenFlowUtils.loadAndVerifyToken(
|
? allocationTokenFlowUtils.loadTokenAndValidateDomainCreate(
|
||||||
command, extension.get().getAllocationToken(), registry, clientId, now)
|
command, extension.get().getAllocationToken(), registry, clientId, now)
|
||||||
: null);
|
: null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,8 @@ import org.joda.time.DateTime;
|
||||||
*/
|
*/
|
||||||
public class AllocationTokenCustomLogic {
|
public class AllocationTokenCustomLogic {
|
||||||
|
|
||||||
/** Performs additional custom logic for verifying a token. */
|
/** Performs additional custom logic for validating a token. */
|
||||||
public AllocationToken verifyToken(
|
public AllocationToken validateToken(
|
||||||
DomainCommand.Create command,
|
DomainCommand.Create command,
|
||||||
AllocationToken token,
|
AllocationToken token,
|
||||||
Registry registry,
|
Registry registry,
|
||||||
|
|
|
@ -25,8 +25,10 @@ import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.EppException.AssociationProhibitsOperationException;
|
import google.registry.flows.EppException.AssociationProhibitsOperationException;
|
||||||
import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
|
import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
|
||||||
|
import google.registry.flows.EppException.StatusProhibitsOperationException;
|
||||||
import google.registry.model.domain.DomainCommand;
|
import google.registry.model.domain.DomainCommand;
|
||||||
import google.registry.model.domain.token.AllocationToken;
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
|
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||||
import google.registry.model.domain.token.AllocationToken.TokenType;
|
import google.registry.model.domain.token.AllocationToken.TokenType;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
@ -46,16 +48,19 @@ public class AllocationTokenFlowUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies that a given allocation token string is valid.
|
* Loads an allocation token given a string and verifies that the token is valid for the domain
|
||||||
|
* create request.
|
||||||
*
|
*
|
||||||
* @return the loaded {@link AllocationToken} for that string.
|
* @return the loaded {@link AllocationToken} for that string.
|
||||||
* @throws InvalidAllocationTokenException if the token doesn't exist.
|
* @throws EppException if the token doesn't exist, is already redeemed, or is otherwise invalid
|
||||||
|
* for this request.
|
||||||
*/
|
*/
|
||||||
public AllocationToken loadAndVerifyToken(
|
public AllocationToken loadTokenAndValidateDomainCreate(
|
||||||
DomainCommand.Create command, String token, Registry registry, String clientId, DateTime now)
|
DomainCommand.Create command, String token, Registry registry, String clientId, DateTime now)
|
||||||
throws EppException {
|
throws EppException {
|
||||||
AllocationToken tokenEntity = loadToken(token);
|
AllocationToken tokenEntity = loadToken(token);
|
||||||
return tokenCustomLogic.verifyToken(command, tokenEntity, registry, clientId, now);
|
validateToken(tokenEntity, clientId, registry.getTldStr(), now);
|
||||||
|
return tokenCustomLogic.validateToken(command, tokenEntity, registry, clientId, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,24 +72,38 @@ public class AllocationTokenFlowUtils {
|
||||||
*/
|
*/
|
||||||
public AllocationTokenDomainCheckResults checkDomainsWithToken(
|
public AllocationTokenDomainCheckResults checkDomainsWithToken(
|
||||||
List<InternetDomainName> domainNames, String token, String clientId, DateTime now) {
|
List<InternetDomainName> domainNames, String token, String clientId, DateTime now) {
|
||||||
|
// If the token is completely invalid, return the error message for all domain names
|
||||||
|
AllocationToken tokenEntity;
|
||||||
try {
|
try {
|
||||||
AllocationToken tokenEntity = loadToken(token);
|
tokenEntity = loadToken(token);
|
||||||
// Only call custom logic if there wasn't a global allocation token error that applies to all
|
|
||||||
// check results. The custom logic can only add errors, not override existing errors.
|
|
||||||
return AllocationTokenDomainCheckResults.create(
|
|
||||||
Optional.of(tokenEntity),
|
|
||||||
tokenCustomLogic.checkDomainsWithToken(
|
|
||||||
ImmutableList.copyOf(domainNames), tokenEntity, clientId, now));
|
|
||||||
} catch (EppException e) {
|
} catch (EppException e) {
|
||||||
return AllocationTokenDomainCheckResults.create(
|
return AllocationTokenDomainCheckResults.create(
|
||||||
Optional.empty(),
|
Optional.empty(),
|
||||||
ImmutableMap.copyOf(Maps.toMap(domainNames, ignored -> e.getMessage())));
|
ImmutableMap.copyOf(Maps.toMap(domainNames, ignored -> e.getMessage())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the token is only invalid for some domain names (e.g. an invalid TLD), include those error
|
||||||
|
// results for only those domain names
|
||||||
|
ImmutableList.Builder<InternetDomainName> validDomainNames = new ImmutableList.Builder<>();
|
||||||
|
ImmutableMap.Builder<InternetDomainName, String> resultsBuilder = new ImmutableMap.Builder<>();
|
||||||
|
for (InternetDomainName domainName : domainNames) {
|
||||||
|
try {
|
||||||
|
validateToken(tokenEntity, clientId, domainName.parent().toString(), now);
|
||||||
|
validDomainNames.add(domainName);
|
||||||
|
} catch (EppException e) {
|
||||||
|
resultsBuilder.put(domainName, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For all valid domain names, run the custom logic and include the results
|
||||||
|
resultsBuilder.putAll(
|
||||||
|
tokenCustomLogic.checkDomainsWithToken(
|
||||||
|
validDomainNames.build(), tokenEntity, clientId, now));
|
||||||
|
return AllocationTokenDomainCheckResults.create(
|
||||||
|
Optional.of(tokenEntity), resultsBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Redeems a SINGLE_USE {@link AllocationToken}, returning the redeemed copy. */
|
||||||
* Redeems a SINGLE_USE {@link AllocationToken}, returning the redeemed copy.
|
|
||||||
*/
|
|
||||||
public AllocationToken redeemToken(
|
public AllocationToken redeemToken(
|
||||||
AllocationToken token, Key<HistoryEntry> redemptionHistoryEntry) {
|
AllocationToken token, Key<HistoryEntry> redemptionHistoryEntry) {
|
||||||
checkArgument(
|
checkArgument(
|
||||||
|
@ -93,6 +112,30 @@ public class AllocationTokenFlowUtils {
|
||||||
return token.asBuilder().setRedemptionHistoryEntry(redemptionHistoryEntry).build();
|
return token.asBuilder().setRedemptionHistoryEntry(redemptionHistoryEntry).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @throws EppException if the token is invalid in any way
|
||||||
|
*/
|
||||||
|
private void validateToken(AllocationToken token, String clientId, String tld, DateTime now)
|
||||||
|
throws EppException {
|
||||||
|
if (!token.getAllowedClientIds().isEmpty() && !token.getAllowedClientIds().contains(clientId)) {
|
||||||
|
throw new AllocationTokenNotValidForRegistrarException();
|
||||||
|
}
|
||||||
|
if (!token.getAllowedTlds().isEmpty() && !token.getAllowedTlds().contains(tld)) {
|
||||||
|
throw new AllocationTokenNotValidForTldException();
|
||||||
|
}
|
||||||
|
// 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Loads a given token and validates that it is not redeemed */
|
||||||
private AllocationToken loadToken(String token) throws EppException {
|
private AllocationToken loadToken(String token) throws EppException {
|
||||||
AllocationToken tokenEntity = ofy().load().key(Key.create(AllocationToken.class, token)).now();
|
AllocationToken tokenEntity = ofy().load().key(Key.create(AllocationToken.class, token)).now();
|
||||||
if (tokenEntity == null) {
|
if (tokenEntity == null) {
|
||||||
|
@ -104,6 +147,31 @@ public class AllocationTokenFlowUtils {
|
||||||
return tokenEntity;
|
return tokenEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: exception messages should be <= 32 characters long for domain check results
|
||||||
|
|
||||||
|
/** The allocation token is not currently valid. */
|
||||||
|
public static class AllocationTokenNotInPromotionException
|
||||||
|
extends StatusProhibitsOperationException {
|
||||||
|
public AllocationTokenNotInPromotionException() {
|
||||||
|
super("Alloc token not in promo period");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** The allocation token is not valid for this TLD. */
|
||||||
|
public static class AllocationTokenNotValidForTldException
|
||||||
|
extends AssociationProhibitsOperationException {
|
||||||
|
public AllocationTokenNotValidForTldException() {
|
||||||
|
super("Alloc token invalid for TLD");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The allocation token is not valid for this registrar. */
|
||||||
|
public static class AllocationTokenNotValidForRegistrarException
|
||||||
|
extends AssociationProhibitsOperationException {
|
||||||
|
public AllocationTokenNotValidForRegistrarException() {
|
||||||
|
super("Alloc token invalid for client");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** The allocation token was already redeemed. */
|
/** The allocation token was already redeemed. */
|
||||||
public static class AlreadyRedeemedAllocationTokenException
|
public static class AlreadyRedeemedAllocationTokenException
|
||||||
extends AssociationProhibitsOperationException {
|
extends AssociationProhibitsOperationException {
|
||||||
|
|
|
@ -186,6 +186,7 @@ public class DomainCheckFlowTest
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_allocationTokenPromotion() throws Exception {
|
public void testSuccess_allocationTokenPromotion() throws Exception {
|
||||||
|
createTld("example");
|
||||||
persistResource(
|
persistResource(
|
||||||
new AllocationToken.Builder()
|
new AllocationToken.Builder()
|
||||||
.setToken("abc123")
|
.setToken("abc123")
|
||||||
|
@ -194,14 +195,82 @@ public class DomainCheckFlowTest
|
||||||
.setTokenStatusTransitions(
|
.setTokenStatusTransitions(
|
||||||
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||||
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
||||||
.put(clock.nowUtc().plusMillis(1), TokenStatus.VALID)
|
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
|
||||||
.put(clock.nowUtc().plusSeconds(1), TokenStatus.ENDED)
|
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
|
||||||
.build())
|
.build())
|
||||||
.build());
|
.build());
|
||||||
setEppInput("domain_check_allocationtoken_fee.xml");
|
setEppInput("domain_check_allocationtoken_fee.xml");
|
||||||
runFlowAssertResponse(loadFile("domain_check_allocationtoken_fee_response.xml"));
|
runFlowAssertResponse(loadFile("domain_check_allocationtoken_fee_response.xml"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_promotionNotActive() throws Exception {
|
||||||
|
createTld("example");
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken.Builder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(UNLIMITED_USE)
|
||||||
|
.setDiscountFraction(0.5)
|
||||||
|
.setTokenStatusTransitions(
|
||||||
|
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||||
|
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
||||||
|
.put(clock.nowUtc().plusDays(1), TokenStatus.VALID)
|
||||||
|
.put(clock.nowUtc().plusDays(60), TokenStatus.ENDED)
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
setEppInput("domain_check_allocationtoken_fee.xml");
|
||||||
|
doCheckTest(
|
||||||
|
create(false, "example1.tld", "Alloc token not in promo period"),
|
||||||
|
create(false, "example2.example", "Alloc token not in promo period"),
|
||||||
|
create(false, "reserved.tld", "Reserved"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_promoTokenNotValidForTld() throws Exception {
|
||||||
|
createTld("example");
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken.Builder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(UNLIMITED_USE)
|
||||||
|
.setDiscountFraction(0.5)
|
||||||
|
.setAllowedTlds(ImmutableSet.of("example"))
|
||||||
|
.setTokenStatusTransitions(
|
||||||
|
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||||
|
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
||||||
|
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
|
||||||
|
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
setEppInput("domain_check_allocationtoken_fee.xml");
|
||||||
|
doCheckTest(
|
||||||
|
create(false, "example1.tld", "Alloc token invalid for TLD"),
|
||||||
|
create(true, "example2.example", null),
|
||||||
|
create(false, "reserved.tld", "Reserved"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_promoTokenNotValidForRegistrar() throws Exception {
|
||||||
|
createTld("example");
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken.Builder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(UNLIMITED_USE)
|
||||||
|
.setDiscountFraction(0.5)
|
||||||
|
.setAllowedClientIds(ImmutableSet.of("someOtherClient"))
|
||||||
|
.setTokenStatusTransitions(
|
||||||
|
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||||
|
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
||||||
|
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
|
||||||
|
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
setEppInput("domain_check_allocationtoken_fee.xml");
|
||||||
|
doCheckTest(
|
||||||
|
create(false, "example1.tld", "Alloc token invalid for client"),
|
||||||
|
create(false, "example2.example", "Alloc token invalid for client"),
|
||||||
|
create(false, "reserved.tld", "Reserved"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_oneReservedInSunrise() throws Exception {
|
public void testSuccess_oneReservedInSunrise() throws Exception {
|
||||||
createTld("tld", START_DATE_SUNRISE);
|
createTld("tld", START_DATE_SUNRISE);
|
||||||
|
|
|
@ -128,6 +128,9 @@ import google.registry.flows.domain.DomainFlowUtils.TrailingDashException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.UnexpectedClaimsNoticeException;
|
import google.registry.flows.domain.DomainFlowUtils.UnexpectedClaimsNoticeException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException;
|
import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException;
|
||||||
import google.registry.flows.domain.DomainFlowUtils.UnsupportedMarkTypeException;
|
import google.registry.flows.domain.DomainFlowUtils.UnsupportedMarkTypeException;
|
||||||
|
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException;
|
||||||
|
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException;
|
||||||
|
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException;
|
||||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException;
|
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AlreadyRedeemedAllocationTokenException;
|
||||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException;
|
import google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException;
|
||||||
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
|
import google.registry.flows.exceptions.OnlyToolCanPassMetadataException;
|
||||||
|
@ -472,7 +475,16 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
||||||
persistContactsAndHosts();
|
persistContactsAndHosts();
|
||||||
allocationToken =
|
allocationToken =
|
||||||
persistResource(
|
persistResource(
|
||||||
new AllocationToken.Builder().setTokenType(UNLIMITED_USE).setToken("abc123").build());
|
new AllocationToken.Builder()
|
||||||
|
.setTokenType(UNLIMITED_USE)
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenStatusTransitions(
|
||||||
|
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||||
|
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
||||||
|
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
|
||||||
|
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
clock.advanceOneMilli();
|
clock.advanceOneMilli();
|
||||||
runFlow();
|
runFlow();
|
||||||
assertSuccessfulCreate("tld", ImmutableSet.of(), allocationToken);
|
assertSuccessfulCreate("tld", ImmutableSet.of(), allocationToken);
|
||||||
|
@ -1156,6 +1168,71 @@ public class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow,
|
||||||
.isEqualTo("A nonzero discount code cannot be applied to premium domains");
|
.isEqualTo("A nonzero discount code cannot be applied to premium domains");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_promotionNotActive() {
|
||||||
|
persistContactsAndHosts();
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken.Builder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(TokenType.UNLIMITED_USE)
|
||||||
|
.setDiscountFraction(0.5)
|
||||||
|
.setTokenStatusTransitions(
|
||||||
|
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||||
|
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
||||||
|
.put(clock.nowUtc().plusDays(1), TokenStatus.VALID)
|
||||||
|
.put(clock.nowUtc().plusDays(60), TokenStatus.ENDED)
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld"));
|
||||||
|
assertAboutEppExceptions()
|
||||||
|
.that(assertThrows(AllocationTokenNotInPromotionException.class, this::runFlow))
|
||||||
|
.marshalsToXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_promoTokenNotValidForTld() {
|
||||||
|
persistContactsAndHosts();
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken.Builder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(TokenType.UNLIMITED_USE)
|
||||||
|
.setAllowedTlds(ImmutableSet.of("example"))
|
||||||
|
.setDiscountFraction(0.5)
|
||||||
|
.setTokenStatusTransitions(
|
||||||
|
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||||
|
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
||||||
|
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
|
||||||
|
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld"));
|
||||||
|
assertAboutEppExceptions()
|
||||||
|
.that(assertThrows(AllocationTokenNotValidForTldException.class, this::runFlow))
|
||||||
|
.marshalsToXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_promoTokenNotValidForRegistrar() {
|
||||||
|
persistContactsAndHosts();
|
||||||
|
persistResource(
|
||||||
|
new AllocationToken.Builder()
|
||||||
|
.setToken("abc123")
|
||||||
|
.setTokenType(TokenType.UNLIMITED_USE)
|
||||||
|
.setAllowedClientIds(ImmutableSet.of("someClientId"))
|
||||||
|
.setDiscountFraction(0.5)
|
||||||
|
.setTokenStatusTransitions(
|
||||||
|
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||||
|
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
|
||||||
|
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
|
||||||
|
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
setEppInput("domain_create_allocationtoken.xml", ImmutableMap.of("DOMAIN", "example.tld"));
|
||||||
|
assertAboutEppExceptions()
|
||||||
|
.that(assertThrows(AllocationTokenNotValidForRegistrarException.class, this::runFlow))
|
||||||
|
.marshalsToXml();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_superuserReserved() throws Exception {
|
public void testSuccess_superuserReserved() throws Exception {
|
||||||
setEppInput("domain_create_reserved.xml");
|
setEppInput("domain_create_reserved.xml");
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<domain:check
|
<domain:check
|
||||||
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
||||||
<domain:name>example1.tld</domain:name>
|
<domain:name>example1.tld</domain:name>
|
||||||
<domain:name>example2.tld</domain:name>
|
<domain:name>example2.example</domain:name>
|
||||||
<domain:name>reserved.tld</domain:name>
|
<domain:name>reserved.tld</domain:name>
|
||||||
</domain:check>
|
</domain:check>
|
||||||
</check>
|
</check>
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<fee:period unit="y">1</fee:period>
|
<fee:period unit="y">1</fee:period>
|
||||||
</fee:domain>
|
</fee:domain>
|
||||||
<fee:domain>
|
<fee:domain>
|
||||||
<fee:name>example2.tld</fee:name>
|
<fee:name>example2.example</fee:name>
|
||||||
<fee:currency>USD</fee:currency>
|
<fee:currency>USD</fee:currency>
|
||||||
<fee:command>create</fee:command>
|
<fee:command>create</fee:command>
|
||||||
<fee:period unit="y">1</fee:period>
|
<fee:period unit="y">1</fee:period>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<domain:name avail="true">example1.tld</domain:name>
|
<domain:name avail="true">example1.tld</domain:name>
|
||||||
</domain:cd>
|
</domain:cd>
|
||||||
<domain:cd>
|
<domain:cd>
|
||||||
<domain:name avail="true">example2.tld</domain:name>
|
<domain:name avail="true">example2.example</domain:name>
|
||||||
</domain:cd>
|
</domain:cd>
|
||||||
<domain:cd>
|
<domain:cd>
|
||||||
<domain:name avail="false">reserved.tld</domain:name>
|
<domain:name avail="false">reserved.tld</domain:name>
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
<extension>
|
<extension>
|
||||||
<fee:chkData>
|
<fee:chkData>
|
||||||
<fee:cd>
|
<fee:cd>
|
||||||
<fee:name>example2.tld</fee:name>
|
<fee:name>example2.example</fee:name>
|
||||||
<fee:currency>USD</fee:currency>
|
<fee:currency>USD</fee:currency>
|
||||||
<fee:command>create</fee:command>
|
<fee:command>create</fee:command>
|
||||||
<fee:period unit="y">1</fee:period>
|
<fee:period unit="y">1</fee:period>
|
||||||
|
|
|
@ -15,23 +15,35 @@
|
||||||
package google.registry.flows.domain.token;
|
package google.registry.flows.domain.token;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.domain.token.AllocationToken.TokenStatus.CANCELLED;
|
||||||
|
import static google.registry.model.domain.token.AllocationToken.TokenStatus.ENDED;
|
||||||
|
import static google.registry.model.domain.token.AllocationToken.TokenStatus.NOT_STARTED;
|
||||||
|
import static google.registry.model.domain.token.AllocationToken.TokenStatus.VALID;
|
||||||
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
|
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
|
||||||
|
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
|
||||||
import static google.registry.testing.DatastoreHelper.createTld;
|
import static google.registry.testing.DatastoreHelper.createTld;
|
||||||
import static google.registry.testing.DatastoreHelper.persistResource;
|
import static google.registry.testing.DatastoreHelper.persistResource;
|
||||||
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
|
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
|
||||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||||
|
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||||
import static org.joda.time.DateTimeZone.UTC;
|
import static org.joda.time.DateTimeZone.UTC;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSortedMap;
|
||||||
import com.google.common.net.InternetDomainName;
|
import com.google.common.net.InternetDomainName;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
|
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotInPromotionException;
|
||||||
|
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForRegistrarException;
|
||||||
|
import google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForTldException;
|
||||||
import google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException;
|
import google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException;
|
||||||
import google.registry.model.domain.DomainCommand;
|
import google.registry.model.domain.DomainCommand;
|
||||||
import google.registry.model.domain.token.AllocationToken;
|
import google.registry.model.domain.token.AllocationToken;
|
||||||
|
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
|
@ -48,6 +60,9 @@ import org.junit.runners.JUnit4;
|
||||||
@RunWith(JUnit4.class)
|
@RunWith(JUnit4.class)
|
||||||
public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
|
public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
|
||||||
|
|
||||||
|
private final AllocationTokenFlowUtils flowUtils =
|
||||||
|
new AllocationTokenFlowUtils(new AllocationTokenCustomLogic());
|
||||||
|
|
||||||
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
|
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -56,14 +71,12 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_verifyToken_successfullyVerifiesValidToken() throws Exception {
|
public void test_validateToken_successfullyVerifiesValidToken() throws Exception {
|
||||||
AllocationToken token =
|
AllocationToken token =
|
||||||
persistResource(
|
persistResource(
|
||||||
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
||||||
AllocationTokenFlowUtils flowUtils =
|
|
||||||
new AllocationTokenFlowUtils(new AllocationTokenCustomLogic());
|
|
||||||
assertThat(
|
assertThat(
|
||||||
flowUtils.loadAndVerifyToken(
|
flowUtils.loadTokenAndValidateDomainCreate(
|
||||||
createCommand("blah.tld"),
|
createCommand("blah.tld"),
|
||||||
"tokeN",
|
"tokeN",
|
||||||
Registry.get("tld"),
|
Registry.get("tld"),
|
||||||
|
@ -73,33 +86,21 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_verifyToken_failsOnNonexistentToken() {
|
public void test_validateToken_failsOnNonexistentToken() {
|
||||||
AllocationTokenFlowUtils flowUtils =
|
assertValidateThrowsEppException(InvalidAllocationTokenException.class);
|
||||||
new AllocationTokenFlowUtils(new AllocationTokenCustomLogic());
|
|
||||||
EppException thrown =
|
|
||||||
assertThrows(
|
|
||||||
InvalidAllocationTokenException.class,
|
|
||||||
() ->
|
|
||||||
flowUtils.loadAndVerifyToken(
|
|
||||||
createCommand("blah.tld"),
|
|
||||||
"tokeN",
|
|
||||||
Registry.get("tld"),
|
|
||||||
"TheRegistrar",
|
|
||||||
DateTime.now(UTC)));
|
|
||||||
assertAboutEppExceptions().that(thrown).marshalsToXml();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_verifyToken_callsCustomLogic() {
|
public void test_validateToken_callsCustomLogic() {
|
||||||
|
AllocationTokenFlowUtils failingFlowUtils =
|
||||||
|
new AllocationTokenFlowUtils(new FailingAllocationTokenCustomLogic());
|
||||||
persistResource(
|
persistResource(
|
||||||
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
||||||
AllocationTokenFlowUtils flowUtils =
|
|
||||||
new AllocationTokenFlowUtils(new FailingAllocationTokenCustomLogic());
|
|
||||||
Exception thrown =
|
Exception thrown =
|
||||||
assertThrows(
|
assertThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() ->
|
() ->
|
||||||
flowUtils.loadAndVerifyToken(
|
failingFlowUtils.loadTokenAndValidateDomainCreate(
|
||||||
createCommand("blah.tld"),
|
createCommand("blah.tld"),
|
||||||
"tokeN",
|
"tokeN",
|
||||||
Registry.get("tld"),
|
Registry.get("tld"),
|
||||||
|
@ -108,12 +109,55 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
|
||||||
assertThat(thrown).hasMessageThat().isEqualTo("failed for tests");
|
assertThat(thrown).hasMessageThat().isEqualTo("failed for tests");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_validateToken_invalidForClientId() {
|
||||||
|
persistResource(
|
||||||
|
createOneMonthPromoTokenBuilder(DateTime.now(UTC).minusDays(1))
|
||||||
|
.setAllowedClientIds(ImmutableSet.of("NewRegistrar"))
|
||||||
|
.build());
|
||||||
|
assertValidateThrowsEppException(AllocationTokenNotValidForRegistrarException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_validateToken_invalidForTld() {
|
||||||
|
persistResource(
|
||||||
|
createOneMonthPromoTokenBuilder(DateTime.now(UTC).minusDays(1))
|
||||||
|
.setAllowedTlds(ImmutableSet.of("nottld"))
|
||||||
|
.build());
|
||||||
|
assertValidateThrowsEppException(AllocationTokenNotValidForTldException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_validateToken_beforePromoStart() {
|
||||||
|
persistResource(createOneMonthPromoTokenBuilder(DateTime.now(UTC).plusDays(1)).build());
|
||||||
|
assertValidateThrowsEppException(AllocationTokenNotInPromotionException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_validateToken_afterPromoEnd() {
|
||||||
|
persistResource(createOneMonthPromoTokenBuilder(DateTime.now(UTC).minusMonths(2)).build());
|
||||||
|
assertValidateThrowsEppException(AllocationTokenNotInPromotionException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_validateToken_promoCancelled() {
|
||||||
|
// the promo would be valid but it was cancelled 12 hours ago
|
||||||
|
persistResource(
|
||||||
|
createOneMonthPromoTokenBuilder(DateTime.now(UTC).minusDays(1))
|
||||||
|
.setTokenStatusTransitions(
|
||||||
|
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||||
|
.put(START_OF_TIME, NOT_STARTED)
|
||||||
|
.put(DateTime.now(UTC).minusMonths(1), VALID)
|
||||||
|
.put(DateTime.now(UTC).minusHours(12), CANCELLED)
|
||||||
|
.build())
|
||||||
|
.build());
|
||||||
|
assertValidateThrowsEppException(AllocationTokenNotInPromotionException.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_checkDomainsWithToken_successfullyVerifiesValidToken() {
|
public void test_checkDomainsWithToken_successfullyVerifiesValidToken() {
|
||||||
persistResource(
|
persistResource(
|
||||||
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
||||||
AllocationTokenFlowUtils flowUtils =
|
|
||||||
new AllocationTokenFlowUtils(new AllocationTokenCustomLogic());
|
|
||||||
assertThat(
|
assertThat(
|
||||||
flowUtils
|
flowUtils
|
||||||
.checkDomainsWithToken(
|
.checkDomainsWithToken(
|
||||||
|
@ -137,8 +181,6 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
|
||||||
.setTokenType(SINGLE_USE)
|
.setTokenType(SINGLE_USE)
|
||||||
.setRedemptionHistoryEntry(Key.create(HistoryEntry.class, 101L))
|
.setRedemptionHistoryEntry(Key.create(HistoryEntry.class, 101L))
|
||||||
.build());
|
.build());
|
||||||
AllocationTokenFlowUtils flowUtils =
|
|
||||||
new AllocationTokenFlowUtils(new AllocationTokenCustomLogic());
|
|
||||||
assertThat(
|
assertThat(
|
||||||
flowUtils
|
flowUtils
|
||||||
.checkDomainsWithToken(
|
.checkDomainsWithToken(
|
||||||
|
@ -161,13 +203,13 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
|
||||||
public void test_checkDomainsWithToken_callsCustomLogic() {
|
public void test_checkDomainsWithToken_callsCustomLogic() {
|
||||||
persistResource(
|
persistResource(
|
||||||
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
||||||
AllocationTokenFlowUtils flowUtils =
|
AllocationTokenFlowUtils failingFlowUtils =
|
||||||
new AllocationTokenFlowUtils(new FailingAllocationTokenCustomLogic());
|
new AllocationTokenFlowUtils(new FailingAllocationTokenCustomLogic());
|
||||||
Exception thrown =
|
Exception thrown =
|
||||||
assertThrows(
|
assertThrows(
|
||||||
IllegalStateException.class,
|
IllegalStateException.class,
|
||||||
() ->
|
() ->
|
||||||
flowUtils.checkDomainsWithToken(
|
failingFlowUtils.checkDomainsWithToken(
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
InternetDomainName.from("blah.tld"), InternetDomainName.from("blah2.tld")),
|
InternetDomainName.from("blah.tld"), InternetDomainName.from("blah2.tld")),
|
||||||
"tokeN",
|
"tokeN",
|
||||||
|
@ -180,10 +222,10 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
|
||||||
public void test_checkDomainsWithToken_resultsFromCustomLogicAreIntegrated() {
|
public void test_checkDomainsWithToken_resultsFromCustomLogicAreIntegrated() {
|
||||||
persistResource(
|
persistResource(
|
||||||
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
new AllocationToken.Builder().setToken("tokeN").setTokenType(SINGLE_USE).build());
|
||||||
AllocationTokenFlowUtils flowUtils =
|
AllocationTokenFlowUtils customResultFlowUtils =
|
||||||
new AllocationTokenFlowUtils(new CustomResultAllocationTokenCustomLogic());
|
new AllocationTokenFlowUtils(new CustomResultAllocationTokenCustomLogic());
|
||||||
assertThat(
|
assertThat(
|
||||||
flowUtils
|
customResultFlowUtils
|
||||||
.checkDomainsWithToken(
|
.checkDomainsWithToken(
|
||||||
ImmutableList.of(
|
ImmutableList.of(
|
||||||
InternetDomainName.from("blah.tld"), InternetDomainName.from("bunny.tld")),
|
InternetDomainName.from("blah.tld"), InternetDomainName.from("bunny.tld")),
|
||||||
|
@ -200,17 +242,44 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
|
||||||
.inOrder();
|
.inOrder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertValidateThrowsEppException(Class<? extends EppException> clazz) {
|
||||||
|
assertAboutEppExceptions()
|
||||||
|
.that(
|
||||||
|
assertThrows(
|
||||||
|
clazz,
|
||||||
|
() ->
|
||||||
|
flowUtils.loadTokenAndValidateDomainCreate(
|
||||||
|
createCommand("blah.tld"),
|
||||||
|
"tokeN",
|
||||||
|
Registry.get("tld"),
|
||||||
|
"TheRegistrar",
|
||||||
|
DateTime.now(UTC))))
|
||||||
|
.marshalsToXml();
|
||||||
|
}
|
||||||
|
|
||||||
private static DomainCommand.Create createCommand(String domainName) {
|
private static DomainCommand.Create createCommand(String domainName) {
|
||||||
DomainCommand.Create command = mock(DomainCommand.Create.class);
|
DomainCommand.Create command = mock(DomainCommand.Create.class);
|
||||||
when(command.getFullyQualifiedDomainName()).thenReturn(domainName);
|
when(command.getFullyQualifiedDomainName()).thenReturn(domainName);
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static AllocationToken.Builder createOneMonthPromoTokenBuilder(DateTime promoStart) {
|
||||||
|
return new AllocationToken.Builder()
|
||||||
|
.setToken("tokeN")
|
||||||
|
.setTokenType(UNLIMITED_USE)
|
||||||
|
.setTokenStatusTransitions(
|
||||||
|
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
|
||||||
|
.put(START_OF_TIME, NOT_STARTED)
|
||||||
|
.put(promoStart, VALID)
|
||||||
|
.put(promoStart.plusMonths(1), ENDED)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
/** An {@link AllocationTokenCustomLogic} class that throws exceptions on every method. */
|
/** An {@link AllocationTokenCustomLogic} class that throws exceptions on every method. */
|
||||||
private static class FailingAllocationTokenCustomLogic extends AllocationTokenCustomLogic {
|
private static class FailingAllocationTokenCustomLogic extends AllocationTokenCustomLogic {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AllocationToken verifyToken(
|
public AllocationToken validateToken(
|
||||||
DomainCommand.Create command,
|
DomainCommand.Create command,
|
||||||
AllocationToken token,
|
AllocationToken token,
|
||||||
Registry registry,
|
Registry registry,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue