diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java index f968077d8..94bddeea9 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java @@ -44,6 +44,7 @@ import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; import google.registry.flows.annotations.ReportingSpec; +import google.registry.flows.domain.token.AllocationTokenFlowUtils; import google.registry.model.ImmutableObject; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.Flag; @@ -55,7 +56,10 @@ import google.registry.model.domain.DomainHistory.DomainHistoryId; import google.registry.model.domain.GracePeriod; import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.rgp.GracePeriodStatus; +import google.registry.model.domain.token.AllocationToken; +import google.registry.model.domain.token.AllocationTokenExtension; import google.registry.model.eppcommon.AuthInfo; +import google.registry.model.eppinput.EppInput; import google.registry.model.eppoutput.EppResponse; import google.registry.model.poll.PollMessage; import google.registry.model.reporting.DomainTransactionRecord; @@ -85,6 +89,18 @@ import org.joda.time.DateTime; * @error {@link google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException} * @error {@link google.registry.flows.exceptions.NotPendingTransferException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException} + * @error {@link + * google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForDomainException} + * @error {@link + * google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException} + * @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} */ @ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_APPROVE) public final class DomainTransferApproveFlow implements TransactionalFlow { @@ -97,6 +113,8 @@ public final class DomainTransferApproveFlow implements TransactionalFlow { @Inject DomainHistory.Builder historyBuilder; @Inject EppResponse.Builder responseBuilder; @Inject DomainPricingLogic pricingLogic; + @Inject AllocationTokenFlowUtils allocationTokenFlowUtils; + @Inject EppInput eppInput; @Inject DomainTransferApproveFlow() {} @@ -106,11 +124,20 @@ public final class DomainTransferApproveFlow implements TransactionalFlow { */ @Override public EppResponse run() throws EppException { - extensionManager.register(MetadataExtension.class); + extensionManager.register(MetadataExtension.class, AllocationTokenExtension.class); validateRegistrarIsLoggedIn(registrarId); extensionManager.validate(); DateTime now = tm().getTransactionTime(); Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now); + // Currently we do not do anything with this allocation token, but just want it loaded and + // available in this flow in case we use it in the future + Optional allocationToken = + allocationTokenFlowUtils.verifyAllocationTokenIfPresent( + existingDomain, + Registry.get(existingDomain.getTld()), + registrarId, + now, + eppInput.getSingleExtension(AllocationTokenExtension.class)); verifyOptionalAuthInfo(authInfo, existingDomain); verifyHasPendingTransfer(existingDomain); verifyResourceOwnership(registrarId, existingDomain); diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java index 3cbf510cd..ad1ea37c1 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java @@ -47,6 +47,7 @@ import google.registry.flows.FlowModule.Superuser; import google.registry.flows.FlowModule.TargetId; import google.registry.flows.TransactionalFlow; import google.registry.flows.annotations.ReportingSpec; +import google.registry.flows.domain.token.AllocationTokenFlowUtils; import google.registry.flows.exceptions.AlreadyPendingTransferException; import google.registry.flows.exceptions.InvalidTransferPeriodValueException; import google.registry.flows.exceptions.ObjectAlreadySponsoredException; @@ -61,6 +62,8 @@ import google.registry.model.domain.fee.FeeTransferCommandExtension; import google.registry.model.domain.fee.FeeTransformResponseExtension; import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.superuser.DomainTransferRequestSuperuserExtension; +import google.registry.model.domain.token.AllocationToken; +import google.registry.model.domain.token.AllocationTokenExtension; import google.registry.model.eppcommon.AuthInfo; import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.Trid; @@ -117,6 +120,18 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.PremiumNameBlockedException} * @error {@link DomainFlowUtils.RegistrarMustBeActiveForThisOperationException} * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} + * @error {@link + * google.registry.flows.domain.token.AllocationTokenFlowUtils.AllocationTokenNotValidForDomainException} + * @error {@link + * google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException} + * @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} */ @ReportingSpec(ActivityReportField.DOMAIN_TRANSFER_REQUEST) public final class DomainTransferRequestFlow implements TransactionalFlow { @@ -138,6 +153,8 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { @Inject AsyncTaskEnqueuer asyncTaskEnqueuer; @Inject EppResponse.Builder responseBuilder; @Inject DomainPricingLogic pricingLogic; + @Inject AllocationTokenFlowUtils allocationTokenFlowUtils; + @Inject DomainTransferRequestFlow() {} @Override @@ -145,12 +162,22 @@ public final class DomainTransferRequestFlow implements TransactionalFlow { extensionManager.register( DomainTransferRequestSuperuserExtension.class, FeeTransferCommandExtension.class, - MetadataExtension.class); + MetadataExtension.class, + AllocationTokenExtension.class); validateRegistrarIsLoggedIn(gainingClientId); verifyRegistrarIsActive(gainingClientId); extensionManager.validate(); DateTime now = tm().getTransactionTime(); Domain existingDomain = loadAndVerifyExistence(Domain.class, targetId, now); + // Currently we do not do anything with this allocation token, but just want it loaded and + // available in this flow in case we use it in the future + Optional allocationToken = + allocationTokenFlowUtils.verifyAllocationTokenIfPresent( + existingDomain, + Registry.get(existingDomain.getTld()), + gainingClientId, + now, + eppInput.getSingleExtension(AllocationTokenExtension.class)); Optional superuserExtension = eppInput.getSingleExtension(DomainTransferRequestSuperuserExtension.class); Period period = diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java index 5bb01f963..6f3d1eca1 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java @@ -16,6 +16,8 @@ package google.registry.flows.domain; import static com.google.common.collect.MoreCollectors.onlyElement; import static com.google.common.truth.Truth.assertThat; +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.model.reporting.DomainTransactionRecord.TransactionReportField.NET_ADDS_4_YR; import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE; @@ -43,12 +45,19 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; import com.google.common.collect.Ordering; import com.google.common.collect.Streams; +import com.googlecode.objectify.Key; import google.registry.flows.EppException; import google.registry.flows.FlowUtils.NotLoggedInException; import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException; import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; +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; +import google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException; import google.registry.flows.exceptions.NotPendingTransferException; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.OneTime; @@ -63,6 +72,8 @@ import google.registry.model.domain.GracePeriod; import google.registry.model.domain.Period; import google.registry.model.domain.Period.Unit; import google.registry.model.domain.rgp.GracePeriodStatus; +import google.registry.model.domain.token.AllocationToken; +import google.registry.model.domain.token.AllocationToken.TokenStatus; import google.registry.model.eppcommon.AuthInfo.PasswordAuth; import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.Trid; @@ -77,6 +88,7 @@ import google.registry.model.transfer.DomainTransferData; import google.registry.model.transfer.TransferResponse.DomainTransferResponse; import google.registry.model.transfer.TransferStatus; import google.registry.persistence.VKey; +import google.registry.testing.DatabaseHelper; import java.math.BigDecimal; import java.util.Arrays; import java.util.stream.Stream; @@ -775,4 +787,115 @@ class DomainTransferApproveFlowTest domain.getRegistrationExpirationTime()); assertHistoryEntriesDoNotContainTransferBillingEventsOrGracePeriods(); } + + @Test + void testSuccess_allocationToken() throws Exception { + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(SINGLE_USE) + .setDomainName("example.tld") + .build()); + doSuccessfulTest( + "tld", + "domain_transfer_approve_allocation_token.xml", + "domain_transfer_approve_response.xml"); + } + + @Test + void testFailure_invalidAllocationToken() throws Exception { + setEppInput("domain_transfer_approve_allocation_token.xml"); + EppException thrown = assertThrows(InvalidAllocationTokenException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + void testFailure_allocationTokenIsForDifferentName() throws Exception { + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(SINGLE_USE) + .setDomainName("otherdomain.tld") + .build()); + setEppInput("domain_transfer_approve_allocation_token.xml"); + EppException thrown = + assertThrows(AllocationTokenNotValidForDomainException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + void testFailure_allocationTokenNotActive() throws Exception { + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(UNLIMITED_USE) + .setDiscountFraction(0.5) + .setTokenStatusTransitions( + ImmutableSortedMap.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_transfer_approve_allocation_token.xml"); + EppException thrown = assertThrows(AllocationTokenNotInPromotionException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + void testFailure_allocationTokenNotValidForRegistrar() throws Exception { + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(UNLIMITED_USE) + .setAllowedRegistrarIds(ImmutableSet.of("someClientId")) + .setDiscountFraction(0.5) + .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()); + setEppInput("domain_transfer_approve_allocation_token.xml"); + EppException thrown = + assertThrows(AllocationTokenNotValidForRegistrarException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + void testFailure_allocationTokenNotValidForTld() throws Exception { + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(UNLIMITED_USE) + .setAllowedTlds(ImmutableSet.of("example")) + .setDiscountFraction(0.5) + .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()); + setEppInput("domain_transfer_approve_allocation_token.xml"); + EppException thrown = assertThrows(AllocationTokenNotValidForTldException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + void testFailure_allocationTokenAlreadyRedeemed() throws Exception { + Domain domain = DatabaseHelper.newDomain("foo.tld"); + Key historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 505L); + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(SINGLE_USE) + .setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey)) + .build()); + setEppInput("domain_transfer_approve_allocation_token.xml"); + EppException thrown = + assertThrows(AlreadyRedeemedAllocationTokenException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } } diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java index 3790814c3..cb413a5c4 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java @@ -21,6 +21,8 @@ import static com.google.common.truth.Truth8.assertThat; import static google.registry.batch.AsyncTaskEnqueuer.PARAM_REQUESTED_TIME; import static google.registry.batch.AsyncTaskEnqueuer.PARAM_RESOURCE_KEY; import static google.registry.batch.AsyncTaskEnqueuer.QUEUE_ASYNC_ACTIONS; +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.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST; @@ -59,6 +61,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.collect.Streams; +import com.googlecode.objectify.Key; import google.registry.batch.ResaveEntityAction; import google.registry.flows.EppException; import google.registry.flows.EppRequestSource; @@ -76,6 +79,12 @@ import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException; import google.registry.flows.domain.DomainFlowUtils.RegistrarMustBeActiveForThisOperationException; import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException; +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; +import google.registry.flows.domain.token.AllocationTokenFlowUtils.InvalidAllocationTokenException; import google.registry.flows.exceptions.AlreadyPendingTransferException; import google.registry.flows.exceptions.InvalidTransferPeriodValueException; import google.registry.flows.exceptions.MissingTransferRequestAuthInfoException; @@ -94,6 +103,8 @@ import google.registry.model.domain.GracePeriod; import google.registry.model.domain.Period; import google.registry.model.domain.Period.Unit; import google.registry.model.domain.rgp.GracePeriodStatus; +import google.registry.model.domain.token.AllocationToken; +import google.registry.model.domain.token.AllocationToken.TokenStatus; import google.registry.model.eppcommon.AuthInfo.PasswordAuth; import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.Trid; @@ -111,6 +122,7 @@ import google.registry.model.transfer.TransferResponse; import google.registry.model.transfer.TransferStatus; import google.registry.persistence.VKey; import google.registry.testing.CloudTasksHelper.TaskMatcher; +import google.registry.testing.DatabaseHelper; import java.math.BigDecimal; import java.util.Map; import java.util.Optional; @@ -1677,4 +1689,120 @@ class DomainTransferRequestFlowTest DomainTransactionRecord.create( "tld", clock.nowUtc().plusDays(5), TRANSFER_SUCCESSFUL, 1)); } + + @Test + void testSuccess_allocationToken() throws Exception { + setupDomain("example", "tld"); + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(SINGLE_USE) + .setDomainName("example.tld") + .build()); + doSuccessfulTest( + "domain_transfer_request_allocation_token.xml", "domain_transfer_request_response.xml"); + } + + @Test + void testFailure_invalidAllocationToken() throws Exception { + setupDomain("example", "tld"); + setEppInput("domain_transfer_request_allocation_token.xml"); + EppException thrown = assertThrows(InvalidAllocationTokenException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + void testFailure_allocationTokenIsForDifferentName() throws Exception { + setupDomain("example", "tld"); + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(SINGLE_USE) + .setDomainName("otherdomain.tld") + .build()); + setEppInput("domain_transfer_request_allocation_token.xml"); + EppException thrown = + assertThrows(AllocationTokenNotValidForDomainException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + void testFailure_allocationTokenNotActive() throws Exception { + setupDomain("example", "tld"); + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(UNLIMITED_USE) + .setDiscountFraction(0.5) + .setTokenStatusTransitions( + ImmutableSortedMap.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_transfer_request_allocation_token.xml"); + EppException thrown = assertThrows(AllocationTokenNotInPromotionException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + void testFailure_allocationTokenNotValidForRegistrar() throws Exception { + setupDomain("example", "tld"); + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(UNLIMITED_USE) + .setAllowedRegistrarIds(ImmutableSet.of("someClientId")) + .setDiscountFraction(0.5) + .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()); + setEppInput("domain_transfer_request_allocation_token.xml"); + EppException thrown = + assertThrows(AllocationTokenNotValidForRegistrarException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + void testFailure_allocationTokenNotValidForTld() throws Exception { + setupDomain("example", "tld"); + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(UNLIMITED_USE) + .setAllowedTlds(ImmutableSet.of("example")) + .setDiscountFraction(0.5) + .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()); + setEppInput("domain_transfer_request_allocation_token.xml"); + EppException thrown = assertThrows(AllocationTokenNotValidForTldException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } + + @Test + void testFailure_allocationTokenAlreadyRedeemed() throws Exception { + setupDomain("example", "tld"); + Domain domain = DatabaseHelper.newDomain("foo.tld"); + Key historyEntryKey = Key.create(Key.create(domain), HistoryEntry.class, 505L); + persistResource( + new AllocationToken.Builder() + .setToken("abc123") + .setTokenType(SINGLE_USE) + .setRedemptionHistoryEntry(HistoryEntry.createVKey(historyEntryKey)) + .build()); + setEppInput("domain_transfer_request_allocation_token.xml"); + EppException thrown = + assertThrows(AlreadyRedeemedAllocationTokenException.class, this::runFlow); + assertAboutEppExceptions().that(thrown).marshalsToXml(); + } } diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_approve_allocation_token.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_approve_allocation_token.xml new file mode 100644 index 000000000..acc406606 --- /dev/null +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_approve_allocation_token.xml @@ -0,0 +1,18 @@ + + + + + example.tld + + + + + abc123 + + + ABC-12345 + + \ No newline at end of file diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_allocation_token.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_allocation_token.xml new file mode 100644 index 000000000..12c6800d1 --- /dev/null +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_allocation_token.xml @@ -0,0 +1,22 @@ + + + + + example.tld + 1 + + 2fooBAR + + + + + + abc123 + + + ABC-12345 + + diff --git a/docs/flows.md b/docs/flows.md index bb9c3b59a..e3aa479af 100644 --- a/docs/flows.md +++ b/docs/flows.md @@ -589,12 +589,20 @@ replaced with new ones with the correct approval time. * 2201 * The specified resource belongs to another client. * Registrar is not authorized to access this TLD. + * The allocation token is invalid. * 2202 * Authorization information for accessing resource is invalid. * 2301 * The resource does not have a pending transfer. * 2303 * Resource with this id does not exist. +* 2304 + * The allocation token is not currently valid. +* 2305 + * The allocation token is not valid for this domain. + * The allocation token is not valid for this registrar. + * The allocation token is not valid for this TLD. + * The allocation token was already redeemed. ## DomainTransferCancelFlow @@ -723,6 +731,7 @@ new ones with the correct approval time). * Registrar is missing the billing account map for this currency type. * Registrar is not authorized to access this TLD. * Registrar must be active in order to perform this operation. + * The allocation token is invalid. * 2202 * Authorization information for accessing resource is invalid. * 2300 @@ -735,6 +744,12 @@ new ones with the correct approval time). extension. * The requested domain name is on the premium price list, and this registrar has blocked premium registrations. + * The allocation token is not currently valid. +* 2305 + * The allocation token is not valid for this domain. + * The allocation token is not valid for this registrar. + * The allocation token is not valid for this TLD. + * The allocation token was already redeemed. * 2306 * Domain transfer period must be one year. * Domain transfer period must be zero or one year when using the superuser