From a6d8509dcf14632015c69e6dde081ff7d7dbfc8c Mon Sep 17 00:00:00 2001 From: gbrodman Date: Thu, 23 Jan 2020 11:45:07 -0500 Subject: [PATCH] Allow checking reserved domains with a valid token (#451) * Add test for checking reserved domain with token * Allow domain checks with a valid token if the domain isn't fully blocked * Check specifically for specific-use or anchor reservations * Add test for LRP in-time token --- .../flows/domain/DomainCheckFlow.java | 22 ++-- .../flows/domain/DomainCheckFlowTest.java | 109 ++++++++++++++++-- .../domain/domain_check_allocationtoken.xml | 1 + .../domain_check_anchor_allocationtoken.xml | 18 +++ 4 files changed, 135 insertions(+), 15 deletions(-) create mode 100644 core/src/test/resources/google/registry/flows/domain/domain_check_anchor_allocationtoken.xml diff --git a/core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java b/core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java index 1aa3b1ff0..c12116d2f 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainCheckFlow.java @@ -20,7 +20,9 @@ import static google.registry.flows.ResourceFlowUtils.verifyTargetIdCount; import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; import static google.registry.flows.domain.DomainFlowUtils.getReservationTypes; import static google.registry.flows.domain.DomainFlowUtils.handleFeeRequest; +import static google.registry.flows.domain.DomainFlowUtils.isAnchorTenant; import static google.registry.flows.domain.DomainFlowUtils.isReserved; +import static google.registry.flows.domain.DomainFlowUtils.isValidReservedCreate; import static google.registry.flows.domain.DomainFlowUtils.validateDomainName; import static google.registry.flows.domain.DomainFlowUtils.validateDomainNameWithIdnTables; import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPredelegation; @@ -168,17 +170,18 @@ public final class DomainCheckFlow implements Flow { tokenDomainCheckResults .map(AllocationTokenDomainCheckResults::domainCheckResults) .orElse(ImmutableMap.of()); + Optional allocationToken = + tokenDomainCheckResults.flatMap(AllocationTokenDomainCheckResults::token); for (String targetId : targetIds) { Optional message = getMessageForCheck( domainNames.get(targetId), existingIds, domainCheckResults, - tldStates); + tldStates, + allocationToken); checks.add(DomainCheck.create(!message.isPresent(), targetId, message.orElse(null))); } - Optional allocationToken = - tokenDomainCheckResults.flatMap(AllocationTokenDomainCheckResults::token); BeforeResponseReturnData responseData = flowCustomLogic.beforeResponse( BeforeResponseParameters.newBuilder() @@ -196,15 +199,20 @@ public final class DomainCheckFlow implements Flow { InternetDomainName domainName, Set existingIds, ImmutableMap tokenCheckResults, - Map tldStates) { + Map tldStates, + Optional allocationToken) { if (existingIds.contains(domainName.toString())) { return Optional.of("In use"); } TldState tldState = tldStates.get(domainName.parent().toString()); if (isReserved(domainName, START_DATE_SUNRISE.equals(tldState))) { - ImmutableSet reservationTypes = getReservationTypes(domainName); - if (!reservationTypes.isEmpty()) { - return Optional.of(getTypeOfHighestSeverity(reservationTypes).getMessageForCheck()); + if (!isValidReservedCreate(domainName, allocationToken) + && !isAnchorTenant(domainName, allocationToken, Optional.empty())) { + ImmutableSet reservationTypes = getReservationTypes(domainName); + if (!reservationTypes.isEmpty()) { + ReservationType highestSeverityType = getTypeOfHighestSeverity(reservationTypes); + return Optional.of(highestSeverityType.getMessageForCheck()); + } } } return Optional.ofNullable(emptyToNull(tokenCheckResults.get(domainName))); diff --git a/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java index 85e72529f..15df3d38d 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java @@ -77,8 +77,7 @@ import org.junit.Ignore; import org.junit.Test; /** Unit tests for {@link DomainCheckFlow}. */ -public class DomainCheckFlowTest - extends ResourceCheckFlowTestCase { +public class DomainCheckFlowTest extends ResourceCheckFlowTestCase { public DomainCheckFlowTest() { setEppInput("domain_check_one_tld.xml"); @@ -93,11 +92,12 @@ public class DomainCheckFlowTest .build()); return persistReservedList( "tld-reserved", - "reserved,FULLY_BLOCKED", - "anchor,RESERVED_FOR_ANCHOR_TENANT", "allowedinsunrise,ALLOWED_IN_SUNRISE", + "anchor,RESERVED_FOR_ANCHOR_TENANT", "collision,NAME_COLLISION", - "premiumcollision,NAME_COLLISION"); + "premiumcollision,NAME_COLLISION", + "reserved,FULLY_BLOCKED", + "specificuse,RESERVED_FOR_SPECIFIC_USE"); } @Before @@ -140,7 +140,8 @@ public class DomainCheckFlowTest doCheckTest( create(false, "example1.tld", "In use"), create(false, "example2.tld", "The allocation token is invalid"), - create(false, "reserved.tld", "Reserved")); + create(false, "reserved.tld", "Reserved"), + create(false, "specificuse.tld", "Reserved")); } @Test @@ -152,7 +153,8 @@ public class DomainCheckFlowTest doCheckTest( create(false, "example1.tld", "In use"), create(true, "example2.tld", null), - create(false, "reserved.tld", "Reserved")); + create(false, "reserved.tld", "Reserved"), + create(false, "specificuse.tld", "Reserved")); } @Test @@ -168,7 +170,86 @@ public class DomainCheckFlowTest doCheckTest( create(false, "example1.tld", "In use"), create(false, "example2.tld", "Alloc token was already redeemed"), - create(false, "reserved.tld", "Reserved")); + create(false, "reserved.tld", "Reserved"), + create(false, "specificuse.tld", "Reserved")); + } + + @Test + public void testSuccess_oneExists_allocationTokenForReservedDomain() throws Exception { + setEppInput("domain_check_allocationtoken.xml"); + persistActiveDomain("example1.tld"); + persistResource( + new AllocationToken.Builder() + .setDomainName("specificuse.tld") + .setToken("abc123") + .setTokenType(SINGLE_USE) + .build()); + doCheckTest( + create(false, "example1.tld", "In use"), + create(true, "example2.tld", null), + create(false, "reserved.tld", "Reserved"), + create(true, "specificuse.tld", null)); + } + + @Test + public void testSuccess_oneExists_allocationTokenForWrongDomain() throws Exception { + setEppInput("domain_check_allocationtoken.xml"); + persistActiveDomain("example1.tld"); + persistResource( + new AllocationToken.Builder() + .setDomainName("someotherdomain.tld") + .setToken("abc123") + .setTokenType(SINGLE_USE) + .build()); + doCheckTest( + create(false, "example1.tld", "In use"), + create(true, "example2.tld", null), + create(false, "reserved.tld", "Reserved"), + create(false, "specificuse.tld", "Reserved")); + } + + @Test + public void testSuccess_notOutOfDateToken_forSpecificDomain() throws Exception { + setEppInput("domain_check_allocationtoken.xml"); + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(SINGLE_USE) + .setDomainName("specificuse.tld") + .setTokenStatusTransitions( + ImmutableSortedMap.naturalOrder() + .put(START_OF_TIME, TokenStatus.NOT_STARTED) + .put(clock.nowUtc().minusDays(1), TokenStatus.VALID) + .put(clock.nowUtc().plusDays(1), TokenStatus.ENDED) + .build()) + .build()); + doCheckTest( + create(true, "example1.tld", null), + create(true, "example2.tld", null), + create(false, "reserved.tld", "Reserved"), + create(true, "specificuse.tld", null)); + } + + @Test + public void testSuccess_outOfDateToken_forSpecificDomain() throws Exception { + setEppInput("domain_check_allocationtoken.xml"); + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(SINGLE_USE) + .setDomainName("specificuse.tld") + .setTokenStatusTransitions( + ImmutableSortedMap.naturalOrder() + .put(START_OF_TIME, TokenStatus.NOT_STARTED) + .put(clock.nowUtc().minusDays(2), TokenStatus.VALID) + .put(clock.nowUtc().minusDays(1), TokenStatus.ENDED) + .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, "reserved.tld", "Reserved"), + create(false, "specificuse.tld", "Alloc token not in promo period")); } @Test @@ -317,6 +398,18 @@ public class DomainCheckFlowTest doCheckTest(create(false, "anchor.tld", "Reserved")); } + @Test + public void testSuccess_anchorTenantWithToken() throws Exception { + setEppInput("domain_check_anchor_allocationtoken.xml"); + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(SINGLE_USE) + .setDomainName("anchor.tld") + .build()); + doCheckTest(create(true, "anchor.tld", null)); + } + @Test public void testSuccess_multipartTld_oneReserved() throws Exception { createTld("tld.foo"); diff --git a/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken.xml b/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken.xml index 0ef949ce7..80ee08b9a 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_check_allocationtoken.xml @@ -6,6 +6,7 @@ example1.tld example2.tld reserved.tld + specificuse.tld diff --git a/core/src/test/resources/google/registry/flows/domain/domain_check_anchor_allocationtoken.xml b/core/src/test/resources/google/registry/flows/domain/domain_check_anchor_allocationtoken.xml new file mode 100644 index 000000000..fe78247b8 --- /dev/null +++ b/core/src/test/resources/google/registry/flows/domain/domain_check_anchor_allocationtoken.xml @@ -0,0 +1,18 @@ + + + + + anchor.tld + + + + + abc123 + + + ABC-12345 + +