mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 07:57:13 +02:00
Record domain transaction for domain transfers
This is the last of many cls adding explicit logging in all our domain mutation flows to facilitate transaction reporting. The transfer process is as follows: GAINING sends a TransferRequest to LOSING LOSING either acks (TransferApprove), nacks (TransferReject) or does nothing (auto approve). For acks and autoapproves, we produce a +1 counter for GAINING and LOSING for domain-gaining/losing-successful for each registrar, to be reported on the approve date + the transfer grace period. For nacks, we produce a +1 counter for domain-gaining/losing-nacked for each registrar. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=166535579
This commit is contained in:
parent
7ee8bc9070
commit
16e8286dca
15 changed files with 319 additions and 95 deletions
|
@ -160,7 +160,7 @@ public class DomainAllocateFlow implements TransactionalFlow {
|
||||||
String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
|
String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
|
||||||
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
|
||||||
HistoryEntry historyEntry = buildHistoryEntry(
|
HistoryEntry historyEntry = buildHistoryEntry(
|
||||||
repoId, period, now, registry.getAddGracePeriodLength(), registry.getTldStr());
|
repoId, registry.getTldStr(), now, period, registry.getAddGracePeriodLength());
|
||||||
entitiesToSave.add(historyEntry);
|
entitiesToSave.add(historyEntry);
|
||||||
ImmutableSet<? extends ImmutableObject> billsAndPolls = createBillingEventsAndPollMessages(
|
ImmutableSet<? extends ImmutableObject> billsAndPolls = createBillingEventsAndPollMessages(
|
||||||
domainName, application, historyEntry, isSunrushAddGracePeriod, registry, now, years);
|
domainName, application, historyEntry, isSunrushAddGracePeriod, registry, now, years);
|
||||||
|
@ -234,7 +234,7 @@ public class DomainAllocateFlow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistoryEntry(
|
private HistoryEntry buildHistoryEntry(
|
||||||
String repoId, Period period, DateTime now, Duration addGracePeriod, String tld) {
|
String repoId, String tld, DateTime now, Period period, Duration addGracePeriod) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_ALLOCATE)
|
.setType(HistoryEntry.Type.DOMAIN_ALLOCATE)
|
||||||
.setPeriod(period)
|
.setPeriod(period)
|
||||||
|
|
|
@ -262,7 +262,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||||
String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
|
String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
|
||||||
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
|
||||||
HistoryEntry historyEntry = buildHistoryEntry(
|
HistoryEntry historyEntry = buildHistoryEntry(
|
||||||
repoId, period, now, registry.getAddGracePeriodLength(), registry.getTldStr());
|
repoId, registry.getTldStr(), now, period, registry.getAddGracePeriodLength());
|
||||||
// Bill for the create.
|
// Bill for the create.
|
||||||
BillingEvent.OneTime createBillingEvent =
|
BillingEvent.OneTime createBillingEvent =
|
||||||
createOneTimeBillingEvent(
|
createOneTimeBillingEvent(
|
||||||
|
@ -365,7 +365,7 @@ public class DomainCreateFlow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistoryEntry(
|
private HistoryEntry buildHistoryEntry(
|
||||||
String repoId, Period period, DateTime now, Duration addGracePeriod, String tld) {
|
String repoId, String tld, DateTime now, Period period, Duration addGracePeriod) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||||
.setPeriod(period)
|
.setPeriod(period)
|
||||||
|
|
|
@ -24,22 +24,22 @@ import static google.registry.flows.ResourceFlowUtils.verifyNoDisallowedStatuses
|
||||||
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.createCancellingRecords;
|
import static google.registry.flows.domain.DomainFlowUtils.createCancelingRecords;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPredelegation;
|
import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPredelegation;
|
||||||
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
import static google.registry.model.eppoutput.Result.Code.SUCCESS;
|
||||||
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.model.reporting.DomainTransactionRecord.TransactionReportField.isAddsField;
|
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.ADD_FIELDS;
|
||||||
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.isRenewsField;
|
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.RENEW_FIELDS;
|
||||||
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
||||||
import static google.registry.util.CollectionUtils.nullToEmpty;
|
import static google.registry.util.CollectionUtils.nullToEmpty;
|
||||||
import static google.registry.util.CollectionUtils.union;
|
import static google.registry.util.CollectionUtils.union;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.dns.DnsQueue;
|
import google.registry.dns.DnsQueue;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
|
@ -245,17 +245,11 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
||||||
registry.getAutoRenewGracePeriodLength(),
|
registry.getAutoRenewGracePeriodLength(),
|
||||||
registry.getRenewGracePeriodLength()));
|
registry.getRenewGracePeriodLength()));
|
||||||
ImmutableSet<DomainTransactionRecord> cancelledRecords =
|
ImmutableSet<DomainTransactionRecord> cancelledRecords =
|
||||||
createCancellingRecords(
|
createCancelingRecords(
|
||||||
existingResource,
|
existingResource,
|
||||||
now,
|
now,
|
||||||
maxGracePeriod,
|
maxGracePeriod,
|
||||||
new Predicate<DomainTransactionRecord>() {
|
Sets.immutableEnumSet(Sets.union(ADD_FIELDS, RENEW_FIELDS)));
|
||||||
@Override
|
|
||||||
public boolean apply(@Nullable DomainTransactionRecord domainTransactionRecord) {
|
|
||||||
return isAddsField(domainTransactionRecord.getReportField())
|
|
||||||
|| isRenewsField(domainTransactionRecord.getReportField());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_DELETE)
|
.setType(HistoryEntry.Type.DOMAIN_DELETE)
|
||||||
.setModificationTime(now)
|
.setModificationTime(now)
|
||||||
|
|
|
@ -108,6 +108,7 @@ 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.registry.label.ReservedList;
|
import google.registry.model.registry.label.ReservedList;
|
||||||
import google.registry.model.reporting.DomainTransactionRecord;
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
|
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||||
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.util.FormattingLogger;
|
import google.registry.util.FormattingLogger;
|
||||||
|
@ -925,11 +926,11 @@ public class DomainFlowUtils {
|
||||||
* hasn't been reported yet and b) matches the predicate 3. Return the transactionRecords under
|
* hasn't been reported yet and b) matches the predicate 3. Return the transactionRecords under
|
||||||
* the most recent HistoryEntry that fits the above criteria, with negated reportAmounts.
|
* the most recent HistoryEntry that fits the above criteria, with negated reportAmounts.
|
||||||
*/
|
*/
|
||||||
static ImmutableSet<DomainTransactionRecord> createCancellingRecords(
|
static ImmutableSet<DomainTransactionRecord> createCancelingRecords(
|
||||||
DomainResource domainResource,
|
DomainResource domainResource,
|
||||||
final DateTime now,
|
final DateTime now,
|
||||||
Duration maxSearchPeriod,
|
Duration maxSearchPeriod,
|
||||||
final Predicate<DomainTransactionRecord> isCancellable) {
|
final ImmutableSet<TransactionReportField> cancelableFields) {
|
||||||
|
|
||||||
List<HistoryEntry> recentHistoryEntries = ofy().load()
|
List<HistoryEntry> recentHistoryEntries = ofy().load()
|
||||||
.type(HistoryEntry.class)
|
.type(HistoryEntry.class)
|
||||||
|
@ -937,22 +938,25 @@ public class DomainFlowUtils {
|
||||||
.filter("modificationTime >=", now.minus(maxSearchPeriod))
|
.filter("modificationTime >=", now.minus(maxSearchPeriod))
|
||||||
.order("modificationTime")
|
.order("modificationTime")
|
||||||
.list();
|
.list();
|
||||||
Optional<HistoryEntry> entryToCancel = FluentIterable.from(recentHistoryEntries)
|
Optional<HistoryEntry> entryToCancel =
|
||||||
.filter(
|
FluentIterable.from(recentHistoryEntries)
|
||||||
new Predicate<HistoryEntry>() {
|
.filter(
|
||||||
@Override
|
new Predicate<HistoryEntry>() {
|
||||||
public boolean apply(HistoryEntry historyEntry) {
|
@Override
|
||||||
// Look for add and renew transaction records that have yet to be reported
|
public boolean apply(HistoryEntry historyEntry) {
|
||||||
for (DomainTransactionRecord record : historyEntry.getDomainTransactionRecords()) {
|
// Look for add and renew transaction records that have yet to be reported
|
||||||
if (isCancellable.apply(record) && record.getReportingTime().isAfter(now)) {
|
for (DomainTransactionRecord record :
|
||||||
return true;
|
historyEntry.getDomainTransactionRecords()) {
|
||||||
|
if (cancelableFields.contains(record.getReportField())
|
||||||
|
&& record.getReportingTime().isAfter(now)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
return false;
|
// We only want to cancel out the most recent add or renewal
|
||||||
}
|
.last();
|
||||||
})
|
|
||||||
// We only want to cancel out the most recent add or renewal
|
|
||||||
.last();
|
|
||||||
ImmutableSet.Builder<DomainTransactionRecord> recordsBuilder = new ImmutableSet.Builder<>();
|
ImmutableSet.Builder<DomainTransactionRecord> recordsBuilder = new ImmutableSet.Builder<>();
|
||||||
if (entryToCancel.isPresent()) {
|
if (entryToCancel.isPresent()) {
|
||||||
for (DomainTransactionRecord record : entryToCancel.get().getDomainTransactionRecords()) {
|
for (DomainTransactionRecord record : entryToCancel.get().getDomainTransactionRecords()) {
|
||||||
|
|
|
@ -156,7 +156,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||||
.build());
|
.build());
|
||||||
Registry registry = Registry.get(existingDomain.getTld());
|
Registry registry = Registry.get(existingDomain.getTld());
|
||||||
HistoryEntry historyEntry = buildHistoryEntry(
|
HistoryEntry historyEntry = buildHistoryEntry(
|
||||||
existingDomain, command.getPeriod(), now, registry.getRenewGracePeriodLength());
|
existingDomain, now, command.getPeriod(), registry.getRenewGracePeriodLength());
|
||||||
String tld = existingDomain.getTld();
|
String tld = existingDomain.getTld();
|
||||||
// Bill for this explicit renew itself.
|
// Bill for this explicit renew itself.
|
||||||
BillingEvent.OneTime explicitRenewEvent =
|
BillingEvent.OneTime explicitRenewEvent =
|
||||||
|
@ -213,7 +213,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistoryEntry(
|
private HistoryEntry buildHistoryEntry(
|
||||||
DomainResource existingDomain, Period period, DateTime now, Duration renewGracePeriod) {
|
DomainResource existingDomain, DateTime now, Period period, Duration renewGracePeriod) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_RENEW)
|
.setType(HistoryEntry.Type.DOMAIN_RENEW)
|
||||||
.setPeriod(period)
|
.setPeriod(period)
|
||||||
|
|
|
@ -22,12 +22,15 @@ 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.createCancelingRecords;
|
||||||
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.createGainingTransferPollMessage;
|
||||||
import static google.registry.flows.domain.DomainTransferUtils.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 static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
|
||||||
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
|
||||||
|
import static google.registry.util.CollectionUtils.union;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||||
|
|
||||||
import com.google.common.base.Optional;
|
import com.google.common.base.Optional;
|
||||||
|
@ -52,6 +55,7 @@ import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppoutput.EppResponse;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||||
import google.registry.model.transfer.TransferData;
|
import google.registry.model.transfer.TransferData;
|
||||||
|
@ -109,12 +113,8 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
TransferData transferData = existingDomain.getTransferData();
|
TransferData transferData = existingDomain.getTransferData();
|
||||||
String gainingClientId = transferData.getGainingClientId();
|
String gainingClientId = transferData.getGainingClientId();
|
||||||
HistoryEntry historyEntry = historyBuilder
|
Registry registry = Registry.get(existingDomain.getTld());
|
||||||
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE)
|
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now, gainingClientId);
|
||||||
.setModificationTime(now)
|
|
||||||
.setOtherClientId(gainingClientId)
|
|
||||||
.setParent(Key.create(existingDomain))
|
|
||||||
.build();
|
|
||||||
// Bill for the transfer.
|
// Bill for the transfer.
|
||||||
BillingEvent.OneTime billingEvent = new BillingEvent.OneTime.Builder()
|
BillingEvent.OneTime billingEvent = new BillingEvent.OneTime.Builder()
|
||||||
.setReason(Reason.TRANSFER)
|
.setReason(Reason.TRANSFER)
|
||||||
|
@ -191,4 +191,28 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
||||||
targetId, newDomain.getTransferData(), newDomain.getRegistrationExpirationTime()))
|
targetId, newDomain.getTransferData(), newDomain.getRegistrationExpirationTime()))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HistoryEntry buildHistoryEntry(
|
||||||
|
DomainResource existingDomain, Registry registry, DateTime now, String gainingClientId) {
|
||||||
|
ImmutableSet<DomainTransactionRecord> cancelingRecords =
|
||||||
|
createCancelingRecords(
|
||||||
|
existingDomain,
|
||||||
|
now,
|
||||||
|
registry.getAutomaticTransferLength().plus(registry.getTransferGracePeriodLength()),
|
||||||
|
ImmutableSet.of(TRANSFER_SUCCESSFUL));
|
||||||
|
return historyBuilder
|
||||||
|
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE)
|
||||||
|
.setModificationTime(now)
|
||||||
|
.setOtherClientId(gainingClientId)
|
||||||
|
.setParent(Key.create(existingDomain))
|
||||||
|
.setDomainTransactionRecords(
|
||||||
|
union(
|
||||||
|
cancelingRecords,
|
||||||
|
DomainTransactionRecord.create(
|
||||||
|
existingDomain.getTld(),
|
||||||
|
now.plus(registry.getTransferGracePeriodLength()),
|
||||||
|
TRANSFER_SUCCESSFUL,
|
||||||
|
1)))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,13 +21,16 @@ 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.verifyTransferInitiator;
|
import static google.registry.flows.ResourceFlowUtils.verifyTransferInitiator;
|
||||||
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld;
|
||||||
|
import static google.registry.flows.domain.DomainFlowUtils.createCancelingRecords;
|
||||||
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.createLosingTransferPollMessage;
|
||||||
import static google.registry.flows.domain.DomainTransferUtils.createTransferResponse;
|
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.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
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.ImmutableSet;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
|
@ -41,6 +44,8 @@ import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.domain.metadata.MetadataExtension;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppoutput.EppResponse;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
|
import google.registry.model.registry.Registry;
|
||||||
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
|
@ -90,12 +95,8 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
|
||||||
if (!isSuperuser) {
|
if (!isSuperuser) {
|
||||||
checkAllowedAccessToTld(clientId, existingDomain.getTld());
|
checkAllowedAccessToTld(clientId, existingDomain.getTld());
|
||||||
}
|
}
|
||||||
HistoryEntry historyEntry = historyBuilder
|
Registry registry = Registry.get(existingDomain.getTld());
|
||||||
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_CANCEL)
|
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now);
|
||||||
.setOtherClientId(existingDomain.getTransferData().getLosingClientId())
|
|
||||||
.setModificationTime(now)
|
|
||||||
.setParent(Key.create(existingDomain))
|
|
||||||
.build();
|
|
||||||
DomainResource newDomain =
|
DomainResource newDomain =
|
||||||
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_CANCELLED, now);
|
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_CANCELLED, now);
|
||||||
ofy().save().<ImmutableObject>entities(
|
ofy().save().<ImmutableObject>entities(
|
||||||
|
@ -113,4 +114,21 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
|
||||||
.setResData(createTransferResponse(targetId, newDomain.getTransferData(), null))
|
.setResData(createTransferResponse(targetId, newDomain.getTransferData(), null))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HistoryEntry buildHistoryEntry(
|
||||||
|
DomainResource existingDomain, Registry registry, DateTime now) {
|
||||||
|
ImmutableSet<DomainTransactionRecord> cancelingRecords =
|
||||||
|
createCancelingRecords(
|
||||||
|
existingDomain,
|
||||||
|
now,
|
||||||
|
registry.getAutomaticTransferLength().plus(registry.getTransferGracePeriodLength()),
|
||||||
|
ImmutableSet.of(TRANSFER_SUCCESSFUL));
|
||||||
|
return historyBuilder
|
||||||
|
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_CANCEL)
|
||||||
|
.setOtherClientId(existingDomain.getTransferData().getLosingClientId())
|
||||||
|
.setModificationTime(now)
|
||||||
|
.setParent(Key.create(existingDomain))
|
||||||
|
.setDomainTransactionRecords(cancelingRecords)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,13 +21,18 @@ 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.createCancelingRecords;
|
||||||
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.createGainingTransferPollMessage;
|
||||||
import static google.registry.flows.domain.DomainTransferUtils.createTransferResponse;
|
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.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_NACKED;
|
||||||
|
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
|
||||||
|
import static google.registry.util.CollectionUtils.union;
|
||||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
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.ImmutableSet;
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import google.registry.flows.EppException;
|
import google.registry.flows.EppException;
|
||||||
import google.registry.flows.ExtensionManager;
|
import google.registry.flows.ExtensionManager;
|
||||||
|
@ -41,6 +46,8 @@ import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.domain.metadata.MetadataExtension;
|
import google.registry.model.domain.metadata.MetadataExtension;
|
||||||
import google.registry.model.eppcommon.AuthInfo;
|
import google.registry.model.eppcommon.AuthInfo;
|
||||||
import google.registry.model.eppoutput.EppResponse;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
|
import google.registry.model.registry.Registry;
|
||||||
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
|
@ -84,12 +91,8 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
|
||||||
validateClientIsLoggedIn(clientId);
|
validateClientIsLoggedIn(clientId);
|
||||||
DateTime now = ofy().getTransactionTime();
|
DateTime now = ofy().getTransactionTime();
|
||||||
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
DomainResource existingDomain = loadAndVerifyExistence(DomainResource.class, targetId, now);
|
||||||
HistoryEntry historyEntry = historyBuilder
|
Registry registry = Registry.get(existingDomain.getTld());
|
||||||
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REJECT)
|
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now);
|
||||||
.setModificationTime(now)
|
|
||||||
.setOtherClientId(existingDomain.getTransferData().getGainingClientId())
|
|
||||||
.setParent(Key.create(existingDomain))
|
|
||||||
.build();
|
|
||||||
verifyOptionalAuthInfo(authInfo, existingDomain);
|
verifyOptionalAuthInfo(authInfo, existingDomain);
|
||||||
verifyHasPendingTransfer(existingDomain);
|
verifyHasPendingTransfer(existingDomain);
|
||||||
verifyResourceOwnership(clientId, existingDomain);
|
verifyResourceOwnership(clientId, existingDomain);
|
||||||
|
@ -113,4 +116,25 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
|
||||||
.setResData(createTransferResponse(targetId, newDomain.getTransferData(), null))
|
.setResData(createTransferResponse(targetId, newDomain.getTransferData(), null))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HistoryEntry buildHistoryEntry(
|
||||||
|
DomainResource existingDomain, Registry registry, DateTime now) {
|
||||||
|
ImmutableSet<DomainTransactionRecord> cancelingRecords =
|
||||||
|
createCancelingRecords(
|
||||||
|
existingDomain,
|
||||||
|
now,
|
||||||
|
registry.getAutomaticTransferLength().plus(registry.getTransferGracePeriodLength()),
|
||||||
|
ImmutableSet.of(TRANSFER_SUCCESSFUL));
|
||||||
|
return historyBuilder
|
||||||
|
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REJECT)
|
||||||
|
.setModificationTime(now)
|
||||||
|
.setOtherClientId(existingDomain.getTransferData().getGainingClientId())
|
||||||
|
.setParent(Key.create(existingDomain))
|
||||||
|
.setDomainTransactionRecords(
|
||||||
|
union(
|
||||||
|
cancelingRecords,
|
||||||
|
DomainTransactionRecord.create(
|
||||||
|
existingDomain.getTld(), now, TRANSFER_NACKED, 1)))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,8 @@ import google.registry.model.eppinput.ResourceCommand;
|
||||||
import google.registry.model.eppoutput.EppResponse;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
|
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
|
||||||
import google.registry.model.transfer.TransferData;
|
import google.registry.model.transfer.TransferData;
|
||||||
|
@ -141,7 +143,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||||
eppInput.getSingleExtension(FeeTransferCommandExtension.class);
|
eppInput.getSingleExtension(FeeTransferCommandExtension.class);
|
||||||
FeesAndCredits feesAndCredits = pricingLogic.getTransferPrice(registry, targetId, now);
|
FeesAndCredits feesAndCredits = pricingLogic.getTransferPrice(registry, targetId, now);
|
||||||
validateFeeChallenge(targetId, tld, now, feeTransfer, feesAndCredits);
|
validateFeeChallenge(targetId, tld, now, feeTransfer, feesAndCredits);
|
||||||
HistoryEntry historyEntry = buildHistoryEntry(period, existingDomain, now);
|
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now, period);
|
||||||
DateTime automaticTransferTime = now.plus(registry.getAutomaticTransferLength());
|
DateTime automaticTransferTime = now.plus(registry.getAutomaticTransferLength());
|
||||||
|
|
||||||
// If the domain will be in the auto-renew grace period at the moment of transfer, the transfer
|
// If the domain will be in the auto-renew grace period at the moment of transfer, the transfer
|
||||||
|
@ -252,13 +254,21 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
private HistoryEntry buildHistoryEntry(
|
private HistoryEntry buildHistoryEntry(
|
||||||
Period period, DomainResource existingDomain, DateTime now) {
|
DomainResource existingDomain, Registry registry, DateTime now, Period period) {
|
||||||
return historyBuilder
|
return historyBuilder
|
||||||
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST)
|
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST)
|
||||||
.setOtherClientId(existingDomain.getCurrentSponsorClientId())
|
.setOtherClientId(existingDomain.getCurrentSponsorClientId())
|
||||||
.setPeriod(period)
|
.setPeriod(period)
|
||||||
.setModificationTime(now)
|
.setModificationTime(now)
|
||||||
.setParent(Key.create(existingDomain))
|
.setParent(Key.create(existingDomain))
|
||||||
|
.setDomainTransactionRecords(
|
||||||
|
ImmutableSet.of(
|
||||||
|
DomainTransactionRecord.create(
|
||||||
|
registry.getTldStr(),
|
||||||
|
now.plus(registry.getAutomaticTransferLength())
|
||||||
|
.plus(registry.getTransferGracePeriodLength()),
|
||||||
|
TransactionReportField.TRANSFER_SUCCESSFUL,
|
||||||
|
1)))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,10 +97,8 @@ public class DomainTransactionRecord extends ImmutableObject implements Buildabl
|
||||||
NET_RENEWS_8_YR,
|
NET_RENEWS_8_YR,
|
||||||
NET_RENEWS_9_YR,
|
NET_RENEWS_9_YR,
|
||||||
NET_RENEWS_10_YR,
|
NET_RENEWS_10_YR,
|
||||||
TRANSFER_GAINING_SUCCESSFUL,
|
TRANSFER_SUCCESSFUL,
|
||||||
TRANSFER_GAINING_NACKED,
|
TRANSFER_NACKED,
|
||||||
TRANSFER_LOSING_SUCCESSFUL,
|
|
||||||
TRANSFER_LOSING_NACKED,
|
|
||||||
DELETED_DOMAINS_GRACE,
|
DELETED_DOMAINS_GRACE,
|
||||||
DELETED_DOMAINS_NOGRACE,
|
DELETED_DOMAINS_NOGRACE,
|
||||||
RESTORED_DOMAINS;
|
RESTORED_DOMAINS;
|
||||||
|
@ -115,7 +113,7 @@ public class DomainTransactionRecord extends ImmutableObject implements Buildabl
|
||||||
return nameToField("NET_RENEWS_%d_YR", years);
|
return nameToField("NET_RENEWS_%d_YR", years);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final ImmutableSet<TransactionReportField> ADD_FIELDS =
|
public static final ImmutableSet<TransactionReportField> ADD_FIELDS =
|
||||||
ImmutableSet.of(
|
ImmutableSet.of(
|
||||||
NET_ADDS_1_YR,
|
NET_ADDS_1_YR,
|
||||||
NET_ADDS_2_YR,
|
NET_ADDS_2_YR,
|
||||||
|
@ -128,7 +126,7 @@ public class DomainTransactionRecord extends ImmutableObject implements Buildabl
|
||||||
NET_ADDS_9_YR,
|
NET_ADDS_9_YR,
|
||||||
NET_ADDS_10_YR);
|
NET_ADDS_10_YR);
|
||||||
|
|
||||||
private static final ImmutableSet<TransactionReportField> RENEW_FIELDS =
|
public static final ImmutableSet<TransactionReportField> RENEW_FIELDS =
|
||||||
ImmutableSet.of(
|
ImmutableSet.of(
|
||||||
NET_RENEWS_1_YR,
|
NET_RENEWS_1_YR,
|
||||||
NET_RENEWS_2_YR,
|
NET_RENEWS_2_YR,
|
||||||
|
@ -141,16 +139,6 @@ public class DomainTransactionRecord extends ImmutableObject implements Buildabl
|
||||||
NET_RENEWS_9_YR,
|
NET_RENEWS_9_YR,
|
||||||
NET_RENEWS_10_YR);
|
NET_RENEWS_10_YR);
|
||||||
|
|
||||||
|
|
||||||
/** Boilerplate to determine if a field is one of the NET_ADDS fields. */
|
|
||||||
public static boolean isAddsField(TransactionReportField field) {
|
|
||||||
return ADD_FIELDS.contains(field);
|
|
||||||
}
|
|
||||||
/** Boilerplate to determine if a field is one of the NET_ADDS fields. */
|
|
||||||
public static boolean isRenewsField(TransactionReportField field) {
|
|
||||||
return RENEW_FIELDS.contains(field);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static TransactionReportField nameToField(String enumTemplate, int years) {
|
private static TransactionReportField nameToField(String enumTemplate, int years) {
|
||||||
checkArgument(
|
checkArgument(
|
||||||
years >= 1 && years <= 10, "domain add and renew years must be between 1 and 10");
|
years >= 1 && years <= 10, "domain add and renew years must be between 1 and 10");
|
||||||
|
|
|
@ -17,6 +17,10 @@ package google.registry.flows.domain;
|
||||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
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_APPROVE;
|
||||||
|
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST;
|
||||||
import static google.registry.testing.DatastoreHelper.assertBillingEventsForResource;
|
import static google.registry.testing.DatastoreHelper.assertBillingEventsForResource;
|
||||||
import static google.registry.testing.DatastoreHelper.createTld;
|
import static google.registry.testing.DatastoreHelper.createTld;
|
||||||
import static google.registry.testing.DatastoreHelper.deleteResource;
|
import static google.registry.testing.DatastoreHelper.deleteResource;
|
||||||
|
@ -57,6 +61,7 @@ import google.registry.model.eppcommon.Trid;
|
||||||
import google.registry.model.poll.PendingActionNotificationResponse;
|
import google.registry.model.poll.PendingActionNotificationResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
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;
|
||||||
|
@ -139,12 +144,12 @@ public class DomainTransferApproveFlowTest
|
||||||
runFlowAssertResponse(readFile(expectedXmlFilename));
|
runFlowAssertResponse(readFile(expectedXmlFilename));
|
||||||
// Transfer should have succeeded. Verify correct fields were set.
|
// Transfer should have succeeded. Verify correct fields were set.
|
||||||
domain = reloadResourceByForeignKey();
|
domain = reloadResourceByForeignKey();
|
||||||
assertAboutDomains().that(domain).hasOneHistoryEntryEachOfTypes(
|
assertAboutDomains()
|
||||||
HistoryEntry.Type.DOMAIN_CREATE,
|
.that(domain)
|
||||||
HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST,
|
.hasOneHistoryEntryEachOfTypes(
|
||||||
HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE);
|
DOMAIN_CREATE, DOMAIN_TRANSFER_REQUEST, DOMAIN_TRANSFER_APPROVE);
|
||||||
final HistoryEntry historyEntryTransferApproved =
|
final HistoryEntry historyEntryTransferApproved =
|
||||||
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE);
|
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_APPROVE);
|
||||||
assertAboutHistoryEntries().that(historyEntryTransferApproved)
|
assertAboutHistoryEntries().that(historyEntryTransferApproved)
|
||||||
.hasOtherClientId("NewRegistrar");
|
.hasOtherClientId("NewRegistrar");
|
||||||
assertTransferApproved(domain);
|
assertTransferApproved(domain);
|
||||||
|
@ -445,4 +450,53 @@ public class DomainTransferApproveFlowTest
|
||||||
assertIcannReportingActivityFieldLogged("srs-dom-transfer-approve");
|
assertIcannReportingActivityFieldLogged("srs-dom-transfer-approve");
|
||||||
assertTldsFieldLogged("tld");
|
assertTldsFieldLogged("tld");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setUpGracePeriodDurations() {
|
||||||
|
persistResource(
|
||||||
|
Registry.get("tld")
|
||||||
|
.asBuilder()
|
||||||
|
.setAutomaticTransferLength(Duration.standardDays(2))
|
||||||
|
.setTransferGracePeriodLength(Duration.standardDays(3))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIcannTransactionRecord_noRecordsToCancel() throws Exception {
|
||||||
|
setUpGracePeriodDurations();
|
||||||
|
clock.advanceOneMilli();
|
||||||
|
runFlow();
|
||||||
|
HistoryEntry persistedEntry = getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_APPROVE);
|
||||||
|
// We should only produce a transfer success record for (now + transfer grace period)
|
||||||
|
assertThat(persistedEntry.getDomainTransactionRecords())
|
||||||
|
.containsExactly(
|
||||||
|
DomainTransactionRecord.create(
|
||||||
|
"tld", clock.nowUtc().plusDays(3), TRANSFER_SUCCESSFUL, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIcannTransactionRecord_cancelsPreviousRecords() throws Exception {
|
||||||
|
clock.advanceOneMilli();
|
||||||
|
setUpGracePeriodDurations();
|
||||||
|
DomainTransactionRecord previousSuccessRecord =
|
||||||
|
DomainTransactionRecord.create(
|
||||||
|
"tld", clock.nowUtc().plusDays(1), TRANSFER_SUCCESSFUL, 1);
|
||||||
|
persistResource(
|
||||||
|
new HistoryEntry.Builder()
|
||||||
|
.setType(DOMAIN_TRANSFER_REQUEST)
|
||||||
|
.setParent(domain)
|
||||||
|
.setModificationTime(clock.nowUtc().minusDays(4))
|
||||||
|
.setDomainTransactionRecords(
|
||||||
|
ImmutableSet.of(previousSuccessRecord))
|
||||||
|
.build());
|
||||||
|
runFlow();
|
||||||
|
HistoryEntry persistedEntry = getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_APPROVE);
|
||||||
|
// We should produce cancellation records for the original reporting date (now + 1 day) and
|
||||||
|
// success records for the new reporting date (now + transferGracePeriod=3 days)
|
||||||
|
assertThat(persistedEntry.getDomainTransactionRecords())
|
||||||
|
.containsExactly(
|
||||||
|
previousSuccessRecord.asBuilder().setReportAmount(-1).build(),
|
||||||
|
DomainTransactionRecord.create(
|
||||||
|
"tld", clock.nowUtc().plusDays(3), TRANSFER_SUCCESSFUL, 1));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
package google.registry.flows.domain;
|
package google.registry.flows.domain;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
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_CANCEL;
|
||||||
|
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST;
|
||||||
import static google.registry.testing.DatastoreHelper.assertBillingEvents;
|
import static google.registry.testing.DatastoreHelper.assertBillingEvents;
|
||||||
import static google.registry.testing.DatastoreHelper.createPollMessageForImplicitTransfer;
|
import static google.registry.testing.DatastoreHelper.createPollMessageForImplicitTransfer;
|
||||||
import static google.registry.testing.DatastoreHelper.deleteResource;
|
import static google.registry.testing.DatastoreHelper.deleteResource;
|
||||||
|
@ -39,10 +43,13 @@ import google.registry.model.domain.DomainResource;
|
||||||
import google.registry.model.domain.GracePeriod;
|
import google.registry.model.domain.GracePeriod;
|
||||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
|
import google.registry.model.registry.Registry;
|
||||||
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
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 org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.Duration;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -113,12 +120,12 @@ public class DomainTransferCancelFlowTest
|
||||||
assertAboutDomains().that(domain)
|
assertAboutDomains().that(domain)
|
||||||
.hasRegistrationExpirationTime(originalExpirationTime).and()
|
.hasRegistrationExpirationTime(originalExpirationTime).and()
|
||||||
.hasLastTransferTimeNotEqualTo(clock.nowUtc());
|
.hasLastTransferTimeNotEqualTo(clock.nowUtc());
|
||||||
assertAboutDomains().that(domain).hasOneHistoryEntryEachOfTypes(
|
assertAboutDomains()
|
||||||
HistoryEntry.Type.DOMAIN_CREATE,
|
.that(domain)
|
||||||
HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST,
|
.hasOneHistoryEntryEachOfTypes(
|
||||||
HistoryEntry.Type.DOMAIN_TRANSFER_CANCEL);
|
DOMAIN_CREATE, DOMAIN_TRANSFER_REQUEST, DOMAIN_TRANSFER_CANCEL);
|
||||||
final HistoryEntry historyEntryTransferCancel =
|
final HistoryEntry historyEntryTransferCancel =
|
||||||
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_TRANSFER_CANCEL);
|
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_CANCEL);
|
||||||
assertAboutHistoryEntries().that(historyEntryTransferCancel).hasClientId("NewRegistrar")
|
assertAboutHistoryEntries().that(historyEntryTransferCancel).hasClientId("NewRegistrar")
|
||||||
.and().hasOtherClientId("TheRegistrar");
|
.and().hasOtherClientId("TheRegistrar");
|
||||||
// The only billing event left should be the original autorenew event, now reopened.
|
// The only billing event left should be the original autorenew event, now reopened.
|
||||||
|
@ -138,7 +145,7 @@ public class DomainTransferCancelFlowTest
|
||||||
.setEventTime(originalExpirationTime)
|
.setEventTime(originalExpirationTime)
|
||||||
.setAutorenewEndTime(END_OF_TIME)
|
.setAutorenewEndTime(END_OF_TIME)
|
||||||
.setMsg("Domain was auto-renewed.")
|
.setMsg("Domain was auto-renewed.")
|
||||||
.setParent(getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_CREATE))
|
.setParent(getOnlyHistoryEntryOfType(domain, DOMAIN_CREATE))
|
||||||
.build(),
|
.build(),
|
||||||
new PollMessage.OneTime.Builder()
|
new PollMessage.OneTime.Builder()
|
||||||
.setClientId("TheRegistrar")
|
.setClientId("TheRegistrar")
|
||||||
|
@ -152,7 +159,7 @@ public class DomainTransferCancelFlowTest
|
||||||
.setPendingTransferExpirationTime(clock.nowUtc())
|
.setPendingTransferExpirationTime(clock.nowUtc())
|
||||||
.build()))
|
.build()))
|
||||||
.setMsg("Transfer cancelled.")
|
.setMsg("Transfer cancelled.")
|
||||||
.setParent(getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_TRANSFER_CANCEL))
|
.setParent(getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_CANCEL))
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
// The original grace periods should remain untouched.
|
// The original grace periods should remain untouched.
|
||||||
|
@ -323,4 +330,38 @@ public class DomainTransferCancelFlowTest
|
||||||
assertIcannReportingActivityFieldLogged("srs-dom-transfer-cancel");
|
assertIcannReportingActivityFieldLogged("srs-dom-transfer-cancel");
|
||||||
assertTldsFieldLogged("tld");
|
assertTldsFieldLogged("tld");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIcannTransactionRecord_noRecordsToCancel() throws Exception {
|
||||||
|
clock.advanceOneMilli();
|
||||||
|
runFlow();
|
||||||
|
HistoryEntry persistedEntry = getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_CANCEL);
|
||||||
|
// No cancellation records should be produced
|
||||||
|
assertThat(persistedEntry.getDomainTransactionRecords()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIcannTransactionRecord_cancelsPreviousRecords() throws Exception {
|
||||||
|
clock.advanceOneMilli();
|
||||||
|
persistResource(
|
||||||
|
Registry.get("tld")
|
||||||
|
.asBuilder()
|
||||||
|
.setAutomaticTransferLength(Duration.standardDays(2))
|
||||||
|
.setTransferGracePeriodLength(Duration.standardDays(3))
|
||||||
|
.build());
|
||||||
|
DomainTransactionRecord previousSuccessRecord =
|
||||||
|
DomainTransactionRecord.create("tld", clock.nowUtc().plusDays(1), TRANSFER_SUCCESSFUL, 1);
|
||||||
|
persistResource(
|
||||||
|
new HistoryEntry.Builder()
|
||||||
|
.setType(DOMAIN_TRANSFER_REQUEST)
|
||||||
|
.setParent(domain)
|
||||||
|
.setModificationTime(clock.nowUtc().minusDays(4))
|
||||||
|
.setDomainTransactionRecords(ImmutableSet.of(previousSuccessRecord))
|
||||||
|
.build());
|
||||||
|
runFlow();
|
||||||
|
HistoryEntry persistedEntry = getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_CANCEL);
|
||||||
|
// We should produce a cancellation record for the original transfer success
|
||||||
|
assertThat(persistedEntry.getDomainTransactionRecords())
|
||||||
|
.containsExactly(previousSuccessRecord.asBuilder().setReportAmount(-1).build());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
package google.registry.flows.domain;
|
package google.registry.flows.domain;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_NACKED;
|
||||||
|
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_REJECT;
|
||||||
|
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST;
|
||||||
import static google.registry.testing.DatastoreHelper.assertBillingEvents;
|
import static google.registry.testing.DatastoreHelper.assertBillingEvents;
|
||||||
import static google.registry.testing.DatastoreHelper.deleteResource;
|
import static google.registry.testing.DatastoreHelper.deleteResource;
|
||||||
import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType;
|
import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType;
|
||||||
|
@ -42,10 +47,13 @@ import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||||
import google.registry.model.eppcommon.Trid;
|
import google.registry.model.eppcommon.Trid;
|
||||||
import google.registry.model.poll.PendingActionNotificationResponse;
|
import google.registry.model.poll.PendingActionNotificationResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
|
import google.registry.model.registry.Registry;
|
||||||
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.transfer.TransferResponse;
|
import google.registry.model.transfer.TransferResponse;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.Duration;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
@ -88,11 +96,9 @@ public class DomainTransferRejectFlowTest
|
||||||
.hasRegistrationExpirationTime(originalExpirationTime).and()
|
.hasRegistrationExpirationTime(originalExpirationTime).and()
|
||||||
.hasLastTransferTimeNotEqualTo(clock.nowUtc()).and()
|
.hasLastTransferTimeNotEqualTo(clock.nowUtc()).and()
|
||||||
.hasOneHistoryEntryEachOfTypes(
|
.hasOneHistoryEntryEachOfTypes(
|
||||||
HistoryEntry.Type.DOMAIN_CREATE,
|
DOMAIN_CREATE, DOMAIN_TRANSFER_REQUEST, DOMAIN_TRANSFER_REJECT);
|
||||||
HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST,
|
|
||||||
HistoryEntry.Type.DOMAIN_TRANSFER_REJECT);
|
|
||||||
final HistoryEntry historyEntryTransferRejected =
|
final HistoryEntry historyEntryTransferRejected =
|
||||||
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_TRANSFER_REJECT);
|
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REJECT);
|
||||||
assertAboutHistoryEntries()
|
assertAboutHistoryEntries()
|
||||||
.that(historyEntryTransferRejected)
|
.that(historyEntryTransferRejected)
|
||||||
.hasOtherClientId("NewRegistrar");
|
.hasOtherClientId("NewRegistrar");
|
||||||
|
@ -285,4 +291,46 @@ public class DomainTransferRejectFlowTest
|
||||||
assertIcannReportingActivityFieldLogged("srs-dom-transfer-reject");
|
assertIcannReportingActivityFieldLogged("srs-dom-transfer-reject");
|
||||||
assertTldsFieldLogged("tld");
|
assertTldsFieldLogged("tld");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setUpGracePeriodDurations() {
|
||||||
|
persistResource(
|
||||||
|
Registry.get("tld")
|
||||||
|
.asBuilder()
|
||||||
|
.setAutomaticTransferLength(Duration.standardDays(2))
|
||||||
|
.setTransferGracePeriodLength(Duration.standardDays(3))
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIcannTransactionRecord_noRecordsToCancel() throws Exception {
|
||||||
|
setUpGracePeriodDurations();
|
||||||
|
runFlow();
|
||||||
|
HistoryEntry persistedEntry = getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REJECT);
|
||||||
|
// We should only produce transfer nacked records, reported now
|
||||||
|
assertThat(persistedEntry.getDomainTransactionRecords())
|
||||||
|
.containsExactly(DomainTransactionRecord.create("tld", clock.nowUtc(), TRANSFER_NACKED, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIcannTransactionRecord_cancelsPreviousRecords() throws Exception {
|
||||||
|
setUpGracePeriodDurations();
|
||||||
|
DomainTransactionRecord previousSuccessRecord =
|
||||||
|
DomainTransactionRecord.create(
|
||||||
|
"tld", clock.nowUtc().plusDays(1), TRANSFER_SUCCESSFUL, 1);
|
||||||
|
persistResource(
|
||||||
|
new HistoryEntry.Builder()
|
||||||
|
.setType(DOMAIN_TRANSFER_REQUEST)
|
||||||
|
.setParent(domain)
|
||||||
|
.setModificationTime(clock.nowUtc().minusDays(4))
|
||||||
|
.setDomainTransactionRecords(
|
||||||
|
ImmutableSet.of(previousSuccessRecord))
|
||||||
|
.build());
|
||||||
|
runFlow();
|
||||||
|
HistoryEntry persistedEntry = getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REJECT);
|
||||||
|
// We should produce cancellation records for the original success records and nack records
|
||||||
|
assertThat(persistedEntry.getDomainTransactionRecords())
|
||||||
|
.containsExactly(
|
||||||
|
previousSuccessRecord.asBuilder().setReportAmount(-1).build(),
|
||||||
|
DomainTransactionRecord.create("tld", clock.nowUtc(), TRANSFER_NACKED, 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@ package google.registry.flows.domain;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||||
|
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;
|
||||||
import static google.registry.testing.DatastoreHelper.assertBillingEvents;
|
import static google.registry.testing.DatastoreHelper.assertBillingEvents;
|
||||||
import static google.registry.testing.DatastoreHelper.createTld;
|
import static google.registry.testing.DatastoreHelper.createTld;
|
||||||
import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType;
|
import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType;
|
||||||
|
@ -68,6 +71,7 @@ import google.registry.model.eppcommon.StatusValue;
|
||||||
import google.registry.model.poll.PendingActionNotificationResponse;
|
import google.registry.model.poll.PendingActionNotificationResponse;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
|
import google.registry.model.reporting.DomainTransactionRecord;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.transfer.TransferResponse;
|
import google.registry.model.transfer.TransferResponse;
|
||||||
import google.registry.model.transfer.TransferStatus;
|
import google.registry.model.transfer.TransferStatus;
|
||||||
|
@ -163,14 +167,12 @@ public class DomainTransferRequestFlowTest
|
||||||
// Transfer should have been requested. Verify correct fields were set.
|
// Transfer should have been requested. Verify correct fields were set.
|
||||||
domain = reloadResourceByForeignKey();
|
domain = reloadResourceByForeignKey();
|
||||||
final HistoryEntry historyEntryTransferRequest =
|
final HistoryEntry historyEntryTransferRequest =
|
||||||
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST);
|
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REQUEST);
|
||||||
subordinateHost = reloadResourceAndCloneAtTime(subordinateHost, clock.nowUtc());
|
subordinateHost = reloadResourceAndCloneAtTime(subordinateHost, clock.nowUtc());
|
||||||
assertTransferRequested(domain);
|
assertTransferRequested(domain);
|
||||||
assertAboutDomains().that(domain)
|
assertAboutDomains().that(domain)
|
||||||
.hasPendingTransferExpirationTime(implicitTransferTime).and()
|
.hasPendingTransferExpirationTime(implicitTransferTime).and()
|
||||||
.hasOneHistoryEntryEachOfTypes(
|
.hasOneHistoryEntryEachOfTypes(DOMAIN_CREATE, DOMAIN_TRANSFER_REQUEST);
|
||||||
HistoryEntry.Type.DOMAIN_CREATE,
|
|
||||||
HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST);
|
|
||||||
assertAboutHistoryEntries()
|
assertAboutHistoryEntries()
|
||||||
.that(historyEntryTransferRequest)
|
.that(historyEntryTransferRequest)
|
||||||
.hasPeriodYears(1)
|
.hasPeriodYears(1)
|
||||||
|
@ -971,4 +973,23 @@ public class DomainTransferRequestFlowTest
|
||||||
assertIcannReportingActivityFieldLogged("srs-dom-transfer-request");
|
assertIcannReportingActivityFieldLogged("srs-dom-transfer-request");
|
||||||
assertTldsFieldLogged("tld");
|
assertTldsFieldLogged("tld");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIcannTransactionRecord_getsStored() throws Exception {
|
||||||
|
setupDomain("example", "tld");
|
||||||
|
persistResource(
|
||||||
|
Registry.get("tld")
|
||||||
|
.asBuilder()
|
||||||
|
.setAutomaticTransferLength(Duration.standardDays(2))
|
||||||
|
.setTransferGracePeriodLength(Duration.standardDays(3))
|
||||||
|
.build());
|
||||||
|
clock.advanceOneMilli();
|
||||||
|
runTest("domain_transfer_request.xml", UserPrivileges.NORMAL);
|
||||||
|
HistoryEntry persistedEntry = getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REQUEST);
|
||||||
|
// We should produce a transfer success record
|
||||||
|
assertThat(persistedEntry.getDomainTransactionRecords())
|
||||||
|
.containsExactly(
|
||||||
|
DomainTransactionRecord.create(
|
||||||
|
"tld", clock.nowUtc().plusDays(5), TRANSFER_SUCCESSFUL, 1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -811,10 +811,8 @@ enum google.registry.model.reporting.DomainTransactionRecord$TransactionReportFi
|
||||||
NET_RENEWS_8_YR;
|
NET_RENEWS_8_YR;
|
||||||
NET_RENEWS_9_YR;
|
NET_RENEWS_9_YR;
|
||||||
RESTORED_DOMAINS;
|
RESTORED_DOMAINS;
|
||||||
TRANSFER_GAINING_NACKED;
|
TRANSFER_NACKED;
|
||||||
TRANSFER_GAINING_SUCCESSFUL;
|
TRANSFER_SUCCESSFUL;
|
||||||
TRANSFER_LOSING_NACKED;
|
|
||||||
TRANSFER_LOSING_SUCCESSFUL;
|
|
||||||
}
|
}
|
||||||
class google.registry.model.reporting.HistoryEntry {
|
class google.registry.model.reporting.HistoryEntry {
|
||||||
@Id long id;
|
@Id long id;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue