Populate the domain in DomainHistory objects created in Domain flows (#1106)

Unfortunately, much of the time there's a bit of a circular dependency
in the object creation, e.g. the Domain object stores references to the
billing events which store references to the history object which
contains the Domain object. As a result, we allocate the history
object's ID before creating it, so that it can be referenced in the
other objects that store that reference, e.g. billing events.

In addition, we add a utility copyFrom method in HistoryEntry.Builder to
avoid unnecessary ID allocations.
This commit is contained in:
gbrodman 2021-05-04 19:09:27 -04:00 committed by GitHub
parent 60224741df
commit 11f7bb8f6e
32 changed files with 670 additions and 562 deletions

View file

@ -243,7 +243,7 @@ public class FlowModule {
@Provides @Provides
static DomainHistory.Builder provideDomainHistoryBuilder( static DomainHistory.Builder provideDomainHistoryBuilder(
HistoryEntry.Builder historyEntryBuilder) { HistoryEntry.Builder historyEntryBuilder) {
return new DomainHistory.Builder().copyFrom(historyEntryBuilder.build()); return new DomainHistory.Builder().copyFrom(historyEntryBuilder);
} }
/** /**

View file

@ -22,15 +22,19 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.flogger.FluentLogger; import com.google.common.flogger.FluentLogger;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException.CommandUseErrorException; import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.ParameterValueRangeErrorException; import google.registry.flows.EppException.ParameterValueRangeErrorException;
import google.registry.flows.EppException.SyntaxErrorException; import google.registry.flows.EppException.SyntaxErrorException;
import google.registry.flows.EppException.UnimplementedProtocolVersionException; import google.registry.flows.EppException.UnimplementedProtocolVersionException;
import google.registry.flows.custom.EntityChanges; import google.registry.flows.custom.EntityChanges;
import google.registry.model.EppResource;
import google.registry.model.eppcommon.EppXmlTransformer; import google.registry.model.eppcommon.EppXmlTransformer;
import google.registry.model.eppinput.EppInput.WrongProtocolVersionException; import google.registry.model.eppinput.EppInput.WrongProtocolVersionException;
import google.registry.model.eppoutput.EppOutput; import google.registry.model.eppoutput.EppOutput;
import google.registry.model.host.InetAddressAdapter.IpVersionMismatchException; import google.registry.model.host.InetAddressAdapter.IpVersionMismatchException;
import google.registry.model.ofy.ObjectifyService;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.translators.CurrencyUnitAdapter.UnknownCurrencyException; import google.registry.model.translators.CurrencyUnitAdapter.UnknownCurrencyException;
import google.registry.xml.XmlException; import google.registry.xml.XmlException;
import java.util.List; import java.util.List;
@ -99,6 +103,11 @@ public final class FlowUtils {
} }
} }
public static <H extends HistoryEntry> Key<H> createHistoryKey(
EppResource parent, Class<H> clazz) {
return Key.create(Key.create(parent), clazz, ObjectifyService.allocateId());
}
/** Registrar is not logged in. */ /** Registrar is not logged in. */
public static class NotLoggedInException extends CommandUseErrorException { public static class NotLoggedInException extends CommandUseErrorException {
public NotLoggedInException() { public NotLoggedInException() {

View file

@ -97,7 +97,6 @@ import google.registry.model.eppinput.EppInput;
import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppoutput.CreateData.DomainCreateData; import google.registry.model.eppoutput.CreateData.DomainCreateData;
import google.registry.model.eppoutput.EppResponse; import google.registry.model.eppoutput.EppResponse;
import google.registry.model.host.HostResource;
import google.registry.model.index.EppResourceIndex; import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.ForeignKeyIndex; import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.ofy.ObjectifyService; import google.registry.model.ofy.ObjectifyService;
@ -107,11 +106,11 @@ import google.registry.model.poll.PollMessage.Autorenew;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.Registry.TldState;
import google.registry.model.registry.Registry.TldType; import google.registry.model.registry.Registry.TldType;
import google.registry.model.registry.label.ReservationType;
import google.registry.model.reporting.DomainTransactionRecord; import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField; 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.persistence.VKey;
import google.registry.tmch.LordnTaskUtils; import google.registry.tmch.LordnTaskUtils;
import java.util.Optional; import java.util.Optional;
import javax.inject.Inject; import javax.inject.Inject;
@ -302,10 +301,14 @@ public class DomainCreateFlow implements TransactionalFlow {
validateFeeChallenge(targetId, now, feeCreate, feesAndCredits); validateFeeChallenge(targetId, now, feeCreate, feesAndCredits);
Optional<SecDnsCreateExtension> secDnsCreate = Optional<SecDnsCreateExtension> secDnsCreate =
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class)); validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
DateTime registrationExpirationTime = leapSafeAddYears(now, years); DateTime registrationExpirationTime = leapSafeAddYears(now, years);
DomainHistory domainHistory = String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
buildHistoryEntry(repoId, registry, now, period, registry.getAddGracePeriodLength()); Key<DomainHistory> domainHistoryKey =
Key.create(
Key.create(DomainBase.class, repoId),
DomainHistory.class,
ObjectifyService.allocateId());
historyBuilder.setId(domainHistoryKey.getId());
// Bill for the create. // Bill for the create.
BillingEvent.OneTime createBillingEvent = BillingEvent.OneTime createBillingEvent =
createOneTimeBillingEvent( createOneTimeBillingEvent(
@ -315,14 +318,14 @@ public class DomainCreateFlow implements TransactionalFlow {
isReserved(domainName, isSunriseCreate), isReserved(domainName, isSunriseCreate),
years, years,
feesAndCredits, feesAndCredits,
domainHistory, domainHistoryKey,
allocationToken, allocationToken,
now); now);
// Create a new autorenew billing event and poll message starting at the expiration time. // Create a new autorenew billing event and poll message starting at the expiration time.
BillingEvent.Recurring autorenewBillingEvent = BillingEvent.Recurring autorenewBillingEvent =
createAutorenewBillingEvent(domainHistory, registrationExpirationTime); createAutorenewBillingEvent(domainHistoryKey, registrationExpirationTime);
PollMessage.Autorenew autorenewPollMessage = PollMessage.Autorenew autorenewPollMessage =
createAutorenewPollMessage(domainHistory, registrationExpirationTime); createAutorenewPollMessage(domainHistoryKey, registrationExpirationTime);
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>(); ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
entitiesToSave.add(createBillingEvent, autorenewBillingEvent, autorenewPollMessage); entitiesToSave.add(createBillingEvent, autorenewBillingEvent, autorenewPollMessage);
// Bill for EAP cost, if any. // Bill for EAP cost, if any.
@ -330,14 +333,12 @@ public class DomainCreateFlow implements TransactionalFlow {
entitiesToSave.add(createEapBillingEvent(feesAndCredits, createBillingEvent)); entitiesToSave.add(createEapBillingEvent(feesAndCredits, createBillingEvent));
} }
ImmutableSet.Builder<StatusValue> statuses = new ImmutableSet.Builder<>(); ImmutableSet<ReservationType> reservationTypes = getReservationTypes(domainName);
if (getReservationTypes(domainName).contains(NAME_COLLISION)) { ImmutableSet<StatusValue> statuses =
statuses.add(SERVER_HOLD); reservationTypes.contains(NAME_COLLISION)
entitiesToSave.add( ? ImmutableSet.of(SERVER_HOLD)
createNameCollisionOneTimePollMessage(targetId, domainHistory, clientId, now)); : ImmutableSet.of();
} DomainBase domain =
DomainBase newDomain =
new DomainBase.Builder() new DomainBase.Builder()
.setCreationClientId(clientId) .setCreationClientId(clientId)
.setPersistedCurrentSponsorClientId(clientId) .setPersistedCurrentSponsorClientId(clientId)
@ -348,34 +349,38 @@ public class DomainCreateFlow implements TransactionalFlow {
.setAutorenewPollMessage(autorenewPollMessage.createVKey()) .setAutorenewPollMessage(autorenewPollMessage.createVKey())
.setLaunchNotice(hasClaimsNotice ? launchCreate.get().getNotice() : null) .setLaunchNotice(hasClaimsNotice ? launchCreate.get().getNotice() : null)
.setSmdId(signedMarkId) .setSmdId(signedMarkId)
.setDsData(secDnsCreate.isPresent() ? secDnsCreate.get().getDsData() : null) .setDsData(secDnsCreate.map(SecDnsCreateExtension::getDsData).orElse(null))
.setRegistrant(command.getRegistrant()) .setRegistrant(command.getRegistrant())
.setAuthInfo(command.getAuthInfo()) .setAuthInfo(command.getAuthInfo())
.setDomainName(targetId) .setDomainName(targetId)
.setNameservers( .setNameservers(command.getNameservers().stream().collect(toImmutableSet()))
(ImmutableSet<VKey<HostResource>>) .setStatusValues(statuses)
command.getNameservers().stream().collect(toImmutableSet()))
.setStatusValues(statuses.build())
.setContacts(command.getContacts()) .setContacts(command.getContacts())
.addGracePeriod( .addGracePeriod(
GracePeriod.forBillingEvent(GracePeriodStatus.ADD, repoId, createBillingEvent)) GracePeriod.forBillingEvent(GracePeriodStatus.ADD, repoId, createBillingEvent))
.build(); .build();
DomainHistory domainHistory =
buildDomainHistory(domain, registry, now, period, registry.getAddGracePeriodLength());
if (reservationTypes.contains(NAME_COLLISION)) {
entitiesToSave.add(
createNameCollisionOneTimePollMessage(targetId, domainHistory, clientId, now));
}
entitiesToSave.add( entitiesToSave.add(
newDomain, domain,
domainHistory.asBuilder().setDomainContent(newDomain).build(), domainHistory,
ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()), ForeignKeyIndex.create(domain, domain.getDeletionTime()),
EppResourceIndex.create(Key.create(newDomain))); EppResourceIndex.create(Key.create(domain)));
if (allocationToken.isPresent() if (allocationToken.isPresent()
&& TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) { && TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) {
entitiesToSave.add( entitiesToSave.add(
allocationTokenFlowUtils.redeemToken(allocationToken.get(), domainHistory.createVKey())); allocationTokenFlowUtils.redeemToken(allocationToken.get(), domainHistory.createVKey()));
} }
enqueueTasks(newDomain, hasSignedMarks, hasClaimsNotice); enqueueTasks(domain, hasSignedMarks, hasClaimsNotice);
EntityChanges entityChanges = EntityChanges entityChanges =
flowCustomLogic.beforeSave( flowCustomLogic.beforeSave(
DomainCreateFlowCustomLogic.BeforeSaveParameters.newBuilder() DomainCreateFlowCustomLogic.BeforeSaveParameters.newBuilder()
.setNewDomain(newDomain) .setNewDomain(domain)
.setHistoryEntry(domainHistory) .setHistoryEntry(domainHistory)
.setEntityChanges( .setEntityChanges(
EntityChanges.newBuilder().setSaves(entitiesToSave.build()).build()) EntityChanges.newBuilder().setSaves(entitiesToSave.build()).build())
@ -480,8 +485,8 @@ public class DomainCreateFlow implements TransactionalFlow {
: null); : null);
} }
private DomainHistory buildHistoryEntry( private DomainHistory buildDomainHistory(
String repoId, Registry registry, DateTime now, Period period, Duration addGracePeriod) { DomainBase domain, Registry registry, DateTime now, Period period, Duration addGracePeriod) {
// We ignore prober transactions // We ignore prober transactions
if (registry.getTldType() == TldType.REAL) { if (registry.getTldType() == TldType.REAL) {
historyBuilder historyBuilder
@ -497,7 +502,7 @@ public class DomainCreateFlow implements TransactionalFlow {
.setType(HistoryEntry.Type.DOMAIN_CREATE) .setType(HistoryEntry.Type.DOMAIN_CREATE)
.setPeriod(period) .setPeriod(period)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(DomainBase.class, repoId)) .setDomainContent(domain)
.build(); .build();
} }
@ -508,7 +513,7 @@ public class DomainCreateFlow implements TransactionalFlow {
boolean isReserved, boolean isReserved,
int years, int years,
FeesAndCredits feesAndCredits, FeesAndCredits feesAndCredits,
DomainHistory domainHistory, Key<DomainHistory> domainHistoryKey,
Optional<AllocationToken> allocationToken, Optional<AllocationToken> allocationToken,
DateTime now) { DateTime now) {
ImmutableSet.Builder<Flag> flagsBuilder = new ImmutableSet.Builder<>(); ImmutableSet.Builder<Flag> flagsBuilder = new ImmutableSet.Builder<>();
@ -537,12 +542,12 @@ public class DomainCreateFlow implements TransactionalFlow {
? registry.getAnchorTenantAddGracePeriodLength() ? registry.getAnchorTenantAddGracePeriodLength()
: registry.getAddGracePeriodLength())) : registry.getAddGracePeriodLength()))
.setFlags(flagsBuilder.build()) .setFlags(flagsBuilder.build())
.setParent(domainHistory) .setParent(domainHistoryKey)
.build(); .build();
} }
private Recurring createAutorenewBillingEvent( private Recurring createAutorenewBillingEvent(
DomainHistory domainHistory, DateTime registrationExpirationTime) { Key<DomainHistory> domainHistoryKey, DateTime registrationExpirationTime) {
return new BillingEvent.Recurring.Builder() return new BillingEvent.Recurring.Builder()
.setReason(Reason.RENEW) .setReason(Reason.RENEW)
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) .setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
@ -550,18 +555,18 @@ public class DomainCreateFlow implements TransactionalFlow {
.setClientId(clientId) .setClientId(clientId)
.setEventTime(registrationExpirationTime) .setEventTime(registrationExpirationTime)
.setRecurrenceEndTime(END_OF_TIME) .setRecurrenceEndTime(END_OF_TIME)
.setParent(domainHistory) .setParent(domainHistoryKey)
.build(); .build();
} }
private Autorenew createAutorenewPollMessage( private Autorenew createAutorenewPollMessage(
HistoryEntry historyEntry, DateTime registrationExpirationTime) { Key<DomainHistory> domainHistoryKey, DateTime registrationExpirationTime) {
return new PollMessage.Autorenew.Builder() return new PollMessage.Autorenew.Builder()
.setTargetId(targetId) .setTargetId(targetId)
.setClientId(clientId) .setClientId(clientId)
.setEventTime(registrationExpirationTime) .setEventTime(registrationExpirationTime)
.setMsg("Domain was auto-renewed.") .setMsg("Domain was auto-renewed.")
.setParent(historyEntry) .setParentKey(domainHistoryKey)
.build(); .build();
} }

View file

@ -16,6 +16,7 @@ package google.registry.flows.domain;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.base.Strings.isNullOrEmpty;
import static google.registry.flows.FlowUtils.createHistoryKey;
import static google.registry.flows.FlowUtils.persistEntityChanges; import static google.registry.flows.FlowUtils.persistEntityChanges;
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;
@ -63,6 +64,7 @@ import google.registry.flows.custom.EntityChanges;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod; import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.fee.BaseFee.FeeType; import google.registry.model.domain.fee.BaseFee.FeeType;
import google.registry.model.domain.fee.Credit; import google.registry.model.domain.fee.Credit;
@ -125,7 +127,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
@Inject @ClientId String clientId; @Inject @ClientId String clientId;
@Inject @TargetId String targetId; @Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser; @Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder; @Inject DomainHistory.Builder historyBuilder;
@Inject DnsQueue dnsQueue; @Inject DnsQueue dnsQueue;
@Inject Trid trid; @Inject Trid trid;
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer; @Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
@ -177,8 +179,8 @@ public final class DomainDeleteFlow implements TransactionalFlow {
? Duration.ZERO ? Duration.ZERO
// By default, this should be 30 days of grace, and 5 days of pending delete. // By default, this should be 30 days of grace, and 5 days of pending delete.
: redemptionGracePeriodLength.plus(pendingDeleteLength); : redemptionGracePeriodLength.plus(pendingDeleteLength);
HistoryEntry historyEntry = Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
buildHistoryEntry(existingDomain, registry, now, durationUntilDelete, inAddGracePeriod); historyBuilder.setId(domainHistoryKey.getId());
DateTime deletionTime = now.plus(durationUntilDelete); DateTime deletionTime = now.plus(durationUntilDelete);
if (durationUntilDelete.equals(Duration.ZERO)) { if (durationUntilDelete.equals(Duration.ZERO)) {
builder.setDeletionTime(now).setStatusValues(null); builder.setDeletionTime(now).setStatusValues(null);
@ -210,7 +212,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
// it is synchronous). // it is synchronous).
if (durationUntilDelete.isLongerThan(Duration.ZERO) || isSuperuser) { if (durationUntilDelete.isLongerThan(Duration.ZERO) || isSuperuser) {
PollMessage.OneTime deletePollMessage = PollMessage.OneTime deletePollMessage =
createDeletePollMessage(existingDomain, historyEntry, deletionTime); createDeletePollMessage(existingDomain, domainHistoryKey, deletionTime);
entitiesToSave.add(deletePollMessage); entitiesToSave.add(deletePollMessage);
builder.setDeletePollMessage(deletePollMessage.createVKey()); builder.setDeletePollMessage(deletePollMessage.createVKey());
} }
@ -220,7 +222,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
if (durationUntilDelete.isLongerThan(Duration.ZERO) if (durationUntilDelete.isLongerThan(Duration.ZERO)
&& !clientId.equals(existingDomain.getPersistedCurrentSponsorClientId())) { && !clientId.equals(existingDomain.getPersistedCurrentSponsorClientId())) {
entitiesToSave.add( entitiesToSave.add(
createImmediateDeletePollMessage(existingDomain, historyEntry, now, deletionTime)); createImmediateDeletePollMessage(existingDomain, domainHistoryKey, now, deletionTime));
} }
// Cancel any grace periods that were still active, and set the expiration time accordingly. // Cancel any grace periods that were still active, and set the expiration time accordingly.
@ -229,7 +231,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
// No cancellation is written if the grace period was not for a billable event. // No cancellation is written if the grace period was not for a billable event.
if (gracePeriod.hasBillingEvent()) { if (gracePeriod.hasBillingEvent()) {
entitiesToSave.add( entitiesToSave.add(
BillingEvent.Cancellation.forGracePeriod(gracePeriod, historyEntry, targetId)); BillingEvent.Cancellation.forGracePeriod(gracePeriod, now, domainHistoryKey, targetId));
if (gracePeriod.getOneTimeBillingEvent() != null) { if (gracePeriod.getOneTimeBillingEvent() != null) {
// Take the amount of amount of registration time being refunded off the expiration time. // Take the amount of amount of registration time being refunded off the expiration time.
// This can be either add grace periods or renew grace periods. // This can be either add grace periods or renew grace periods.
@ -245,8 +247,10 @@ public final class DomainDeleteFlow implements TransactionalFlow {
builder.setRegistrationExpirationTime(newExpirationTime); builder.setRegistrationExpirationTime(newExpirationTime);
DomainBase newDomain = builder.build(); DomainBase newDomain = builder.build();
DomainHistory domainHistory =
buildDomainHistory(newDomain, registry, now, durationUntilDelete, inAddGracePeriod);
updateForeignKeyIndexDeletionTime(newDomain); updateForeignKeyIndexDeletionTime(newDomain);
handlePendingTransferOnDelete(existingDomain, newDomain, now, historyEntry); handlePendingTransferOnDelete(existingDomain, newDomain, now, domainHistory);
// Close the autorenew billing event and poll message. This may delete the poll message. // Close the autorenew billing event and poll message. This may delete the poll message.
updateAutorenewRecurrenceEndTime(existingDomain, now); updateAutorenewRecurrenceEndTime(existingDomain, now);
// If there's a pending transfer, the gaining client's autorenew billing // If there's a pending transfer, the gaining client's autorenew billing
@ -254,14 +258,16 @@ public final class DomainDeleteFlow implements TransactionalFlow {
// ResourceDeleteFlow since it's listed in serverApproveEntities. // ResourceDeleteFlow since it's listed in serverApproveEntities.
dnsQueue.addDomainRefreshTask(existingDomain.getDomainName()); dnsQueue.addDomainRefreshTask(existingDomain.getDomainName());
entitiesToSave.add(newDomain, historyEntry); entitiesToSave.add(newDomain, domainHistory);
EntityChanges entityChanges = flowCustomLogic.beforeSave( EntityChanges entityChanges =
BeforeSaveParameters.newBuilder() flowCustomLogic.beforeSave(
.setExistingDomain(existingDomain) BeforeSaveParameters.newBuilder()
.setNewDomain(newDomain) .setExistingDomain(existingDomain)
.setHistoryEntry(historyEntry) .setNewDomain(newDomain)
.setEntityChanges(EntityChanges.newBuilder().setSaves(entitiesToSave.build()).build()) .setHistoryEntry(domainHistory)
.build()); .setEntityChanges(
EntityChanges.newBuilder().setSaves(entitiesToSave.build()).build())
.build());
BeforeResponseReturnData responseData = BeforeResponseReturnData responseData =
flowCustomLogic.beforeResponse( flowCustomLogic.beforeResponse(
BeforeResponseParameters.newBuilder() BeforeResponseParameters.newBuilder()
@ -292,8 +298,8 @@ public final class DomainDeleteFlow implements TransactionalFlow {
} }
} }
private HistoryEntry buildHistoryEntry( private DomainHistory buildDomainHistory(
DomainBase existingResource, DomainBase domain,
Registry registry, Registry registry,
DateTime now, DateTime now,
Duration durationUntilDelete, Duration durationUntilDelete,
@ -307,31 +313,30 @@ public final class DomainDeleteFlow implements TransactionalFlow {
registry.getRenewGracePeriodLength())); registry.getRenewGracePeriodLength()));
ImmutableSet<DomainTransactionRecord> cancelledRecords = ImmutableSet<DomainTransactionRecord> cancelledRecords =
createCancelingRecords( createCancelingRecords(
existingResource, domain,
now, now,
maxGracePeriod, maxGracePeriod,
Sets.immutableEnumSet(Sets.union(ADD_FIELDS, RENEW_FIELDS))); Sets.immutableEnumSet(Sets.union(ADD_FIELDS, RENEW_FIELDS)));
historyBuilder historyBuilder.setDomainTransactionRecords(
.setDomainTransactionRecords( union(
union( cancelledRecords,
cancelledRecords, DomainTransactionRecord.create(
DomainTransactionRecord.create( domain.getTld(),
existingResource.getTld(), now.plus(durationUntilDelete),
now.plus(durationUntilDelete), inAddGracePeriod
inAddGracePeriod ? TransactionReportField.DELETED_DOMAINS_GRACE
? TransactionReportField.DELETED_DOMAINS_GRACE : TransactionReportField.DELETED_DOMAINS_NOGRACE,
: TransactionReportField.DELETED_DOMAINS_NOGRACE, 1)));
1)));
} }
return historyBuilder return historyBuilder
.setType(HistoryEntry.Type.DOMAIN_DELETE) .setType(HistoryEntry.Type.DOMAIN_DELETE)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingResource)) .setDomainContent(domain)
.build(); .build();
} }
private PollMessage.OneTime createDeletePollMessage( private PollMessage.OneTime createDeletePollMessage(
DomainBase existingDomain, HistoryEntry historyEntry, DateTime deletionTime) { DomainBase existingDomain, Key<DomainHistory> domainHistoryKey, DateTime deletionTime) {
Optional<MetadataExtension> metadataExtension = Optional<MetadataExtension> metadataExtension =
eppInput.getSingleExtension(MetadataExtension.class); eppInput.getSingleExtension(MetadataExtension.class);
boolean hasMetadataMessage = boolean hasMetadataMessage =
@ -350,16 +355,19 @@ public final class DomainDeleteFlow implements TransactionalFlow {
ImmutableList.of( ImmutableList.of(
DomainPendingActionNotificationResponse.create( DomainPendingActionNotificationResponse.create(
existingDomain.getDomainName(), true, trid, deletionTime))) existingDomain.getDomainName(), true, trid, deletionTime)))
.setParent(historyEntry) .setParentKey(domainHistoryKey)
.build(); .build();
} }
private PollMessage.OneTime createImmediateDeletePollMessage( private PollMessage.OneTime createImmediateDeletePollMessage(
DomainBase existingDomain, HistoryEntry historyEntry, DateTime now, DateTime deletionTime) { DomainBase existingDomain,
Key<DomainHistory> domainHistoryKey,
DateTime now,
DateTime deletionTime) {
return new PollMessage.OneTime.Builder() return new PollMessage.OneTime.Builder()
.setClientId(existingDomain.getPersistedCurrentSponsorClientId()) .setClientId(existingDomain.getPersistedCurrentSponsorClientId())
.setEventTime(now) .setEventTime(now)
.setParent(historyEntry) .setParentKey(domainHistoryKey)
.setMsg( .setMsg(
String.format( String.format(
"Domain %s was deleted by registry administrator with final deletion effective: %s", "Domain %s was deleted by registry administrator with final deletion effective: %s",

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain; package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.createHistoryKey;
import static google.registry.flows.FlowUtils.persistEntityChanges; import static google.registry.flows.FlowUtils.persistEntityChanges;
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;
@ -33,6 +34,7 @@ import static google.registry.util.DateTimeUtils.leapSafeAddYears;
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.googlecode.objectify.Key;
import google.registry.flows.EppException; import google.registry.flows.EppException;
import google.registry.flows.EppException.ParameterValueRangeErrorException; import google.registry.flows.EppException.ParameterValueRangeErrorException;
import google.registry.flows.ExtensionManager; import google.registry.flows.ExtensionManager;
@ -52,6 +54,7 @@ import google.registry.model.billing.BillingEvent.OneTime;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainCommand.Renew; import google.registry.model.domain.DomainCommand.Renew;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.DomainRenewData; import google.registry.model.domain.DomainRenewData;
import google.registry.model.domain.GracePeriod; import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.Period; import google.registry.model.domain.Period;
@ -123,7 +126,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
@Inject @ClientId String clientId; @Inject @ClientId String clientId;
@Inject @TargetId String targetId; @Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser; @Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder; @Inject DomainHistory.Builder historyBuilder;
@Inject EppResponse.Builder responseBuilder; @Inject EppResponse.Builder responseBuilder;
@Inject DomainRenewFlowCustomLogic flowCustomLogic; @Inject DomainRenewFlowCustomLogic flowCustomLogic;
@Inject DomainPricingLogic pricingLogic; @Inject DomainPricingLogic pricingLogic;
@ -156,22 +159,23 @@ public final class DomainRenewFlow implements TransactionalFlow {
.setNow(now) .setNow(now)
.setYears(years) .setYears(years)
.build()); .build());
Registry registry = Registry.get(existingDomain.getTld()); Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
HistoryEntry historyEntry = buildHistoryEntry( historyBuilder.setId(domainHistoryKey.getId());
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 =
createRenewBillingEvent(tld, feesAndCredits.getTotalCost(), years, historyEntry, now); createRenewBillingEvent(tld, feesAndCredits.getTotalCost(), years, domainHistoryKey, now);
// Create a new autorenew billing event and poll message starting at the new expiration time. // Create a new autorenew billing event and poll message starting at the new expiration time.
BillingEvent.Recurring newAutorenewEvent = newAutorenewBillingEvent(existingDomain) BillingEvent.Recurring newAutorenewEvent =
.setEventTime(newExpirationTime) newAutorenewBillingEvent(existingDomain)
.setParent(historyEntry) .setEventTime(newExpirationTime)
.build(); .setParent(domainHistoryKey)
PollMessage.Autorenew newAutorenewPollMessage = newAutorenewPollMessage(existingDomain) .build();
.setEventTime(newExpirationTime) PollMessage.Autorenew newAutorenewPollMessage =
.setParent(historyEntry) newAutorenewPollMessage(existingDomain)
.build(); .setEventTime(newExpirationTime)
.setParentKey(domainHistoryKey)
.build();
// End the old autorenew billing event and poll message now. This may delete the poll message. // End the old autorenew billing event and poll message now. This may delete the poll message.
updateAutorenewRecurrenceEndTime(existingDomain, now); updateAutorenewRecurrenceEndTime(existingDomain, now);
DomainBase newDomain = DomainBase newDomain =
@ -186,6 +190,10 @@ public final class DomainRenewFlow implements TransactionalFlow {
GracePeriod.forBillingEvent( GracePeriod.forBillingEvent(
GracePeriodStatus.RENEW, existingDomain.getRepoId(), explicitRenewEvent)) GracePeriodStatus.RENEW, existingDomain.getRepoId(), explicitRenewEvent))
.build(); .build();
Registry registry = Registry.get(existingDomain.getTld());
DomainHistory domainHistory =
buildDomainHistory(
newDomain, now, command.getPeriod(), registry.getRenewGracePeriodLength());
EntityChanges entityChanges = EntityChanges entityChanges =
flowCustomLogic.beforeSave( flowCustomLogic.beforeSave(
BeforeSaveParameters.newBuilder() BeforeSaveParameters.newBuilder()
@ -193,19 +201,18 @@ public final class DomainRenewFlow implements TransactionalFlow {
.setNewDomain(newDomain) .setNewDomain(newDomain)
.setNow(now) .setNow(now)
.setYears(years) .setYears(years)
.setHistoryEntry(historyEntry) .setHistoryEntry(domainHistory)
.setEntityChanges( .setEntityChanges(
EntityChanges.newBuilder() EntityChanges.newBuilder()
.setSaves( .setSaves(
ImmutableSet.of( ImmutableSet.of(
newDomain, newDomain,
historyEntry, domainHistory,
explicitRenewEvent, explicitRenewEvent,
newAutorenewEvent, newAutorenewEvent,
newAutorenewPollMessage)) newAutorenewPollMessage))
.build()) .build())
.build()); .build());
persistEntityChanges(entityChanges);
BeforeResponseReturnData responseData = BeforeResponseReturnData responseData =
flowCustomLogic.beforeResponse( flowCustomLogic.beforeResponse(
BeforeResponseParameters.newBuilder() BeforeResponseParameters.newBuilder()
@ -213,23 +220,24 @@ public final class DomainRenewFlow implements TransactionalFlow {
.setResData(DomainRenewData.create(targetId, newExpirationTime)) .setResData(DomainRenewData.create(targetId, newExpirationTime))
.setResponseExtensions(createResponseExtensions(feesAndCredits, feeRenew)) .setResponseExtensions(createResponseExtensions(feesAndCredits, feeRenew))
.build()); .build());
persistEntityChanges(entityChanges);
return responseBuilder return responseBuilder
.setResData(responseData.resData()) .setResData(responseData.resData())
.setExtensions(responseData.responseExtensions()) .setExtensions(responseData.responseExtensions())
.build(); .build();
} }
private HistoryEntry buildHistoryEntry( private DomainHistory buildDomainHistory(
DomainBase existingDomain, DateTime now, Period period, Duration renewGracePeriod) { DomainBase newDomain, DateTime now, Period period, Duration renewGracePeriod) {
return historyBuilder return historyBuilder
.setType(HistoryEntry.Type.DOMAIN_RENEW) .setType(HistoryEntry.Type.DOMAIN_RENEW)
.setPeriod(period) .setPeriod(period)
.setModificationTime(now) .setModificationTime(now)
.setParent(existingDomain) .setDomainContent(newDomain)
.setDomainTransactionRecords( .setDomainTransactionRecords(
ImmutableSet.of( ImmutableSet.of(
DomainTransactionRecord.create( DomainTransactionRecord.create(
existingDomain.getTld(), newDomain.getTld(),
now.plus(renewGracePeriod), now.plus(renewGracePeriod),
TransactionReportField.netRenewsFieldFromYears(period.getValue()), TransactionReportField.netRenewsFieldFromYears(period.getValue()),
1))) 1)))
@ -255,7 +263,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
} }
private OneTime createRenewBillingEvent( private OneTime createRenewBillingEvent(
String tld, Money renewCost, int years, HistoryEntry historyEntry, DateTime now) { String tld, Money renewCost, int years, Key<DomainHistory> domainHistoryKey, DateTime now) {
return new BillingEvent.OneTime.Builder() return new BillingEvent.OneTime.Builder()
.setReason(Reason.RENEW) .setReason(Reason.RENEW)
.setTargetId(targetId) .setTargetId(targetId)
@ -264,7 +272,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
.setCost(renewCost) .setCost(renewCost)
.setEventTime(now) .setEventTime(now)
.setBillingTime(now.plus(Registry.get(tld).getRenewGracePeriodLength())) .setBillingTime(now.plus(Registry.get(tld).getRenewGracePeriodLength()))
.setParent(historyEntry) .setParent(domainHistoryKey)
.build(); .build();
} }

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain; package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.createHistoryKey;
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;
@ -49,6 +50,7 @@ import google.registry.model.billing.BillingEvent.OneTime;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainCommand.Update; import google.registry.model.domain.DomainCommand.Update;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.fee.BaseFee.FeeType; import google.registry.model.domain.fee.BaseFee.FeeType;
import google.registry.model.domain.fee.Fee; import google.registry.model.domain.fee.Fee;
import google.registry.model.domain.fee.FeeTransformResponseExtension; import google.registry.model.domain.fee.FeeTransformResponseExtension;
@ -117,7 +119,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
@Inject @ClientId String clientId; @Inject @ClientId String clientId;
@Inject @TargetId String targetId; @Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser; @Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder; @Inject DomainHistory.Builder historyBuilder;
@Inject DnsQueue dnsQueue; @Inject DnsQueue dnsQueue;
@Inject EppResponse.Builder responseBuilder; @Inject EppResponse.Builder responseBuilder;
@Inject DomainPricingLogic pricingLogic; @Inject DomainPricingLogic pricingLogic;
@ -142,7 +144,8 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
Optional<FeeUpdateCommandExtension> feeUpdate = Optional<FeeUpdateCommandExtension> feeUpdate =
eppInput.getSingleExtension(FeeUpdateCommandExtension.class); eppInput.getSingleExtension(FeeUpdateCommandExtension.class);
verifyRestoreAllowed(command, existingDomain, feeUpdate, feesAndCredits, now); verifyRestoreAllowed(command, existingDomain, feeUpdate, feesAndCredits, now);
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, now); Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
historyBuilder.setId(domainHistoryKey.getId());
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>(); ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
DateTime newExpirationTime = DateTime newExpirationTime =
@ -150,29 +153,31 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
// Restore the expiration time on the deleted domain, except if that's already passed, then add // Restore the expiration time on the deleted domain, except if that's already passed, then add
// a year and bill for it immediately, with no grace period. // a year and bill for it immediately, with no grace period.
if (isExpired) { if (isExpired) {
entitiesToSave.add(createRenewBillingEvent(historyEntry, feesAndCredits.getRenewCost(), now)); entitiesToSave.add(
createRenewBillingEvent(domainHistoryKey, feesAndCredits.getRenewCost(), now));
} }
// Always bill for the restore itself. // Always bill for the restore itself.
entitiesToSave.add( entitiesToSave.add(
createRestoreBillingEvent(historyEntry, feesAndCredits.getRestoreCost(), now)); createRestoreBillingEvent(domainHistoryKey, feesAndCredits.getRestoreCost(), now));
BillingEvent.Recurring autorenewEvent = BillingEvent.Recurring autorenewEvent =
newAutorenewBillingEvent(existingDomain) newAutorenewBillingEvent(existingDomain)
.setEventTime(newExpirationTime) .setEventTime(newExpirationTime)
.setRecurrenceEndTime(END_OF_TIME) .setRecurrenceEndTime(END_OF_TIME)
.setParent(historyEntry) .setParent(domainHistoryKey)
.build(); .build();
PollMessage.Autorenew autorenewPollMessage = PollMessage.Autorenew autorenewPollMessage =
newAutorenewPollMessage(existingDomain) newAutorenewPollMessage(existingDomain)
.setEventTime(newExpirationTime) .setEventTime(newExpirationTime)
.setAutorenewEndTime(END_OF_TIME) .setAutorenewEndTime(END_OF_TIME)
.setParent(historyEntry) .setParentKey(domainHistoryKey)
.build(); .build();
DomainBase newDomain = DomainBase newDomain =
performRestore( performRestore(
existingDomain, newExpirationTime, autorenewEvent, autorenewPollMessage, now, clientId); existingDomain, newExpirationTime, autorenewEvent, autorenewPollMessage, now, clientId);
updateForeignKeyIndexDeletionTime(newDomain); updateForeignKeyIndexDeletionTime(newDomain);
entitiesToSave.add(newDomain, historyEntry, autorenewEvent, autorenewPollMessage); DomainHistory domainHistory = buildDomainHistory(newDomain, now);
entitiesToSave.add(newDomain, domainHistory, autorenewEvent, autorenewPollMessage);
tm().putAll(entitiesToSave.build()); tm().putAll(entitiesToSave.build());
tm().delete(existingDomain.getDeletePollMessage()); tm().delete(existingDomain.getDeletePollMessage());
dnsQueue.addDomainRefreshTask(existingDomain.getDomainName()); dnsQueue.addDomainRefreshTask(existingDomain.getDomainName());
@ -181,15 +186,15 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
.build(); .build();
} }
private HistoryEntry buildHistoryEntry(DomainBase existingDomain, DateTime now) { private DomainHistory buildDomainHistory(DomainBase newDomain, DateTime now) {
return historyBuilder return historyBuilder
.setType(HistoryEntry.Type.DOMAIN_RESTORE) .setType(HistoryEntry.Type.DOMAIN_RESTORE)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingDomain)) .setDomainContent(newDomain)
.setDomainTransactionRecords( .setDomainTransactionRecords(
ImmutableSet.of( ImmutableSet.of(
DomainTransactionRecord.create( DomainTransactionRecord.create(
existingDomain.getTld(), now, TransactionReportField.RESTORED_DOMAINS, 1))) newDomain.getTld(), now, TransactionReportField.RESTORED_DOMAINS, 1)))
.build(); .build();
} }
@ -242,20 +247,19 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
} }
private OneTime createRenewBillingEvent( private OneTime createRenewBillingEvent(
HistoryEntry historyEntry, Money renewCost, DateTime now) { Key<DomainHistory> domainHistoryKey, Money renewCost, DateTime now) {
return prepareBillingEvent(historyEntry, renewCost, now) return prepareBillingEvent(domainHistoryKey, renewCost, now).setReason(Reason.RENEW).build();
.setReason(Reason.RENEW)
.build();
} }
private BillingEvent.OneTime createRestoreBillingEvent( private BillingEvent.OneTime createRestoreBillingEvent(
HistoryEntry historyEntry, Money restoreCost, DateTime now) { Key<DomainHistory> domainHistoryKey, Money restoreCost, DateTime now) {
return prepareBillingEvent(historyEntry, restoreCost, now) return prepareBillingEvent(domainHistoryKey, restoreCost, now)
.setReason(Reason.RESTORE) .setReason(Reason.RESTORE)
.build(); .build();
} }
private OneTime.Builder prepareBillingEvent(HistoryEntry historyEntry, Money cost, DateTime now) { private OneTime.Builder prepareBillingEvent(
Key<DomainHistory> domainHistoryKey, Money cost, DateTime now) {
return new BillingEvent.OneTime.Builder() return new BillingEvent.OneTime.Builder()
.setTargetId(targetId) .setTargetId(targetId)
.setClientId(clientId) .setClientId(clientId)
@ -263,7 +267,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
.setBillingTime(now) .setBillingTime(now)
.setPeriodYears(1) .setPeriodYears(1)
.setCost(cost) .setCost(cost)
.setParent(historyEntry); .setParent(domainHistoryKey);
} }
private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions( private static ImmutableList<FeeTransformResponseExtension> createResponseExtensions(

View file

@ -15,6 +15,7 @@
package google.registry.flows.domain; package google.registry.flows.domain;
import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.collect.Iterables.getOnlyElement;
import static google.registry.flows.FlowUtils.createHistoryKey;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn; import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime; import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
@ -48,6 +49,7 @@ import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag; import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod; import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
@ -90,7 +92,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
@Inject @ClientId String clientId; @Inject @ClientId String clientId;
@Inject @TargetId String targetId; @Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser; @Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder; @Inject DomainHistory.Builder historyBuilder;
@Inject EppResponse.Builder responseBuilder; @Inject EppResponse.Builder responseBuilder;
@Inject DomainTransferApproveFlow() {} @Inject DomainTransferApproveFlow() {}
@ -114,10 +116,10 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
} }
DomainTransferData transferData = existingDomain.getTransferData(); DomainTransferData transferData = existingDomain.getTransferData();
String gainingClientId = transferData.getGainingClientId(); String gainingClientId = transferData.getGainingClientId();
Registry registry = Registry.get(existingDomain.getTld());
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now, gainingClientId);
// Create a transfer billing event for 1 year, unless the superuser extension was used to set // Create a transfer billing event for 1 year, unless the superuser extension was used to set
// the transfer period to zero. There is not a transfer cost if the transfer period is zero. // the transfer period to zero. There is not a transfer cost if the transfer period is zero.
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
historyBuilder.setId(domainHistoryKey.getId());
Optional<BillingEvent.OneTime> billingEvent = Optional<BillingEvent.OneTime> billingEvent =
(transferData.getTransferPeriod().getValue() == 0) (transferData.getTransferPeriod().getValue() == 0)
? Optional.empty() ? Optional.empty()
@ -130,10 +132,9 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
.setCost(getDomainRenewCost(targetId, transferData.getTransferRequestTime(), 1)) .setCost(getDomainRenewCost(targetId, transferData.getTransferRequestTime(), 1))
.setEventTime(now) .setEventTime(now)
.setBillingTime(now.plus(Registry.get(tld).getTransferGracePeriodLength())) .setBillingTime(now.plus(Registry.get(tld).getTransferGracePeriodLength()))
.setParent(historyEntry) .setParent(domainHistoryKey)
.build()); .build());
ImmutableList.Builder<ImmutableObject> entitiesToSave = new ImmutableList.Builder<>(); ImmutableList.Builder<ImmutableObject> entitiesToSave = new ImmutableList.Builder<>();
entitiesToSave.add(historyEntry);
// If we are within an autorenew grace period, cancel the autorenew billing event and don't // If we are within an autorenew grace period, cancel the autorenew billing event and don't
// increase the registration time, since the transfer subsumes the autorenew's extra year. // increase the registration time, since the transfer subsumes the autorenew's extra year.
GracePeriod autorenewGrace = GracePeriod autorenewGrace =
@ -146,7 +147,8 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
// still needs to be charged for the auto-renew. // still needs to be charged for the auto-renew.
if (billingEvent.isPresent()) { if (billingEvent.isPresent()) {
entitiesToSave.add( entitiesToSave.add(
BillingEvent.Cancellation.forGracePeriod(autorenewGrace, historyEntry, targetId)); BillingEvent.Cancellation.forGracePeriod(
autorenewGrace, now, domainHistoryKey, targetId));
} }
} }
// Close the old autorenew event and poll message at the transfer time (aka now). This may end // Close the old autorenew event and poll message at the transfer time (aka now). This may end
@ -155,24 +157,26 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
DateTime newExpirationTime = DateTime newExpirationTime =
computeExDateForApprovalTime(existingDomain, now, transferData.getTransferPeriod()); computeExDateForApprovalTime(existingDomain, now, transferData.getTransferPeriod());
// Create a new autorenew event starting at the expiration time. // Create a new autorenew event starting at the expiration time.
BillingEvent.Recurring autorenewEvent = new BillingEvent.Recurring.Builder() BillingEvent.Recurring autorenewEvent =
.setReason(Reason.RENEW) new BillingEvent.Recurring.Builder()
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) .setReason(Reason.RENEW)
.setTargetId(targetId) .setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
.setClientId(gainingClientId) .setTargetId(targetId)
.setEventTime(newExpirationTime) .setClientId(gainingClientId)
.setRecurrenceEndTime(END_OF_TIME) .setEventTime(newExpirationTime)
.setParent(historyEntry) .setRecurrenceEndTime(END_OF_TIME)
.build(); .setParent(domainHistoryKey)
.build();
// Create a new autorenew poll message. // Create a new autorenew poll message.
PollMessage.Autorenew gainingClientAutorenewPollMessage = new PollMessage.Autorenew.Builder() PollMessage.Autorenew gainingClientAutorenewPollMessage =
.setTargetId(targetId) new PollMessage.Autorenew.Builder()
.setClientId(gainingClientId) .setTargetId(targetId)
.setEventTime(newExpirationTime) .setClientId(gainingClientId)
.setAutorenewEndTime(END_OF_TIME) .setEventTime(newExpirationTime)
.setMsg("Domain was auto-renewed.") .setAutorenewEndTime(END_OF_TIME)
.setParent(historyEntry) .setMsg("Domain was auto-renewed.")
.build(); .setParentKey(domainHistoryKey)
.build();
// Construct the post-transfer domain. // Construct the post-transfer domain.
DomainBase partiallyApprovedDomain = DomainBase partiallyApprovedDomain =
approvePendingTransfer(existingDomain, TransferStatus.CLIENT_APPROVED, now); approvePendingTransfer(existingDomain, TransferStatus.CLIENT_APPROVED, now);
@ -204,13 +208,19 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
.setLastEppUpdateTime(now) .setLastEppUpdateTime(now)
.setLastEppUpdateClientId(clientId) .setLastEppUpdateClientId(clientId)
.build(); .build();
Registry registry = Registry.get(existingDomain.getTld());
DomainHistory domainHistory = buildDomainHistory(newDomain, registry, now, gainingClientId);
// Create a poll message for the gaining client. // Create a poll message for the gaining client.
PollMessage gainingClientPollMessage = PollMessage gainingClientPollMessage =
createGainingTransferPollMessage( createGainingTransferPollMessage(
targetId, newDomain.getTransferData(), newExpirationTime, historyEntry); targetId, newDomain.getTransferData(), newExpirationTime, now, domainHistoryKey);
billingEvent.ifPresent(entitiesToSave::add); billingEvent.ifPresent(entitiesToSave::add);
entitiesToSave.add( entitiesToSave.add(
autorenewEvent, gainingClientPollMessage, gainingClientAutorenewPollMessage, newDomain); autorenewEvent,
gainingClientPollMessage,
gainingClientAutorenewPollMessage,
newDomain,
domainHistory);
tm().putAll(entitiesToSave.build()); tm().putAll(entitiesToSave.build());
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
@ -221,11 +231,11 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
.build(); .build();
} }
private HistoryEntry buildHistoryEntry( private DomainHistory buildDomainHistory(
DomainBase existingDomain, Registry registry, DateTime now, String gainingClientId) { DomainBase newDomain, Registry registry, DateTime now, String gainingClientId) {
ImmutableSet<DomainTransactionRecord> cancelingRecords = ImmutableSet<DomainTransactionRecord> cancelingRecords =
createCancelingRecords( createCancelingRecords(
existingDomain, newDomain,
now, now,
registry.getAutomaticTransferLength().plus(registry.getTransferGracePeriodLength()), registry.getAutomaticTransferLength().plus(registry.getTransferGracePeriodLength()),
ImmutableSet.of(TRANSFER_SUCCESSFUL)); ImmutableSet.of(TRANSFER_SUCCESSFUL));
@ -233,15 +243,15 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE) .setType(HistoryEntry.Type.DOMAIN_TRANSFER_APPROVE)
.setModificationTime(now) .setModificationTime(now)
.setOtherClientId(gainingClientId) .setOtherClientId(gainingClientId)
.setParent(Key.create(existingDomain)) .setDomainContent(newDomain)
.setDomainTransactionRecords( .setDomainTransactionRecords(
union( union(
cancelingRecords, cancelingRecords,
DomainTransactionRecord.create( DomainTransactionRecord.create(
existingDomain.getTld(), newDomain.getTld(),
now.plus(registry.getTransferGracePeriodLength()), now.plus(registry.getTransferGracePeriodLength()),
TRANSFER_SUCCESSFUL, TRANSFER_SUCCESSFUL,
1))) 1)))
.build(); .build();
} }
} }

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain; package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.createHistoryKey;
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.verifyHasPendingTransfer; import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
@ -39,6 +40,7 @@ import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow; import google.registry.flows.TransactionalFlow;
import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.annotations.ReportingSpec;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
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;
@ -77,7 +79,7 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
@Inject @ClientId String clientId; @Inject @ClientId String clientId;
@Inject @TargetId String targetId; @Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser; @Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder; @Inject DomainHistory.Builder historyBuilder;
@Inject EppResponse.Builder responseBuilder; @Inject EppResponse.Builder responseBuilder;
@Inject DomainTransferCancelFlow() {} @Inject DomainTransferCancelFlow() {}
@ -95,14 +97,20 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
checkAllowedAccessToTld(clientId, existingDomain.getTld()); checkAllowedAccessToTld(clientId, existingDomain.getTld());
} }
Registry registry = Registry.get(existingDomain.getTld()); Registry registry = Registry.get(existingDomain.getTld());
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now);
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
historyBuilder
.setId(domainHistoryKey.getId())
.setOtherClientId(existingDomain.getTransferData().getLosingClientId());
DomainBase newDomain = DomainBase newDomain =
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_CANCELLED, now, clientId); denyPendingTransfer(existingDomain, TransferStatus.CLIENT_CANCELLED, now, clientId);
DomainHistory domainHistory = buildDomainHistory(newDomain, registry, now);
tm().putAll( tm().putAll(
newDomain, newDomain,
historyEntry, domainHistory,
createLosingTransferPollMessage( createLosingTransferPollMessage(
targetId, newDomain.getTransferData(), null, historyEntry)); targetId, newDomain.getTransferData(), null, domainHistoryKey));
// Reopen the autorenew event and poll message that we closed for the implicit transfer. This // Reopen the autorenew event and poll message that we closed for the implicit transfer. This
// may recreate the autorenew poll message if it was deleted when the transfer request was made. // may recreate the autorenew poll message if it was deleted when the transfer request was made.
updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME); updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME);
@ -114,19 +122,17 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
.build(); .build();
} }
private HistoryEntry buildHistoryEntry( private DomainHistory buildDomainHistory(DomainBase newDomain, Registry registry, DateTime now) {
DomainBase existingDomain, Registry registry, DateTime now) {
ImmutableSet<DomainTransactionRecord> cancelingRecords = ImmutableSet<DomainTransactionRecord> cancelingRecords =
createCancelingRecords( createCancelingRecords(
existingDomain, newDomain,
now, now,
registry.getAutomaticTransferLength().plus(registry.getTransferGracePeriodLength()), registry.getAutomaticTransferLength().plus(registry.getTransferGracePeriodLength()),
ImmutableSet.of(TRANSFER_SUCCESSFUL)); ImmutableSet.of(TRANSFER_SUCCESSFUL));
return historyBuilder return historyBuilder
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_CANCEL) .setType(HistoryEntry.Type.DOMAIN_TRANSFER_CANCEL)
.setOtherClientId(existingDomain.getTransferData().getLosingClientId())
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingDomain)) .setDomainContent(newDomain)
.setDomainTransactionRecords(cancelingRecords) .setDomainTransactionRecords(cancelingRecords)
.build(); .build();
} }

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain; package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.createHistoryKey;
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.verifyHasPendingTransfer; import static google.registry.flows.ResourceFlowUtils.verifyHasPendingTransfer;
@ -41,6 +42,7 @@ import google.registry.flows.FlowModule.TargetId;
import google.registry.flows.TransactionalFlow; import google.registry.flows.TransactionalFlow;
import google.registry.flows.annotations.ReportingSpec; import google.registry.flows.annotations.ReportingSpec;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
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;
@ -79,7 +81,7 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
@Inject @ClientId String clientId; @Inject @ClientId String clientId;
@Inject @TargetId String targetId; @Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser; @Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder; @Inject DomainHistory.Builder historyBuilder;
@Inject EppResponse.Builder responseBuilder; @Inject EppResponse.Builder responseBuilder;
@Inject DomainTransferRejectFlow() {} @Inject DomainTransferRejectFlow() {}
@ -91,7 +93,11 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
DateTime now = tm().getTransactionTime(); DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now); DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
Registry registry = Registry.get(existingDomain.getTld()); Registry registry = Registry.get(existingDomain.getTld());
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now); Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
historyBuilder
.setId(domainHistoryKey.getId())
.setOtherClientId(existingDomain.getTransferData().getGainingClientId());
verifyOptionalAuthInfo(authInfo, existingDomain); verifyOptionalAuthInfo(authInfo, existingDomain);
verifyHasPendingTransfer(existingDomain); verifyHasPendingTransfer(existingDomain);
verifyResourceOwnership(clientId, existingDomain); verifyResourceOwnership(clientId, existingDomain);
@ -100,11 +106,12 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
} }
DomainBase newDomain = DomainBase newDomain =
denyPendingTransfer(existingDomain, TransferStatus.CLIENT_REJECTED, now, clientId); denyPendingTransfer(existingDomain, TransferStatus.CLIENT_REJECTED, now, clientId);
DomainHistory domainHistory = buildDomainHistory(newDomain, registry, now);
tm().putAll( tm().putAll(
newDomain, newDomain,
historyEntry, domainHistory,
createGainingTransferPollMessage( createGainingTransferPollMessage(
targetId, newDomain.getTransferData(), null, historyEntry)); targetId, newDomain.getTransferData(), null, now, domainHistoryKey));
// Reopen the autorenew event and poll message that we closed for the implicit transfer. This // Reopen the autorenew event and poll message that we closed for the implicit transfer. This
// may end up recreating the poll message if it was deleted upon the transfer request. // may end up recreating the poll message if it was deleted upon the transfer request.
updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME); updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME);
@ -116,24 +123,21 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
.build(); .build();
} }
private HistoryEntry buildHistoryEntry( private DomainHistory buildDomainHistory(DomainBase newDomain, Registry registry, DateTime now) {
DomainBase existingDomain, Registry registry, DateTime now) {
ImmutableSet<DomainTransactionRecord> cancelingRecords = ImmutableSet<DomainTransactionRecord> cancelingRecords =
createCancelingRecords( createCancelingRecords(
existingDomain, newDomain,
now, now,
registry.getAutomaticTransferLength().plus(registry.getTransferGracePeriodLength()), registry.getAutomaticTransferLength().plus(registry.getTransferGracePeriodLength()),
ImmutableSet.of(TRANSFER_SUCCESSFUL)); ImmutableSet.of(TRANSFER_SUCCESSFUL));
return historyBuilder return historyBuilder
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REJECT) .setType(HistoryEntry.Type.DOMAIN_TRANSFER_REJECT)
.setModificationTime(now) .setModificationTime(now)
.setOtherClientId(existingDomain.getTransferData().getGainingClientId())
.setParent(Key.create(existingDomain))
.setDomainTransactionRecords( .setDomainTransactionRecords(
union( union(
cancelingRecords, cancelingRecords,
DomainTransactionRecord.create( DomainTransactionRecord.create(newDomain.getTld(), now, TRANSFER_NACKED, 1)))
existingDomain.getTld(), now, TRANSFER_NACKED, 1))) .setDomainContent(newDomain)
.build(); .build();
} }
} }

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain; package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.createHistoryKey;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn; import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime; import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime;
import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence; import static google.registry.flows.ResourceFlowUtils.loadAndVerifyExistence;
@ -51,6 +52,7 @@ import google.registry.flows.exceptions.TransferPeriodMustBeOneYearException;
import google.registry.flows.exceptions.TransferPeriodZeroAndFeeTransferExtensionException; import google.registry.flows.exceptions.TransferPeriodZeroAndFeeTransferExtensionException;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainCommand.Transfer; import google.registry.model.domain.DomainCommand.Transfer;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.Period; import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeTransferCommandExtension; import google.registry.model.domain.fee.FeeTransferCommandExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtension; import google.registry.model.domain.fee.FeeTransformResponseExtension;
@ -126,7 +128,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
@Inject @ClientId String gainingClientId; @Inject @ClientId String gainingClientId;
@Inject @TargetId String targetId; @Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser; @Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder; @Inject DomainHistory.Builder historyBuilder;
@Inject Trid trid; @Inject Trid trid;
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer; @Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
@Inject EppResponse.Builder responseBuilder; @Inject EppResponse.Builder responseBuilder;
@ -169,7 +171,10 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
if (feesAndCredits.isPresent()) { if (feesAndCredits.isPresent()) {
validateFeeChallenge(targetId, now, feeTransfer, feesAndCredits.get()); validateFeeChallenge(targetId, now, feeTransfer, feesAndCredits.get());
} }
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, registry, now, period); Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
historyBuilder
.setId(domainHistoryKey.getId())
.setOtherClientId(existingDomain.getCurrentSponsorClientId());
DateTime automaticTransferTime = DateTime automaticTransferTime =
superuserExtension.isPresent() superuserExtension.isPresent()
? now.plusDays(superuserExtension.get().getAutomaticTransferLength()) ? now.plusDays(superuserExtension.get().getAutomaticTransferLength())
@ -190,7 +195,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
createTransferServerApproveEntities( createTransferServerApproveEntities(
automaticTransferTime, automaticTransferTime,
serverApproveNewExpirationTime, serverApproveNewExpirationTime,
historyEntry, domainHistoryKey,
existingDomain, existingDomain,
trid, trid,
gainingClientId, gainingClientId,
@ -209,9 +214,12 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
serverApproveEntities, serverApproveEntities,
period); period);
// Create a poll message to notify the losing registrar that a transfer was requested. // Create a poll message to notify the losing registrar that a transfer was requested.
PollMessage requestPollMessage = createLosingTransferPollMessage( PollMessage requestPollMessage =
targetId, pendingTransferData, serverApproveNewExpirationTime, historyEntry) createLosingTransferPollMessage(
.asBuilder().setEventTime(now).build(); targetId, pendingTransferData, serverApproveNewExpirationTime, domainHistoryKey)
.asBuilder()
.setEventTime(now)
.build();
// End the old autorenew event and poll message at the implicit transfer time. This may delete // End the old autorenew event and poll message at the implicit transfer time. This may delete
// the poll message if it has no events left. Note that if the automatic transfer succeeds, then // the poll message if it has no events left. Note that if the automatic transfer succeeds, then
// cloneProjectedAtTime() will replace these old autorenew entities with the server approve ones // cloneProjectedAtTime() will replace these old autorenew entities with the server approve ones
@ -225,10 +233,12 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
.setLastEppUpdateTime(now) .setLastEppUpdateTime(now)
.setLastEppUpdateClientId(gainingClientId) .setLastEppUpdateClientId(gainingClientId)
.build(); .build();
DomainHistory domainHistory = buildDomainHistory(newDomain, registry, now, period);
asyncTaskEnqueuer.enqueueAsyncResave(newDomain, now, automaticTransferTime); asyncTaskEnqueuer.enqueueAsyncResave(newDomain, now, automaticTransferTime);
tm().putAll( tm().putAll(
new ImmutableSet.Builder<>() new ImmutableSet.Builder<>()
.add(newDomain, historyEntry, requestPollMessage) .add(newDomain, domainHistory, requestPollMessage)
.addAll(serverApproveEntities) .addAll(serverApproveEntities)
.build()); .build());
return responseBuilder return responseBuilder
@ -302,14 +312,13 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
} }
} }
private HistoryEntry buildHistoryEntry( private DomainHistory buildDomainHistory(
DomainBase existingDomain, Registry registry, DateTime now, Period period) { DomainBase newDomain, 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())
.setPeriod(period) .setPeriod(period)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingDomain)) .setDomainContent(newDomain)
.setDomainTransactionRecords( .setDomainTransactionRecords(
ImmutableSet.of( ImmutableSet.of(
DomainTransactionRecord.create( DomainTransactionRecord.create(

View file

@ -20,10 +20,12 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
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.googlecode.objectify.Key;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag; import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod; import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.Period; import google.registry.model.domain.Period;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
@ -31,7 +33,6 @@ import google.registry.model.eppcommon.Trid;
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
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.HistoryEntry;
import google.registry.model.transfer.DomainTransferData; import google.registry.model.transfer.DomainTransferData;
import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferData;
import google.registry.model.transfer.TransferData.TransferServerApproveEntity; import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
@ -90,20 +91,21 @@ public final class DomainTransferUtils {
* Returns a set of entities created speculatively in anticipation of a server approval. * Returns a set of entities created speculatively in anticipation of a server approval.
* *
* <p>This set consists of: * <p>This set consists of:
*
* <ul> * <ul>
* <li>The one-time billing event charging the gaining registrar for the transfer * <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 * <li>A cancellation of an autorenew charge for the losing registrar, if the autorenew grace
* period will apply at transfer time * 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 billing event for the domain (and gaining registrar)
* <li>A new post-transfer autorenew poll message 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 gaining registrar
* <li>A poll message for the losing registrar * <li>A poll message for the losing registrar
* </ul> * </ul>
*/ */
public static ImmutableSet<TransferServerApproveEntity> createTransferServerApproveEntities( public static ImmutableSet<TransferServerApproveEntity> createTransferServerApproveEntities(
DateTime automaticTransferTime, DateTime automaticTransferTime,
DateTime serverApproveNewExpirationTime, DateTime serverApproveNewExpirationTime,
HistoryEntry historyEntry, Key<DomainHistory> domainHistoryKey,
DomainBase existingDomain, DomainBase existingDomain,
Trid trid, Trid trid,
String gainingClientId, String gainingClientId,
@ -123,32 +125,39 @@ public final class DomainTransferUtils {
.build(); .build();
Registry registry = Registry.get(existingDomain.getTld()); Registry registry = Registry.get(existingDomain.getTld());
ImmutableSet.Builder<TransferServerApproveEntity> builder = new ImmutableSet.Builder<>(); ImmutableSet.Builder<TransferServerApproveEntity> builder = new ImmutableSet.Builder<>();
if (transferCost.isPresent()) { transferCost.ifPresent(
builder.add( cost ->
createTransferBillingEvent( builder.add(
automaticTransferTime, createTransferBillingEvent(
historyEntry, automaticTransferTime,
targetId, domainHistoryKey,
gainingClientId, targetId,
registry, gainingClientId,
transferCost.get())); registry,
} cost)));
createOptionalAutorenewCancellation( createOptionalAutorenewCancellation(
automaticTransferTime, historyEntry, targetId, existingDomain, transferCost) automaticTransferTime, now, domainHistoryKey, targetId, existingDomain, transferCost)
.ifPresent(builder::add); .ifPresent(builder::add);
return builder return builder
.add( .add(
createGainingClientAutorenewEvent( createGainingClientAutorenewEvent(
serverApproveNewExpirationTime, historyEntry, targetId, gainingClientId)) serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingClientId))
.add( .add(
createGainingClientAutorenewPollMessage( createGainingClientAutorenewPollMessage(
serverApproveNewExpirationTime, historyEntry, targetId, gainingClientId)) serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingClientId))
.add( .add(
createGainingTransferPollMessage( createGainingTransferPollMessage(
targetId, serverApproveTransferData, serverApproveNewExpirationTime, historyEntry)) targetId,
serverApproveTransferData,
serverApproveNewExpirationTime,
now,
domainHistoryKey))
.add( .add(
createLosingTransferPollMessage( createLosingTransferPollMessage(
targetId, serverApproveTransferData, serverApproveNewExpirationTime, historyEntry)) targetId,
serverApproveTransferData,
serverApproveNewExpirationTime,
domainHistoryKey))
.build(); .build();
} }
@ -157,19 +166,21 @@ public final class DomainTransferUtils {
String targetId, String targetId,
TransferData transferData, TransferData transferData,
@Nullable DateTime extendedRegistrationExpirationTime, @Nullable DateTime extendedRegistrationExpirationTime,
HistoryEntry historyEntry) { DateTime now,
Key<DomainHistory> domainHistoryKey) {
return new PollMessage.OneTime.Builder() return new PollMessage.OneTime.Builder()
.setClientId(transferData.getGainingClientId()) .setClientId(transferData.getGainingClientId())
.setEventTime(transferData.getPendingTransferExpirationTime()) .setEventTime(transferData.getPendingTransferExpirationTime())
.setMsg(transferData.getTransferStatus().getMessage()) .setMsg(transferData.getTransferStatus().getMessage())
.setResponseData(ImmutableList.of( .setResponseData(
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime), ImmutableList.of(
DomainPendingActionNotificationResponse.create( createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime),
targetId, DomainPendingActionNotificationResponse.create(
transferData.getTransferStatus().isApproved(), targetId,
transferData.getTransferRequestTrid(), transferData.getTransferStatus().isApproved(),
historyEntry.getModificationTime()))) transferData.getTransferRequestTrid(),
.setParent(historyEntry) now)))
.setParentKey(domainHistoryKey)
.build(); .build();
} }
@ -178,14 +189,15 @@ public final class DomainTransferUtils {
String targetId, String targetId,
TransferData transferData, TransferData transferData,
@Nullable DateTime extendedRegistrationExpirationTime, @Nullable DateTime extendedRegistrationExpirationTime,
HistoryEntry historyEntry) { Key<DomainHistory> domainHistoryKey) {
return new PollMessage.OneTime.Builder() return new PollMessage.OneTime.Builder()
.setClientId(transferData.getLosingClientId()) .setClientId(transferData.getLosingClientId())
.setEventTime(transferData.getPendingTransferExpirationTime()) .setEventTime(transferData.getPendingTransferExpirationTime())
.setMsg(transferData.getTransferStatus().getMessage()) .setMsg(transferData.getTransferStatus().getMessage())
.setResponseData(ImmutableList.of( .setResponseData(
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime))) ImmutableList.of(
.setParent(historyEntry) createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime)))
.setParentKey(domainHistoryKey)
.build(); .build();
} }
@ -207,7 +219,7 @@ public final class DomainTransferUtils {
private static PollMessage.Autorenew createGainingClientAutorenewPollMessage( private static PollMessage.Autorenew createGainingClientAutorenewPollMessage(
DateTime serverApproveNewExpirationTime, DateTime serverApproveNewExpirationTime,
HistoryEntry historyEntry, Key<DomainHistory> domainHistoryKey,
String targetId, String targetId,
String gainingClientId) { String gainingClientId) {
return new PollMessage.Autorenew.Builder() return new PollMessage.Autorenew.Builder()
@ -216,13 +228,13 @@ public final class DomainTransferUtils {
.setEventTime(serverApproveNewExpirationTime) .setEventTime(serverApproveNewExpirationTime)
.setAutorenewEndTime(END_OF_TIME) .setAutorenewEndTime(END_OF_TIME)
.setMsg("Domain was auto-renewed.") .setMsg("Domain was auto-renewed.")
.setParent(historyEntry) .setParentKey(domainHistoryKey)
.build(); .build();
} }
private static BillingEvent.Recurring createGainingClientAutorenewEvent( private static BillingEvent.Recurring createGainingClientAutorenewEvent(
DateTime serverApproveNewExpirationTime, DateTime serverApproveNewExpirationTime,
HistoryEntry historyEntry, Key<DomainHistory> domainHistoryKey,
String targetId, String targetId,
String gainingClientId) { String gainingClientId) {
return new BillingEvent.Recurring.Builder() return new BillingEvent.Recurring.Builder()
@ -232,7 +244,7 @@ public final class DomainTransferUtils {
.setClientId(gainingClientId) .setClientId(gainingClientId)
.setEventTime(serverApproveNewExpirationTime) .setEventTime(serverApproveNewExpirationTime)
.setRecurrenceEndTime(END_OF_TIME) .setRecurrenceEndTime(END_OF_TIME)
.setParent(historyEntry) .setParent(domainHistoryKey)
.build(); .build();
} }
@ -254,7 +266,8 @@ public final class DomainTransferUtils {
*/ */
private static Optional<BillingEvent.Cancellation> createOptionalAutorenewCancellation( private static Optional<BillingEvent.Cancellation> createOptionalAutorenewCancellation(
DateTime automaticTransferTime, DateTime automaticTransferTime,
HistoryEntry historyEntry, DateTime now,
Key<DomainHistory> domainHistoryKey,
String targetId, String targetId,
DomainBase existingDomain, DomainBase existingDomain,
Optional<Money> transferCost) { Optional<Money> transferCost) {
@ -265,7 +278,8 @@ public final class DomainTransferUtils {
domainAtTransferTime.getGracePeriodsOfType(GracePeriodStatus.AUTO_RENEW), null); domainAtTransferTime.getGracePeriodsOfType(GracePeriodStatus.AUTO_RENEW), null);
if (autorenewGracePeriod != null && transferCost.isPresent()) { if (autorenewGracePeriod != null && transferCost.isPresent()) {
return Optional.of( return Optional.of(
BillingEvent.Cancellation.forGracePeriod(autorenewGracePeriod, historyEntry, targetId) BillingEvent.Cancellation.forGracePeriod(
autorenewGracePeriod, now, domainHistoryKey, targetId)
.asBuilder() .asBuilder()
.setEventTime(automaticTransferTime) .setEventTime(automaticTransferTime)
.build()); .build());
@ -275,7 +289,7 @@ public final class DomainTransferUtils {
private static BillingEvent.OneTime createTransferBillingEvent( private static BillingEvent.OneTime createTransferBillingEvent(
DateTime automaticTransferTime, DateTime automaticTransferTime,
HistoryEntry historyEntry, Key<DomainHistory> domainHistoryKey,
String targetId, String targetId,
String gainingClientId, String gainingClientId,
Registry registry, Registry registry,
@ -288,7 +302,7 @@ public final class DomainTransferUtils {
.setPeriodYears(1) .setPeriodYears(1)
.setEventTime(automaticTransferTime) .setEventTime(automaticTransferTime)
.setBillingTime(automaticTransferTime.plus(registry.getTransferGracePeriodLength())) .setBillingTime(automaticTransferTime.plus(registry.getTransferGracePeriodLength()))
.setParent(historyEntry) .setParent(domainHistoryKey)
.build(); .build();
} }

View file

@ -43,7 +43,6 @@ import static google.registry.persistence.transaction.TransactionManagerFactory.
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.net.InternetDomainName; import com.google.common.net.InternetDomainName;
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;
import google.registry.flows.ExtensionManager; import google.registry.flows.ExtensionManager;
@ -65,6 +64,7 @@ import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainCommand.Update; import google.registry.model.domain.DomainCommand.Update;
import google.registry.model.domain.DomainCommand.Update.AddRemove; import google.registry.model.domain.DomainCommand.Update.AddRemove;
import google.registry.model.domain.DomainCommand.Update.Change; import google.registry.model.domain.DomainCommand.Update.Change;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.fee.FeeUpdateCommandExtension; import google.registry.model.domain.fee.FeeUpdateCommandExtension;
import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.domain.metadata.MetadataExtension;
import google.registry.model.domain.secdns.DelegationSignerData; import google.registry.model.domain.secdns.DelegationSignerData;
@ -142,7 +142,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
@Inject @ClientId String clientId; @Inject @ClientId String clientId;
@Inject @TargetId String targetId; @Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser; @Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder; @Inject DomainHistory.Builder historyBuilder;
@Inject DnsQueue dnsQueue; @Inject DnsQueue dnsQueue;
@Inject EppResponse.Builder responseBuilder; @Inject EppResponse.Builder responseBuilder;
@Inject DomainUpdateFlowCustomLogic flowCustomLogic; @Inject DomainUpdateFlowCustomLogic flowCustomLogic;
@ -165,19 +165,19 @@ public final class DomainUpdateFlow implements TransactionalFlow {
verifyUpdateAllowed(command, existingDomain, now); verifyUpdateAllowed(command, existingDomain, now);
flowCustomLogic.afterValidation( flowCustomLogic.afterValidation(
AfterValidationParameters.newBuilder().setExistingDomain(existingDomain).build()); AfterValidationParameters.newBuilder().setExistingDomain(existingDomain).build());
HistoryEntry historyEntry = buildHistoryEntry(existingDomain, now);
DomainBase newDomain = performUpdate(command, existingDomain, now); DomainBase newDomain = performUpdate(command, existingDomain, now);
DomainHistory domainHistory = buildDomainHistory(newDomain, now);
validateNewState(newDomain); validateNewState(newDomain);
dnsQueue.addDomainRefreshTask(targetId); dnsQueue.addDomainRefreshTask(targetId);
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>(); ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
entitiesToSave.add(newDomain, historyEntry); entitiesToSave.add(newDomain, domainHistory);
Optional<BillingEvent.OneTime> statusUpdateBillingEvent = Optional<BillingEvent.OneTime> statusUpdateBillingEvent =
createBillingEventForStatusUpdates(existingDomain, newDomain, historyEntry, now); createBillingEventForStatusUpdates(existingDomain, newDomain, domainHistory, now);
statusUpdateBillingEvent.ifPresent(entitiesToSave::add); statusUpdateBillingEvent.ifPresent(entitiesToSave::add);
EntityChanges entityChanges = EntityChanges entityChanges =
flowCustomLogic.beforeSave( flowCustomLogic.beforeSave(
BeforeSaveParameters.newBuilder() BeforeSaveParameters.newBuilder()
.setHistoryEntry(historyEntry) .setHistoryEntry(domainHistory)
.setNewDomain(newDomain) .setNewDomain(newDomain)
.setExistingDomain(existingDomain) .setExistingDomain(existingDomain)
.setEntityChanges( .setEntityChanges(
@ -217,11 +217,11 @@ public final class DomainUpdateFlow implements TransactionalFlow {
tld, add.getNameserverFullyQualifiedHostNames()); tld, add.getNameserverFullyQualifiedHostNames());
} }
private HistoryEntry buildHistoryEntry(DomainBase existingDomain, DateTime now) { private DomainHistory buildDomainHistory(DomainBase newDomain, DateTime now) {
return historyBuilder return historyBuilder
.setType(HistoryEntry.Type.DOMAIN_UPDATE) .setType(HistoryEntry.Type.DOMAIN_UPDATE)
.setModificationTime(now) .setModificationTime(now)
.setParent(Key.create(existingDomain)) .setDomainContent(newDomain)
.build(); .build();
} }

View file

@ -42,6 +42,7 @@ import google.registry.model.ImmutableObject;
import google.registry.model.annotations.ReportedOn; import google.registry.model.annotations.ReportedOn;
import google.registry.model.common.TimeOfYear; import google.registry.model.common.TimeOfYear;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod; import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
@ -114,7 +115,7 @@ public abstract class BillingEvent extends ImmutableObject
/** Entity id. */ /** Entity id. */
@Id @javax.persistence.Id Long id; @Id @javax.persistence.Id Long id;
@Parent @DoNotHydrate @Transient Key<HistoryEntry> parent; @Parent @DoNotHydrate @Transient Key<? extends HistoryEntry> parent;
/** The registrar to bill. */ /** The registrar to bill. */
@Index @Index
@ -191,7 +192,7 @@ public abstract class BillingEvent extends ImmutableObject
return targetId; return targetId;
} }
public Key<HistoryEntry> getParentKey() { public Key<? extends HistoryEntry> getParentKey() {
return parent; return parent;
} }
@ -258,7 +259,7 @@ public abstract class BillingEvent extends ImmutableObject
return thisCastToDerived(); return thisCastToDerived();
} }
public B setParent(Key<HistoryEntry> parentKey) { public B setParent(Key<? extends HistoryEntry> parentKey) {
getInstance().parent = parentKey; getInstance().parent = parentKey;
return thisCastToDerived(); return thisCastToDerived();
} }
@ -602,23 +603,27 @@ public abstract class BillingEvent extends ImmutableObject
GracePeriodStatus.TRANSFER, Reason.TRANSFER); GracePeriodStatus.TRANSFER, Reason.TRANSFER);
/** /**
* Creates a cancellation billing event (parented on the provided history entry, and with the * Creates a cancellation billing event (parented on the provided history key, and with the
* history entry's event time) that will cancel out the provided grace period's billing event, * corresponding event time) that will cancel out the provided grace period's billing event,
* using the supplied targetId and deriving other metadata (clientId, billing time, and the * using the supplied targetId and deriving other metadata (clientId, billing time, and the
* cancellation reason) from the grace period. * cancellation reason) from the grace period.
*/ */
public static BillingEvent.Cancellation forGracePeriod( public static BillingEvent.Cancellation forGracePeriod(
GracePeriod gracePeriod, HistoryEntry historyEntry, String targetId) { GracePeriod gracePeriod,
DateTime eventTime,
Key<DomainHistory> domainHistoryKey,
String targetId) {
checkArgument(gracePeriod.hasBillingEvent(), checkArgument(gracePeriod.hasBillingEvent(),
"Cannot create cancellation for grace period without billing event"); "Cannot create cancellation for grace period without billing event");
BillingEvent.Cancellation.Builder builder = new BillingEvent.Cancellation.Builder() BillingEvent.Cancellation.Builder builder =
.setReason(checkNotNull(GRACE_PERIOD_TO_REASON.get(gracePeriod.getType()))) new BillingEvent.Cancellation.Builder()
.setTargetId(targetId) .setReason(checkNotNull(GRACE_PERIOD_TO_REASON.get(gracePeriod.getType())))
.setClientId(gracePeriod.getClientId()) .setTargetId(targetId)
.setEventTime(historyEntry.getModificationTime()) .setClientId(gracePeriod.getClientId())
// The charge being cancelled will take place at the grace period's expiration time. .setEventTime(eventTime)
.setBillingTime(gracePeriod.getExpirationTime()) // The charge being cancelled will take place at the grace period's expiration time.
.setParent(historyEntry); .setBillingTime(gracePeriod.getExpirationTime())
.setParent(domainHistoryKey);
// Set the grace period's billing event using the appropriate Cancellation builder method. // Set the grace period's billing event using the appropriate Cancellation builder method.
if (gracePeriod.getOneTimeBillingEvent() != null) { if (gracePeriod.getOneTimeBillingEvent() != null) {
builder.setOneTimeEventKey(gracePeriod.getOneTimeBillingEvent()); builder.setOneTimeEventKey(gracePeriod.getOneTimeBillingEvent());

View file

@ -377,12 +377,16 @@ public class HistoryEntry extends ImmutableObject implements Buildable, Datastor
return thisCastToDerived(); return thisCastToDerived();
} }
public B copyFrom(HistoryEntry.Builder<? extends HistoryEntry, ?> builder) {
return copyFrom(builder.getInstance());
}
@Override @Override
public T build() { public T build() {
return super.build(); return super.build();
} }
public B setId(long id) { public B setId(Long id) {
getInstance().id = id; getInstance().id = id;
return thisCastToDerived(); return thisCastToDerived();
} }

View file

@ -22,7 +22,7 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.START_OF_TIME; import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.Iterables; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams; import com.google.common.collect.Streams;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.contact.ContactHistory; import google.registry.model.contact.ContactHistory;
@ -34,6 +34,7 @@ import google.registry.model.host.HostResource;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.persistence.transaction.CriteriaQueryBuilder; import google.registry.persistence.transaction.CriteriaQueryBuilder;
import java.util.Comparator; import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
@ -48,7 +49,7 @@ import org.joda.time.DateTime;
public class HistoryEntryDao { public class HistoryEntryDao {
/** Loads all history objects in the times specified, including all types. */ /** Loads all history objects in the times specified, including all types. */
public static Iterable<? extends HistoryEntry> loadAllHistoryObjects( public static ImmutableList<? extends HistoryEntry> loadAllHistoryObjects(
DateTime afterTime, DateTime beforeTime) { DateTime afterTime, DateTime beforeTime) {
if (tm().isOfy()) { if (tm().isOfy()) {
return Streams.stream( return Streams.stream(
@ -64,21 +65,25 @@ public class HistoryEntryDao {
return jpaTm() return jpaTm()
.transact( .transact(
() -> () ->
Iterables.concat( new ImmutableList.Builder<HistoryEntry>()
loadAllHistoryObjectsFromSql(ContactHistory.class, afterTime, beforeTime), .addAll(
loadAllHistoryObjectsFromSql(DomainHistory.class, afterTime, beforeTime), loadAllHistoryObjectsFromSql(ContactHistory.class, afterTime, beforeTime))
loadAllHistoryObjectsFromSql(HostHistory.class, afterTime, beforeTime))); .addAll(
loadAllHistoryObjectsFromSql(DomainHistory.class, afterTime, beforeTime))
.addAll(
loadAllHistoryObjectsFromSql(HostHistory.class, afterTime, beforeTime))
.build());
} }
} }
/** Loads all history objects corresponding to the given {@link EppResource}. */ /** Loads all history objects corresponding to the given {@link EppResource}. */
public static Iterable<? extends HistoryEntry> loadHistoryObjectsForResource( public static ImmutableList<? extends HistoryEntry> loadHistoryObjectsForResource(
VKey<? extends EppResource> parentKey) { VKey<? extends EppResource> parentKey) {
return loadHistoryObjectsForResource(parentKey, START_OF_TIME, END_OF_TIME); return loadHistoryObjectsForResource(parentKey, START_OF_TIME, END_OF_TIME);
} }
/** Loads all history objects in the time period specified for the given {@link EppResource}. */ /** Loads all history objects in the time period specified for the given {@link EppResource}. */
public static Iterable<? extends HistoryEntry> loadHistoryObjectsForResource( public static ImmutableList<? extends HistoryEntry> loadHistoryObjectsForResource(
VKey<? extends EppResource> parentKey, DateTime afterTime, DateTime beforeTime) { VKey<? extends EppResource> parentKey, DateTime afterTime, DateTime beforeTime) {
if (tm().isOfy()) { if (tm().isOfy()) {
return Streams.stream( return Streams.stream(
@ -130,7 +135,7 @@ public class HistoryEntryDao {
.getResultStream(); .getResultStream();
} }
private static Iterable<? extends HistoryEntry> loadHistoryObjectsForResourceFromSql( private static ImmutableList<? extends HistoryEntry> loadHistoryObjectsForResourceFromSql(
VKey<? extends EppResource> parentKey, DateTime afterTime, DateTime beforeTime) { VKey<? extends EppResource> parentKey, DateTime afterTime, DateTime beforeTime) {
// The class we're searching from is based on which parent type (e.g. Domain) we have // The class we're searching from is based on which parent type (e.g. Domain) we have
Class<? extends HistoryEntry> historyClass = getHistoryClassFromParent(parentKey.getKind()); Class<? extends HistoryEntry> historyClass = getHistoryClassFromParent(parentKey.getKind());
@ -144,12 +149,9 @@ public class HistoryEntryDao {
.where(repoIdFieldName, criteriaBuilder::equal, parentKey.getSqlKey().toString()) .where(repoIdFieldName, criteriaBuilder::equal, parentKey.getSqlKey().toString())
.build(); .build();
return jpaTm() return ImmutableList.sortedCopyOf(
.getEntityManager() Comparator.comparing(HistoryEntry::getModificationTime),
.createQuery(criteriaQuery) jpaTm().getEntityManager().createQuery(criteriaQuery).getResultList());
.getResultStream()
.sorted(Comparator.comparing(HistoryEntry::getModificationTime))
.collect(toImmutableList());
} }
private static Class<? extends HistoryEntry> getHistoryClassFromParent( private static Class<? extends HistoryEntry> getHistoryClassFromParent(
@ -172,7 +174,7 @@ public class HistoryEntryDao {
: historyClass.equals(DomainHistory.class) ? "domainRepoId" : "hostRepoId"; : historyClass.equals(DomainHistory.class) ? "domainRepoId" : "hostRepoId";
} }
private static Iterable<? extends HistoryEntry> loadAllHistoryObjectsFromSql( private static List<? extends HistoryEntry> loadAllHistoryObjectsFromSql(
Class<? extends HistoryEntry> historyClass, DateTime afterTime, DateTime beforeTime) { Class<? extends HistoryEntry> historyClass, DateTime afterTime, DateTime beforeTime) {
CriteriaBuilder criteriaBuilder = jpaTm().getEntityManager().getCriteriaBuilder(); CriteriaBuilder criteriaBuilder = jpaTm().getEntityManager().getCriteriaBuilder();
return jpaTm() return jpaTm()

View file

@ -164,6 +164,7 @@ public class DomainTransferData extends TransferData<DomainTransferData.Builder>
serverApproveEntities = null; serverApproveEntities = null;
postLoad(); postLoad();
} }
hashCode = null; // reset the hash code since we may have changed the entities
} }
/** /**
@ -271,6 +272,7 @@ public class DomainTransferData extends TransferData<DomainTransferData.Builder>
serverApproveEntitiesBuilder.add(billingCancellationId); serverApproveEntitiesBuilder.add(billingCancellationId);
} }
serverApproveEntities = forceEmptyToNull(serverApproveEntitiesBuilder.build()); serverApproveEntities = forceEmptyToNull(serverApproveEntitiesBuilder.build());
hashCode = null; // reset the hash code since we may have changed the entities
} }
@Override @Override

View file

@ -757,11 +757,11 @@ class EppLifecycleDomainTest extends EppTestCase {
.hasResponse( .hasResponse(
"poll_response_autorenew.xml", "poll_response_autorenew.xml",
ImmutableMap.of( ImmutableMap.of(
"ID", "1-D-EXAMPLE-11-16-2002", "ID", "1-C-EXAMPLE-13-16-2002",
"QDATE", "2002-06-01T00:04:00Z", "QDATE", "2002-06-01T00:04:00Z",
"DOMAIN", "fakesite.example", "DOMAIN", "fakesite.example",
"EXDATE", "2003-06-01T00:04:00Z")); "EXDATE", "2003-06-01T00:04:00Z"));
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-D-EXAMPLE-11-16-2002")) assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-C-EXAMPLE-13-16-2002"))
.atTime("2002-07-01T00:02:00Z") .atTime("2002-07-01T00:02:00Z")
.hasResponse("poll_ack_response_empty.xml"); .hasResponse("poll_ack_response_empty.xml");
@ -775,13 +775,13 @@ class EppLifecycleDomainTest extends EppTestCase {
.hasResponse( .hasResponse(
"poll_response_autorenew.xml", "poll_response_autorenew.xml",
ImmutableMap.of( ImmutableMap.of(
"ID", "1-D-EXAMPLE-11-16-2003", // Note -- Year is different from previous ID. "ID", "1-C-EXAMPLE-13-16-2003", // Note -- Year is different from previous ID.
"QDATE", "2003-06-01T00:04:00Z", "QDATE", "2003-06-01T00:04:00Z",
"DOMAIN", "fakesite.example", "DOMAIN", "fakesite.example",
"EXDATE", "2004-06-01T00:04:00Z")); "EXDATE", "2004-06-01T00:04:00Z"));
// Ack the second poll message and verify that none remain. // Ack the second poll message and verify that none remain.
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-D-EXAMPLE-11-16-2003")) assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-C-EXAMPLE-13-16-2003"))
.atTime("2003-07-01T00:05:05Z") .atTime("2003-07-01T00:05:05Z")
.hasResponse("poll_ack_response_empty.xml"); .hasResponse("poll_ack_response_empty.xml");
assertThatCommand("poll.xml") assertThatCommand("poll.xml")
@ -811,7 +811,7 @@ class EppLifecycleDomainTest extends EppTestCase {
// As the losing registrar, read the request poll message, and then ack it. // As the losing registrar, read the request poll message, and then ack it.
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2"); assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
String messageId = "1-D-EXAMPLE-19-25-2001"; String messageId = "1-C-EXAMPLE-19-25-2001";
assertThatCommand("poll.xml") assertThatCommand("poll.xml")
.atTime("2001-01-01T00:01:00Z") .atTime("2001-01-01T00:01:00Z")
.hasResponse("poll_response_domain_transfer_request.xml", ImmutableMap.of("ID", messageId)); .hasResponse("poll_response_domain_transfer_request.xml", ImmutableMap.of("ID", messageId));
@ -820,7 +820,7 @@ class EppLifecycleDomainTest extends EppTestCase {
.hasResponse("poll_ack_response_empty.xml"); .hasResponse("poll_ack_response_empty.xml");
// Five days in the future, expect a server approval poll message to the loser, and ack it. // Five days in the future, expect a server approval poll message to the loser, and ack it.
messageId = "1-D-EXAMPLE-19-24-2001"; messageId = "1-C-EXAMPLE-19-24-2001";
assertThatCommand("poll.xml") assertThatCommand("poll.xml")
.atTime("2001-01-06T00:01:00Z") .atTime("2001-01-06T00:01:00Z")
.hasResponse( .hasResponse(
@ -832,7 +832,7 @@ class EppLifecycleDomainTest extends EppTestCase {
assertThatLogoutSucceeds(); assertThatLogoutSucceeds();
// Also expect a server approval poll message to the winner, with the transfer request trid. // Also expect a server approval poll message to the winner, with the transfer request trid.
messageId = "1-D-EXAMPLE-19-23-2001"; messageId = "1-C-EXAMPLE-19-23-2001";
assertThatLoginSucceeds("TheRegistrar", "password2"); assertThatLoginSucceeds("TheRegistrar", "password2");
assertThatCommand("poll.xml") assertThatCommand("poll.xml")
.atTime("2001-01-06T00:02:00Z") .atTime("2001-01-06T00:02:00Z")

View file

@ -17,6 +17,7 @@ package google.registry.flows;
import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm; import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
@ -27,19 +28,28 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams; import com.google.common.collect.Streams;
import com.google.common.flogger.LoggerConfig; import com.google.common.flogger.LoggerConfig;
import com.google.common.testing.TestLogHandler; import com.google.common.testing.TestLogHandler;
import com.googlecode.objectify.Key; import com.googlecode.objectify.Key;
import google.registry.flows.FlowUtils.NotLoggedInException; import google.registry.flows.FlowUtils.NotLoggedInException;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.contact.ContactBase;
import google.registry.model.contact.ContactHistory;
import google.registry.model.domain.DomainContent;
import google.registry.model.domain.DomainHistory;
import google.registry.model.eppcommon.Trid; import google.registry.model.eppcommon.Trid;
import google.registry.model.eppinput.EppInput.ResourceCommandWrapper; import google.registry.model.eppinput.EppInput.ResourceCommandWrapper;
import google.registry.model.eppinput.ResourceCommand; import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.host.HostBase;
import google.registry.model.host.HostHistory;
import google.registry.model.index.EppResourceIndex; import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.EppResourceIndexBucket; import google.registry.model.index.EppResourceIndexBucket;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.tmch.ClaimsListDualDatabaseDao; import google.registry.model.tmch.ClaimsListDualDatabaseDao;
import google.registry.model.tmch.ClaimsListShard; import google.registry.model.tmch.ClaimsListShard;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.TaskQueueHelper.TaskMatcher; import google.registry.testing.TaskQueueHelper.TaskMatcher;
import google.registry.util.TypeUtils.TypeInstantiator; import google.registry.util.TypeUtils.TypeInstantiator;
import java.util.logging.Level; import java.util.logging.Level;
@ -177,4 +187,22 @@ public abstract class ResourceFlowTestCase<F extends Flow, R extends EppResource
.which() .which()
.contains("\"icannActivityReportField\":" + JSONValue.toJSONString(fieldName)); .contains("\"icannActivityReportField\":" + JSONValue.toJSONString(fieldName));
} }
protected void assertLastHistoryContainsResource(EppResource resource) {
if (!tm().isOfy()) {
HistoryEntry historyEntry = Iterables.getLast(DatabaseHelper.getHistoryEntries(resource));
if (resource instanceof ContactBase) {
ContactHistory contactHistory = (ContactHistory) historyEntry;
assertThat(contactHistory.getContactBase().get()).isEqualTo(resource);
} else if (resource instanceof DomainContent) {
DomainHistory domainHistory = (DomainHistory) historyEntry;
assertAboutImmutableObjects()
.that(domainHistory.getDomainContent().get())
.isEqualExceptFields(resource, "gracePeriods", "dsData", "nsHosts");
} else if (resource instanceof HostBase) {
HostHistory hostHistory = (HostHistory) historyEntry;
assertThat(hostHistory.getHostBase().get()).isEqualTo(resource);
}
}
}
} }

View file

@ -265,6 +265,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
isAnchorTenant isAnchorTenant
? clock.nowUtc().plus(Registry.get(domainTld).getAnchorTenantAddGracePeriodLength()) ? clock.nowUtc().plus(Registry.get(domainTld).getAnchorTenantAddGracePeriodLength())
: clock.nowUtc().plus(Registry.get(domainTld).getAddGracePeriodLength()); : clock.nowUtc().plus(Registry.get(domainTld).getAddGracePeriodLength());
assertLastHistoryContainsResource(domain);
HistoryEntry historyEntry = getHistoryEntries(domain).get(0); HistoryEntry historyEntry = getHistoryEntries(domain).get(0);
assertAboutDomains() assertAboutDomains()
.that(domain) .that(domain)

View file

@ -456,6 +456,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
// where the expirationTime advances and the grace period appears, but since the delete flow // where the expirationTime advances and the grace period appears, but since the delete flow
// closed the autorenew recurrences immediately, there are no other autorenew effects. // closed the autorenew recurrences immediately, there are no other autorenew effects.
assertAboutDomains().that(resource).hasRegistrationExpirationTime(expectedExpirationTime); assertAboutDomains().that(resource).hasRegistrationExpirationTime(expectedExpirationTime);
assertLastHistoryContainsResource(resource);
// All existing grace periods that were for billable actions should cause cancellations. // All existing grace periods that were for billable actions should cause cancellations.
assertAutorenewClosedAndCancellationCreatedFor( assertAutorenewClosedAndCancellationCreatedFor(
renewBillingEvent, getOnlyHistoryEntryOfType(resource, DOMAIN_DELETE)); renewBillingEvent, getOnlyHistoryEntryOfType(resource, DOMAIN_DELETE));

View file

@ -21,6 +21,7 @@ import static google.registry.testing.DatabaseHelper.assertBillingEvents;
import static google.registry.testing.DatabaseHelper.assertPollMessages; import static google.registry.testing.DatabaseHelper.assertPollMessages;
import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType; import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.loadRegistrar; import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.newDomainBase; import static google.registry.testing.DatabaseHelper.newDomainBase;
import static google.registry.testing.DatabaseHelper.persistActiveDomain; import static google.registry.testing.DatabaseHelper.persistActiveDomain;
@ -60,6 +61,7 @@ import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag; import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod; import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.StatusValue;
@ -70,18 +72,20 @@ import google.registry.model.registry.Registry;
import google.registry.model.reporting.DomainTransactionRecord; import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField; import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension; import google.registry.testing.ReplayExtension;
import google.registry.testing.SetClockExtension; import google.registry.testing.SetClockExtension;
import google.registry.testing.TestOfyAndSql;
import java.util.Map; import java.util.Map;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration; import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainRenewFlow}. */ /** Unit tests for {@link DomainRenewFlow}. */
@DualDatabaseTest
class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBase> { class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBase> {
private static final ImmutableMap<String, String> FEE_BASE_MAP = private static final ImmutableMap<String, String> FEE_BASE_MAP =
@ -121,8 +125,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
tm().transact( tm().transact(
() -> { () -> {
try { try {
HistoryEntry historyEntryDomainCreate = DomainHistory historyEntryDomainCreate =
new HistoryEntry.Builder() new DomainHistory.Builder()
.setParent(domain) .setParent(domain)
.setType(HistoryEntry.Type.DOMAIN_CREATE) .setType(HistoryEntry.Type.DOMAIN_CREATE)
.setModificationTime(clock.nowUtc()) .setModificationTime(clock.nowUtc())
@ -195,9 +199,10 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
runFlowAssertResponse( runFlowAssertResponse(
CommitMode.LIVE, userPrivileges, loadFile(responseFilename, substitutions)); CommitMode.LIVE, userPrivileges, loadFile(responseFilename, substitutions));
DomainBase domain = reloadResourceByForeignKey(); DomainBase domain = reloadResourceByForeignKey();
assertLastHistoryContainsResource(domain);
HistoryEntry historyEntryDomainRenew = HistoryEntry historyEntryDomainRenew =
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RENEW); getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RENEW);
assertThat(tm().loadByKey(domain.getAutorenewBillingEvent()).getEventTime()) assertThat(loadByKey(domain.getAutorenewBillingEvent()).getEventTime())
.isEqualTo(newExpiration); .isEqualTo(newExpiration);
assertAboutDomains() assertAboutDomains()
.that(domain) .that(domain)
@ -266,7 +271,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
renewBillingEvent)); renewBillingEvent));
} }
@Test @TestOfyAndSql
void testDryRun() throws Exception { void testDryRun() throws Exception {
persistDomain(); persistDomain();
dryRunFlowAssertResponse( dryRunFlowAssertResponse(
@ -275,7 +280,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z"))); ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z")));
} }
@Test @TestOfyAndSql
void testSuccess() throws Exception { void testSuccess() throws Exception {
clock.advanceOneMilli(); clock.advanceOneMilli();
persistDomain(); persistDomain();
@ -285,7 +290,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z")); ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z"));
} }
@Test @TestOfyAndSql
void testSuccess_recurringClientIdIsSame_whenSuperuserOverridesRenewal() throws Exception { void testSuccess_recurringClientIdIsSame_whenSuperuserOverridesRenewal() throws Exception {
persistDomain(); persistDomain();
setClientIdForFlow("NewRegistrar"); setClientIdForFlow("NewRegistrar");
@ -298,7 +303,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
Money.of(USD, 55)); Money.of(USD, 55));
} }
@Test @TestOfyAndSql
void testSuccess_customLogicFee() throws Exception { void testSuccess_customLogicFee() throws Exception {
// The "costly-renew" domain has an additional RENEW fee of 100 from custom logic on top of the // The "costly-renew" domain has an additional RENEW fee of 100 from custom logic on top of the
// normal $11 standard renew price for this TLD. // normal $11 standard renew price for this TLD.
@ -320,56 +325,56 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
Money.of(USD, 111)); Money.of(USD, 111));
} }
@Test @TestOfyAndSql
void testSuccess_fee_v06() throws Exception { void testSuccess_fee_v06() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_06_MAP); setEppInput("domain_renew_fee.xml", FEE_06_MAP);
persistDomain(); persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_06_MAP); doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_06_MAP);
} }
@Test @TestOfyAndSql
void testSuccess_fee_v11() throws Exception { void testSuccess_fee_v11() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_11_MAP); setEppInput("domain_renew_fee.xml", FEE_11_MAP);
persistDomain(); persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_11_MAP); doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_11_MAP);
} }
@Test @TestOfyAndSql
void testSuccess_fee_v12() throws Exception { void testSuccess_fee_v12() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_12_MAP); setEppInput("domain_renew_fee.xml", FEE_12_MAP);
persistDomain(); persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_12_MAP); doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_12_MAP);
} }
@Test @TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v06() throws Exception { void testSuccess_fee_withDefaultAttributes_v06() throws Exception {
setEppInput("domain_renew_fee_defaults.xml", FEE_06_MAP); setEppInput("domain_renew_fee_defaults.xml", FEE_06_MAP);
persistDomain(); persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_06_MAP); doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_06_MAP);
} }
@Test @TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v11() throws Exception { void testSuccess_fee_withDefaultAttributes_v11() throws Exception {
setEppInput("domain_renew_fee_defaults.xml", FEE_11_MAP); setEppInput("domain_renew_fee_defaults.xml", FEE_11_MAP);
persistDomain(); persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_11_MAP); doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_11_MAP);
} }
@Test @TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v12() throws Exception { void testSuccess_fee_withDefaultAttributes_v12() throws Exception {
setEppInput("domain_renew_fee_defaults.xml", FEE_12_MAP); setEppInput("domain_renew_fee_defaults.xml", FEE_12_MAP);
persistDomain(); persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_12_MAP); doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_12_MAP);
} }
@Test @TestOfyAndSql
void testFailure_fee_unknownCurrency() { void testFailure_fee_unknownCurrency() {
setEppInput("domain_renew_fee.xml", updateSubstitutions(FEE_06_MAP, "CURRENCY", "BAD")); setEppInput("domain_renew_fee.xml", updateSubstitutions(FEE_06_MAP, "CURRENCY", "BAD"));
EppException thrown = assertThrows(UnknownCurrencyEppException.class, this::persistDomain); EppException thrown = assertThrows(UnknownCurrencyEppException.class, this::persistDomain);
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_refundableFee_v06() throws Exception { void testFailure_refundableFee_v06() throws Exception {
setEppInput("domain_renew_fee_refundable.xml", FEE_06_MAP); setEppInput("domain_renew_fee_refundable.xml", FEE_06_MAP);
persistDomain(); persistDomain();
@ -377,7 +382,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_refundableFee_v11() throws Exception { void testFailure_refundableFee_v11() throws Exception {
setEppInput("domain_renew_fee_refundable.xml", FEE_11_MAP); setEppInput("domain_renew_fee_refundable.xml", FEE_11_MAP);
persistDomain(); persistDomain();
@ -385,7 +390,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_refundableFee_v12() throws Exception { void testFailure_refundableFee_v12() throws Exception {
setEppInput("domain_renew_fee_refundable.xml", FEE_12_MAP); setEppInput("domain_renew_fee_refundable.xml", FEE_12_MAP);
persistDomain(); persistDomain();
@ -393,7 +398,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_gracePeriodFee_v06() throws Exception { void testFailure_gracePeriodFee_v06() throws Exception {
setEppInput("domain_renew_fee_grace_period.xml", FEE_06_MAP); setEppInput("domain_renew_fee_grace_period.xml", FEE_06_MAP);
persistDomain(); persistDomain();
@ -401,7 +406,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_gracePeriodFee_v11() throws Exception { void testFailure_gracePeriodFee_v11() throws Exception {
setEppInput("domain_renew_fee_grace_period.xml", FEE_11_MAP); setEppInput("domain_renew_fee_grace_period.xml", FEE_11_MAP);
persistDomain(); persistDomain();
@ -409,7 +414,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_gracePeriodFee_v12() throws Exception { void testFailure_gracePeriodFee_v12() throws Exception {
setEppInput("domain_renew_fee_grace_period.xml", FEE_12_MAP); setEppInput("domain_renew_fee_grace_period.xml", FEE_12_MAP);
persistDomain(); persistDomain();
@ -417,7 +422,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_appliedFee_v06() throws Exception { void testFailure_appliedFee_v06() throws Exception {
setEppInput("domain_renew_fee_applied.xml", FEE_06_MAP); setEppInput("domain_renew_fee_applied.xml", FEE_06_MAP);
persistDomain(); persistDomain();
@ -425,7 +430,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_appliedFee_v11() throws Exception { void testFailure_appliedFee_v11() throws Exception {
setEppInput("domain_renew_fee_applied.xml", FEE_11_MAP); setEppInput("domain_renew_fee_applied.xml", FEE_11_MAP);
persistDomain(); persistDomain();
@ -433,7 +438,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_appliedFee_v12() throws Exception { void testFailure_appliedFee_v12() throws Exception {
setEppInput("domain_renew_fee_applied.xml", FEE_12_MAP); setEppInput("domain_renew_fee_applied.xml", FEE_12_MAP);
persistDomain(); persistDomain();
@ -441,17 +446,17 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_suspendedRegistrarCantRenewDomain() { void testFailure_suspendedRegistrarCantRenewDomain() {
doFailingTest_invalidRegistrarState(State.SUSPENDED); doFailingTest_invalidRegistrarState(State.SUSPENDED);
} }
@Test @TestOfyAndSql
void testFailure_pendingRegistrarCantRenewDomain() { void testFailure_pendingRegistrarCantRenewDomain() {
doFailingTest_invalidRegistrarState(State.PENDING); doFailingTest_invalidRegistrarState(State.PENDING);
} }
@Test @TestOfyAndSql
void testFailure_disabledRegistrarCantRenewDomain() { void testFailure_disabledRegistrarCantRenewDomain() {
doFailingTest_invalidRegistrarState(State.DISABLED); doFailingTest_invalidRegistrarState(State.DISABLED);
} }
@ -468,7 +473,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_nonDefaultRenewGracePeriod() throws Exception { void testSuccess_nonDefaultRenewGracePeriod() throws Exception {
persistResource( persistResource(
Registry.get("tld") Registry.get("tld")
@ -482,19 +487,19 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z")); ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z"));
} }
@Test @TestOfyAndSql
void testSuccess_missingPeriod() throws Exception { void testSuccess_missingPeriod() throws Exception {
setEppInput("domain_renew_missing_period.xml"); setEppInput("domain_renew_missing_period.xml");
persistDomain(); persistDomain();
doSuccessfulTest("domain_renew_response_missing_period.xml", 1); doSuccessfulTest("domain_renew_response_missing_period.xml", 1);
} }
@Test @TestOfyAndSql
void testSuccess_autorenewPollMessageIsNotDeleted() throws Exception { void testSuccess_autorenewPollMessageIsNotDeleted() throws Exception {
persistDomain(); persistDomain();
// Modify the autorenew poll message so that it has an undelivered message in the past. // Modify the autorenew poll message so that it has an undelivered message in the past.
persistResource( persistResource(
tm().loadByKey(reloadResourceByForeignKey().getAutorenewPollMessage()) loadByKey(reloadResourceByForeignKey().getAutorenewPollMessage())
.asBuilder() .asBuilder()
.setEventTime(expirationTime.minusYears(1)) .setEventTime(expirationTime.minusYears(1))
.build()); .build());
@ -525,14 +530,14 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
.build()); .build());
} }
@Test @TestOfyAndSql
void testFailure_neverExisted() throws Exception { void testFailure_neverExisted() throws Exception {
ResourceDoesNotExistException thrown = ResourceDoesNotExistException thrown =
assertThrows(ResourceDoesNotExistException.class, this::runFlow); assertThrows(ResourceDoesNotExistException.class, this::runFlow);
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
} }
@Test @TestOfyAndSql
void testFailure_existedButWasDeleted() throws Exception { void testFailure_existedButWasDeleted() throws Exception {
persistDeletedDomain(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1)); persistDeletedDomain(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1));
ResourceDoesNotExistException thrown = ResourceDoesNotExistException thrown =
@ -540,7 +545,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
} }
@Test @TestOfyAndSql
void testFailure_clientRenewProhibited() throws Exception { void testFailure_clientRenewProhibited() throws Exception {
persistDomain(StatusValue.CLIENT_RENEW_PROHIBITED); persistDomain(StatusValue.CLIENT_RENEW_PROHIBITED);
ResourceStatusProhibitsOperationException thrown = ResourceStatusProhibitsOperationException thrown =
@ -548,7 +553,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertThat(thrown).hasMessageThat().contains("clientRenewProhibited"); assertThat(thrown).hasMessageThat().contains("clientRenewProhibited");
} }
@Test @TestOfyAndSql
void testFailure_serverRenewProhibited() throws Exception { void testFailure_serverRenewProhibited() throws Exception {
persistDomain(StatusValue.SERVER_RENEW_PROHIBITED); persistDomain(StatusValue.SERVER_RENEW_PROHIBITED);
ResourceStatusProhibitsOperationException thrown = ResourceStatusProhibitsOperationException thrown =
@ -556,7 +561,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertThat(thrown).hasMessageThat().contains("serverRenewProhibited"); assertThat(thrown).hasMessageThat().contains("serverRenewProhibited");
} }
@Test @TestOfyAndSql
void testFailure_pendingDelete() throws Exception { void testFailure_pendingDelete() throws Exception {
persistResource( persistResource(
newDomainBase(getUniqueIdFromCommand()) newDomainBase(getUniqueIdFromCommand())
@ -570,7 +575,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertThat(thrown).hasMessageThat().contains("pendingDelete"); assertThat(thrown).hasMessageThat().contains("pendingDelete");
} }
@Test @TestOfyAndSql
void testFailure_wrongFeeAmount_v06() throws Exception { void testFailure_wrongFeeAmount_v06() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_06_MAP); setEppInput("domain_renew_fee.xml", FEE_06_MAP);
persistResource( persistResource(
@ -583,7 +588,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_wrongFeeAmount_v11() throws Exception { void testFailure_wrongFeeAmount_v11() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_11_MAP); setEppInput("domain_renew_fee.xml", FEE_11_MAP);
persistResource( persistResource(
@ -596,7 +601,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_wrongFeeAmount_v12() throws Exception { void testFailure_wrongFeeAmount_v12() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_12_MAP); setEppInput("domain_renew_fee.xml", FEE_12_MAP);
persistResource( persistResource(
@ -609,7 +614,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_wrongCurrency_v06() throws Exception { void testFailure_wrongCurrency_v06() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_06_MAP); setEppInput("domain_renew_fee.xml", FEE_06_MAP);
persistResource( persistResource(
@ -628,7 +633,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_wrongCurrency_v11() throws Exception { void testFailure_wrongCurrency_v11() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_11_MAP); setEppInput("domain_renew_fee.xml", FEE_11_MAP);
persistResource( persistResource(
@ -647,7 +652,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_wrongCurrency_v12() throws Exception { void testFailure_wrongCurrency_v12() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_12_MAP); setEppInput("domain_renew_fee.xml", FEE_12_MAP);
persistResource( persistResource(
@ -666,7 +671,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_feeGivenInWrongScale_v06() throws Exception { void testFailure_feeGivenInWrongScale_v06() throws Exception {
setEppInput("domain_renew_fee_bad_scale.xml", FEE_06_MAP); setEppInput("domain_renew_fee_bad_scale.xml", FEE_06_MAP);
persistDomain(); persistDomain();
@ -674,7 +679,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_feeGivenInWrongScale_v11() throws Exception { void testFailure_feeGivenInWrongScale_v11() throws Exception {
setEppInput("domain_renew_fee_bad_scale.xml", FEE_11_MAP); setEppInput("domain_renew_fee_bad_scale.xml", FEE_11_MAP);
persistDomain(); persistDomain();
@ -682,7 +687,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_feeGivenInWrongScale_v12() throws Exception { void testFailure_feeGivenInWrongScale_v12() throws Exception {
setEppInput("domain_renew_fee_bad_scale.xml", FEE_12_MAP); setEppInput("domain_renew_fee_bad_scale.xml", FEE_12_MAP);
persistDomain(); persistDomain();
@ -690,7 +695,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_pendingTransfer() throws Exception { void testFailure_pendingTransfer() throws Exception {
persistDomain(); persistDomain();
persistWithPendingTransfer( persistWithPendingTransfer(
@ -703,7 +708,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertThat(thrown).hasMessageThat().contains("pendingTransfer"); assertThat(thrown).hasMessageThat().contains("pendingTransfer");
} }
@Test @TestOfyAndSql
void testFailure_periodInMonths() throws Exception { void testFailure_periodInMonths() throws Exception {
setEppInput("domain_renew_months.xml"); setEppInput("domain_renew_months.xml");
persistDomain(); persistDomain();
@ -711,7 +716,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_max10Years() throws Exception { void testFailure_max10Years() throws Exception {
setEppInput("domain_renew_11_years.xml"); setEppInput("domain_renew_11_years.xml");
persistDomain(); persistDomain();
@ -719,7 +724,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_curExpDateMustMatch() throws Exception { void testFailure_curExpDateMustMatch() throws Exception {
persistDomain(); persistDomain();
// Note expiration time is off by one day. // Note expiration time is off by one day.
@ -733,7 +738,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_unauthorizedClient() throws Exception { void testFailure_unauthorizedClient() throws Exception {
setClientIdForFlow("NewRegistrar"); setClientIdForFlow("NewRegistrar");
persistActiveDomain(getUniqueIdFromCommand()); persistActiveDomain(getUniqueIdFromCommand());
@ -741,7 +746,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_superuserUnauthorizedClient() throws Exception { void testSuccess_superuserUnauthorizedClient() throws Exception {
setClientIdForFlow("NewRegistrar"); setClientIdForFlow("NewRegistrar");
persistDomain(); persistDomain();
@ -753,7 +758,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z"))); ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z")));
} }
@Test @TestOfyAndSql
void testFailure_notAuthorizedForTld() throws Exception { void testFailure_notAuthorizedForTld() throws Exception {
persistResource( persistResource(
loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build()); loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build());
@ -762,7 +767,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_superuserNotAuthorizedForTld() throws Exception { void testSuccess_superuserNotAuthorizedForTld() throws Exception {
persistResource( persistResource(
loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build()); loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build());
@ -775,7 +780,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z"))); ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z")));
} }
@Test @TestOfyAndSql
void testFailure_feeNotProvidedOnPremiumName() throws Exception { void testFailure_feeNotProvidedOnPremiumName() throws Exception {
createTld("example"); createTld("example");
setEppInput("domain_renew_premium.xml"); setEppInput("domain_renew_premium.xml");
@ -784,7 +789,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testIcannActivityReportField_getsLogged() throws Exception { void testIcannActivityReportField_getsLogged() throws Exception {
persistDomain(); persistDomain();
runFlow(); runFlow();
@ -792,7 +797,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertTldsFieldLogged("tld"); assertTldsFieldLogged("tld");
} }
@Test @TestOfyAndSql
void testIcannTransactionRecord_getsStored() throws Exception { void testIcannTransactionRecord_getsStored() throws Exception {
persistDomain(); persistDomain();
// Test with a nonstandard Renew period to ensure the reporting time is correct regardless // Test with a nonstandard Renew period to ensure the reporting time is correct regardless

View file

@ -16,12 +16,12 @@ package google.registry.flows.domain;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat; import static com.google.common.truth.Truth8.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.assertBillingEvents; import static google.registry.testing.DatabaseHelper.assertBillingEvents;
import static google.registry.testing.DatabaseHelper.assertPollMessages; import static google.registry.testing.DatabaseHelper.assertPollMessages;
import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType; import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType;
import static google.registry.testing.DatabaseHelper.getPollMessages; import static google.registry.testing.DatabaseHelper.getPollMessages;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.loadRegistrar; import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.newDomainBase; import static google.registry.testing.DatabaseHelper.newDomainBase;
import static google.registry.testing.DatabaseHelper.persistActiveDomain; import static google.registry.testing.DatabaseHelper.persistActiveDomain;
@ -71,17 +71,19 @@ import google.registry.model.registry.Registry;
import google.registry.model.reporting.DomainTransactionRecord; import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField; import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension; import google.registry.testing.ReplayExtension;
import google.registry.testing.TestOfyAndSql;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainRestoreRequestFlow}. */ /** Unit tests for {@link DomainRestoreRequestFlow}. */
@DualDatabaseTest
class DomainRestoreRequestFlowTest class DomainRestoreRequestFlowTest
extends ResourceFlowTestCase<DomainRestoreRequestFlow, DomainBase> { extends ResourceFlowTestCase<DomainRestoreRequestFlow, DomainBase> {
@ -141,14 +143,14 @@ class DomainRestoreRequestFlowTest
clock.advanceOneMilli(); clock.advanceOneMilli();
} }
@Test @TestOfyAndSql
void testDryRun() throws Exception { void testDryRun() throws Exception {
setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "example.tld")); setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "example.tld"));
persistPendingDeleteDomain(); persistPendingDeleteDomain();
dryRunFlowAssertResponse(loadFile("generic_success_response.xml")); dryRunFlowAssertResponse(loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testSuccess_expiryStillInFuture_notExtended() throws Exception { void testSuccess_expiryStillInFuture_notExtended() throws Exception {
setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "example.tld")); setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "example.tld"));
DateTime expirationTime = clock.nowUtc().plusYears(5).plusDays(45); DateTime expirationTime = clock.nowUtc().plusYears(5).plusDays(45);
@ -160,7 +162,8 @@ class DomainRestoreRequestFlowTest
DomainBase domain = reloadResourceByForeignKey(); DomainBase domain = reloadResourceByForeignKey();
HistoryEntry historyEntryDomainRestore = HistoryEntry historyEntryDomainRestore =
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RESTORE); getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RESTORE);
assertThat(tm().loadByKey(domain.getAutorenewBillingEvent()).getEventTime()) assertLastHistoryContainsResource(domain);
assertThat(loadByKey(domain.getAutorenewBillingEvent()).getEventTime())
.isEqualTo(expirationTime); .isEqualTo(expirationTime);
assertAboutDomains() assertAboutDomains()
.that(domain) .that(domain)
@ -215,7 +218,7 @@ class DomainRestoreRequestFlowTest
.build()); .build());
} }
@Test @TestOfyAndSql
void testSuccess_expiryInPast_extendedByOneYear() throws Exception { void testSuccess_expiryInPast_extendedByOneYear() throws Exception {
setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "example.tld")); setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "example.tld"));
DateTime expirationTime = clock.nowUtc().minusDays(20); DateTime expirationTime = clock.nowUtc().minusDays(20);
@ -228,7 +231,8 @@ class DomainRestoreRequestFlowTest
DomainBase domain = reloadResourceByForeignKey(); DomainBase domain = reloadResourceByForeignKey();
HistoryEntry historyEntryDomainRestore = HistoryEntry historyEntryDomainRestore =
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RESTORE); getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RESTORE);
assertThat(tm().loadByKey(domain.getAutorenewBillingEvent()).getEventTime()) assertLastHistoryContainsResource(domain);
assertThat(loadByKey(domain.getAutorenewBillingEvent()).getEventTime())
.isEqualTo(newExpirationTime); .isEqualTo(newExpirationTime);
assertAboutDomains() assertAboutDomains()
.that(domain) .that(domain)
@ -293,7 +297,7 @@ class DomainRestoreRequestFlowTest
.build()); .build());
} }
@Test @TestOfyAndSql
void testSuccess_autorenewEndTimeIsCleared() throws Exception { void testSuccess_autorenewEndTimeIsCleared() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP); setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -307,14 +311,14 @@ class DomainRestoreRequestFlowTest
assertThat(reloadResourceByForeignKey().getAutorenewEndTime()).isEmpty(); assertThat(reloadResourceByForeignKey().getAutorenewEndTime()).isEmpty();
} }
@Test @TestOfyAndSql
void testSuccess_fee_v06() throws Exception { void testSuccess_fee_v06() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP); setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_06_MAP)); runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_06_MAP));
} }
@Test @TestOfyAndSql
void testSuccess_fee_v06_noRenewal() throws Exception { void testSuccess_fee_v06_noRenewal() throws Exception {
setEppInput("domain_update_restore_request_fee_no_renewal.xml", FEE_06_MAP); setEppInput("domain_update_restore_request_fee_no_renewal.xml", FEE_06_MAP);
persistPendingDeleteDomain(clock.nowUtc().plusMonths(6)); persistPendingDeleteDomain(clock.nowUtc().plusMonths(6));
@ -322,42 +326,42 @@ class DomainRestoreRequestFlowTest
loadFile("domain_update_restore_request_response_fee_no_renewal.xml", FEE_06_MAP)); loadFile("domain_update_restore_request_response_fee_no_renewal.xml", FEE_06_MAP));
} }
@Test @TestOfyAndSql
void testSuccess_fee_v11() throws Exception { void testSuccess_fee_v11() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_11_MAP); setEppInput("domain_update_restore_request_fee.xml", FEE_11_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_11_MAP)); runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_11_MAP));
} }
@Test @TestOfyAndSql
void testSuccess_fee_v12() throws Exception { void testSuccess_fee_v12() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_12_MAP); setEppInput("domain_update_restore_request_fee.xml", FEE_12_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_12_MAP)); runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_12_MAP));
} }
@Test @TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v06() throws Exception { void testSuccess_fee_withDefaultAttributes_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_06_MAP); setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_06_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_06_MAP)); runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_06_MAP));
} }
@Test @TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v11() throws Exception { void testSuccess_fee_withDefaultAttributes_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_11_MAP); setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_11_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_11_MAP)); runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_11_MAP));
} }
@Test @TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v12() throws Exception { void testSuccess_fee_withDefaultAttributes_v12() throws Exception {
setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_12_MAP); setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_12_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_12_MAP)); runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_12_MAP));
} }
@Test @TestOfyAndSql
void testFailure_fee_unknownCurrency() { void testFailure_fee_unknownCurrency() {
ImmutableMap<String, String> substitutions = ImmutableMap<String, String> substitutions =
ImmutableMap.of("FEE_VERSION", "0.12", "FEE_NS", "fee12", "CURRENCY", "BAD"); ImmutableMap.of("FEE_VERSION", "0.12", "FEE_NS", "fee12", "CURRENCY", "BAD");
@ -367,7 +371,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_refundableFee_v06() throws Exception { void testFailure_refundableFee_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_06_MAP); setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_06_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -375,7 +379,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_refundableFee_v11() throws Exception { void testFailure_refundableFee_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_11_MAP); setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_11_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -383,7 +387,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_refundableFee_v12() throws Exception { void testFailure_refundableFee_v12() throws Exception {
setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_12_MAP); setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_12_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -391,7 +395,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_gracePeriodFee_v06() throws Exception { void testFailure_gracePeriodFee_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_06_MAP); setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_06_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -399,7 +403,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_gracePeriodFee_v11() throws Exception { void testFailure_gracePeriodFee_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_11_MAP); setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_11_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -407,7 +411,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_gracePeriodFee_v12() throws Exception { void testFailure_gracePeriodFee_v12() throws Exception {
setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_12_MAP); setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_12_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -415,7 +419,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_appliedFee_v06() throws Exception { void testFailure_appliedFee_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_applied.xml", FEE_06_MAP); setEppInput("domain_update_restore_request_fee_applied.xml", FEE_06_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -423,7 +427,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_appliedFee_v11() throws Exception { void testFailure_appliedFee_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_applied.xml", FEE_11_MAP); setEppInput("domain_update_restore_request_fee_applied.xml", FEE_11_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -431,7 +435,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_appliedFee_v12() throws Exception { void testFailure_appliedFee_v12() throws Exception {
setEppInput("domain_update_restore_request_fee_applied.xml", FEE_12_MAP); setEppInput("domain_update_restore_request_fee_applied.xml", FEE_12_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -439,7 +443,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_premiumNotBlocked() throws Exception { void testSuccess_premiumNotBlocked() throws Exception {
createTld("example"); createTld("example");
setEppInput("domain_update_restore_request_premium.xml"); setEppInput("domain_update_restore_request_premium.xml");
@ -447,7 +451,7 @@ class DomainRestoreRequestFlowTest
runFlowAssertResponse(loadFile("domain_update_restore_request_response_premium.xml")); runFlowAssertResponse(loadFile("domain_update_restore_request_response_premium.xml"));
} }
@Test @TestOfyAndSql
void testSuccess_premiumNotBlocked_andNoRenewal() throws Exception { void testSuccess_premiumNotBlocked_andNoRenewal() throws Exception {
createTld("example"); createTld("example");
setEppInput("domain_update_restore_request_premium_no_renewal.xml"); setEppInput("domain_update_restore_request_premium_no_renewal.xml");
@ -456,7 +460,7 @@ class DomainRestoreRequestFlowTest
loadFile("domain_update_restore_request_response_fee_no_renewal.xml", FEE_12_MAP)); loadFile("domain_update_restore_request_response_fee_no_renewal.xml", FEE_12_MAP));
} }
@Test @TestOfyAndSql
void testSuccess_superuserOverridesReservedList() throws Exception { void testSuccess_superuserOverridesReservedList() throws Exception {
persistResource( persistResource(
Registry.get("tld") Registry.get("tld")
@ -468,7 +472,7 @@ class DomainRestoreRequestFlowTest
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml")); CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testSuccess_superuserOverridesPremiumNameBlock() throws Exception { void testSuccess_superuserOverridesPremiumNameBlock() throws Exception {
createTld("example"); createTld("example");
setEppInput("domain_update_restore_request_premium.xml"); setEppInput("domain_update_restore_request_premium.xml");
@ -481,7 +485,7 @@ class DomainRestoreRequestFlowTest
loadFile("domain_update_restore_request_response_premium.xml")); loadFile("domain_update_restore_request_response_premium.xml"));
} }
@Test @TestOfyAndSql
void testFailure_doesNotExist() throws Exception { void testFailure_doesNotExist() throws Exception {
ResourceDoesNotExistException thrown = ResourceDoesNotExistException thrown =
assertThrows(ResourceDoesNotExistException.class, this::runFlow); assertThrows(ResourceDoesNotExistException.class, this::runFlow);
@ -489,7 +493,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_suspendedRegistrarCantRestoreDomain() { void testFailure_suspendedRegistrarCantRestoreDomain() {
persistResource( persistResource(
Registrar.loadByClientId("TheRegistrar") Registrar.loadByClientId("TheRegistrar")
@ -502,7 +506,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_pendingRegistrarCantRestoreDomain() { void testFailure_pendingRegistrarCantRestoreDomain() {
persistResource( persistResource(
Registrar.loadByClientId("TheRegistrar") Registrar.loadByClientId("TheRegistrar")
@ -515,7 +519,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_wrongFeeAmount_v06() throws Exception { void testFailure_wrongFeeAmount_v06() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP); setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -525,7 +529,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_wrongFeeAmount_v11() throws Exception { void testFailure_wrongFeeAmount_v11() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_11_MAP); setEppInput("domain_update_restore_request_fee.xml", FEE_11_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -535,7 +539,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_wrongFeeAmount_v12() throws Exception { void testFailure_wrongFeeAmount_v12() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_12_MAP); setEppInput("domain_update_restore_request_fee.xml", FEE_12_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -563,22 +567,22 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_wrongCurrency_v06() throws Exception { void testFailure_wrongCurrency_v06() throws Exception {
runWrongCurrencyTest(FEE_06_MAP); runWrongCurrencyTest(FEE_06_MAP);
} }
@Test @TestOfyAndSql
void testFailure_wrongCurrency_v11() throws Exception { void testFailure_wrongCurrency_v11() throws Exception {
runWrongCurrencyTest(FEE_11_MAP); runWrongCurrencyTest(FEE_11_MAP);
} }
@Test @TestOfyAndSql
void testFailure_wrongCurrency_v12() throws Exception { void testFailure_wrongCurrency_v12() throws Exception {
runWrongCurrencyTest(FEE_12_MAP); runWrongCurrencyTest(FEE_12_MAP);
} }
@Test @TestOfyAndSql
void testFailure_feeGivenInWrongScale_v06() throws Exception { void testFailure_feeGivenInWrongScale_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_06_MAP); setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_06_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -586,7 +590,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_feeGivenInWrongScale_v11() throws Exception { void testFailure_feeGivenInWrongScale_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_11_MAP); setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_11_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -594,7 +598,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_feeGivenInWrongScale_v12() throws Exception { void testFailure_feeGivenInWrongScale_v12() throws Exception {
setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_12_MAP); setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_12_MAP);
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -602,7 +606,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_notInRedemptionPeriod() throws Exception { void testFailure_notInRedemptionPeriod() throws Exception {
persistResource( persistResource(
newDomainBase(getUniqueIdFromCommand()) newDomainBase(getUniqueIdFromCommand())
@ -614,21 +618,21 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_notDeleted() throws Exception { void testFailure_notDeleted() throws Exception {
persistActiveDomain(getUniqueIdFromCommand()); persistActiveDomain(getUniqueIdFromCommand());
EppException thrown = assertThrows(DomainNotEligibleForRestoreException.class, this::runFlow); EppException thrown = assertThrows(DomainNotEligibleForRestoreException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_fullyDeleted() throws Exception { void testFailure_fullyDeleted() throws Exception {
persistDeletedDomain(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1)); persistDeletedDomain(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1));
EppException thrown = assertThrows(ResourceDoesNotExistException.class, this::runFlow); EppException thrown = assertThrows(ResourceDoesNotExistException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_withChange() throws Exception { void testFailure_withChange() throws Exception {
persistPendingDeleteDomain(); persistPendingDeleteDomain();
setEppInput("domain_update_restore_request_with_change.xml"); setEppInput("domain_update_restore_request_with_change.xml");
@ -636,7 +640,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_withAdd() throws Exception { void testFailure_withAdd() throws Exception {
persistPendingDeleteDomain(); persistPendingDeleteDomain();
setEppInput("domain_update_restore_request_with_add.xml"); setEppInput("domain_update_restore_request_with_add.xml");
@ -644,7 +648,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_withRemove() throws Exception { void testFailure_withRemove() throws Exception {
persistPendingDeleteDomain(); persistPendingDeleteDomain();
setEppInput("domain_update_restore_request_with_remove.xml"); setEppInput("domain_update_restore_request_with_remove.xml");
@ -652,7 +656,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_withSecDnsExtension() throws Exception { void testFailure_withSecDnsExtension() throws Exception {
persistPendingDeleteDomain(); persistPendingDeleteDomain();
setEppInput("domain_update_restore_request_with_secdns.xml"); setEppInput("domain_update_restore_request_with_secdns.xml");
@ -660,7 +664,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_unauthorizedClient() throws Exception { void testFailure_unauthorizedClient() throws Exception {
sessionMetadata.setClientId("NewRegistrar"); sessionMetadata.setClientId("NewRegistrar");
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -668,7 +672,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_superuserUnauthorizedClient() throws Exception { void testSuccess_superuserUnauthorizedClient() throws Exception {
sessionMetadata.setClientId("NewRegistrar"); sessionMetadata.setClientId("NewRegistrar");
persistPendingDeleteDomain(); persistPendingDeleteDomain();
@ -679,7 +683,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_notAuthorizedForTld() throws Exception { void testFailure_notAuthorizedForTld() throws Exception {
persistResource( persistResource(
loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build()); loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build());
@ -688,7 +692,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_superuserNotAuthorizedForTld() throws Exception { void testSuccess_superuserNotAuthorizedForTld() throws Exception {
persistResource( persistResource(
loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build()); loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build());
@ -697,7 +701,7 @@ class DomainRestoreRequestFlowTest
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml")); CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testFailure_premiumBlocked() throws Exception { void testFailure_premiumBlocked() throws Exception {
createTld("example"); createTld("example");
setEppInput("domain_update_restore_request_premium.xml"); setEppInput("domain_update_restore_request_premium.xml");
@ -708,7 +712,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_reservedBlocked() throws Exception { void testFailure_reservedBlocked() throws Exception {
createTld("tld"); createTld("tld");
persistResource( persistResource(
@ -721,7 +725,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_premiumNotAcked() throws Exception { void testFailure_premiumNotAcked() throws Exception {
createTld("example"); createTld("example");
setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "rich.example")); setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "rich.example"));
@ -730,7 +734,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testIcannActivityReportField_getsLogged() throws Exception { void testIcannActivityReportField_getsLogged() throws Exception {
persistPendingDeleteDomain(); persistPendingDeleteDomain();
runFlow(); runFlow();
@ -738,7 +742,7 @@ class DomainRestoreRequestFlowTest
assertTldsFieldLogged("tld"); assertTldsFieldLogged("tld");
} }
@Test @TestOfyAndSql
void testIcannTransactionReportField_getsStored() throws Exception { void testIcannTransactionReportField_getsStored() throws Exception {
persistPendingDeleteDomain(); persistPendingDeleteDomain();
runFlow(); runFlow();
@ -754,7 +758,7 @@ class DomainRestoreRequestFlowTest
1)); 1));
} }
@Test @TestOfyAndSql
void testFailure_restoreReportsAreNotSupported() { void testFailure_restoreReportsAreNotSupported() {
setEppInput("domain_update_restore_report.xml"); setEppInput("domain_update_restore_report.xml");
// This exception is referred to by its fully qualified path (rather than being imported) so // This exception is referred to by its fully qualified path (rather than being imported) so

View file

@ -132,6 +132,7 @@ class DomainTransferCancelFlowTest
// Transfer should have been cancelled. Verify correct fields were set. // Transfer should have been cancelled. Verify correct fields were set.
domain = reloadResourceByForeignKey(); domain = reloadResourceByForeignKey();
assertLastHistoryContainsResource(domain);
assertTransferFailed(domain, TransferStatus.CLIENT_CANCELLED, originalTransferData); assertTransferFailed(domain, TransferStatus.CLIENT_CANCELLED, originalTransferData);
assertAboutDomains() assertAboutDomains()
.that(domain) .that(domain)

View file

@ -34,13 +34,15 @@ import google.registry.model.domain.DomainBase;
import google.registry.model.eppcommon.AuthInfo.PasswordAuth; import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.model.transfer.TransferStatus; import google.registry.model.transfer.TransferStatus;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension; import google.registry.testing.ReplayExtension;
import google.registry.testing.TestOfyAndSql;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainTransferQueryFlow}. */ /** Unit tests for {@link DomainTransferQueryFlow}. */
@DualDatabaseTest
class DomainTransferQueryFlowTest class DomainTransferQueryFlowTest
extends DomainTransferFlowTestCase<DomainTransferQueryFlow, DomainBase> { extends DomainTransferFlowTestCase<DomainTransferQueryFlow, DomainBase> {
@ -86,67 +88,67 @@ class DomainTransferQueryFlowTest
runFlow(); runFlow();
} }
@Test @TestOfyAndSql
void testSuccess() throws Exception { void testSuccess() throws Exception {
doSuccessfulTest("domain_transfer_query.xml", "domain_transfer_query_response.xml", 1); doSuccessfulTest("domain_transfer_query.xml", "domain_transfer_query_response.xml", 1);
} }
@Test @TestOfyAndSql
void testSuccess_sponsoringClient() throws Exception { void testSuccess_sponsoringClient() throws Exception {
setClientIdForFlow("TheRegistrar"); setClientIdForFlow("TheRegistrar");
doSuccessfulTest("domain_transfer_query.xml", "domain_transfer_query_response.xml", 1); doSuccessfulTest("domain_transfer_query.xml", "domain_transfer_query_response.xml", 1);
} }
@Test @TestOfyAndSql
void testSuccess_domainAuthInfo() throws Exception { void testSuccess_domainAuthInfo() throws Exception {
setClientIdForFlow("ClientZ"); setClientIdForFlow("ClientZ");
doSuccessfulTest( doSuccessfulTest(
"domain_transfer_query_domain_authinfo.xml", "domain_transfer_query_response.xml", 1); "domain_transfer_query_domain_authinfo.xml", "domain_transfer_query_response.xml", 1);
} }
@Test @TestOfyAndSql
void testSuccess_contactAuthInfo() throws Exception { void testSuccess_contactAuthInfo() throws Exception {
setClientIdForFlow("ClientZ"); setClientIdForFlow("ClientZ");
doSuccessfulTest( doSuccessfulTest(
"domain_transfer_query_contact_authinfo.xml", "domain_transfer_query_response.xml", 1); "domain_transfer_query_contact_authinfo.xml", "domain_transfer_query_response.xml", 1);
} }
@Test @TestOfyAndSql
void testSuccess_clientApproved() throws Exception { void testSuccess_clientApproved() throws Exception {
changeTransferStatus(TransferStatus.CLIENT_APPROVED); changeTransferStatus(TransferStatus.CLIENT_APPROVED);
doSuccessfulTest( doSuccessfulTest(
"domain_transfer_query.xml", "domain_transfer_query_response_client_approved.xml", 1); "domain_transfer_query.xml", "domain_transfer_query_response_client_approved.xml", 1);
} }
@Test @TestOfyAndSql
void testSuccess_clientRejected() throws Exception { void testSuccess_clientRejected() throws Exception {
changeTransferStatus(TransferStatus.CLIENT_REJECTED); changeTransferStatus(TransferStatus.CLIENT_REJECTED);
doSuccessfulTest( doSuccessfulTest(
"domain_transfer_query.xml", "domain_transfer_query_response_client_rejected.xml", 1); "domain_transfer_query.xml", "domain_transfer_query_response_client_rejected.xml", 1);
} }
@Test @TestOfyAndSql
void testSuccess_clientCancelled() throws Exception { void testSuccess_clientCancelled() throws Exception {
changeTransferStatus(TransferStatus.CLIENT_CANCELLED); changeTransferStatus(TransferStatus.CLIENT_CANCELLED);
doSuccessfulTest( doSuccessfulTest(
"domain_transfer_query.xml", "domain_transfer_query_response_client_cancelled.xml", 1); "domain_transfer_query.xml", "domain_transfer_query_response_client_cancelled.xml", 1);
} }
@Test @TestOfyAndSql
void testSuccess_serverApproved() throws Exception { void testSuccess_serverApproved() throws Exception {
changeTransferStatus(TransferStatus.SERVER_APPROVED); changeTransferStatus(TransferStatus.SERVER_APPROVED);
doSuccessfulTest( doSuccessfulTest(
"domain_transfer_query.xml", "domain_transfer_query_response_server_approved.xml", 1); "domain_transfer_query.xml", "domain_transfer_query_response_server_approved.xml", 1);
} }
@Test @TestOfyAndSql
void testSuccess_serverCancelled() throws Exception { void testSuccess_serverCancelled() throws Exception {
changeTransferStatus(TransferStatus.SERVER_CANCELLED); changeTransferStatus(TransferStatus.SERVER_CANCELLED);
doSuccessfulTest( doSuccessfulTest(
"domain_transfer_query.xml", "domain_transfer_query_response_server_cancelled.xml", 1); "domain_transfer_query.xml", "domain_transfer_query_response_server_cancelled.xml", 1);
} }
@Test @TestOfyAndSql
void testSuccess_tenYears() throws Exception { void testSuccess_tenYears() throws Exception {
// Extend registration by 9 years here; with the extra 1 year from the transfer, we should // Extend registration by 9 years here; with the extra 1 year from the transfer, we should
// hit the 10-year capping. // hit the 10-year capping.
@ -159,7 +161,7 @@ class DomainTransferQueryFlowTest
doSuccessfulTest("domain_transfer_query.xml", "domain_transfer_query_response_10_years.xml", 1); doSuccessfulTest("domain_transfer_query.xml", "domain_transfer_query_response_10_years.xml", 1);
} }
@Test @TestOfyAndSql
void testFailure_pendingDeleteDomain() throws Exception { void testFailure_pendingDeleteDomain() throws Exception {
changeTransferStatus(TransferStatus.SERVER_CANCELLED); changeTransferStatus(TransferStatus.SERVER_CANCELLED);
domain = domain =
@ -168,7 +170,7 @@ class DomainTransferQueryFlowTest
"domain_transfer_query.xml", "domain_transfer_query_response_server_cancelled.xml", 1); "domain_transfer_query.xml", "domain_transfer_query_response_server_cancelled.xml", 1);
} }
@Test @TestOfyAndSql
void testFailure_badContactPassword() { void testFailure_badContactPassword() {
// Change the contact's password so it does not match the password in the file. // Change the contact's password so it does not match the password in the file.
contact = contact =
@ -184,7 +186,7 @@ class DomainTransferQueryFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_badDomainPassword() { void testFailure_badDomainPassword() {
// Change the domain's password so it does not match the password in the file. // Change the domain's password so it does not match the password in the file.
domain = domain =
@ -200,7 +202,7 @@ class DomainTransferQueryFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_neverBeenTransferred() { void testFailure_neverBeenTransferred() {
changeTransferStatus(null); changeTransferStatus(null);
EppException thrown = EppException thrown =
@ -210,7 +212,7 @@ class DomainTransferQueryFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_unrelatedClient() { void testFailure_unrelatedClient() {
setClientIdForFlow("ClientZ"); setClientIdForFlow("ClientZ");
EppException thrown = EppException thrown =
@ -220,7 +222,7 @@ class DomainTransferQueryFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_deletedDomain() throws Exception { void testFailure_deletedDomain() throws Exception {
domain = domain =
persistResource(domain.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build()); persistResource(domain.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build());
@ -230,7 +232,7 @@ class DomainTransferQueryFlowTest
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
} }
@Test @TestOfyAndSql
void testFailure_nonexistentDomain() throws Exception { void testFailure_nonexistentDomain() throws Exception {
deleteTestDomain(domain, clock.nowUtc()); deleteTestDomain(domain, clock.nowUtc());
ResourceDoesNotExistException thrown = ResourceDoesNotExistException thrown =
@ -239,14 +241,14 @@ class DomainTransferQueryFlowTest
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
} }
@Test @TestOfyAndSql
void testIcannActivityReportField_getsLogged() throws Exception { void testIcannActivityReportField_getsLogged() throws Exception {
runFlow(); runFlow();
assertIcannReportingActivityFieldLogged("srs-dom-transfer-query"); assertIcannReportingActivityFieldLogged("srs-dom-transfer-query");
assertTldsFieldLogged("tld"); assertTldsFieldLogged("tld");
} }
@Test @TestOfyAndSql
void testSuccess_serverApproved_afterAutorenews() throws Exception { void testSuccess_serverApproved_afterAutorenews() throws Exception {
// Set the clock to just past the extended registration time. We'd expect the domain to have // Set the clock to just past the extended registration time. We'd expect the domain to have
// auto-renewed once, but the transfer query response should be the same. // auto-renewed once, but the transfer query response should be the same.

View file

@ -119,6 +119,7 @@ class DomainTransferRejectFlowTest
final HistoryEntry historyEntryTransferRejected = final HistoryEntry historyEntryTransferRejected =
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REJECT); getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REJECT);
assertAboutHistoryEntries().that(historyEntryTransferRejected).hasOtherClientId("NewRegistrar"); assertAboutHistoryEntries().that(historyEntryTransferRejected).hasOtherClientId("NewRegistrar");
assertLastHistoryContainsResource(domain);
// 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.
assertBillingEvents( assertBillingEvents(
getLosingClientAutorenewEvent().asBuilder().setRecurrenceEndTime(END_OF_TIME).build()); getLosingClientAutorenewEvent().asBuilder().setRecurrenceEndTime(END_OF_TIME).build());

View file

@ -484,6 +484,7 @@ class DomainTransferRequestFlowTest
assertAboutDomains() assertAboutDomains()
.that(domain) .that(domain)
.hasOneHistoryEntryEachOfTypes(DOMAIN_CREATE, DOMAIN_TRANSFER_REQUEST); .hasOneHistoryEntryEachOfTypes(DOMAIN_CREATE, DOMAIN_TRANSFER_REQUEST);
assertLastHistoryContainsResource(domain);
final HistoryEntry historyEntryTransferRequest = final HistoryEntry historyEntryTransferRequest =
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REQUEST); getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REQUEST);
assertAboutHistoryEntries() assertAboutHistoryEntries()

View file

@ -21,11 +21,11 @@ import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.eppcommon.StatusValue.SERVER_UPDATE_PROHIBITED; import static google.registry.model.eppcommon.StatusValue.SERVER_UPDATE_PROHIBITED;
import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD; import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.assertBillingEvents; import static google.registry.testing.DatabaseHelper.assertBillingEvents;
import static google.registry.testing.DatabaseHelper.assertNoBillingEvents; import static google.registry.testing.DatabaseHelper.assertNoBillingEvents;
import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType; import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.loadRegistrar; import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.newDomainBase; import static google.registry.testing.DatabaseHelper.newDomainBase;
import static google.registry.testing.DatabaseHelper.persistActiveContact; import static google.registry.testing.DatabaseHelper.persistActiveContact;
@ -90,16 +90,18 @@ import google.registry.model.host.HostResource;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension; import google.registry.testing.ReplayExtension;
import google.registry.testing.TestOfyAndSql;
import java.util.Optional; import java.util.Optional;
import org.joda.money.Money; import org.joda.money.Money;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainUpdateFlow}. */ /** Unit tests for {@link DomainUpdateFlow}. */
@DualDatabaseTest
class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, DomainBase> { class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, DomainBase> {
private static final DelegationSignerData SOME_DSDATA = private static final DelegationSignerData SOME_DSDATA =
@ -207,23 +209,24 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.hasNoAutorenewEndTime(); .hasNoAutorenewEndTime();
assertNoBillingEvents(); assertNoBillingEvents();
assertDnsTasksEnqueued("example.tld"); assertDnsTasksEnqueued("example.tld");
assertLastHistoryContainsResource(reloadResourceByForeignKey());
} }
@Test @TestOfyAndSql
void testDryRun() throws Exception { void testDryRun() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
dryRunFlowAssertResponse(loadFile("generic_success_response.xml")); dryRunFlowAssertResponse(loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testSuccess() throws Exception { void testSuccess() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
doSuccessfulTest(); doSuccessfulTest();
} }
@Test @TestOfyAndSql
void testSuccess_clTridNotSpecified() throws Exception { void testSuccess_clTridNotSpecified() throws Exception {
setEppInput("domain_update_no_cltrid.xml"); setEppInput("domain_update_no_cltrid.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -231,7 +234,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doSuccessfulTest("generic_success_response_no_cltrid.xml"); doSuccessfulTest("generic_success_response_no_cltrid.xml");
} }
@Test @TestOfyAndSql
void testSuccess_cachingDisabled() throws Exception { void testSuccess_cachingDisabled() throws Exception {
boolean origIsCachingEnabled = RegistryConfig.isEppResourceCachingEnabled(); boolean origIsCachingEnabled = RegistryConfig.isEppResourceCachingEnabled();
try { try {
@ -244,7 +247,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
} }
} }
@Test @TestOfyAndSql
void testSuccess_inQuietPeriod() throws Exception { void testSuccess_inQuietPeriod() throws Exception {
persistResource( persistResource(
Registry.get("tld") Registry.get("tld")
@ -256,7 +259,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doSuccessfulTest(); doSuccessfulTest();
} }
@Test @TestOfyAndSql
void testFailure_emptyRegistrant() throws Exception { void testFailure_emptyRegistrant() throws Exception {
setEppInput("domain_update_empty_registrant.xml"); setEppInput("domain_update_empty_registrant.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -282,7 +285,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
clock.advanceOneMilli(); clock.advanceOneMilli();
} }
@Test @TestOfyAndSql
void testSuccess_maxNumberOfNameservers() throws Exception { void testSuccess_maxNumberOfNameservers() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
@ -291,7 +294,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doSuccessfulTest(); doSuccessfulTest();
} }
@Test @TestOfyAndSql
void testSuccess_addAndRemoveLargeNumberOfNameserversAndContacts() throws Exception { void testSuccess_addAndRemoveLargeNumberOfNameserversAndContacts() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
@ -330,12 +333,12 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(domain.getNameservers()).hasSize(13); assertThat(domain.getNameservers()).hasSize(13);
// getContacts does not return contacts of type REGISTRANT, so check these separately. // getContacts does not return contacts of type REGISTRANT, so check these separately.
assertThat(domain.getContacts()).hasSize(3); assertThat(domain.getContacts()).hasSize(3);
assertThat(tm().loadByKey(domain.getRegistrant()).getContactId()).isEqualTo("max_test_7"); assertThat(loadByKey(domain.getRegistrant()).getContactId()).isEqualTo("max_test_7");
assertNoBillingEvents(); assertNoBillingEvents();
assertDnsTasksEnqueued("example.tld"); assertDnsTasksEnqueued("example.tld");
} }
@Test @TestOfyAndSql
void testSuccess_metadata() throws Exception { void testSuccess_metadata() throws Exception {
eppRequestSource = EppRequestSource.TOOL; eppRequestSource = EppRequestSource.TOOL;
setEppInput("domain_update_metadata.xml"); setEppInput("domain_update_metadata.xml");
@ -354,7 +357,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.hasMetadataRequestedByRegistrar(true); .hasMetadataRequestedByRegistrar(true);
} }
@Test @TestOfyAndSql
void testSuccess_metadataNotFromTool() throws Exception { void testSuccess_metadataNotFromTool() throws Exception {
setEppInput("domain_update_metadata.xml"); setEppInput("domain_update_metadata.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -363,7 +366,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_removeContact() throws Exception { void testSuccess_removeContact() throws Exception {
setEppInput("domain_update_remove_contact.xml"); setEppInput("domain_update_remove_contact.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -371,7 +374,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doSuccessfulTest(); doSuccessfulTest();
} }
@Test @TestOfyAndSql
void testSuccess_addAndRemoveSubordinateHostNameservers() throws Exception { void testSuccess_addAndRemoveSubordinateHostNameservers() throws Exception {
// Test that operations involving subordinate hosts as nameservers do not change the subordinate // Test that operations involving subordinate hosts as nameservers do not change the subordinate
// host relationship itself. // host relationship itself.
@ -404,7 +407,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(addedHost.getSuperordinateDomain()).isEqualTo(domain.createVKey()); assertThat(addedHost.getSuperordinateDomain()).isEqualTo(domain.createVKey());
} }
@Test @TestOfyAndSql
void testSuccess_registrantMovedToTechContact() throws Exception { void testSuccess_registrantMovedToTechContact() throws Exception {
setEppInput("domain_update_registrant_to_tech.xml"); setEppInput("domain_update_registrant_to_tech.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -419,7 +422,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
runFlowAssertResponse(loadFile("generic_success_response.xml")); runFlowAssertResponse(loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testSuccess_multipleReferencesToSameContactRemoved() throws Exception { void testSuccess_multipleReferencesToSameContactRemoved() throws Exception {
setEppInput("domain_update_remove_multiple_contacts.xml"); setEppInput("domain_update_remove_multiple_contacts.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -440,7 +443,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
runFlowAssertResponse(loadFile("generic_success_response.xml")); runFlowAssertResponse(loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testSuccess_removeClientUpdateProhibited() throws Exception { void testSuccess_removeClientUpdateProhibited() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistResource( persistResource(
@ -488,7 +491,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertDnsTasksEnqueued("example.tld"); assertDnsTasksEnqueued("example.tld");
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAdd() throws Exception { void testSuccess_secDnsAdd() throws Exception {
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
"domain_update_dsdata_add.xml", "domain_update_dsdata_add.xml",
@ -499,7 +502,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
"KEY_TAG", "12346", "ALG", "3", "DIGEST_TYPE", "1", "DIGEST", "38EC35D5B3A34B44C39B")); "KEY_TAG", "12346", "ALG", "3", "DIGEST_TYPE", "1", "DIGEST", "38EC35D5B3A34B44C39B"));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAddPreservesExisting() throws Exception { void testSuccess_secDnsAddPreservesExisting() throws Exception {
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
"domain_update_dsdata_add.xml", "domain_update_dsdata_add.xml",
@ -511,7 +514,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
"KEY_TAG", "12346", "ALG", "3", "DIGEST_TYPE", "1", "DIGEST", "38EC35D5B3A34B44C39B")); "KEY_TAG", "12346", "ALG", "3", "DIGEST_TYPE", "1", "DIGEST", "38EC35D5B3A34B44C39B"));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAddSameDoesNothing() throws Exception { void testSuccess_secDnsAddSameDoesNothing() throws Exception {
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
"domain_update_dsdata_add.xml", "domain_update_dsdata_add.xml",
@ -520,7 +523,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
ImmutableMap.of("KEY_TAG", "1", "ALG", "2", "DIGEST_TYPE", "3", "DIGEST", "0123")); ImmutableMap.of("KEY_TAG", "1", "ALG", "2", "DIGEST_TYPE", "3", "DIGEST", "0123"));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAddOnlyKeyTagRemainsSame() throws Exception { void testSuccess_secDnsAddOnlyKeyTagRemainsSame() throws Exception {
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
"domain_update_dsdata_add.xml", "domain_update_dsdata_add.xml",
@ -531,7 +534,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
} }
// Changing any of the four fields in DelegationSignerData should result in a new object // Changing any of the four fields in DelegationSignerData should result in a new object
@Test @TestOfyAndSql
void testSuccess_secDnsAddOnlyChangeKeyTag() throws Exception { void testSuccess_secDnsAddOnlyChangeKeyTag() throws Exception {
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
"domain_update_dsdata_add.xml", "domain_update_dsdata_add.xml",
@ -541,7 +544,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
ImmutableMap.of("KEY_TAG", "12346", "ALG", "2", "DIGEST_TYPE", "3", "DIGEST", "0123")); ImmutableMap.of("KEY_TAG", "12346", "ALG", "2", "DIGEST_TYPE", "3", "DIGEST", "0123"));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAddOnlyChangeAlgorithm() throws Exception { void testSuccess_secDnsAddOnlyChangeAlgorithm() throws Exception {
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
"domain_update_dsdata_add.xml", "domain_update_dsdata_add.xml",
@ -550,7 +553,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
ImmutableMap.of("KEY_TAG", "1", "ALG", "8", "DIGEST_TYPE", "3", "DIGEST", "0123")); ImmutableMap.of("KEY_TAG", "1", "ALG", "8", "DIGEST_TYPE", "3", "DIGEST", "0123"));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAddOnlyChangeDigestType() throws Exception { void testSuccess_secDnsAddOnlyChangeDigestType() throws Exception {
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
"domain_update_dsdata_add.xml", "domain_update_dsdata_add.xml",
@ -559,7 +562,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
ImmutableMap.of("KEY_TAG", "1", "ALG", "2", "DIGEST_TYPE", "4", "DIGEST", "0123")); ImmutableMap.of("KEY_TAG", "1", "ALG", "2", "DIGEST_TYPE", "4", "DIGEST", "0123"));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAddOnlyChangeDigest() throws Exception { void testSuccess_secDnsAddOnlyChangeDigest() throws Exception {
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
"domain_update_dsdata_add.xml", "domain_update_dsdata_add.xml",
@ -568,7 +571,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
ImmutableMap.of("KEY_TAG", "1", "ALG", "2", "DIGEST_TYPE", "3", "DIGEST", "4567")); ImmutableMap.of("KEY_TAG", "1", "ALG", "2", "DIGEST_TYPE", "3", "DIGEST", "4567"));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAddToMaxRecords() throws Exception { void testSuccess_secDnsAddToMaxRecords() throws Exception {
ImmutableSet.Builder<DelegationSignerData> builder = new ImmutableSet.Builder<>(); ImmutableSet.Builder<DelegationSignerData> builder = new ImmutableSet.Builder<>();
for (int i = 0; i < 7; ++i) { for (int i = 0; i < 7; ++i) {
@ -587,7 +590,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
12346, 3, 1, base16().decode("38EC35D5B3A34B44C39B")))))); 12346, 3, 1, base16().decode("38EC35D5B3A34B44C39B"))))));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsRemove() throws Exception { void testSuccess_secDnsRemove() throws Exception {
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
"domain_update_dsdata_rem.xml", "domain_update_dsdata_rem.xml",
@ -597,7 +600,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
ImmutableSet.of(SOME_DSDATA)); ImmutableSet.of(SOME_DSDATA));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsRemoveAll() throws Exception { void testSuccess_secDnsRemoveAll() throws Exception {
// As an aside, this test also validates that it's ok to set the 'urgent' attribute to false. // As an aside, this test also validates that it's ok to set the 'urgent' attribute to false.
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
@ -608,7 +611,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
ImmutableSet.of()); ImmutableSet.of());
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAddRemove() throws Exception { void testSuccess_secDnsAddRemove() throws Exception {
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
"domain_update_dsdata_add_rem.xml", "domain_update_dsdata_add_rem.xml",
@ -620,7 +623,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
DelegationSignerData.create(12346, 3, 1, base16().decode("38EC35D5B3A34B44C39B")))); DelegationSignerData.create(12346, 3, 1, base16().decode("38EC35D5B3A34B44C39B"))));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAddRemoveToMaxRecords() throws Exception { void testSuccess_secDnsAddRemoveToMaxRecords() throws Exception {
ImmutableSet.Builder<DelegationSignerData> builder = new ImmutableSet.Builder<>(); ImmutableSet.Builder<DelegationSignerData> builder = new ImmutableSet.Builder<>();
for (int i = 0; i < 7; ++i) { for (int i = 0; i < 7; ++i) {
@ -644,7 +647,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
12346, 3, 1, base16().decode("38EC35D5B3A34B44C39B")))))); 12346, 3, 1, base16().decode("38EC35D5B3A34B44C39B"))))));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsAddRemoveSame() throws Exception { void testSuccess_secDnsAddRemoveSame() throws Exception {
// Adding and removing the same dsData is a no-op because removes are processed first. // Adding and removing the same dsData is a no-op because removes are processed first.
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
@ -657,7 +660,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
DelegationSignerData.create(12345, 3, 1, base16().decode("38EC35D5B3A34B33C99B")))); DelegationSignerData.create(12345, 3, 1, base16().decode("38EC35D5B3A34B33C99B"))));
} }
@Test @TestOfyAndSql
void testSuccess_secDnsRemoveAlreadyNotThere() throws Exception { void testSuccess_secDnsRemoveAlreadyNotThere() throws Exception {
// Removing a dsData that isn't there is a no-op. // Removing a dsData that isn't there is a no-op.
doSecDnsSuccessfulTest( doSecDnsSuccessfulTest(
@ -688,7 +691,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
} }
} }
@Test @TestOfyAndSql
void testSuccess_addServerStatusBillingEvent() throws Exception { void testSuccess_addServerStatusBillingEvent() throws Exception {
eppRequestSource = EppRequestSource.TOOL; eppRequestSource = EppRequestSource.TOOL;
persistReferencedEntities(); persistReferencedEntities();
@ -696,7 +699,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doServerStatusBillingTest("domain_update_add_server_status.xml", true); doServerStatusBillingTest("domain_update_add_server_status.xml", true);
} }
@Test @TestOfyAndSql
void testSuccess_noBillingOnPreExistingServerStatus() throws Exception { void testSuccess_noBillingOnPreExistingServerStatus() throws Exception {
eppRequestSource = EppRequestSource.TOOL; eppRequestSource = EppRequestSource.TOOL;
DomainBase addStatusDomain = persistActiveDomain(getUniqueIdFromCommand()); DomainBase addStatusDomain = persistActiveDomain(getUniqueIdFromCommand());
@ -705,7 +708,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doServerStatusBillingTest("domain_update_add_server_status.xml", false); doServerStatusBillingTest("domain_update_add_server_status.xml", false);
} }
@Test @TestOfyAndSql
void testSuccess_removeServerStatusBillingEvent() throws Exception { void testSuccess_removeServerStatusBillingEvent() throws Exception {
eppRequestSource = EppRequestSource.TOOL; eppRequestSource = EppRequestSource.TOOL;
persistReferencedEntities(); persistReferencedEntities();
@ -715,7 +718,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doServerStatusBillingTest("domain_update_remove_server_status.xml", true); doServerStatusBillingTest("domain_update_remove_server_status.xml", true);
} }
@Test @TestOfyAndSql
void testSuccess_changeServerStatusBillingEvent() throws Exception { void testSuccess_changeServerStatusBillingEvent() throws Exception {
eppRequestSource = EppRequestSource.TOOL; eppRequestSource = EppRequestSource.TOOL;
persistReferencedEntities(); persistReferencedEntities();
@ -725,26 +728,26 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doServerStatusBillingTest("domain_update_change_server_status.xml", true); doServerStatusBillingTest("domain_update_change_server_status.xml", true);
} }
@Test @TestOfyAndSql
void testSuccess_noBillingEventOnNonServerStatusChange() throws Exception { void testSuccess_noBillingEventOnNonServerStatusChange() throws Exception {
persistActiveDomain(getUniqueIdFromCommand()); persistActiveDomain(getUniqueIdFromCommand());
doServerStatusBillingTest("domain_update_add_non_server_status.xml", false); doServerStatusBillingTest("domain_update_add_non_server_status.xml", false);
} }
@Test @TestOfyAndSql
void testSuccess_noBillingEventOnServerHoldStatusChange() throws Exception { void testSuccess_noBillingEventOnServerHoldStatusChange() throws Exception {
persistActiveDomain(getUniqueIdFromCommand()); persistActiveDomain(getUniqueIdFromCommand());
doServerStatusBillingTest("domain_update_add_server_hold_status.xml", false); doServerStatusBillingTest("domain_update_add_server_hold_status.xml", false);
} }
@Test @TestOfyAndSql
void testSuccess_noBillingEventOnServerStatusChangeNotFromRegistrar() throws Exception { void testSuccess_noBillingEventOnServerStatusChangeNotFromRegistrar() throws Exception {
eppRequestSource = EppRequestSource.TOOL; eppRequestSource = EppRequestSource.TOOL;
persistActiveDomain(getUniqueIdFromCommand()); persistActiveDomain(getUniqueIdFromCommand());
doServerStatusBillingTest("domain_update_add_server_status_non_registrar.xml", false); doServerStatusBillingTest("domain_update_add_server_status_non_registrar.xml", false);
} }
@Test @TestOfyAndSql
void testSuccess_superuserClientUpdateProhibited() throws Exception { void testSuccess_superuserClientUpdateProhibited() throws Exception {
setEppInput("domain_update_add_server_hold_status.xml"); setEppInput("domain_update_add_server_hold_status.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -772,29 +775,29 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_secDnsAllCannotBeFalse() throws Exception { void testFailure_secDnsAllCannotBeFalse() throws Exception {
doSecDnsFailingTest(SecDnsAllUsageException.class, "domain_update_dsdata_rem_all_false.xml"); doSecDnsFailingTest(SecDnsAllUsageException.class, "domain_update_dsdata_rem_all_false.xml");
} }
@Test @TestOfyAndSql
void testFailure_secDnsEmptyNotAllowed() throws Exception { void testFailure_secDnsEmptyNotAllowed() throws Exception {
doSecDnsFailingTest(EmptySecDnsUpdateException.class, "domain_update_dsdata_empty.xml"); doSecDnsFailingTest(EmptySecDnsUpdateException.class, "domain_update_dsdata_empty.xml");
} }
@Test @TestOfyAndSql
void testFailure_secDnsUrgentNotSupported() throws Exception { void testFailure_secDnsUrgentNotSupported() throws Exception {
doSecDnsFailingTest( doSecDnsFailingTest(
UrgentAttributeNotSupportedException.class, "domain_update_dsdata_urgent.xml"); UrgentAttributeNotSupportedException.class, "domain_update_dsdata_urgent.xml");
} }
@Test @TestOfyAndSql
void testFailure_secDnsChangeNotSupported() throws Exception { void testFailure_secDnsChangeNotSupported() throws Exception {
doSecDnsFailingTest( doSecDnsFailingTest(
MaxSigLifeChangeNotSupportedException.class, "domain_update_maxsiglife.xml"); MaxSigLifeChangeNotSupportedException.class, "domain_update_maxsiglife.xml");
} }
@Test @TestOfyAndSql
void testFailure_secDnsTooManyDsRecords() throws Exception { void testFailure_secDnsTooManyDsRecords() throws Exception {
ImmutableSet.Builder<DelegationSignerData> builder = new ImmutableSet.Builder<>(); ImmutableSet.Builder<DelegationSignerData> builder = new ImmutableSet.Builder<>();
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
@ -808,7 +811,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_tooManyNameservers() throws Exception { void testFailure_tooManyNameservers() throws Exception {
setEppInput("domain_update_add_nameserver.xml"); setEppInput("domain_update_add_nameserver.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -819,7 +822,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_wrongExtension() throws Exception { void testFailure_wrongExtension() throws Exception {
setEppInput("domain_update_wrong_extension.xml"); setEppInput("domain_update_wrong_extension.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -828,7 +831,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_neverExisted() throws Exception { void testFailure_neverExisted() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
ResourceDoesNotExistException thrown = ResourceDoesNotExistException thrown =
@ -836,7 +839,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
} }
@Test @TestOfyAndSql
void testFailure_existedButWasDeleted() throws Exception { void testFailure_existedButWasDeleted() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDeletedDomain(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1)); persistDeletedDomain(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1));
@ -845,7 +848,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand())); assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
} }
@Test @TestOfyAndSql
void testFailure_missingHost() throws Exception { void testFailure_missingHost() throws Exception {
persistActiveHost("ns1.example.foo"); persistActiveHost("ns1.example.foo");
persistActiveContact("sh8013"); persistActiveContact("sh8013");
@ -856,7 +859,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("(ns2.example.foo)"); assertThat(thrown).hasMessageThat().contains("(ns2.example.foo)");
} }
@Test @TestOfyAndSql
void testFailure_missingContact() throws Exception { void testFailure_missingContact() throws Exception {
persistActiveHost("ns1.example.foo"); persistActiveHost("ns1.example.foo");
persistActiveHost("ns2.example.foo"); persistActiveHost("ns2.example.foo");
@ -867,7 +870,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("(sh8013)"); assertThat(thrown).hasMessageThat().contains("(sh8013)");
} }
@Test @TestOfyAndSql
void testFailure_addingDuplicateContact() throws Exception { void testFailure_addingDuplicateContact() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistActiveContact("foo"); persistActiveContact("foo");
@ -892,7 +895,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
+ "role [tech] has contacts [foo, mak21]"); + "role [tech] has contacts [foo, mak21]");
} }
@Test @TestOfyAndSql
void testFailure_statusValueNotClientSettable() throws Exception { void testFailure_statusValueNotClientSettable() throws Exception {
setEppInput("domain_update_prohibited_status.xml"); setEppInput("domain_update_prohibited_status.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -901,7 +904,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_superuserStatusValueNotClientSettable() throws Exception { void testSuccess_superuserStatusValueNotClientSettable() throws Exception {
setEppInput("domain_update_prohibited_status.xml"); setEppInput("domain_update_prohibited_status.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -910,7 +913,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml")); CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testFailure_serverUpdateProhibited_prohibitsNonSuperuserUpdates() throws Exception { void testFailure_serverUpdateProhibited_prohibitsNonSuperuserUpdates() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistResource( persistResource(
@ -922,7 +925,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(e).hasMessageThat().contains("serverUpdateProhibited"); assertThat(e).hasMessageThat().contains("serverUpdateProhibited");
} }
@Test @TestOfyAndSql
void testSuccess_serverUpdateProhibited_allowsSuperuserUpdates() throws Exception { void testSuccess_serverUpdateProhibited_allowsSuperuserUpdates() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistResource(persistDomain().asBuilder().addStatusValue(SERVER_UPDATE_PROHIBITED).build()); persistResource(persistDomain().asBuilder().addStatusValue(SERVER_UPDATE_PROHIBITED).build());
@ -931,7 +934,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml")); CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testFailure_serverUpdateProhibited_notSettableWithoutSuperuser() throws Exception { void testFailure_serverUpdateProhibited_notSettableWithoutSuperuser() throws Exception {
setEppInput("domain_update_add_registry_lock.xml"); setEppInput("domain_update_add_registry_lock.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -940,7 +943,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(e).hasMessageThat().contains("serverUpdateProhibited"); assertThat(e).hasMessageThat().contains("serverUpdateProhibited");
} }
@Test @TestOfyAndSql
void testSuccess_serverUpdateProhibited_isSettableWithSuperuser() throws Exception { void testSuccess_serverUpdateProhibited_isSettableWithSuperuser() throws Exception {
setEppInput("domain_update_add_registry_lock.xml"); setEppInput("domain_update_add_registry_lock.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -949,7 +952,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml")); CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testFailure_clientUpdateProhibited() throws Exception { void testFailure_clientUpdateProhibited() throws Exception {
createTld("com"); createTld("com");
setEppInput("domain_update_authinfo.xml"); setEppInput("domain_update_authinfo.xml");
@ -964,7 +967,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_serverUpdateProhibited() throws Exception { void testFailure_serverUpdateProhibited() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistResource( persistResource(
@ -977,7 +980,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("serverUpdateProhibited"); assertThat(thrown).hasMessageThat().contains("serverUpdateProhibited");
} }
@Test @TestOfyAndSql
void testFailure_pendingDelete() throws Exception { void testFailure_pendingDelete() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistResource( persistResource(
@ -991,7 +994,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("pendingDelete"); assertThat(thrown).hasMessageThat().contains("pendingDelete");
} }
@Test @TestOfyAndSql
void testFailure_duplicateContactInCommand() throws Exception { void testFailure_duplicateContactInCommand() throws Exception {
setEppInput("domain_update_duplicate_contact.xml"); setEppInput("domain_update_duplicate_contact.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -1000,7 +1003,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_multipleDuplicateContactInCommand() throws Exception { void testFailure_multipleDuplicateContactInCommand() throws Exception {
setEppInput("domain_update_multiple_duplicate_contacts.xml"); setEppInput("domain_update_multiple_duplicate_contacts.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -1015,7 +1018,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_missingContactType() throws Exception { void testFailure_missingContactType() throws Exception {
// We need to test for missing type, but not for invalid - the schema enforces that for us. // We need to test for missing type, but not for invalid - the schema enforces that for us.
setEppInput("domain_update_missing_contact_type.xml"); setEppInput("domain_update_missing_contact_type.xml");
@ -1025,7 +1028,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_unauthorizedClient() throws Exception { void testFailure_unauthorizedClient() throws Exception {
sessionMetadata.setClientId("NewRegistrar"); sessionMetadata.setClientId("NewRegistrar");
persistReferencedEntities(); persistReferencedEntities();
@ -1034,7 +1037,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_superuserUnauthorizedClient() throws Exception { void testSuccess_superuserUnauthorizedClient() throws Exception {
sessionMetadata.setClientId("NewRegistrar"); sessionMetadata.setClientId("NewRegistrar");
persistReferencedEntities(); persistReferencedEntities();
@ -1044,7 +1047,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml")); CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testFailure_notAuthorizedForTld() throws Exception { void testFailure_notAuthorizedForTld() throws Exception {
persistResource( persistResource(
loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build()); loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build());
@ -1054,7 +1057,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_superuserNotAuthorizedForTld() throws Exception { void testSuccess_superuserNotAuthorizedForTld() throws Exception {
persistResource( persistResource(
loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build()); loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build());
@ -1065,7 +1068,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml")); CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
} }
@Test @TestOfyAndSql
void testFailure_sameNameserverAddedAndRemoved() throws Exception { void testFailure_sameNameserverAddedAndRemoved() throws Exception {
setEppInput("domain_update_add_remove_same_host.xml"); setEppInput("domain_update_add_remove_same_host.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -1082,7 +1085,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_sameContactAddedAndRemoved() throws Exception { void testFailure_sameContactAddedAndRemoved() throws Exception {
setEppInput("domain_update_add_remove_same_contact.xml"); setEppInput("domain_update_add_remove_same_contact.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -1100,7 +1103,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_removeAdmin() throws Exception { void testFailure_removeAdmin() throws Exception {
setEppInput("domain_update_remove_admin.xml"); setEppInput("domain_update_remove_admin.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -1116,7 +1119,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_removeTech() throws Exception { void testFailure_removeTech() throws Exception {
setEppInput("domain_update_remove_tech.xml"); setEppInput("domain_update_remove_tech.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -1132,7 +1135,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_addPendingDeleteContact() throws Exception { void testFailure_addPendingDeleteContact() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
@ -1151,7 +1154,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("mak21"); assertThat(thrown).hasMessageThat().contains("mak21");
} }
@Test @TestOfyAndSql
void testFailure_addPendingDeleteHost() throws Exception { void testFailure_addPendingDeleteHost() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
@ -1170,7 +1173,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("ns2.example.foo"); assertThat(thrown).hasMessageThat().contains("ns2.example.foo");
} }
@Test @TestOfyAndSql
void testFailure_newRegistrantNotAllowListed() throws Exception { void testFailure_newRegistrantNotAllowListed() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
@ -1184,7 +1187,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testFailure_addedNameserverDisallowedInTld() throws Exception { void testFailure_addedNameserverDisallowedInTld() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
@ -1199,7 +1202,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_newNameserverAllowListed() throws Exception { void testSuccess_newNameserverAllowListed() throws Exception {
setEppInput("domain_update_add_nameserver.xml"); setEppInput("domain_update_add_nameserver.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -1225,7 +1228,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.createVKey()); .createVKey());
} }
@Test @TestOfyAndSql
void testSuccess_changeRegistrantAllowListed() throws Exception { void testSuccess_changeRegistrantAllowListed() throws Exception {
setEppInput("domain_update_registrant.xml"); setEppInput("domain_update_registrant.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -1238,11 +1241,11 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.example.foo")) .setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.example.foo"))
.build()); .build());
runFlow(); runFlow();
assertThat(tm().loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId()) assertThat(loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
.isEqualTo("sh8013"); .isEqualTo("sh8013");
} }
@Test @TestOfyAndSql
void testSuccess_changeContactsAndRegistrant() throws Exception { void testSuccess_changeContactsAndRegistrant() throws Exception {
setEppInput("domain_update_contacts_and_registrant.xml"); setEppInput("domain_update_contacts_and_registrant.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -1251,10 +1254,9 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
reloadResourceByForeignKey() reloadResourceByForeignKey()
.getContacts() .getContacts()
.forEach( .forEach(
contact -> { contact ->
assertThat(tm().loadByKey(contact.getContactKey()).getContactId()).isEqualTo("mak21"); assertThat(loadByKey(contact.getContactKey()).getContactId()).isEqualTo("mak21"));
}); assertThat(loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
assertThat(tm().loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
.isEqualTo("mak21"); .isEqualTo("mak21");
runFlow(); runFlow();
@ -1262,15 +1264,13 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
reloadResourceByForeignKey() reloadResourceByForeignKey()
.getContacts() .getContacts()
.forEach( .forEach(
contact -> { contact ->
assertThat(tm().loadByKey(contact.getContactKey()).getContactId()) assertThat(loadByKey(contact.getContactKey()).getContactId()).isEqualTo("sh8013"));
.isEqualTo("sh8013"); assertThat(loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
});
assertThat(tm().loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
.isEqualTo("sh8013"); .isEqualTo("sh8013");
} }
@Test @TestOfyAndSql
void testSuccess_nameserverAndRegistrantAllowListed() throws Exception { void testSuccess_nameserverAndRegistrantAllowListed() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
@ -1283,7 +1283,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doSuccessfulTest(); doSuccessfulTest();
} }
@Test @TestOfyAndSql
void testSuccess_tldWithNameserverAllowList_removeNameserver() throws Exception { void testSuccess_tldWithNameserverAllowList_removeNameserver() throws Exception {
setEppInput("domain_update_remove_nameserver.xml"); setEppInput("domain_update_remove_nameserver.xml");
persistReferencedEntities(); persistReferencedEntities();
@ -1315,7 +1315,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc()).get())); loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc()).get()));
} }
@Test @TestOfyAndSql
void testFailure_tldWithNameserverAllowList_removeLastNameserver() throws Exception { void testFailure_tldWithNameserverAllowList_removeLastNameserver() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
@ -1331,7 +1331,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testSuccess_domainCreateNotRestricted_doNotApplyServerProhibitedStatusCodes() void testSuccess_domainCreateNotRestricted_doNotApplyServerProhibitedStatusCodes()
throws Exception { throws Exception {
persistReferencedEntities(); persistReferencedEntities();
@ -1342,7 +1342,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.hasExactlyStatusValues(StatusValue.CLIENT_HOLD); .hasExactlyStatusValues(StatusValue.CLIENT_HOLD);
} }
@Test @TestOfyAndSql
void testFailure_freePremium_wrongFee() throws Exception { void testFailure_freePremium_wrongFee() throws Exception {
setEppInput("domain_update_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11")); setEppInput("domain_update_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
persistReferencedEntities(); persistReferencedEntities();
@ -1353,7 +1353,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
// This test should throw an exception, because the fee extension is required when the fee is not // This test should throw an exception, because the fee extension is required when the fee is not
// zero. // zero.
@Test @TestOfyAndSql
void testFailure_missingFeeOnNonFreeUpdate() throws Exception { void testFailure_missingFeeOnNonFreeUpdate() throws Exception {
setEppInput("domain_update_wildcard.xml", ImmutableMap.of("DOMAIN", "non-free-update.tld")); setEppInput("domain_update_wildcard.xml", ImmutableMap.of("DOMAIN", "non-free-update.tld"));
persistReferencedEntities(); persistReferencedEntities();
@ -1363,7 +1363,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml(); assertAboutEppExceptions().that(thrown).marshalsToXml();
} }
@Test @TestOfyAndSql
void testIcannActivityReportField_getsLogged() throws Exception { void testIcannActivityReportField_getsLogged() throws Exception {
persistReferencedEntities(); persistReferencedEntities();
persistDomain(); persistDomain();
@ -1372,7 +1372,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertTldsFieldLogged("tld"); assertTldsFieldLogged("tld");
} }
@Test @TestOfyAndSql
void testSuperuserExtension_turnsOffAutorenew() throws Exception { void testSuperuserExtension_turnsOffAutorenew() throws Exception {
eppRequestSource = EppRequestSource.TOOL; eppRequestSource = EppRequestSource.TOOL;
setEppInput("domain_update_superuser_extension.xml", ImmutableMap.of("AUTORENEWS", "false")); setEppInput("domain_update_superuser_extension.xml", ImmutableMap.of("AUTORENEWS", "false"));
@ -1385,7 +1385,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutDomains().that(reloadResourceByForeignKey()).hasAutorenewEndTime(expirationTime); assertAboutDomains().that(reloadResourceByForeignKey()).hasAutorenewEndTime(expirationTime);
} }
@Test @TestOfyAndSql
void testSuperuserExtension_turnsOnAutorenew() throws Exception { void testSuperuserExtension_turnsOnAutorenew() throws Exception {
eppRequestSource = EppRequestSource.TOOL; eppRequestSource = EppRequestSource.TOOL;
setEppInput("domain_update_superuser_extension.xml", ImmutableMap.of("AUTORENEWS", "true")); setEppInput("domain_update_superuser_extension.xml", ImmutableMap.of("AUTORENEWS", "true"));

View file

@ -36,6 +36,7 @@ import google.registry.model.EntityTestCase;
import google.registry.model.billing.BillingEvent.Flag; import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod; import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
@ -59,8 +60,8 @@ public class BillingEventTest extends EntityTestCase {
super(JpaEntityCoverageCheck.ENABLED); super(JpaEntityCoverageCheck.ENABLED);
} }
private HistoryEntry historyEntry; private DomainHistory domainHistory;
private HistoryEntry historyEntry2; private DomainHistory domainHistory2;
private DomainBase domain; private DomainBase domain;
private BillingEvent.OneTime oneTime; private BillingEvent.OneTime oneTime;
private BillingEvent.OneTime oneTimeSynthetic; private BillingEvent.OneTime oneTimeSynthetic;
@ -73,26 +74,24 @@ public class BillingEventTest extends EntityTestCase {
void setUp() { void setUp() {
createTld("tld"); createTld("tld");
domain = persistActiveDomain("foo.tld"); domain = persistActiveDomain("foo.tld");
historyEntry = domainHistory =
persistResource( persistResource(
new HistoryEntry.Builder() new DomainHistory.Builder()
.setParent(domain) .setDomainContent(domain)
.setModificationTime(now) .setModificationTime(now)
.setRequestedByRegistrar(false) .setRequestedByRegistrar(false)
.setType(HistoryEntry.Type.DOMAIN_CREATE) .setType(HistoryEntry.Type.DOMAIN_CREATE)
.setXmlBytes(new byte[0]) .setXmlBytes(new byte[0])
.build() .build());
.toChildHistoryEntity()); domainHistory2 =
historyEntry2 =
persistResource( persistResource(
new HistoryEntry.Builder() new DomainHistory.Builder()
.setParent(domain) .setDomainContent(domain)
.setModificationTime(now.plusDays(1)) .setModificationTime(now.plusDays(1))
.setRequestedByRegistrar(false) .setRequestedByRegistrar(false)
.setType(HistoryEntry.Type.DOMAIN_CREATE) .setType(HistoryEntry.Type.DOMAIN_CREATE)
.setXmlBytes(new byte[0]) .setXmlBytes(new byte[0])
.build() .build());
.toChildHistoryEntity());
AllocationToken allocationToken = AllocationToken allocationToken =
persistResource( persistResource(
@ -112,7 +111,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource( persistResource(
commonInit( commonInit(
new BillingEvent.OneTime.Builder() new BillingEvent.OneTime.Builder()
.setParent(historyEntry) .setParent(domainHistory)
.setReason(Reason.CREATE) .setReason(Reason.CREATE)
.setFlags(ImmutableSet.of(BillingEvent.Flag.ANCHOR_TENANT)) .setFlags(ImmutableSet.of(BillingEvent.Flag.ANCHOR_TENANT))
.setPeriodYears(2) .setPeriodYears(2)
@ -125,7 +124,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource( persistResource(
commonInit( commonInit(
new BillingEvent.Recurring.Builder() new BillingEvent.Recurring.Builder()
.setParent(historyEntry) .setParent(domainHistory)
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) .setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
.setReason(Reason.RENEW) .setReason(Reason.RENEW)
.setEventTime(now.plusYears(1)) .setEventTime(now.plusYears(1))
@ -134,7 +133,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource( persistResource(
commonInit( commonInit(
new BillingEvent.OneTime.Builder() new BillingEvent.OneTime.Builder()
.setParent(historyEntry) .setParent(domainHistory)
.setReason(Reason.CREATE) .setReason(Reason.CREATE)
.setFlags( .setFlags(
ImmutableSet.of( ImmutableSet.of(
@ -150,7 +149,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource( persistResource(
commonInit( commonInit(
new BillingEvent.Cancellation.Builder() new BillingEvent.Cancellation.Builder()
.setParent(historyEntry2) .setParent(domainHistory2)
.setReason(Reason.CREATE) .setReason(Reason.CREATE)
.setEventTime(now.plusDays(1)) .setEventTime(now.plusDays(1))
.setBillingTime(now.plusDays(5)) .setBillingTime(now.plusDays(5))
@ -160,7 +159,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource( persistResource(
commonInit( commonInit(
new BillingEvent.Cancellation.Builder() new BillingEvent.Cancellation.Builder()
.setParent(historyEntry2) .setParent(domainHistory2)
.setReason(Reason.RENEW) .setReason(Reason.RENEW)
.setEventTime(now.plusDays(1)) .setEventTime(now.plusDays(1))
.setBillingTime(now.plusYears(1).plusDays(45)) .setBillingTime(now.plusYears(1).plusDays(45))
@ -171,7 +170,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource( persistResource(
commonInit( commonInit(
new BillingEvent.Modification.Builder() new BillingEvent.Modification.Builder()
.setParent(historyEntry2) .setParent(domainHistory2)
.setReason(Reason.CREATE) .setReason(Reason.CREATE)
.setCost(Money.of(USD, 1)) .setCost(Money.of(USD, 1))
.setDescription("Something happened") .setDescription("Something happened")
@ -206,13 +205,13 @@ public class BillingEventTest extends EntityTestCase {
.containsExactly(cancellationOneTime, cancellationRecurring); .containsExactly(cancellationOneTime, cancellationRecurring);
assertThat(ofy().load().type(BillingEvent.Modification.class).ancestor(domain).list()) assertThat(ofy().load().type(BillingEvent.Modification.class).ancestor(domain).list())
.containsExactly(modification); .containsExactly(modification);
assertThat(ofy().load().type(BillingEvent.OneTime.class).ancestor(historyEntry).list()) assertThat(ofy().load().type(BillingEvent.OneTime.class).ancestor(domainHistory).list())
.containsExactly(oneTime, oneTimeSynthetic); .containsExactly(oneTime, oneTimeSynthetic);
assertThat(ofy().load().type(BillingEvent.Recurring.class).ancestor(historyEntry).list()) assertThat(ofy().load().type(BillingEvent.Recurring.class).ancestor(domainHistory).list())
.containsExactly(recurring); .containsExactly(recurring);
assertThat(ofy().load().type(BillingEvent.Cancellation.class).ancestor(historyEntry2).list()) assertThat(ofy().load().type(BillingEvent.Cancellation.class).ancestor(domainHistory2).list())
.containsExactly(cancellationOneTime, cancellationRecurring); .containsExactly(cancellationOneTime, cancellationRecurring);
assertThat(ofy().load().type(BillingEvent.Modification.class).ancestor(historyEntry2).list()) assertThat(ofy().load().type(BillingEvent.Modification.class).ancestor(domainHistory2).list())
.containsExactly(modification); .containsExactly(modification);
} }
@ -311,7 +310,8 @@ public class BillingEventTest extends EntityTestCase {
BillingEvent.Cancellation newCancellation = BillingEvent.Cancellation newCancellation =
BillingEvent.Cancellation.forGracePeriod( BillingEvent.Cancellation.forGracePeriod(
GracePeriod.forBillingEvent(GracePeriodStatus.ADD, domain.getRepoId(), oneTime), GracePeriod.forBillingEvent(GracePeriodStatus.ADD, domain.getRepoId(), oneTime),
historyEntry2, domainHistory2.getModificationTime(),
Key.create(domainHistory2),
"foo.tld"); "foo.tld");
// Set ID to be the same to ignore for the purposes of comparison. // Set ID to be the same to ignore for the purposes of comparison.
assertThat(newCancellation.asBuilder().setId(cancellationOneTime.getId()).build()) assertThat(newCancellation.asBuilder().setId(cancellationOneTime.getId()).build())
@ -328,7 +328,8 @@ public class BillingEventTest extends EntityTestCase {
now.plusYears(1).plusDays(45), now.plusYears(1).plusDays(45),
"TheRegistrar", "TheRegistrar",
recurring.createVKey()), recurring.createVKey()),
historyEntry2, domainHistory2.getModificationTime(),
Key.create(domainHistory2),
"foo.tld"); "foo.tld");
// Set ID to be the same to ignore for the purposes of comparison. // Set ID to be the same to ignore for the purposes of comparison.
assertThat(newCancellation.asBuilder().setId(cancellationRecurring.getId()).build()) assertThat(newCancellation.asBuilder().setId(cancellationRecurring.getId()).build())
@ -347,7 +348,8 @@ public class BillingEventTest extends EntityTestCase {
domain.getRepoId(), domain.getRepoId(),
now.plusDays(1), now.plusDays(1),
"a registrar"), "a registrar"),
historyEntry, domainHistory.getModificationTime(),
Key.create(domainHistory),
"foo.tld")); "foo.tld"));
assertThat(thrown).hasMessageThat().contains("grace period without billing event"); assertThat(thrown).hasMessageThat().contains("grace period without billing event");
} }
@ -382,7 +384,7 @@ public class BillingEventTest extends EntityTestCase {
@TestOfyAndSql @TestOfyAndSql
void testDeadCodeThatDeletedScrapCommandsReference() { void testDeadCodeThatDeletedScrapCommandsReference() {
assertThat(recurring.getParentKey()).isEqualTo(Key.create(historyEntry)); assertThat(recurring.getParentKey()).isEqualTo(Key.create(domainHistory));
new BillingEvent.OneTime.Builder().setParent(Key.create(historyEntry)); new BillingEvent.OneTime.Builder().setParent(Key.create(domainHistory));
} }
} }

View file

@ -50,7 +50,6 @@ import static google.registry.util.PreconditionsUtils.checkArgumentPresent;
import static google.registry.util.ResourceUtils.readResourceUtf8; import static google.registry.util.ResourceUtils.readResourceUtf8;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static org.joda.money.CurrencyUnit.USD; import static org.joda.money.CurrencyUnit.USD;
import static org.junit.jupiter.api.Assertions.fail;
import com.google.common.base.Ascii; import com.google.common.base.Ascii;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
@ -73,8 +72,6 @@ import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag; import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.contact.ContactAuthInfo; import google.registry.model.contact.ContactAuthInfo;
import google.registry.model.contact.ContactBase;
import google.registry.model.contact.ContactHistory;
import google.registry.model.contact.ContactResource; import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DesignatedContact; import google.registry.model.domain.DesignatedContact;
import google.registry.model.domain.DesignatedContact.Type; import google.registry.model.domain.DesignatedContact.Type;
@ -88,8 +85,6 @@ import google.registry.model.domain.token.AllocationToken;
import google.registry.model.eppcommon.AuthInfo.PasswordAuth; import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid; import google.registry.model.eppcommon.Trid;
import google.registry.model.host.HostBase;
import google.registry.model.host.HostHistory;
import google.registry.model.host.HostResource; import google.registry.model.host.HostResource;
import google.registry.model.index.EppResourceIndex; import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.EppResourceIndexBucket; import google.registry.model.index.EppResourceIndexBucket;
@ -117,7 +112,6 @@ import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import google.registry.tmch.LordnTaskUtils; import google.registry.tmch.LordnTaskUtils;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
@ -1127,29 +1121,7 @@ public class DatabaseHelper {
/** Returns all of the history entries that are parented off the given EppResource. */ /** Returns all of the history entries that are parented off the given EppResource. */
public static List<? extends HistoryEntry> getHistoryEntries(EppResource resource) { public static List<? extends HistoryEntry> getHistoryEntries(EppResource resource) {
return tm().isOfy() return HistoryEntryDao.loadHistoryObjectsForResource(resource.createVKey());
? ofy().load().type(HistoryEntry.class).ancestor(resource).order("modificationTime").list()
: tm().transact(
() -> {
ImmutableList<? extends HistoryEntry> unsorted = null;
if (resource instanceof ContactBase) {
unsorted = tm().loadAllOf(ContactHistory.class);
} else if (resource instanceof HostBase) {
unsorted = tm().loadAllOf(HostHistory.class);
} else if (resource instanceof DomainContent) {
unsorted = tm().loadAllOf(DomainHistory.class);
} else {
fail("Expected an EppResource instance, but got " + resource.getClass());
}
ImmutableList<? extends HistoryEntry> filtered =
unsorted.stream()
.filter(
historyEntry ->
historyEntry.getParent().getName().equals(resource.getRepoId()))
.collect(toImmutableList());
return ImmutableList.sortedCopyOf(
Comparator.comparing(HistoryEntry::getModificationTime), filtered);
});
} }
/** /**

View file

@ -108,7 +108,7 @@ class EppLifecycleToolsTest extends EppTestCase {
.atTime("2001-06-08T00:00:00Z") .atTime("2001-06-08T00:00:00Z")
.hasResponse("poll_response_unrenew.xml"); .hasResponse("poll_response_unrenew.xml");
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-9-TLD-20-21-2001")) assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-8-TLD-21-22-2001"))
.atTime("2001-06-08T00:00:01Z") .atTime("2001-06-08T00:00:01Z")
.hasResponse("poll_ack_response_empty.xml"); .hasResponse("poll_ack_response_empty.xml");
@ -129,7 +129,7 @@ class EppLifecycleToolsTest extends EppTestCase {
.hasResponse( .hasResponse(
"poll_response_autorenew.xml", "poll_response_autorenew.xml",
ImmutableMap.of( ImmutableMap.of(
"ID", "1-9-TLD-20-23-2003", "ID", "1-8-TLD-21-24-2003",
"QDATE", "2003-06-01T00:02:00Z", "QDATE", "2003-06-01T00:02:00Z",
"DOMAIN", "example.tld", "DOMAIN", "example.tld",
"EXDATE", "2004-06-01T00:02:00Z")); "EXDATE", "2004-06-01T00:02:00Z"));

View file

@ -3,7 +3,7 @@
<result code="1301"> <result code="1301">
<msg>Command completed successfully; ack to dequeue</msg> <msg>Command completed successfully; ack to dequeue</msg>
</result> </result>
<msgQ count="1" id="1-9-TLD-20-21-2001"> <msgQ count="1" id="1-8-TLD-21-22-2001">
<qDate>2001-06-07T00:00:00Z</qDate> <qDate>2001-06-07T00:00:00Z</qDate>
<msg>Domain example.tld was unrenewed by 3 years; now expires at 2003-06-01T00:02:00.000Z.</msg> <msg>Domain example.tld was unrenewed by 3 years; now expires at 2003-06-01T00:02:00.000Z.</msg>
</msgQ> </msgQ>

View file

@ -6,7 +6,7 @@ class google.registry.model.UpdateAutoTimestamp {
} }
class google.registry.model.billing.BillingEvent$Cancellation { class google.registry.model.billing.BillingEvent$Cancellation {
@Id java.lang.Long id; @Id java.lang.Long id;
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent; @Parent com.googlecode.objectify.Key<? extends google.registry.model.reporting.HistoryEntry> parent;
google.registry.model.billing.BillingEvent$Reason reason; google.registry.model.billing.BillingEvent$Reason reason;
google.registry.persistence.BillingVKey$BillingEventVKey refOneTime; google.registry.persistence.BillingVKey$BillingEventVKey refOneTime;
google.registry.persistence.BillingVKey$BillingRecurrenceVKey refRecurring; google.registry.persistence.BillingVKey$BillingRecurrenceVKey refRecurring;
@ -27,7 +27,7 @@ enum google.registry.model.billing.BillingEvent$Flag {
} }
class google.registry.model.billing.BillingEvent$Modification { class google.registry.model.billing.BillingEvent$Modification {
@Id java.lang.Long id; @Id java.lang.Long id;
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent; @Parent com.googlecode.objectify.Key<? extends google.registry.model.reporting.HistoryEntry> parent;
com.googlecode.objectify.Key<google.registry.model.billing.BillingEvent$OneTime> eventRef; com.googlecode.objectify.Key<google.registry.model.billing.BillingEvent$OneTime> eventRef;
google.registry.model.billing.BillingEvent$Reason reason; google.registry.model.billing.BillingEvent$Reason reason;
java.lang.String clientId; java.lang.String clientId;
@ -39,7 +39,7 @@ class google.registry.model.billing.BillingEvent$Modification {
} }
class google.registry.model.billing.BillingEvent$OneTime { class google.registry.model.billing.BillingEvent$OneTime {
@Id java.lang.Long id; @Id java.lang.Long id;
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent; @Parent com.googlecode.objectify.Key<? extends google.registry.model.reporting.HistoryEntry> parent;
google.registry.model.billing.BillingEvent$Reason reason; google.registry.model.billing.BillingEvent$Reason reason;
google.registry.persistence.VKey<google.registry.model.billing.BillingEvent$Recurring> cancellationMatchingBillingEvent; google.registry.persistence.VKey<google.registry.model.billing.BillingEvent$Recurring> cancellationMatchingBillingEvent;
google.registry.persistence.VKey<google.registry.model.domain.token.AllocationToken> allocationToken; google.registry.persistence.VKey<google.registry.model.domain.token.AllocationToken> allocationToken;
@ -63,7 +63,7 @@ enum google.registry.model.billing.BillingEvent$Reason {
} }
class google.registry.model.billing.BillingEvent$Recurring { class google.registry.model.billing.BillingEvent$Recurring {
@Id java.lang.Long id; @Id java.lang.Long id;
@Parent com.googlecode.objectify.Key<google.registry.model.reporting.HistoryEntry> parent; @Parent com.googlecode.objectify.Key<? extends google.registry.model.reporting.HistoryEntry> parent;
google.registry.model.billing.BillingEvent$Reason reason; google.registry.model.billing.BillingEvent$Reason reason;
google.registry.model.common.TimeOfYear recurrenceTimeOfYear; google.registry.model.common.TimeOfYear recurrenceTimeOfYear;
java.lang.String clientId; java.lang.String clientId;