mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 16:07:15 +02:00
Refactor common domain transfer logic into a utility class
These methods will also be used for RDE imports (in a follow-up). ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=146955581
This commit is contained in:
parent
135b1f95f4
commit
b9222759dc
7 changed files with 302 additions and 216 deletions
|
@ -94,7 +94,6 @@ import google.registry.model.domain.secdns.SecDnsUpdateExtension.Remove;
|
||||||
import google.registry.model.eppcommon.StatusValue;
|
import google.registry.model.eppcommon.StatusValue;
|
||||||
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
import google.registry.model.eppoutput.EppResponse.ResponseExtension;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
|
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
|
@ -102,8 +101,6 @@ import google.registry.model.registry.Registry.TldState;
|
||||||
import google.registry.model.registry.label.ReservationType;
|
import google.registry.model.registry.label.ReservationType;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.tmch.ClaimsListShard;
|
import google.registry.model.tmch.ClaimsListShard;
|
||||||
import google.registry.model.transfer.TransferData;
|
|
||||||
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
|
||||||
import google.registry.util.Idn;
|
import google.registry.util.Idn;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -624,59 +621,6 @@ public class DomainFlowUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create a poll message for the gaining client in a transfer. */
|
|
||||||
static PollMessage createGainingTransferPollMessage(
|
|
||||||
String targetId,
|
|
||||||
TransferData transferData,
|
|
||||||
@Nullable DateTime extendedRegistrationExpirationTime,
|
|
||||||
HistoryEntry historyEntry) {
|
|
||||||
return new PollMessage.OneTime.Builder()
|
|
||||||
.setClientId(transferData.getGainingClientId())
|
|
||||||
.setEventTime(transferData.getPendingTransferExpirationTime())
|
|
||||||
.setMsg(transferData.getTransferStatus().getMessage())
|
|
||||||
.setResponseData(ImmutableList.of(
|
|
||||||
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime),
|
|
||||||
DomainPendingActionNotificationResponse.create(
|
|
||||||
targetId,
|
|
||||||
transferData.getTransferStatus().isApproved(),
|
|
||||||
transferData.getTransferRequestTrid(),
|
|
||||||
historyEntry.getModificationTime())))
|
|
||||||
.setParent(historyEntry)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a poll message for the losing client in a transfer. */
|
|
||||||
static PollMessage createLosingTransferPollMessage(
|
|
||||||
String targetId,
|
|
||||||
TransferData transferData,
|
|
||||||
@Nullable DateTime extendedRegistrationExpirationTime,
|
|
||||||
HistoryEntry historyEntry) {
|
|
||||||
return new PollMessage.OneTime.Builder()
|
|
||||||
.setClientId(transferData.getLosingClientId())
|
|
||||||
.setEventTime(transferData.getPendingTransferExpirationTime())
|
|
||||||
.setMsg(transferData.getTransferStatus().getMessage())
|
|
||||||
.setResponseData(ImmutableList.of(
|
|
||||||
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime)))
|
|
||||||
.setParent(historyEntry)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a {@link DomainTransferResponse} off of the info in a {@link TransferData}. */
|
|
||||||
static DomainTransferResponse createTransferResponse(
|
|
||||||
String targetId,
|
|
||||||
TransferData transferData,
|
|
||||||
@Nullable DateTime extendedRegistrationExpirationTime) {
|
|
||||||
return new DomainTransferResponse.Builder()
|
|
||||||
.setFullyQualifiedDomainNameName(targetId)
|
|
||||||
.setGainingClientId(transferData.getGainingClientId())
|
|
||||||
.setLosingClientId(transferData.getLosingClientId())
|
|
||||||
.setPendingTransferExpirationTime(transferData.getPendingTransferExpirationTime())
|
|
||||||
.setTransferRequestTime(transferData.getTransferRequestTime())
|
|
||||||
.setTransferStatus(transferData.getTransferStatus())
|
|
||||||
.setExtendedRegistrationExpirationTime(extendedRegistrationExpirationTime)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a secDns extension to a list if the given set of dsData is non-empty.
|
* Adds a secDns extension to a list if the given set of dsData is non-empty.
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,9 +23,9 @@ import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createGainingTransferPollMessage;
|
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
||||||
|
import static google.registry.flows.domain.DomainTransferUtils.createGainingTransferPollMessage;
|
||||||
|
import static google.registry.flows.domain.DomainTransferUtils.createTransferResponse;
|
||||||
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
||||||
|
|
|
@ -20,9 +20,9 @@ import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createLosingTransferPollMessage;
|
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
||||||
|
import static google.registry.flows.domain.DomainTransferUtils.createLosingTransferPollMessage;
|
||||||
|
import static google.registry.flows.domain.DomainTransferUtils.createTransferResponse;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ package google.registry.flows.domain;
|
||||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
import static google.registry.flows.domain.DomainTransferUtils.createTransferResponse;
|
||||||
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
|
|
@ -21,9 +21,9 @@ import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createGainingTransferPollMessage;
|
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
||||||
|
import static google.registry.flows.domain.DomainTransferUtils.createGainingTransferPollMessage;
|
||||||
|
import static google.registry.flows.domain.DomainTransferUtils.createTransferResponse;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
|
|
||||||
|
|
|
@ -14,25 +14,23 @@
|
||||||
|
|
||||||
package google.registry.flows.domain;
|
package google.registry.flows.domain;
|
||||||
|
|
||||||
import static com.google.common.collect.Iterables.filter;
|
|
||||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
|
||||||
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
|
||||||
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfo;
|
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfo;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoPresentForResourceTransfer;
|
import static google.registry.flows.ResourceFlowUtils.verifyAuthInfoPresentForResourceTransfer;
|
||||||
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createGainingTransferPollMessage;
|
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createLosingTransferPollMessage;
|
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.createTransferResponse;
|
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
|
import static google.registry.flows.domain.DomainFlowUtils.validateFeeChallenge;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears;
|
||||||
|
import static google.registry.flows.domain.DomainTransferUtils.createLosingTransferPollMessage;
|
||||||
|
import static google.registry.flows.domain.DomainTransferUtils.createPendingTransferData;
|
||||||
|
import static google.registry.flows.domain.DomainTransferUtils.createTransferResponse;
|
||||||
|
import static google.registry.flows.domain.DomainTransferUtils.createTransferServerApproveEntities;
|
||||||
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
import static google.registry.model.domain.DomainResource.extendRegistrationWithCap;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
|
import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
@ -46,9 +44,6 @@ import google.registry.flows.FlowModule.TargetId;
|
||||||
import google.registry.flows.TransactionalFlow;
|
import google.registry.flows.TransactionalFlow;
|
||||||
import google.registry.flows.exceptions.AlreadyPendingTransferException;
|
import google.registry.flows.exceptions.AlreadyPendingTransferException;
|
||||||
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
|
import google.registry.flows.exceptions.ObjectAlreadySponsoredException;
|
||||||
import google.registry.model.billing.BillingEvent;
|
|
||||||
import google.registry.model.billing.BillingEvent.Flag;
|
|
||||||
import google.registry.model.billing.BillingEvent.Reason;
|
|
||||||
import google.registry.model.domain.DomainCommand.Transfer;
|
import google.registry.model.domain.DomainCommand.Transfer;
|
||||||
import google.registry.model.domain.DomainResource;
|
import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.domain.Period;
|
import google.registry.model.domain.Period;
|
||||||
|
@ -70,9 +65,7 @@ import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
|
||||||
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import org.joda.money.Money;
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Duration;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An EPP flow that requests a transfer on a domain.
|
* An EPP flow that requests a transfer on a domain.
|
||||||
|
@ -155,6 +148,8 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||||
serverApproveNewExpirationTime,
|
serverApproveNewExpirationTime,
|
||||||
historyEntry,
|
historyEntry,
|
||||||
existingDomain,
|
existingDomain,
|
||||||
|
trid,
|
||||||
|
gainingClientId,
|
||||||
feesAndCredits.getTotalCost(),
|
feesAndCredits.getTotalCost(),
|
||||||
years,
|
years,
|
||||||
now);
|
now);
|
||||||
|
@ -218,128 +213,6 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a set of entities created speculatively in anticipation of a server approval.
|
|
||||||
*
|
|
||||||
* <p>This set consists of:
|
|
||||||
* <ul>
|
|
||||||
* <li>The one-time billing event charging the gaining registrar for the transfer
|
|
||||||
* <li>A cancellation of an autorenew charge for the losing registrar, if the autorenew grace
|
|
||||||
* period will apply at transfer time
|
|
||||||
* <li>A new post-transfer autorenew billing event for the domain (and gaining registrar)
|
|
||||||
* <li>A new post-transfer autorenew poll message for the domain (and gaining registrar)
|
|
||||||
* <li>A poll message for the gaining registrar
|
|
||||||
* <li>A poll message for the losing registrar
|
|
||||||
* </ul>
|
|
||||||
*/
|
|
||||||
private ImmutableSet<TransferServerApproveEntity> createTransferServerApproveEntities(
|
|
||||||
DateTime automaticTransferTime,
|
|
||||||
DateTime serverApproveNewExpirationTime,
|
|
||||||
HistoryEntry historyEntry,
|
|
||||||
DomainResource existingDomain,
|
|
||||||
Money transferCost,
|
|
||||||
int years,
|
|
||||||
DateTime now) {
|
|
||||||
// Create a TransferData for the server-approve case to use for the speculative poll messages.
|
|
||||||
TransferData serverApproveTransferData =
|
|
||||||
createTransferDataBuilder(existingDomain, automaticTransferTime, years, now)
|
|
||||||
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
|
||||||
.build();
|
|
||||||
Registry registry = Registry.get(existingDomain.getTld());
|
|
||||||
return new ImmutableSet.Builder<TransferServerApproveEntity>()
|
|
||||||
.add(createTransferBillingEvent(
|
|
||||||
automaticTransferTime, historyEntry, registry, transferCost, years))
|
|
||||||
.addAll(createOptionalAutorenewCancellation(
|
|
||||||
automaticTransferTime, historyEntry, existingDomain)
|
|
||||||
.asSet())
|
|
||||||
.add(createGainingClientAutorenewEvent(
|
|
||||||
serverApproveNewExpirationTime, historyEntry))
|
|
||||||
.add(createGainingClientAutorenewPollMessage(
|
|
||||||
serverApproveNewExpirationTime, historyEntry))
|
|
||||||
.add(createGainingTransferPollMessage(
|
|
||||||
targetId, serverApproveTransferData, serverApproveNewExpirationTime, historyEntry))
|
|
||||||
.add(createLosingTransferPollMessage(
|
|
||||||
targetId, serverApproveTransferData, serverApproveNewExpirationTime, historyEntry))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private BillingEvent.OneTime createTransferBillingEvent(
|
|
||||||
DateTime automaticTransferTime,
|
|
||||||
HistoryEntry historyEntry,
|
|
||||||
Registry registry,
|
|
||||||
Money transferCost,
|
|
||||||
int years) {
|
|
||||||
return new BillingEvent.OneTime.Builder()
|
|
||||||
.setReason(Reason.TRANSFER)
|
|
||||||
.setTargetId(targetId)
|
|
||||||
.setClientId(gainingClientId)
|
|
||||||
.setCost(transferCost)
|
|
||||||
.setPeriodYears(years)
|
|
||||||
.setEventTime(automaticTransferTime)
|
|
||||||
.setBillingTime(automaticTransferTime.plus(registry.getTransferGracePeriodLength()))
|
|
||||||
.setParent(historyEntry)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an optional autorenew cancellation if one would apply to the server-approved transfer.
|
|
||||||
*
|
|
||||||
* <p>If there will be an autorenew between now and the automatic transfer time, and if the
|
|
||||||
* autorenew grace period length is long enough that the domain will still be within it at the
|
|
||||||
* automatic transfer time, then the transfer will subsume the autorenew and we need to write out
|
|
||||||
* a cancellation for it.
|
|
||||||
*/
|
|
||||||
// TODO(b/19430703): the above logic is incomplete; it doesn't handle a grace period that started
|
|
||||||
// before the transfer was requested and continues through the automatic transfer time.
|
|
||||||
private Optional<BillingEvent.Cancellation> createOptionalAutorenewCancellation(
|
|
||||||
DateTime automaticTransferTime,
|
|
||||||
HistoryEntry historyEntry,
|
|
||||||
DomainResource existingDomain) {
|
|
||||||
Registry registry = Registry.get(existingDomain.getTld());
|
|
||||||
DateTime oldExpirationTime = existingDomain.getRegistrationExpirationTime();
|
|
||||||
Duration autoRenewGracePeriodLength = registry.getAutoRenewGracePeriodLength();
|
|
||||||
if (automaticTransferTime.isAfter(oldExpirationTime)
|
|
||||||
&& automaticTransferTime.isBefore(oldExpirationTime.plus(autoRenewGracePeriodLength))) {
|
|
||||||
return Optional.of(new BillingEvent.Cancellation.Builder()
|
|
||||||
.setReason(Reason.RENEW)
|
|
||||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
|
||||||
.setTargetId(targetId)
|
|
||||||
.setClientId(existingDomain.getCurrentSponsorClientId())
|
|
||||||
.setEventTime(automaticTransferTime)
|
|
||||||
.setBillingTime(existingDomain.getRegistrationExpirationTime()
|
|
||||||
.plus(registry.getAutoRenewGracePeriodLength()))
|
|
||||||
.setRecurringEventKey(existingDomain.getAutorenewBillingEvent())
|
|
||||||
.setParent(historyEntry)
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
return Optional.absent();
|
|
||||||
}
|
|
||||||
|
|
||||||
private BillingEvent.Recurring createGainingClientAutorenewEvent(
|
|
||||||
DateTime serverApproveNewExpirationTime, HistoryEntry historyEntry) {
|
|
||||||
return new BillingEvent.Recurring.Builder()
|
|
||||||
.setReason(Reason.RENEW)
|
|
||||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
|
||||||
.setTargetId(targetId)
|
|
||||||
.setClientId(gainingClientId)
|
|
||||||
.setEventTime(serverApproveNewExpirationTime)
|
|
||||||
.setRecurrenceEndTime(END_OF_TIME)
|
|
||||||
.setParent(historyEntry)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private PollMessage.Autorenew createGainingClientAutorenewPollMessage(
|
|
||||||
DateTime serverApproveNewExpirationTime, HistoryEntry historyEntry) {
|
|
||||||
return new PollMessage.Autorenew.Builder()
|
|
||||||
.setTargetId(targetId)
|
|
||||||
.setClientId(gainingClientId)
|
|
||||||
.setEventTime(serverApproveNewExpirationTime)
|
|
||||||
.setAutorenewEndTime(END_OF_TIME)
|
|
||||||
.setMsg("Domain was auto-renewed.")
|
|
||||||
.setParent(historyEntry)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Builder createTransferDataBuilder(
|
private Builder createTransferDataBuilder(
|
||||||
DomainResource existingDomain, DateTime automaticTransferTime, int years, DateTime now) {
|
DomainResource existingDomain, DateTime automaticTransferTime, int years, DateTime now) {
|
||||||
return new TransferData.Builder()
|
return new TransferData.Builder()
|
||||||
|
@ -351,26 +224,6 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||||
.setExtendedRegistrationYears(years);
|
.setExtendedRegistrationYears(years);
|
||||||
}
|
}
|
||||||
|
|
||||||
private TransferData createPendingTransferData(
|
|
||||||
TransferData.Builder transferDataBuilder,
|
|
||||||
ImmutableSet<TransferServerApproveEntity> serverApproveEntities) {
|
|
||||||
ImmutableSet.Builder<Key<? extends TransferServerApproveEntity>> serverApproveEntityKeys =
|
|
||||||
new ImmutableSet.Builder<>();
|
|
||||||
for (TransferServerApproveEntity entity : serverApproveEntities) {
|
|
||||||
serverApproveEntityKeys.add(Key.create(entity));
|
|
||||||
}
|
|
||||||
return transferDataBuilder
|
|
||||||
.setTransferStatus(TransferStatus.PENDING)
|
|
||||||
.setServerApproveBillingEvent(Key.create(
|
|
||||||
getOnlyElement(filter(serverApproveEntities, BillingEvent.OneTime.class))))
|
|
||||||
.setServerApproveAutorenewEvent(Key.create(
|
|
||||||
getOnlyElement(filter(serverApproveEntities, BillingEvent.Recurring.class))))
|
|
||||||
.setServerApproveAutorenewPollMessage(Key.create(
|
|
||||||
getOnlyElement(filter(serverApproveEntities, PollMessage.Autorenew.class))))
|
|
||||||
.setServerApproveEntities(serverApproveEntityKeys.build())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private DomainTransferResponse createResponse(
|
private DomainTransferResponse createResponse(
|
||||||
Period period, DomainResource existingDomain, DomainResource newDomain, DateTime now) {
|
Period period, DomainResource existingDomain, DomainResource newDomain, DateTime now) {
|
||||||
// If the registration were approved this instant, this is what the new expiration would be,
|
// If the registration were approved this instant, this is what the new expiration would be,
|
||||||
|
|
289
java/google/registry/flows/domain/DomainTransferUtils.java
Normal file
289
java/google/registry/flows/domain/DomainTransferUtils.java
Normal file
|
@ -0,0 +1,289 @@
|
||||||
|
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package google.registry.flows.domain;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.filter;
|
||||||
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
|
import google.registry.model.billing.BillingEvent;
|
||||||
|
import google.registry.model.billing.BillingEvent.Flag;
|
||||||
|
import google.registry.model.billing.BillingEvent.Reason;
|
||||||
|
import google.registry.model.domain.DomainResource;
|
||||||
|
import google.registry.model.eppcommon.Trid;
|
||||||
|
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
|
||||||
|
import google.registry.model.poll.PollMessage;
|
||||||
|
import google.registry.model.registry.Registry;
|
||||||
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.model.transfer.TransferData;
|
||||||
|
import google.registry.model.transfer.TransferData.Builder;
|
||||||
|
import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
|
||||||
|
import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
|
||||||
|
import google.registry.model.transfer.TransferStatus;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import org.joda.money.Money;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.Duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility logic for facilitating domain transfers.
|
||||||
|
*/
|
||||||
|
public final class DomainTransferUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up {@link TransferData} for a domain with links to entities for server approval.
|
||||||
|
*/
|
||||||
|
public static TransferData createPendingTransferData(
|
||||||
|
TransferData.Builder transferDataBuilder,
|
||||||
|
ImmutableSet<TransferServerApproveEntity> serverApproveEntities) {
|
||||||
|
ImmutableSet.Builder<Key<? extends TransferServerApproveEntity>> serverApproveEntityKeys =
|
||||||
|
new ImmutableSet.Builder<>();
|
||||||
|
for (TransferServerApproveEntity entity : serverApproveEntities) {
|
||||||
|
serverApproveEntityKeys.add(Key.create(entity));
|
||||||
|
}
|
||||||
|
return transferDataBuilder
|
||||||
|
.setTransferStatus(TransferStatus.PENDING)
|
||||||
|
.setServerApproveBillingEvent(Key.create(
|
||||||
|
getOnlyElement(filter(serverApproveEntities, BillingEvent.OneTime.class))))
|
||||||
|
.setServerApproveAutorenewEvent(Key.create(
|
||||||
|
getOnlyElement(filter(serverApproveEntities, BillingEvent.Recurring.class))))
|
||||||
|
.setServerApproveAutorenewPollMessage(Key.create(
|
||||||
|
getOnlyElement(filter(serverApproveEntities, PollMessage.Autorenew.class))))
|
||||||
|
.setServerApproveEntities(serverApproveEntityKeys.build())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a set of entities created speculatively in anticipation of a server approval.
|
||||||
|
*
|
||||||
|
* <p>This set consists of:
|
||||||
|
* <ul>
|
||||||
|
* <li>The one-time billing event charging the gaining registrar for the transfer
|
||||||
|
* <li>A cancellation of an autorenew charge for the losing registrar, if the autorenew grace
|
||||||
|
* period will apply at transfer time
|
||||||
|
* <li>A new post-transfer autorenew billing event for the domain (and gaining registrar)
|
||||||
|
* <li>A new post-transfer autorenew poll message for the domain (and gaining registrar)
|
||||||
|
* <li>A poll message for the gaining registrar
|
||||||
|
* <li>A poll message for the losing registrar
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public static ImmutableSet<TransferServerApproveEntity> createTransferServerApproveEntities(
|
||||||
|
DateTime automaticTransferTime,
|
||||||
|
DateTime serverApproveNewExpirationTime,
|
||||||
|
HistoryEntry historyEntry,
|
||||||
|
DomainResource existingDomain,
|
||||||
|
Trid trid,
|
||||||
|
String gainingClientId,
|
||||||
|
Money transferCost,
|
||||||
|
int years,
|
||||||
|
DateTime now) {
|
||||||
|
String targetId = existingDomain.getFullyQualifiedDomainName();
|
||||||
|
// Create a TransferData for the server-approve case to use for the speculative poll messages.
|
||||||
|
TransferData serverApproveTransferData =
|
||||||
|
createTransferDataBuilder(
|
||||||
|
existingDomain, trid, gainingClientId, automaticTransferTime, years, now)
|
||||||
|
.setTransferStatus(TransferStatus.SERVER_APPROVED)
|
||||||
|
.build();
|
||||||
|
Registry registry = Registry.get(existingDomain.getTld());
|
||||||
|
return new ImmutableSet.Builder<TransferServerApproveEntity>()
|
||||||
|
.add(
|
||||||
|
createTransferBillingEvent(
|
||||||
|
automaticTransferTime,
|
||||||
|
historyEntry,
|
||||||
|
targetId,
|
||||||
|
gainingClientId,
|
||||||
|
registry,
|
||||||
|
transferCost,
|
||||||
|
years))
|
||||||
|
.addAll(
|
||||||
|
createOptionalAutorenewCancellation(
|
||||||
|
automaticTransferTime, historyEntry, targetId, existingDomain)
|
||||||
|
.asSet())
|
||||||
|
.add(
|
||||||
|
createGainingClientAutorenewEvent(
|
||||||
|
serverApproveNewExpirationTime, historyEntry, targetId, gainingClientId))
|
||||||
|
.add(
|
||||||
|
createGainingClientAutorenewPollMessage(
|
||||||
|
serverApproveNewExpirationTime, historyEntry, targetId, gainingClientId))
|
||||||
|
.add(
|
||||||
|
createGainingTransferPollMessage(
|
||||||
|
targetId, serverApproveTransferData, serverApproveNewExpirationTime, historyEntry))
|
||||||
|
.add(
|
||||||
|
createLosingTransferPollMessage(
|
||||||
|
targetId, serverApproveTransferData, serverApproveNewExpirationTime, historyEntry))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a poll message for the gaining client in a transfer. */
|
||||||
|
public static PollMessage createGainingTransferPollMessage(
|
||||||
|
String targetId,
|
||||||
|
TransferData transferData,
|
||||||
|
@Nullable DateTime extendedRegistrationExpirationTime,
|
||||||
|
HistoryEntry historyEntry) {
|
||||||
|
return new PollMessage.OneTime.Builder()
|
||||||
|
.setClientId(transferData.getGainingClientId())
|
||||||
|
.setEventTime(transferData.getPendingTransferExpirationTime())
|
||||||
|
.setMsg(transferData.getTransferStatus().getMessage())
|
||||||
|
.setResponseData(ImmutableList.of(
|
||||||
|
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime),
|
||||||
|
DomainPendingActionNotificationResponse.create(
|
||||||
|
targetId,
|
||||||
|
transferData.getTransferStatus().isApproved(),
|
||||||
|
transferData.getTransferRequestTrid(),
|
||||||
|
historyEntry.getModificationTime())))
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a poll message for the losing client in a transfer. */
|
||||||
|
public static PollMessage createLosingTransferPollMessage(
|
||||||
|
String targetId,
|
||||||
|
TransferData transferData,
|
||||||
|
@Nullable DateTime extendedRegistrationExpirationTime,
|
||||||
|
HistoryEntry historyEntry) {
|
||||||
|
return new PollMessage.OneTime.Builder()
|
||||||
|
.setClientId(transferData.getLosingClientId())
|
||||||
|
.setEventTime(transferData.getPendingTransferExpirationTime())
|
||||||
|
.setMsg(transferData.getTransferStatus().getMessage())
|
||||||
|
.setResponseData(ImmutableList.of(
|
||||||
|
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime)))
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a {@link DomainTransferResponse} off of the info in a {@link TransferData}. */
|
||||||
|
static DomainTransferResponse createTransferResponse(
|
||||||
|
String targetId,
|
||||||
|
TransferData transferData,
|
||||||
|
@Nullable DateTime extendedRegistrationExpirationTime) {
|
||||||
|
return new DomainTransferResponse.Builder()
|
||||||
|
.setFullyQualifiedDomainNameName(targetId)
|
||||||
|
.setGainingClientId(transferData.getGainingClientId())
|
||||||
|
.setLosingClientId(transferData.getLosingClientId())
|
||||||
|
.setPendingTransferExpirationTime(transferData.getPendingTransferExpirationTime())
|
||||||
|
.setTransferRequestTime(transferData.getTransferRequestTime())
|
||||||
|
.setTransferStatus(transferData.getTransferStatus())
|
||||||
|
.setExtendedRegistrationExpirationTime(extendedRegistrationExpirationTime)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PollMessage.Autorenew createGainingClientAutorenewPollMessage(
|
||||||
|
DateTime serverApproveNewExpirationTime,
|
||||||
|
HistoryEntry historyEntry,
|
||||||
|
String targetId,
|
||||||
|
String gainingClientId) {
|
||||||
|
return new PollMessage.Autorenew.Builder()
|
||||||
|
.setTargetId(targetId)
|
||||||
|
.setClientId(gainingClientId)
|
||||||
|
.setEventTime(serverApproveNewExpirationTime)
|
||||||
|
.setAutorenewEndTime(END_OF_TIME)
|
||||||
|
.setMsg("Domain was auto-renewed.")
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BillingEvent.Recurring createGainingClientAutorenewEvent(
|
||||||
|
DateTime serverApproveNewExpirationTime,
|
||||||
|
HistoryEntry historyEntry,
|
||||||
|
String targetId,
|
||||||
|
String gainingClientId) {
|
||||||
|
return new BillingEvent.Recurring.Builder()
|
||||||
|
.setReason(Reason.RENEW)
|
||||||
|
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||||
|
.setTargetId(targetId)
|
||||||
|
.setClientId(gainingClientId)
|
||||||
|
.setEventTime(serverApproveNewExpirationTime)
|
||||||
|
.setRecurrenceEndTime(END_OF_TIME)
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an optional autorenew cancellation if one would apply to the server-approved transfer.
|
||||||
|
*
|
||||||
|
* <p>If there will be an autorenew between now and the automatic transfer time, and if the
|
||||||
|
* autorenew grace period length is long enough that the domain will still be within it at the
|
||||||
|
* automatic transfer time, then the transfer will subsume the autorenew and we need to write out
|
||||||
|
* a cancellation for it.
|
||||||
|
*/
|
||||||
|
// TODO(b/19430703): the above logic is incomplete; it doesn't handle a grace period that started
|
||||||
|
// before the transfer was requested and continues through the automatic transfer time.
|
||||||
|
private static Optional<BillingEvent.Cancellation> createOptionalAutorenewCancellation(
|
||||||
|
DateTime automaticTransferTime,
|
||||||
|
HistoryEntry historyEntry,
|
||||||
|
String targetId,
|
||||||
|
DomainResource existingDomain) {
|
||||||
|
Registry registry = Registry.get(existingDomain.getTld());
|
||||||
|
DateTime oldExpirationTime = existingDomain.getRegistrationExpirationTime();
|
||||||
|
Duration autoRenewGracePeriodLength = registry.getAutoRenewGracePeriodLength();
|
||||||
|
if (automaticTransferTime.isAfter(oldExpirationTime)
|
||||||
|
&& automaticTransferTime.isBefore(oldExpirationTime.plus(autoRenewGracePeriodLength))) {
|
||||||
|
return Optional.of(new BillingEvent.Cancellation.Builder()
|
||||||
|
.setReason(Reason.RENEW)
|
||||||
|
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||||
|
.setTargetId(targetId)
|
||||||
|
.setClientId(existingDomain.getCurrentSponsorClientId())
|
||||||
|
.setEventTime(automaticTransferTime)
|
||||||
|
.setBillingTime(existingDomain.getRegistrationExpirationTime()
|
||||||
|
.plus(registry.getAutoRenewGracePeriodLength()))
|
||||||
|
.setRecurringEventKey(existingDomain.getAutorenewBillingEvent())
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
return Optional.absent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BillingEvent.OneTime createTransferBillingEvent(
|
||||||
|
DateTime automaticTransferTime,
|
||||||
|
HistoryEntry historyEntry,
|
||||||
|
String targetId,
|
||||||
|
String gainingClientId,
|
||||||
|
Registry registry,
|
||||||
|
Money transferCost,
|
||||||
|
int years) {
|
||||||
|
return new BillingEvent.OneTime.Builder()
|
||||||
|
.setReason(Reason.TRANSFER)
|
||||||
|
.setTargetId(targetId)
|
||||||
|
.setClientId(gainingClientId)
|
||||||
|
.setCost(transferCost)
|
||||||
|
.setPeriodYears(years)
|
||||||
|
.setEventTime(automaticTransferTime)
|
||||||
|
.setBillingTime(automaticTransferTime.plus(registry.getTransferGracePeriodLength()))
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Builder createTransferDataBuilder(
|
||||||
|
DomainResource existingDomain,
|
||||||
|
Trid trid,
|
||||||
|
String gainingClientId,
|
||||||
|
DateTime automaticTransferTime,
|
||||||
|
int years,
|
||||||
|
DateTime now) {
|
||||||
|
return new TransferData.Builder()
|
||||||
|
.setTransferRequestTrid(trid)
|
||||||
|
.setTransferRequestTime(now)
|
||||||
|
.setGainingClientId(gainingClientId)
|
||||||
|
.setLosingClientId(existingDomain.getCurrentSponsorClientId())
|
||||||
|
.setPendingTransferExpirationTime(automaticTransferTime)
|
||||||
|
.setExtendedRegistrationYears(years);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DomainTransferUtils() {}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue