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
static DomainHistory.Builder provideDomainHistoryBuilder(
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.flogger.FluentLogger;
import com.googlecode.objectify.Key;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.ParameterValueRangeErrorException;
import google.registry.flows.EppException.SyntaxErrorException;
import google.registry.flows.EppException.UnimplementedProtocolVersionException;
import google.registry.flows.custom.EntityChanges;
import google.registry.model.EppResource;
import google.registry.model.eppcommon.EppXmlTransformer;
import google.registry.model.eppinput.EppInput.WrongProtocolVersionException;
import google.registry.model.eppoutput.EppOutput;
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.xml.XmlException;
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. */
public static class NotLoggedInException extends CommandUseErrorException {
public NotLoggedInException() {

View file

@ -97,7 +97,6 @@ import google.registry.model.eppinput.EppInput;
import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppoutput.CreateData.DomainCreateData;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.host.HostResource;
import google.registry.model.index.EppResourceIndex;
import google.registry.model.index.ForeignKeyIndex;
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.TldState;
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.TransactionReportField;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.persistence.VKey;
import google.registry.tmch.LordnTaskUtils;
import java.util.Optional;
import javax.inject.Inject;
@ -302,10 +301,14 @@ public class DomainCreateFlow implements TransactionalFlow {
validateFeeChallenge(targetId, now, feeCreate, feesAndCredits);
Optional<SecDnsCreateExtension> secDnsCreate =
validateSecDnsExtension(eppInput.getSingleExtension(SecDnsCreateExtension.class));
String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
DateTime registrationExpirationTime = leapSafeAddYears(now, years);
DomainHistory domainHistory =
buildHistoryEntry(repoId, registry, now, period, registry.getAddGracePeriodLength());
String repoId = createDomainRepoId(ObjectifyService.allocateId(), registry.getTldStr());
Key<DomainHistory> domainHistoryKey =
Key.create(
Key.create(DomainBase.class, repoId),
DomainHistory.class,
ObjectifyService.allocateId());
historyBuilder.setId(domainHistoryKey.getId());
// Bill for the create.
BillingEvent.OneTime createBillingEvent =
createOneTimeBillingEvent(
@ -315,14 +318,14 @@ public class DomainCreateFlow implements TransactionalFlow {
isReserved(domainName, isSunriseCreate),
years,
feesAndCredits,
domainHistory,
domainHistoryKey,
allocationToken,
now);
// Create a new autorenew billing event and poll message starting at the expiration time.
BillingEvent.Recurring autorenewBillingEvent =
createAutorenewBillingEvent(domainHistory, registrationExpirationTime);
createAutorenewBillingEvent(domainHistoryKey, registrationExpirationTime);
PollMessage.Autorenew autorenewPollMessage =
createAutorenewPollMessage(domainHistory, registrationExpirationTime);
createAutorenewPollMessage(domainHistoryKey, registrationExpirationTime);
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
entitiesToSave.add(createBillingEvent, autorenewBillingEvent, autorenewPollMessage);
// Bill for EAP cost, if any.
@ -330,14 +333,12 @@ public class DomainCreateFlow implements TransactionalFlow {
entitiesToSave.add(createEapBillingEvent(feesAndCredits, createBillingEvent));
}
ImmutableSet.Builder<StatusValue> statuses = new ImmutableSet.Builder<>();
if (getReservationTypes(domainName).contains(NAME_COLLISION)) {
statuses.add(SERVER_HOLD);
entitiesToSave.add(
createNameCollisionOneTimePollMessage(targetId, domainHistory, clientId, now));
}
DomainBase newDomain =
ImmutableSet<ReservationType> reservationTypes = getReservationTypes(domainName);
ImmutableSet<StatusValue> statuses =
reservationTypes.contains(NAME_COLLISION)
? ImmutableSet.of(SERVER_HOLD)
: ImmutableSet.of();
DomainBase domain =
new DomainBase.Builder()
.setCreationClientId(clientId)
.setPersistedCurrentSponsorClientId(clientId)
@ -348,34 +349,38 @@ public class DomainCreateFlow implements TransactionalFlow {
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
.setLaunchNotice(hasClaimsNotice ? launchCreate.get().getNotice() : null)
.setSmdId(signedMarkId)
.setDsData(secDnsCreate.isPresent() ? secDnsCreate.get().getDsData() : null)
.setDsData(secDnsCreate.map(SecDnsCreateExtension::getDsData).orElse(null))
.setRegistrant(command.getRegistrant())
.setAuthInfo(command.getAuthInfo())
.setDomainName(targetId)
.setNameservers(
(ImmutableSet<VKey<HostResource>>)
command.getNameservers().stream().collect(toImmutableSet()))
.setStatusValues(statuses.build())
.setNameservers(command.getNameservers().stream().collect(toImmutableSet()))
.setStatusValues(statuses)
.setContacts(command.getContacts())
.addGracePeriod(
GracePeriod.forBillingEvent(GracePeriodStatus.ADD, repoId, createBillingEvent))
.build();
DomainHistory domainHistory =
buildDomainHistory(domain, registry, now, period, registry.getAddGracePeriodLength());
if (reservationTypes.contains(NAME_COLLISION)) {
entitiesToSave.add(
createNameCollisionOneTimePollMessage(targetId, domainHistory, clientId, now));
}
entitiesToSave.add(
newDomain,
domainHistory.asBuilder().setDomainContent(newDomain).build(),
ForeignKeyIndex.create(newDomain, newDomain.getDeletionTime()),
EppResourceIndex.create(Key.create(newDomain)));
domain,
domainHistory,
ForeignKeyIndex.create(domain, domain.getDeletionTime()),
EppResourceIndex.create(Key.create(domain)));
if (allocationToken.isPresent()
&& TokenType.SINGLE_USE.equals(allocationToken.get().getTokenType())) {
entitiesToSave.add(
allocationTokenFlowUtils.redeemToken(allocationToken.get(), domainHistory.createVKey()));
}
enqueueTasks(newDomain, hasSignedMarks, hasClaimsNotice);
enqueueTasks(domain, hasSignedMarks, hasClaimsNotice);
EntityChanges entityChanges =
flowCustomLogic.beforeSave(
DomainCreateFlowCustomLogic.BeforeSaveParameters.newBuilder()
.setNewDomain(newDomain)
.setNewDomain(domain)
.setHistoryEntry(domainHistory)
.setEntityChanges(
EntityChanges.newBuilder().setSaves(entitiesToSave.build()).build())
@ -480,8 +485,8 @@ public class DomainCreateFlow implements TransactionalFlow {
: null);
}
private DomainHistory buildHistoryEntry(
String repoId, Registry registry, DateTime now, Period period, Duration addGracePeriod) {
private DomainHistory buildDomainHistory(
DomainBase domain, Registry registry, DateTime now, Period period, Duration addGracePeriod) {
// We ignore prober transactions
if (registry.getTldType() == TldType.REAL) {
historyBuilder
@ -497,7 +502,7 @@ public class DomainCreateFlow implements TransactionalFlow {
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setPeriod(period)
.setModificationTime(now)
.setParent(Key.create(DomainBase.class, repoId))
.setDomainContent(domain)
.build();
}
@ -508,7 +513,7 @@ public class DomainCreateFlow implements TransactionalFlow {
boolean isReserved,
int years,
FeesAndCredits feesAndCredits,
DomainHistory domainHistory,
Key<DomainHistory> domainHistoryKey,
Optional<AllocationToken> allocationToken,
DateTime now) {
ImmutableSet.Builder<Flag> flagsBuilder = new ImmutableSet.Builder<>();
@ -537,12 +542,12 @@ public class DomainCreateFlow implements TransactionalFlow {
? registry.getAnchorTenantAddGracePeriodLength()
: registry.getAddGracePeriodLength()))
.setFlags(flagsBuilder.build())
.setParent(domainHistory)
.setParent(domainHistoryKey)
.build();
}
private Recurring createAutorenewBillingEvent(
DomainHistory domainHistory, DateTime registrationExpirationTime) {
Key<DomainHistory> domainHistoryKey, DateTime registrationExpirationTime) {
return new BillingEvent.Recurring.Builder()
.setReason(Reason.RENEW)
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
@ -550,18 +555,18 @@ public class DomainCreateFlow implements TransactionalFlow {
.setClientId(clientId)
.setEventTime(registrationExpirationTime)
.setRecurrenceEndTime(END_OF_TIME)
.setParent(domainHistory)
.setParent(domainHistoryKey)
.build();
}
private Autorenew createAutorenewPollMessage(
HistoryEntry historyEntry, DateTime registrationExpirationTime) {
Key<DomainHistory> domainHistoryKey, DateTime registrationExpirationTime) {
return new PollMessage.Autorenew.Builder()
.setTargetId(targetId)
.setClientId(clientId)
.setEventTime(registrationExpirationTime)
.setMsg("Domain was auto-renewed.")
.setParent(historyEntry)
.setParentKey(domainHistoryKey)
.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.Strings.isNullOrEmpty;
import static google.registry.flows.FlowUtils.createHistoryKey;
import static google.registry.flows.FlowUtils.persistEntityChanges;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
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.billing.BillingEvent;
import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.fee.BaseFee.FeeType;
import google.registry.model.domain.fee.Credit;
@ -125,7 +127,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
@Inject @ClientId String clientId;
@Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder;
@Inject DomainHistory.Builder historyBuilder;
@Inject DnsQueue dnsQueue;
@Inject Trid trid;
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
@ -177,8 +179,8 @@ public final class DomainDeleteFlow implements TransactionalFlow {
? Duration.ZERO
// By default, this should be 30 days of grace, and 5 days of pending delete.
: redemptionGracePeriodLength.plus(pendingDeleteLength);
HistoryEntry historyEntry =
buildHistoryEntry(existingDomain, registry, now, durationUntilDelete, inAddGracePeriod);
Key<DomainHistory> domainHistoryKey = createHistoryKey(existingDomain, DomainHistory.class);
historyBuilder.setId(domainHistoryKey.getId());
DateTime deletionTime = now.plus(durationUntilDelete);
if (durationUntilDelete.equals(Duration.ZERO)) {
builder.setDeletionTime(now).setStatusValues(null);
@ -210,7 +212,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
// it is synchronous).
if (durationUntilDelete.isLongerThan(Duration.ZERO) || isSuperuser) {
PollMessage.OneTime deletePollMessage =
createDeletePollMessage(existingDomain, historyEntry, deletionTime);
createDeletePollMessage(existingDomain, domainHistoryKey, deletionTime);
entitiesToSave.add(deletePollMessage);
builder.setDeletePollMessage(deletePollMessage.createVKey());
}
@ -220,7 +222,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
if (durationUntilDelete.isLongerThan(Duration.ZERO)
&& !clientId.equals(existingDomain.getPersistedCurrentSponsorClientId())) {
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.
@ -229,7 +231,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
// No cancellation is written if the grace period was not for a billable event.
if (gracePeriod.hasBillingEvent()) {
entitiesToSave.add(
BillingEvent.Cancellation.forGracePeriod(gracePeriod, historyEntry, targetId));
BillingEvent.Cancellation.forGracePeriod(gracePeriod, now, domainHistoryKey, targetId));
if (gracePeriod.getOneTimeBillingEvent() != null) {
// 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.
@ -245,8 +247,10 @@ public final class DomainDeleteFlow implements TransactionalFlow {
builder.setRegistrationExpirationTime(newExpirationTime);
DomainBase newDomain = builder.build();
DomainHistory domainHistory =
buildDomainHistory(newDomain, registry, now, durationUntilDelete, inAddGracePeriod);
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.
updateAutorenewRecurrenceEndTime(existingDomain, now);
// 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.
dnsQueue.addDomainRefreshTask(existingDomain.getDomainName());
entitiesToSave.add(newDomain, historyEntry);
EntityChanges entityChanges = flowCustomLogic.beforeSave(
BeforeSaveParameters.newBuilder()
.setExistingDomain(existingDomain)
.setNewDomain(newDomain)
.setHistoryEntry(historyEntry)
.setEntityChanges(EntityChanges.newBuilder().setSaves(entitiesToSave.build()).build())
.build());
entitiesToSave.add(newDomain, domainHistory);
EntityChanges entityChanges =
flowCustomLogic.beforeSave(
BeforeSaveParameters.newBuilder()
.setExistingDomain(existingDomain)
.setNewDomain(newDomain)
.setHistoryEntry(domainHistory)
.setEntityChanges(
EntityChanges.newBuilder().setSaves(entitiesToSave.build()).build())
.build());
BeforeResponseReturnData responseData =
flowCustomLogic.beforeResponse(
BeforeResponseParameters.newBuilder()
@ -292,8 +298,8 @@ public final class DomainDeleteFlow implements TransactionalFlow {
}
}
private HistoryEntry buildHistoryEntry(
DomainBase existingResource,
private DomainHistory buildDomainHistory(
DomainBase domain,
Registry registry,
DateTime now,
Duration durationUntilDelete,
@ -307,31 +313,30 @@ public final class DomainDeleteFlow implements TransactionalFlow {
registry.getRenewGracePeriodLength()));
ImmutableSet<DomainTransactionRecord> cancelledRecords =
createCancelingRecords(
existingResource,
domain,
now,
maxGracePeriod,
Sets.immutableEnumSet(Sets.union(ADD_FIELDS, RENEW_FIELDS)));
historyBuilder
.setDomainTransactionRecords(
union(
cancelledRecords,
DomainTransactionRecord.create(
existingResource.getTld(),
now.plus(durationUntilDelete),
inAddGracePeriod
? TransactionReportField.DELETED_DOMAINS_GRACE
: TransactionReportField.DELETED_DOMAINS_NOGRACE,
1)));
historyBuilder.setDomainTransactionRecords(
union(
cancelledRecords,
DomainTransactionRecord.create(
domain.getTld(),
now.plus(durationUntilDelete),
inAddGracePeriod
? TransactionReportField.DELETED_DOMAINS_GRACE
: TransactionReportField.DELETED_DOMAINS_NOGRACE,
1)));
}
return historyBuilder
.setType(HistoryEntry.Type.DOMAIN_DELETE)
.setModificationTime(now)
.setParent(Key.create(existingResource))
.setDomainContent(domain)
.build();
}
private PollMessage.OneTime createDeletePollMessage(
DomainBase existingDomain, HistoryEntry historyEntry, DateTime deletionTime) {
DomainBase existingDomain, Key<DomainHistory> domainHistoryKey, DateTime deletionTime) {
Optional<MetadataExtension> metadataExtension =
eppInput.getSingleExtension(MetadataExtension.class);
boolean hasMetadataMessage =
@ -350,16 +355,19 @@ public final class DomainDeleteFlow implements TransactionalFlow {
ImmutableList.of(
DomainPendingActionNotificationResponse.create(
existingDomain.getDomainName(), true, trid, deletionTime)))
.setParent(historyEntry)
.setParentKey(domainHistoryKey)
.build();
}
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()
.setClientId(existingDomain.getPersistedCurrentSponsorClientId())
.setEventTime(now)
.setParent(historyEntry)
.setParentKey(domainHistoryKey)
.setMsg(
String.format(
"Domain %s was deleted by registry administrator with final deletion effective: %s",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -14,6 +14,7 @@
package google.registry.flows.domain;
import static google.registry.flows.FlowUtils.createHistoryKey;
import static google.registry.flows.FlowUtils.validateClientIsLoggedIn;
import static google.registry.flows.ResourceFlowUtils.computeExDateForApprovalTime;
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.model.domain.DomainBase;
import google.registry.model.domain.DomainCommand.Transfer;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.Period;
import google.registry.model.domain.fee.FeeTransferCommandExtension;
import google.registry.model.domain.fee.FeeTransformResponseExtension;
@ -126,7 +128,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
@Inject @ClientId String gainingClientId;
@Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser;
@Inject HistoryEntry.Builder historyBuilder;
@Inject DomainHistory.Builder historyBuilder;
@Inject Trid trid;
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
@Inject EppResponse.Builder responseBuilder;
@ -169,7 +171,10 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
if (feesAndCredits.isPresent()) {
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 =
superuserExtension.isPresent()
? now.plusDays(superuserExtension.get().getAutomaticTransferLength())
@ -190,7 +195,7 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
createTransferServerApproveEntities(
automaticTransferTime,
serverApproveNewExpirationTime,
historyEntry,
domainHistoryKey,
existingDomain,
trid,
gainingClientId,
@ -209,9 +214,12 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
serverApproveEntities,
period);
// Create a poll message to notify the losing registrar that a transfer was requested.
PollMessage requestPollMessage = createLosingTransferPollMessage(
targetId, pendingTransferData, serverApproveNewExpirationTime, historyEntry)
.asBuilder().setEventTime(now).build();
PollMessage requestPollMessage =
createLosingTransferPollMessage(
targetId, pendingTransferData, serverApproveNewExpirationTime, domainHistoryKey)
.asBuilder()
.setEventTime(now)
.build();
// 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
// cloneProjectedAtTime() will replace these old autorenew entities with the server approve ones
@ -225,10 +233,12 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
.setLastEppUpdateTime(now)
.setLastEppUpdateClientId(gainingClientId)
.build();
DomainHistory domainHistory = buildDomainHistory(newDomain, registry, now, period);
asyncTaskEnqueuer.enqueueAsyncResave(newDomain, now, automaticTransferTime);
tm().putAll(
new ImmutableSet.Builder<>()
.add(newDomain, historyEntry, requestPollMessage)
.add(newDomain, domainHistory, requestPollMessage)
.addAll(serverApproveEntities)
.build());
return responseBuilder
@ -302,14 +312,13 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
}
}
private HistoryEntry buildHistoryEntry(
DomainBase existingDomain, Registry registry, DateTime now, Period period) {
private DomainHistory buildDomainHistory(
DomainBase newDomain, Registry registry, DateTime now, Period period) {
return historyBuilder
.setType(HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST)
.setOtherClientId(existingDomain.getCurrentSponsorClientId())
.setPeriod(period)
.setModificationTime(now)
.setParent(Key.create(existingDomain))
.setDomainContent(newDomain)
.setDomainTransactionRecords(
ImmutableSet.of(
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.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.Period;
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.PollMessage;
import google.registry.model.registry.Registry;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.transfer.DomainTransferData;
import google.registry.model.transfer.TransferData;
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.
*
* <p>This set consists of:
*
* <ul>
* <li>The one-time billing event charging the gaining registrar for the transfer
* <li>A cancellation of an autorenew charge for the losing registrar, if the autorenew grace
* period will apply at transfer time
* <li>A new post-transfer autorenew billing event for the domain (and gaining registrar)
* <li>A new post-transfer autorenew poll message for the domain (and gaining registrar)
* <li>A poll message for the gaining registrar
* <li>A poll message for the losing registrar
* <li>The one-time billing event charging the gaining registrar for the transfer
* <li>A cancellation of an autorenew charge for the losing registrar, if the autorenew grace
* period will apply at transfer time
* <li>A new post-transfer autorenew billing event for the domain (and gaining registrar)
* <li>A new post-transfer autorenew poll message for the domain (and gaining registrar)
* <li>A poll message for the gaining registrar
* <li>A poll message for the losing registrar
* </ul>
*/
public static ImmutableSet<TransferServerApproveEntity> createTransferServerApproveEntities(
DateTime automaticTransferTime,
DateTime serverApproveNewExpirationTime,
HistoryEntry historyEntry,
Key<DomainHistory> domainHistoryKey,
DomainBase existingDomain,
Trid trid,
String gainingClientId,
@ -123,32 +125,39 @@ public final class DomainTransferUtils {
.build();
Registry registry = Registry.get(existingDomain.getTld());
ImmutableSet.Builder<TransferServerApproveEntity> builder = new ImmutableSet.Builder<>();
if (transferCost.isPresent()) {
builder.add(
createTransferBillingEvent(
automaticTransferTime,
historyEntry,
targetId,
gainingClientId,
registry,
transferCost.get()));
}
transferCost.ifPresent(
cost ->
builder.add(
createTransferBillingEvent(
automaticTransferTime,
domainHistoryKey,
targetId,
gainingClientId,
registry,
cost)));
createOptionalAutorenewCancellation(
automaticTransferTime, historyEntry, targetId, existingDomain, transferCost)
automaticTransferTime, now, domainHistoryKey, targetId, existingDomain, transferCost)
.ifPresent(builder::add);
return builder
.add(
createGainingClientAutorenewEvent(
serverApproveNewExpirationTime, historyEntry, targetId, gainingClientId))
serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingClientId))
.add(
createGainingClientAutorenewPollMessage(
serverApproveNewExpirationTime, historyEntry, targetId, gainingClientId))
serverApproveNewExpirationTime, domainHistoryKey, targetId, gainingClientId))
.add(
createGainingTransferPollMessage(
targetId, serverApproveTransferData, serverApproveNewExpirationTime, historyEntry))
targetId,
serverApproveTransferData,
serverApproveNewExpirationTime,
now,
domainHistoryKey))
.add(
createLosingTransferPollMessage(
targetId, serverApproveTransferData, serverApproveNewExpirationTime, historyEntry))
targetId,
serverApproveTransferData,
serverApproveNewExpirationTime,
domainHistoryKey))
.build();
}
@ -157,19 +166,21 @@ public final class DomainTransferUtils {
String targetId,
TransferData transferData,
@Nullable DateTime extendedRegistrationExpirationTime,
HistoryEntry historyEntry) {
DateTime now,
Key<DomainHistory> domainHistoryKey) {
return new PollMessage.OneTime.Builder()
.setClientId(transferData.getGainingClientId())
.setEventTime(transferData.getPendingTransferExpirationTime())
.setMsg(transferData.getTransferStatus().getMessage())
.setResponseData(ImmutableList.of(
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime),
DomainPendingActionNotificationResponse.create(
targetId,
transferData.getTransferStatus().isApproved(),
transferData.getTransferRequestTrid(),
historyEntry.getModificationTime())))
.setParent(historyEntry)
.setResponseData(
ImmutableList.of(
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime),
DomainPendingActionNotificationResponse.create(
targetId,
transferData.getTransferStatus().isApproved(),
transferData.getTransferRequestTrid(),
now)))
.setParentKey(domainHistoryKey)
.build();
}
@ -178,14 +189,15 @@ public final class DomainTransferUtils {
String targetId,
TransferData transferData,
@Nullable DateTime extendedRegistrationExpirationTime,
HistoryEntry historyEntry) {
Key<DomainHistory> domainHistoryKey) {
return new PollMessage.OneTime.Builder()
.setClientId(transferData.getLosingClientId())
.setEventTime(transferData.getPendingTransferExpirationTime())
.setMsg(transferData.getTransferStatus().getMessage())
.setResponseData(ImmutableList.of(
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime)))
.setParent(historyEntry)
.setResponseData(
ImmutableList.of(
createTransferResponse(targetId, transferData, extendedRegistrationExpirationTime)))
.setParentKey(domainHistoryKey)
.build();
}
@ -207,7 +219,7 @@ public final class DomainTransferUtils {
private static PollMessage.Autorenew createGainingClientAutorenewPollMessage(
DateTime serverApproveNewExpirationTime,
HistoryEntry historyEntry,
Key<DomainHistory> domainHistoryKey,
String targetId,
String gainingClientId) {
return new PollMessage.Autorenew.Builder()
@ -216,13 +228,13 @@ public final class DomainTransferUtils {
.setEventTime(serverApproveNewExpirationTime)
.setAutorenewEndTime(END_OF_TIME)
.setMsg("Domain was auto-renewed.")
.setParent(historyEntry)
.setParentKey(domainHistoryKey)
.build();
}
private static BillingEvent.Recurring createGainingClientAutorenewEvent(
DateTime serverApproveNewExpirationTime,
HistoryEntry historyEntry,
Key<DomainHistory> domainHistoryKey,
String targetId,
String gainingClientId) {
return new BillingEvent.Recurring.Builder()
@ -232,7 +244,7 @@ public final class DomainTransferUtils {
.setClientId(gainingClientId)
.setEventTime(serverApproveNewExpirationTime)
.setRecurrenceEndTime(END_OF_TIME)
.setParent(historyEntry)
.setParent(domainHistoryKey)
.build();
}
@ -254,7 +266,8 @@ public final class DomainTransferUtils {
*/
private static Optional<BillingEvent.Cancellation> createOptionalAutorenewCancellation(
DateTime automaticTransferTime,
HistoryEntry historyEntry,
DateTime now,
Key<DomainHistory> domainHistoryKey,
String targetId,
DomainBase existingDomain,
Optional<Money> transferCost) {
@ -265,7 +278,8 @@ public final class DomainTransferUtils {
domainAtTransferTime.getGracePeriodsOfType(GracePeriodStatus.AUTO_RENEW), null);
if (autorenewGracePeriod != null && transferCost.isPresent()) {
return Optional.of(
BillingEvent.Cancellation.forGracePeriod(autorenewGracePeriod, historyEntry, targetId)
BillingEvent.Cancellation.forGracePeriod(
autorenewGracePeriod, now, domainHistoryKey, targetId)
.asBuilder()
.setEventTime(automaticTransferTime)
.build());
@ -275,7 +289,7 @@ public final class DomainTransferUtils {
private static BillingEvent.OneTime createTransferBillingEvent(
DateTime automaticTransferTime,
HistoryEntry historyEntry,
Key<DomainHistory> domainHistoryKey,
String targetId,
String gainingClientId,
Registry registry,
@ -288,7 +302,7 @@ public final class DomainTransferUtils {
.setPeriodYears(1)
.setEventTime(automaticTransferTime)
.setBillingTime(automaticTransferTime.plus(registry.getTransferGracePeriodLength()))
.setParent(historyEntry)
.setParent(domainHistoryKey)
.build();
}

View file

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

View file

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

View file

@ -377,12 +377,16 @@ public class HistoryEntry extends ImmutableObject implements Buildable, Datastor
return thisCastToDerived();
}
public B copyFrom(HistoryEntry.Builder<? extends HistoryEntry, ?> builder) {
return copyFrom(builder.getInstance());
}
@Override
public T build() {
return super.build();
}
public B setId(long id) {
public B setId(Long id) {
getInstance().id = id;
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 com.google.common.collect.ImmutableCollection;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import google.registry.model.EppResource;
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.transaction.CriteriaQueryBuilder;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
@ -48,7 +49,7 @@ import org.joda.time.DateTime;
public class HistoryEntryDao {
/** 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) {
if (tm().isOfy()) {
return Streams.stream(
@ -64,21 +65,25 @@ public class HistoryEntryDao {
return jpaTm()
.transact(
() ->
Iterables.concat(
loadAllHistoryObjectsFromSql(ContactHistory.class, afterTime, beforeTime),
loadAllHistoryObjectsFromSql(DomainHistory.class, afterTime, beforeTime),
loadAllHistoryObjectsFromSql(HostHistory.class, afterTime, beforeTime)));
new ImmutableList.Builder<HistoryEntry>()
.addAll(
loadAllHistoryObjectsFromSql(ContactHistory.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}. */
public static Iterable<? extends HistoryEntry> loadHistoryObjectsForResource(
public static ImmutableList<? extends HistoryEntry> loadHistoryObjectsForResource(
VKey<? extends EppResource> parentKey) {
return loadHistoryObjectsForResource(parentKey, START_OF_TIME, END_OF_TIME);
}
/** 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) {
if (tm().isOfy()) {
return Streams.stream(
@ -130,7 +135,7 @@ public class HistoryEntryDao {
.getResultStream();
}
private static Iterable<? extends HistoryEntry> loadHistoryObjectsForResourceFromSql(
private static ImmutableList<? extends HistoryEntry> loadHistoryObjectsForResourceFromSql(
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
Class<? extends HistoryEntry> historyClass = getHistoryClassFromParent(parentKey.getKind());
@ -144,12 +149,9 @@ public class HistoryEntryDao {
.where(repoIdFieldName, criteriaBuilder::equal, parentKey.getSqlKey().toString())
.build();
return jpaTm()
.getEntityManager()
.createQuery(criteriaQuery)
.getResultStream()
.sorted(Comparator.comparing(HistoryEntry::getModificationTime))
.collect(toImmutableList());
return ImmutableList.sortedCopyOf(
Comparator.comparing(HistoryEntry::getModificationTime),
jpaTm().getEntityManager().createQuery(criteriaQuery).getResultList());
}
private static Class<? extends HistoryEntry> getHistoryClassFromParent(
@ -172,7 +174,7 @@ public class HistoryEntryDao {
: 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) {
CriteriaBuilder criteriaBuilder = jpaTm().getEntityManager().getCriteriaBuilder();
return jpaTm()

View file

@ -164,6 +164,7 @@ public class DomainTransferData extends TransferData<DomainTransferData.Builder>
serverApproveEntities = null;
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);
}
serverApproveEntities = forceEmptyToNull(serverApproveEntitiesBuilder.build());
hashCode = null; // reset the hash code since we may have changed the entities
}
@Override

View file

@ -757,11 +757,11 @@ class EppLifecycleDomainTest extends EppTestCase {
.hasResponse(
"poll_response_autorenew.xml",
ImmutableMap.of(
"ID", "1-D-EXAMPLE-11-16-2002",
"ID", "1-C-EXAMPLE-13-16-2002",
"QDATE", "2002-06-01T00:04:00Z",
"DOMAIN", "fakesite.example",
"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")
.hasResponse("poll_ack_response_empty.xml");
@ -775,13 +775,13 @@ class EppLifecycleDomainTest extends EppTestCase {
.hasResponse(
"poll_response_autorenew.xml",
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",
"DOMAIN", "fakesite.example",
"EXDATE", "2004-06-01T00:04:00Z"));
// 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")
.hasResponse("poll_ack_response_empty.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.
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
String messageId = "1-D-EXAMPLE-19-25-2001";
String messageId = "1-C-EXAMPLE-19-25-2001";
assertThatCommand("poll.xml")
.atTime("2001-01-01T00:01:00Z")
.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");
// 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")
.atTime("2001-01-06T00:01:00Z")
.hasResponse(
@ -832,7 +832,7 @@ class EppLifecycleDomainTest extends EppTestCase {
assertThatLogoutSucceeds();
// 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");
assertThatCommand("poll.xml")
.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.truth.Truth.assertThat;
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.persistence.transaction.TransactionManagerFactory.tm;
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.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Streams;
import com.google.common.flogger.LoggerConfig;
import com.google.common.testing.TestLogHandler;
import com.googlecode.objectify.Key;
import google.registry.flows.FlowUtils.NotLoggedInException;
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.eppinput.EppInput.ResourceCommandWrapper;
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.EppResourceIndexBucket;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.tmch.ClaimsListDualDatabaseDao;
import google.registry.model.tmch.ClaimsListShard;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.TaskQueueHelper.TaskMatcher;
import google.registry.util.TypeUtils.TypeInstantiator;
import java.util.logging.Level;
@ -177,4 +187,22 @@ public abstract class ResourceFlowTestCase<F extends Flow, R extends EppResource
.which()
.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
? clock.nowUtc().plus(Registry.get(domainTld).getAnchorTenantAddGracePeriodLength())
: clock.nowUtc().plus(Registry.get(domainTld).getAddGracePeriodLength());
assertLastHistoryContainsResource(domain);
HistoryEntry historyEntry = getHistoryEntries(domain).get(0);
assertAboutDomains()
.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
// closed the autorenew recurrences immediately, there are no other autorenew effects.
assertAboutDomains().that(resource).hasRegistrationExpirationTime(expectedExpirationTime);
assertLastHistoryContainsResource(resource);
// All existing grace periods that were for billable actions should cause cancellations.
assertAutorenewClosedAndCancellationCreatedFor(
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.createTld;
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.newDomainBase;
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.Reason;
import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.rgp.GracePeriodStatus;
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.TransactionReportField;
import google.registry.model.reporting.HistoryEntry;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension;
import google.registry.testing.SetClockExtension;
import google.registry.testing.TestOfyAndSql;
import java.util.Map;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainRenewFlow}. */
@DualDatabaseTest
class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBase> {
private static final ImmutableMap<String, String> FEE_BASE_MAP =
@ -121,8 +125,8 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
tm().transact(
() -> {
try {
HistoryEntry historyEntryDomainCreate =
new HistoryEntry.Builder()
DomainHistory historyEntryDomainCreate =
new DomainHistory.Builder()
.setParent(domain)
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setModificationTime(clock.nowUtc())
@ -195,9 +199,10 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
runFlowAssertResponse(
CommitMode.LIVE, userPrivileges, loadFile(responseFilename, substitutions));
DomainBase domain = reloadResourceByForeignKey();
assertLastHistoryContainsResource(domain);
HistoryEntry historyEntryDomainRenew =
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RENEW);
assertThat(tm().loadByKey(domain.getAutorenewBillingEvent()).getEventTime())
assertThat(loadByKey(domain.getAutorenewBillingEvent()).getEventTime())
.isEqualTo(newExpiration);
assertAboutDomains()
.that(domain)
@ -266,7 +271,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
renewBillingEvent));
}
@Test
@TestOfyAndSql
void testDryRun() throws Exception {
persistDomain();
dryRunFlowAssertResponse(
@ -275,7 +280,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z")));
}
@Test
@TestOfyAndSql
void testSuccess() throws Exception {
clock.advanceOneMilli();
persistDomain();
@ -285,7 +290,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z"));
}
@Test
@TestOfyAndSql
void testSuccess_recurringClientIdIsSame_whenSuperuserOverridesRenewal() throws Exception {
persistDomain();
setClientIdForFlow("NewRegistrar");
@ -298,7 +303,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
Money.of(USD, 55));
}
@Test
@TestOfyAndSql
void testSuccess_customLogicFee() throws Exception {
// 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.
@ -320,56 +325,56 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
Money.of(USD, 111));
}
@Test
@TestOfyAndSql
void testSuccess_fee_v06() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_06_MAP);
persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_06_MAP);
}
@Test
@TestOfyAndSql
void testSuccess_fee_v11() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_11_MAP);
persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_11_MAP);
}
@Test
@TestOfyAndSql
void testSuccess_fee_v12() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_12_MAP);
persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_12_MAP);
}
@Test
@TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v06() throws Exception {
setEppInput("domain_renew_fee_defaults.xml", FEE_06_MAP);
persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_06_MAP);
}
@Test
@TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v11() throws Exception {
setEppInput("domain_renew_fee_defaults.xml", FEE_11_MAP);
persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_11_MAP);
}
@Test
@TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v12() throws Exception {
setEppInput("domain_renew_fee_defaults.xml", FEE_12_MAP);
persistDomain();
doSuccessfulTest("domain_renew_response_fee.xml", 5, FEE_12_MAP);
}
@Test
@TestOfyAndSql
void testFailure_fee_unknownCurrency() {
setEppInput("domain_renew_fee.xml", updateSubstitutions(FEE_06_MAP, "CURRENCY", "BAD"));
EppException thrown = assertThrows(UnknownCurrencyEppException.class, this::persistDomain);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_refundableFee_v06() throws Exception {
setEppInput("domain_renew_fee_refundable.xml", FEE_06_MAP);
persistDomain();
@ -377,7 +382,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_refundableFee_v11() throws Exception {
setEppInput("domain_renew_fee_refundable.xml", FEE_11_MAP);
persistDomain();
@ -385,7 +390,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_refundableFee_v12() throws Exception {
setEppInput("domain_renew_fee_refundable.xml", FEE_12_MAP);
persistDomain();
@ -393,7 +398,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_gracePeriodFee_v06() throws Exception {
setEppInput("domain_renew_fee_grace_period.xml", FEE_06_MAP);
persistDomain();
@ -401,7 +406,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_gracePeriodFee_v11() throws Exception {
setEppInput("domain_renew_fee_grace_period.xml", FEE_11_MAP);
persistDomain();
@ -409,7 +414,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_gracePeriodFee_v12() throws Exception {
setEppInput("domain_renew_fee_grace_period.xml", FEE_12_MAP);
persistDomain();
@ -417,7 +422,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_appliedFee_v06() throws Exception {
setEppInput("domain_renew_fee_applied.xml", FEE_06_MAP);
persistDomain();
@ -425,7 +430,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_appliedFee_v11() throws Exception {
setEppInput("domain_renew_fee_applied.xml", FEE_11_MAP);
persistDomain();
@ -433,7 +438,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_appliedFee_v12() throws Exception {
setEppInput("domain_renew_fee_applied.xml", FEE_12_MAP);
persistDomain();
@ -441,17 +446,17 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_suspendedRegistrarCantRenewDomain() {
doFailingTest_invalidRegistrarState(State.SUSPENDED);
}
@Test
@TestOfyAndSql
void testFailure_pendingRegistrarCantRenewDomain() {
doFailingTest_invalidRegistrarState(State.PENDING);
}
@Test
@TestOfyAndSql
void testFailure_disabledRegistrarCantRenewDomain() {
doFailingTest_invalidRegistrarState(State.DISABLED);
}
@ -468,7 +473,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_nonDefaultRenewGracePeriod() throws Exception {
persistResource(
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"));
}
@Test
@TestOfyAndSql
void testSuccess_missingPeriod() throws Exception {
setEppInput("domain_renew_missing_period.xml");
persistDomain();
doSuccessfulTest("domain_renew_response_missing_period.xml", 1);
}
@Test
@TestOfyAndSql
void testSuccess_autorenewPollMessageIsNotDeleted() throws Exception {
persistDomain();
// Modify the autorenew poll message so that it has an undelivered message in the past.
persistResource(
tm().loadByKey(reloadResourceByForeignKey().getAutorenewPollMessage())
loadByKey(reloadResourceByForeignKey().getAutorenewPollMessage())
.asBuilder()
.setEventTime(expirationTime.minusYears(1))
.build());
@ -525,14 +530,14 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
.build());
}
@Test
@TestOfyAndSql
void testFailure_neverExisted() throws Exception {
ResourceDoesNotExistException thrown =
assertThrows(ResourceDoesNotExistException.class, this::runFlow);
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
}
@Test
@TestOfyAndSql
void testFailure_existedButWasDeleted() throws Exception {
persistDeletedDomain(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1));
ResourceDoesNotExistException thrown =
@ -540,7 +545,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
}
@Test
@TestOfyAndSql
void testFailure_clientRenewProhibited() throws Exception {
persistDomain(StatusValue.CLIENT_RENEW_PROHIBITED);
ResourceStatusProhibitsOperationException thrown =
@ -548,7 +553,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertThat(thrown).hasMessageThat().contains("clientRenewProhibited");
}
@Test
@TestOfyAndSql
void testFailure_serverRenewProhibited() throws Exception {
persistDomain(StatusValue.SERVER_RENEW_PROHIBITED);
ResourceStatusProhibitsOperationException thrown =
@ -556,7 +561,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertThat(thrown).hasMessageThat().contains("serverRenewProhibited");
}
@Test
@TestOfyAndSql
void testFailure_pendingDelete() throws Exception {
persistResource(
newDomainBase(getUniqueIdFromCommand())
@ -570,7 +575,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertThat(thrown).hasMessageThat().contains("pendingDelete");
}
@Test
@TestOfyAndSql
void testFailure_wrongFeeAmount_v06() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_06_MAP);
persistResource(
@ -583,7 +588,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_wrongFeeAmount_v11() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_11_MAP);
persistResource(
@ -596,7 +601,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_wrongFeeAmount_v12() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_12_MAP);
persistResource(
@ -609,7 +614,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_wrongCurrency_v06() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_06_MAP);
persistResource(
@ -628,7 +633,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_wrongCurrency_v11() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_11_MAP);
persistResource(
@ -647,7 +652,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_wrongCurrency_v12() throws Exception {
setEppInput("domain_renew_fee.xml", FEE_12_MAP);
persistResource(
@ -666,7 +671,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_feeGivenInWrongScale_v06() throws Exception {
setEppInput("domain_renew_fee_bad_scale.xml", FEE_06_MAP);
persistDomain();
@ -674,7 +679,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_feeGivenInWrongScale_v11() throws Exception {
setEppInput("domain_renew_fee_bad_scale.xml", FEE_11_MAP);
persistDomain();
@ -682,7 +687,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_feeGivenInWrongScale_v12() throws Exception {
setEppInput("domain_renew_fee_bad_scale.xml", FEE_12_MAP);
persistDomain();
@ -690,7 +695,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_pendingTransfer() throws Exception {
persistDomain();
persistWithPendingTransfer(
@ -703,7 +708,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertThat(thrown).hasMessageThat().contains("pendingTransfer");
}
@Test
@TestOfyAndSql
void testFailure_periodInMonths() throws Exception {
setEppInput("domain_renew_months.xml");
persistDomain();
@ -711,7 +716,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_max10Years() throws Exception {
setEppInput("domain_renew_11_years.xml");
persistDomain();
@ -719,7 +724,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_curExpDateMustMatch() throws Exception {
persistDomain();
// Note expiration time is off by one day.
@ -733,7 +738,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_unauthorizedClient() throws Exception {
setClientIdForFlow("NewRegistrar");
persistActiveDomain(getUniqueIdFromCommand());
@ -741,7 +746,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_superuserUnauthorizedClient() throws Exception {
setClientIdForFlow("NewRegistrar");
persistDomain();
@ -753,7 +758,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
ImmutableMap.of("DOMAIN", "example.tld", "EXDATE", "2005-04-03T22:00:00.0Z")));
}
@Test
@TestOfyAndSql
void testFailure_notAuthorizedForTld() throws Exception {
persistResource(
loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build());
@ -762,7 +767,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_superuserNotAuthorizedForTld() throws Exception {
persistResource(
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")));
}
@Test
@TestOfyAndSql
void testFailure_feeNotProvidedOnPremiumName() throws Exception {
createTld("example");
setEppInput("domain_renew_premium.xml");
@ -784,7 +789,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testIcannActivityReportField_getsLogged() throws Exception {
persistDomain();
runFlow();
@ -792,7 +797,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, DomainBa
assertTldsFieldLogged("tld");
}
@Test
@TestOfyAndSql
void testIcannTransactionRecord_getsStored() throws Exception {
persistDomain();
// 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.Truth8.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.assertBillingEvents;
import static google.registry.testing.DatabaseHelper.assertPollMessages;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType;
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.newDomainBase;
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.TransactionReportField;
import google.registry.model.reporting.HistoryEntry;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension;
import google.registry.testing.TestOfyAndSql;
import java.util.Map;
import java.util.Optional;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainRestoreRequestFlow}. */
@DualDatabaseTest
class DomainRestoreRequestFlowTest
extends ResourceFlowTestCase<DomainRestoreRequestFlow, DomainBase> {
@ -141,14 +143,14 @@ class DomainRestoreRequestFlowTest
clock.advanceOneMilli();
}
@Test
@TestOfyAndSql
void testDryRun() throws Exception {
setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "example.tld"));
persistPendingDeleteDomain();
dryRunFlowAssertResponse(loadFile("generic_success_response.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_expiryStillInFuture_notExtended() throws Exception {
setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "example.tld"));
DateTime expirationTime = clock.nowUtc().plusYears(5).plusDays(45);
@ -160,7 +162,8 @@ class DomainRestoreRequestFlowTest
DomainBase domain = reloadResourceByForeignKey();
HistoryEntry historyEntryDomainRestore =
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RESTORE);
assertThat(tm().loadByKey(domain.getAutorenewBillingEvent()).getEventTime())
assertLastHistoryContainsResource(domain);
assertThat(loadByKey(domain.getAutorenewBillingEvent()).getEventTime())
.isEqualTo(expirationTime);
assertAboutDomains()
.that(domain)
@ -215,7 +218,7 @@ class DomainRestoreRequestFlowTest
.build());
}
@Test
@TestOfyAndSql
void testSuccess_expiryInPast_extendedByOneYear() throws Exception {
setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "example.tld"));
DateTime expirationTime = clock.nowUtc().minusDays(20);
@ -228,7 +231,8 @@ class DomainRestoreRequestFlowTest
DomainBase domain = reloadResourceByForeignKey();
HistoryEntry historyEntryDomainRestore =
getOnlyHistoryEntryOfType(domain, HistoryEntry.Type.DOMAIN_RESTORE);
assertThat(tm().loadByKey(domain.getAutorenewBillingEvent()).getEventTime())
assertLastHistoryContainsResource(domain);
assertThat(loadByKey(domain.getAutorenewBillingEvent()).getEventTime())
.isEqualTo(newExpirationTime);
assertAboutDomains()
.that(domain)
@ -293,7 +297,7 @@ class DomainRestoreRequestFlowTest
.build());
}
@Test
@TestOfyAndSql
void testSuccess_autorenewEndTimeIsCleared() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP);
persistPendingDeleteDomain();
@ -307,14 +311,14 @@ class DomainRestoreRequestFlowTest
assertThat(reloadResourceByForeignKey().getAutorenewEndTime()).isEmpty();
}
@Test
@TestOfyAndSql
void testSuccess_fee_v06() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP);
persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_06_MAP));
}
@Test
@TestOfyAndSql
void testSuccess_fee_v06_noRenewal() throws Exception {
setEppInput("domain_update_restore_request_fee_no_renewal.xml", FEE_06_MAP);
persistPendingDeleteDomain(clock.nowUtc().plusMonths(6));
@ -322,42 +326,42 @@ class DomainRestoreRequestFlowTest
loadFile("domain_update_restore_request_response_fee_no_renewal.xml", FEE_06_MAP));
}
@Test
@TestOfyAndSql
void testSuccess_fee_v11() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_11_MAP);
persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_11_MAP));
}
@Test
@TestOfyAndSql
void testSuccess_fee_v12() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_12_MAP);
persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_12_MAP));
}
@Test
@TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_06_MAP);
persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_06_MAP));
}
@Test
@TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_11_MAP);
persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_11_MAP));
}
@Test
@TestOfyAndSql
void testSuccess_fee_withDefaultAttributes_v12() throws Exception {
setEppInput("domain_update_restore_request_fee_defaults.xml", FEE_12_MAP);
persistPendingDeleteDomain();
runFlowAssertResponse(loadFile("domain_update_restore_request_response_fee.xml", FEE_12_MAP));
}
@Test
@TestOfyAndSql
void testFailure_fee_unknownCurrency() {
ImmutableMap<String, String> substitutions =
ImmutableMap.of("FEE_VERSION", "0.12", "FEE_NS", "fee12", "CURRENCY", "BAD");
@ -367,7 +371,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_refundableFee_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_06_MAP);
persistPendingDeleteDomain();
@ -375,7 +379,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_refundableFee_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_11_MAP);
persistPendingDeleteDomain();
@ -383,7 +387,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_refundableFee_v12() throws Exception {
setEppInput("domain_update_restore_request_fee_refundable.xml", FEE_12_MAP);
persistPendingDeleteDomain();
@ -391,7 +395,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_gracePeriodFee_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_06_MAP);
persistPendingDeleteDomain();
@ -399,7 +403,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_gracePeriodFee_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_11_MAP);
persistPendingDeleteDomain();
@ -407,7 +411,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_gracePeriodFee_v12() throws Exception {
setEppInput("domain_update_restore_request_fee_grace_period.xml", FEE_12_MAP);
persistPendingDeleteDomain();
@ -415,7 +419,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_appliedFee_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_applied.xml", FEE_06_MAP);
persistPendingDeleteDomain();
@ -423,7 +427,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_appliedFee_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_applied.xml", FEE_11_MAP);
persistPendingDeleteDomain();
@ -431,7 +435,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_appliedFee_v12() throws Exception {
setEppInput("domain_update_restore_request_fee_applied.xml", FEE_12_MAP);
persistPendingDeleteDomain();
@ -439,7 +443,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_premiumNotBlocked() throws Exception {
createTld("example");
setEppInput("domain_update_restore_request_premium.xml");
@ -447,7 +451,7 @@ class DomainRestoreRequestFlowTest
runFlowAssertResponse(loadFile("domain_update_restore_request_response_premium.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_premiumNotBlocked_andNoRenewal() throws Exception {
createTld("example");
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));
}
@Test
@TestOfyAndSql
void testSuccess_superuserOverridesReservedList() throws Exception {
persistResource(
Registry.get("tld")
@ -468,7 +472,7 @@ class DomainRestoreRequestFlowTest
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_superuserOverridesPremiumNameBlock() throws Exception {
createTld("example");
setEppInput("domain_update_restore_request_premium.xml");
@ -481,7 +485,7 @@ class DomainRestoreRequestFlowTest
loadFile("domain_update_restore_request_response_premium.xml"));
}
@Test
@TestOfyAndSql
void testFailure_doesNotExist() throws Exception {
ResourceDoesNotExistException thrown =
assertThrows(ResourceDoesNotExistException.class, this::runFlow);
@ -489,7 +493,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_suspendedRegistrarCantRestoreDomain() {
persistResource(
Registrar.loadByClientId("TheRegistrar")
@ -502,7 +506,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_pendingRegistrarCantRestoreDomain() {
persistResource(
Registrar.loadByClientId("TheRegistrar")
@ -515,7 +519,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_wrongFeeAmount_v06() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_06_MAP);
persistPendingDeleteDomain();
@ -525,7 +529,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_wrongFeeAmount_v11() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_11_MAP);
persistPendingDeleteDomain();
@ -535,7 +539,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_wrongFeeAmount_v12() throws Exception {
setEppInput("domain_update_restore_request_fee.xml", FEE_12_MAP);
persistPendingDeleteDomain();
@ -563,22 +567,22 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_wrongCurrency_v06() throws Exception {
runWrongCurrencyTest(FEE_06_MAP);
}
@Test
@TestOfyAndSql
void testFailure_wrongCurrency_v11() throws Exception {
runWrongCurrencyTest(FEE_11_MAP);
}
@Test
@TestOfyAndSql
void testFailure_wrongCurrency_v12() throws Exception {
runWrongCurrencyTest(FEE_12_MAP);
}
@Test
@TestOfyAndSql
void testFailure_feeGivenInWrongScale_v06() throws Exception {
setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_06_MAP);
persistPendingDeleteDomain();
@ -586,7 +590,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_feeGivenInWrongScale_v11() throws Exception {
setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_11_MAP);
persistPendingDeleteDomain();
@ -594,7 +598,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_feeGivenInWrongScale_v12() throws Exception {
setEppInput("domain_update_restore_request_fee_bad_scale.xml", FEE_12_MAP);
persistPendingDeleteDomain();
@ -602,7 +606,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_notInRedemptionPeriod() throws Exception {
persistResource(
newDomainBase(getUniqueIdFromCommand())
@ -614,21 +618,21 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_notDeleted() throws Exception {
persistActiveDomain(getUniqueIdFromCommand());
EppException thrown = assertThrows(DomainNotEligibleForRestoreException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_fullyDeleted() throws Exception {
persistDeletedDomain(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1));
EppException thrown = assertThrows(ResourceDoesNotExistException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_withChange() throws Exception {
persistPendingDeleteDomain();
setEppInput("domain_update_restore_request_with_change.xml");
@ -636,7 +640,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_withAdd() throws Exception {
persistPendingDeleteDomain();
setEppInput("domain_update_restore_request_with_add.xml");
@ -644,7 +648,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_withRemove() throws Exception {
persistPendingDeleteDomain();
setEppInput("domain_update_restore_request_with_remove.xml");
@ -652,7 +656,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_withSecDnsExtension() throws Exception {
persistPendingDeleteDomain();
setEppInput("domain_update_restore_request_with_secdns.xml");
@ -660,7 +664,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_unauthorizedClient() throws Exception {
sessionMetadata.setClientId("NewRegistrar");
persistPendingDeleteDomain();
@ -668,7 +672,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_superuserUnauthorizedClient() throws Exception {
sessionMetadata.setClientId("NewRegistrar");
persistPendingDeleteDomain();
@ -679,7 +683,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_notAuthorizedForTld() throws Exception {
persistResource(
loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build());
@ -688,7 +692,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_superuserNotAuthorizedForTld() throws Exception {
persistResource(
loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build());
@ -697,7 +701,7 @@ class DomainRestoreRequestFlowTest
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
}
@Test
@TestOfyAndSql
void testFailure_premiumBlocked() throws Exception {
createTld("example");
setEppInput("domain_update_restore_request_premium.xml");
@ -708,7 +712,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_reservedBlocked() throws Exception {
createTld("tld");
persistResource(
@ -721,7 +725,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_premiumNotAcked() throws Exception {
createTld("example");
setEppInput("domain_update_restore_request.xml", ImmutableMap.of("DOMAIN", "rich.example"));
@ -730,7 +734,7 @@ class DomainRestoreRequestFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testIcannActivityReportField_getsLogged() throws Exception {
persistPendingDeleteDomain();
runFlow();
@ -738,7 +742,7 @@ class DomainRestoreRequestFlowTest
assertTldsFieldLogged("tld");
}
@Test
@TestOfyAndSql
void testIcannTransactionReportField_getsStored() throws Exception {
persistPendingDeleteDomain();
runFlow();
@ -754,7 +758,7 @@ class DomainRestoreRequestFlowTest
1));
}
@Test
@TestOfyAndSql
void testFailure_restoreReportsAreNotSupported() {
setEppInput("domain_update_restore_report.xml");
// 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.
domain = reloadResourceByForeignKey();
assertLastHistoryContainsResource(domain);
assertTransferFailed(domain, TransferStatus.CLIENT_CANCELLED, originalTransferData);
assertAboutDomains()
.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.reporting.HistoryEntry;
import google.registry.model.transfer.TransferStatus;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension;
import google.registry.testing.TestOfyAndSql;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainTransferQueryFlow}. */
@DualDatabaseTest
class DomainTransferQueryFlowTest
extends DomainTransferFlowTestCase<DomainTransferQueryFlow, DomainBase> {
@ -86,67 +88,67 @@ class DomainTransferQueryFlowTest
runFlow();
}
@Test
@TestOfyAndSql
void testSuccess() throws Exception {
doSuccessfulTest("domain_transfer_query.xml", "domain_transfer_query_response.xml", 1);
}
@Test
@TestOfyAndSql
void testSuccess_sponsoringClient() throws Exception {
setClientIdForFlow("TheRegistrar");
doSuccessfulTest("domain_transfer_query.xml", "domain_transfer_query_response.xml", 1);
}
@Test
@TestOfyAndSql
void testSuccess_domainAuthInfo() throws Exception {
setClientIdForFlow("ClientZ");
doSuccessfulTest(
"domain_transfer_query_domain_authinfo.xml", "domain_transfer_query_response.xml", 1);
}
@Test
@TestOfyAndSql
void testSuccess_contactAuthInfo() throws Exception {
setClientIdForFlow("ClientZ");
doSuccessfulTest(
"domain_transfer_query_contact_authinfo.xml", "domain_transfer_query_response.xml", 1);
}
@Test
@TestOfyAndSql
void testSuccess_clientApproved() throws Exception {
changeTransferStatus(TransferStatus.CLIENT_APPROVED);
doSuccessfulTest(
"domain_transfer_query.xml", "domain_transfer_query_response_client_approved.xml", 1);
}
@Test
@TestOfyAndSql
void testSuccess_clientRejected() throws Exception {
changeTransferStatus(TransferStatus.CLIENT_REJECTED);
doSuccessfulTest(
"domain_transfer_query.xml", "domain_transfer_query_response_client_rejected.xml", 1);
}
@Test
@TestOfyAndSql
void testSuccess_clientCancelled() throws Exception {
changeTransferStatus(TransferStatus.CLIENT_CANCELLED);
doSuccessfulTest(
"domain_transfer_query.xml", "domain_transfer_query_response_client_cancelled.xml", 1);
}
@Test
@TestOfyAndSql
void testSuccess_serverApproved() throws Exception {
changeTransferStatus(TransferStatus.SERVER_APPROVED);
doSuccessfulTest(
"domain_transfer_query.xml", "domain_transfer_query_response_server_approved.xml", 1);
}
@Test
@TestOfyAndSql
void testSuccess_serverCancelled() throws Exception {
changeTransferStatus(TransferStatus.SERVER_CANCELLED);
doSuccessfulTest(
"domain_transfer_query.xml", "domain_transfer_query_response_server_cancelled.xml", 1);
}
@Test
@TestOfyAndSql
void testSuccess_tenYears() throws Exception {
// Extend registration by 9 years here; with the extra 1 year from the transfer, we should
// hit the 10-year capping.
@ -159,7 +161,7 @@ class DomainTransferQueryFlowTest
doSuccessfulTest("domain_transfer_query.xml", "domain_transfer_query_response_10_years.xml", 1);
}
@Test
@TestOfyAndSql
void testFailure_pendingDeleteDomain() throws Exception {
changeTransferStatus(TransferStatus.SERVER_CANCELLED);
domain =
@ -168,7 +170,7 @@ class DomainTransferQueryFlowTest
"domain_transfer_query.xml", "domain_transfer_query_response_server_cancelled.xml", 1);
}
@Test
@TestOfyAndSql
void testFailure_badContactPassword() {
// Change the contact's password so it does not match the password in the file.
contact =
@ -184,7 +186,7 @@ class DomainTransferQueryFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_badDomainPassword() {
// Change the domain's password so it does not match the password in the file.
domain =
@ -200,7 +202,7 @@ class DomainTransferQueryFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_neverBeenTransferred() {
changeTransferStatus(null);
EppException thrown =
@ -210,7 +212,7 @@ class DomainTransferQueryFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_unrelatedClient() {
setClientIdForFlow("ClientZ");
EppException thrown =
@ -220,7 +222,7 @@ class DomainTransferQueryFlowTest
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_deletedDomain() throws Exception {
domain =
persistResource(domain.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build());
@ -230,7 +232,7 @@ class DomainTransferQueryFlowTest
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
}
@Test
@TestOfyAndSql
void testFailure_nonexistentDomain() throws Exception {
deleteTestDomain(domain, clock.nowUtc());
ResourceDoesNotExistException thrown =
@ -239,14 +241,14 @@ class DomainTransferQueryFlowTest
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
}
@Test
@TestOfyAndSql
void testIcannActivityReportField_getsLogged() throws Exception {
runFlow();
assertIcannReportingActivityFieldLogged("srs-dom-transfer-query");
assertTldsFieldLogged("tld");
}
@Test
@TestOfyAndSql
void testSuccess_serverApproved_afterAutorenews() throws Exception {
// 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.

View file

@ -119,6 +119,7 @@ class DomainTransferRejectFlowTest
final HistoryEntry historyEntryTransferRejected =
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REJECT);
assertAboutHistoryEntries().that(historyEntryTransferRejected).hasOtherClientId("NewRegistrar");
assertLastHistoryContainsResource(domain);
// The only billing event left should be the original autorenew event, now reopened.
assertBillingEvents(
getLosingClientAutorenewEvent().asBuilder().setRecurrenceEndTime(END_OF_TIME).build());

View file

@ -484,6 +484,7 @@ class DomainTransferRequestFlowTest
assertAboutDomains()
.that(domain)
.hasOneHistoryEntryEachOfTypes(DOMAIN_CREATE, DOMAIN_TRANSFER_REQUEST);
assertLastHistoryContainsResource(domain);
final HistoryEntry historyEntryTransferRequest =
getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_REQUEST);
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.eppcommon.StatusValue.SERVER_UPDATE_PROHIBITED;
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.assertNoBillingEvents;
import static google.registry.testing.DatabaseHelper.createTld;
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.newDomainBase;
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.reporting.HistoryEntry;
import google.registry.persistence.VKey;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.ReplayExtension;
import google.registry.testing.TestOfyAndSql;
import java.util.Optional;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainUpdateFlow}. */
@DualDatabaseTest
class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, DomainBase> {
private static final DelegationSignerData SOME_DSDATA =
@ -207,23 +209,24 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.hasNoAutorenewEndTime();
assertNoBillingEvents();
assertDnsTasksEnqueued("example.tld");
assertLastHistoryContainsResource(reloadResourceByForeignKey());
}
@Test
@TestOfyAndSql
void testDryRun() throws Exception {
persistReferencedEntities();
persistDomain();
dryRunFlowAssertResponse(loadFile("generic_success_response.xml"));
}
@Test
@TestOfyAndSql
void testSuccess() throws Exception {
persistReferencedEntities();
persistDomain();
doSuccessfulTest();
}
@Test
@TestOfyAndSql
void testSuccess_clTridNotSpecified() throws Exception {
setEppInput("domain_update_no_cltrid.xml");
persistReferencedEntities();
@ -231,7 +234,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doSuccessfulTest("generic_success_response_no_cltrid.xml");
}
@Test
@TestOfyAndSql
void testSuccess_cachingDisabled() throws Exception {
boolean origIsCachingEnabled = RegistryConfig.isEppResourceCachingEnabled();
try {
@ -244,7 +247,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
}
}
@Test
@TestOfyAndSql
void testSuccess_inQuietPeriod() throws Exception {
persistResource(
Registry.get("tld")
@ -256,7 +259,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doSuccessfulTest();
}
@Test
@TestOfyAndSql
void testFailure_emptyRegistrant() throws Exception {
setEppInput("domain_update_empty_registrant.xml");
persistReferencedEntities();
@ -282,7 +285,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
clock.advanceOneMilli();
}
@Test
@TestOfyAndSql
void testSuccess_maxNumberOfNameservers() throws Exception {
persistReferencedEntities();
persistDomain();
@ -291,7 +294,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doSuccessfulTest();
}
@Test
@TestOfyAndSql
void testSuccess_addAndRemoveLargeNumberOfNameserversAndContacts() throws Exception {
persistReferencedEntities();
persistDomain();
@ -330,12 +333,12 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(domain.getNameservers()).hasSize(13);
// getContacts does not return contacts of type REGISTRANT, so check these separately.
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();
assertDnsTasksEnqueued("example.tld");
}
@Test
@TestOfyAndSql
void testSuccess_metadata() throws Exception {
eppRequestSource = EppRequestSource.TOOL;
setEppInput("domain_update_metadata.xml");
@ -354,7 +357,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.hasMetadataRequestedByRegistrar(true);
}
@Test
@TestOfyAndSql
void testSuccess_metadataNotFromTool() throws Exception {
setEppInput("domain_update_metadata.xml");
persistReferencedEntities();
@ -363,7 +366,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_removeContact() throws Exception {
setEppInput("domain_update_remove_contact.xml");
persistReferencedEntities();
@ -371,7 +374,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doSuccessfulTest();
}
@Test
@TestOfyAndSql
void testSuccess_addAndRemoveSubordinateHostNameservers() throws Exception {
// Test that operations involving subordinate hosts as nameservers do not change the subordinate
// host relationship itself.
@ -404,7 +407,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(addedHost.getSuperordinateDomain()).isEqualTo(domain.createVKey());
}
@Test
@TestOfyAndSql
void testSuccess_registrantMovedToTechContact() throws Exception {
setEppInput("domain_update_registrant_to_tech.xml");
persistReferencedEntities();
@ -419,7 +422,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
runFlowAssertResponse(loadFile("generic_success_response.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_multipleReferencesToSameContactRemoved() throws Exception {
setEppInput("domain_update_remove_multiple_contacts.xml");
persistReferencedEntities();
@ -440,7 +443,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
runFlowAssertResponse(loadFile("generic_success_response.xml"));
}
@Test
@TestOfyAndSql
void testSuccess_removeClientUpdateProhibited() throws Exception {
persistReferencedEntities();
persistResource(
@ -488,7 +491,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertDnsTasksEnqueued("example.tld");
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAdd() throws Exception {
doSecDnsSuccessfulTest(
"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"));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAddPreservesExisting() throws Exception {
doSecDnsSuccessfulTest(
"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"));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAddSameDoesNothing() throws Exception {
doSecDnsSuccessfulTest(
"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"));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAddOnlyKeyTagRemainsSame() throws Exception {
doSecDnsSuccessfulTest(
"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
@Test
@TestOfyAndSql
void testSuccess_secDnsAddOnlyChangeKeyTag() throws Exception {
doSecDnsSuccessfulTest(
"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"));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAddOnlyChangeAlgorithm() throws Exception {
doSecDnsSuccessfulTest(
"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"));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAddOnlyChangeDigestType() throws Exception {
doSecDnsSuccessfulTest(
"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"));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAddOnlyChangeDigest() throws Exception {
doSecDnsSuccessfulTest(
"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"));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAddToMaxRecords() throws Exception {
ImmutableSet.Builder<DelegationSignerData> builder = new ImmutableSet.Builder<>();
for (int i = 0; i < 7; ++i) {
@ -587,7 +590,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
12346, 3, 1, base16().decode("38EC35D5B3A34B44C39B"))))));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsRemove() throws Exception {
doSecDnsSuccessfulTest(
"domain_update_dsdata_rem.xml",
@ -597,7 +600,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
ImmutableSet.of(SOME_DSDATA));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsRemoveAll() throws Exception {
// As an aside, this test also validates that it's ok to set the 'urgent' attribute to false.
doSecDnsSuccessfulTest(
@ -608,7 +611,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
ImmutableSet.of());
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAddRemove() throws Exception {
doSecDnsSuccessfulTest(
"domain_update_dsdata_add_rem.xml",
@ -620,7 +623,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
DelegationSignerData.create(12346, 3, 1, base16().decode("38EC35D5B3A34B44C39B"))));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAddRemoveToMaxRecords() throws Exception {
ImmutableSet.Builder<DelegationSignerData> builder = new ImmutableSet.Builder<>();
for (int i = 0; i < 7; ++i) {
@ -644,7 +647,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
12346, 3, 1, base16().decode("38EC35D5B3A34B44C39B"))))));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsAddRemoveSame() throws Exception {
// Adding and removing the same dsData is a no-op because removes are processed first.
doSecDnsSuccessfulTest(
@ -657,7 +660,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
DelegationSignerData.create(12345, 3, 1, base16().decode("38EC35D5B3A34B33C99B"))));
}
@Test
@TestOfyAndSql
void testSuccess_secDnsRemoveAlreadyNotThere() throws Exception {
// Removing a dsData that isn't there is a no-op.
doSecDnsSuccessfulTest(
@ -688,7 +691,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
}
}
@Test
@TestOfyAndSql
void testSuccess_addServerStatusBillingEvent() throws Exception {
eppRequestSource = EppRequestSource.TOOL;
persistReferencedEntities();
@ -696,7 +699,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doServerStatusBillingTest("domain_update_add_server_status.xml", true);
}
@Test
@TestOfyAndSql
void testSuccess_noBillingOnPreExistingServerStatus() throws Exception {
eppRequestSource = EppRequestSource.TOOL;
DomainBase addStatusDomain = persistActiveDomain(getUniqueIdFromCommand());
@ -705,7 +708,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doServerStatusBillingTest("domain_update_add_server_status.xml", false);
}
@Test
@TestOfyAndSql
void testSuccess_removeServerStatusBillingEvent() throws Exception {
eppRequestSource = EppRequestSource.TOOL;
persistReferencedEntities();
@ -715,7 +718,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doServerStatusBillingTest("domain_update_remove_server_status.xml", true);
}
@Test
@TestOfyAndSql
void testSuccess_changeServerStatusBillingEvent() throws Exception {
eppRequestSource = EppRequestSource.TOOL;
persistReferencedEntities();
@ -725,26 +728,26 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doServerStatusBillingTest("domain_update_change_server_status.xml", true);
}
@Test
@TestOfyAndSql
void testSuccess_noBillingEventOnNonServerStatusChange() throws Exception {
persistActiveDomain(getUniqueIdFromCommand());
doServerStatusBillingTest("domain_update_add_non_server_status.xml", false);
}
@Test
@TestOfyAndSql
void testSuccess_noBillingEventOnServerHoldStatusChange() throws Exception {
persistActiveDomain(getUniqueIdFromCommand());
doServerStatusBillingTest("domain_update_add_server_hold_status.xml", false);
}
@Test
@TestOfyAndSql
void testSuccess_noBillingEventOnServerStatusChangeNotFromRegistrar() throws Exception {
eppRequestSource = EppRequestSource.TOOL;
persistActiveDomain(getUniqueIdFromCommand());
doServerStatusBillingTest("domain_update_add_server_status_non_registrar.xml", false);
}
@Test
@TestOfyAndSql
void testSuccess_superuserClientUpdateProhibited() throws Exception {
setEppInput("domain_update_add_server_hold_status.xml");
persistReferencedEntities();
@ -772,29 +775,29 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_secDnsAllCannotBeFalse() throws Exception {
doSecDnsFailingTest(SecDnsAllUsageException.class, "domain_update_dsdata_rem_all_false.xml");
}
@Test
@TestOfyAndSql
void testFailure_secDnsEmptyNotAllowed() throws Exception {
doSecDnsFailingTest(EmptySecDnsUpdateException.class, "domain_update_dsdata_empty.xml");
}
@Test
@TestOfyAndSql
void testFailure_secDnsUrgentNotSupported() throws Exception {
doSecDnsFailingTest(
UrgentAttributeNotSupportedException.class, "domain_update_dsdata_urgent.xml");
}
@Test
@TestOfyAndSql
void testFailure_secDnsChangeNotSupported() throws Exception {
doSecDnsFailingTest(
MaxSigLifeChangeNotSupportedException.class, "domain_update_maxsiglife.xml");
}
@Test
@TestOfyAndSql
void testFailure_secDnsTooManyDsRecords() throws Exception {
ImmutableSet.Builder<DelegationSignerData> builder = new ImmutableSet.Builder<>();
for (int i = 0; i < 8; ++i) {
@ -808,7 +811,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_tooManyNameservers() throws Exception {
setEppInput("domain_update_add_nameserver.xml");
persistReferencedEntities();
@ -819,7 +822,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_wrongExtension() throws Exception {
setEppInput("domain_update_wrong_extension.xml");
persistReferencedEntities();
@ -828,7 +831,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_neverExisted() throws Exception {
persistReferencedEntities();
ResourceDoesNotExistException thrown =
@ -836,7 +839,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
}
@Test
@TestOfyAndSql
void testFailure_existedButWasDeleted() throws Exception {
persistReferencedEntities();
persistDeletedDomain(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1));
@ -845,7 +848,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains(String.format("(%s)", getUniqueIdFromCommand()));
}
@Test
@TestOfyAndSql
void testFailure_missingHost() throws Exception {
persistActiveHost("ns1.example.foo");
persistActiveContact("sh8013");
@ -856,7 +859,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("(ns2.example.foo)");
}
@Test
@TestOfyAndSql
void testFailure_missingContact() throws Exception {
persistActiveHost("ns1.example.foo");
persistActiveHost("ns2.example.foo");
@ -867,7 +870,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("(sh8013)");
}
@Test
@TestOfyAndSql
void testFailure_addingDuplicateContact() throws Exception {
persistReferencedEntities();
persistActiveContact("foo");
@ -892,7 +895,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
+ "role [tech] has contacts [foo, mak21]");
}
@Test
@TestOfyAndSql
void testFailure_statusValueNotClientSettable() throws Exception {
setEppInput("domain_update_prohibited_status.xml");
persistReferencedEntities();
@ -901,7 +904,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_superuserStatusValueNotClientSettable() throws Exception {
setEppInput("domain_update_prohibited_status.xml");
persistReferencedEntities();
@ -910,7 +913,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
}
@Test
@TestOfyAndSql
void testFailure_serverUpdateProhibited_prohibitsNonSuperuserUpdates() throws Exception {
persistReferencedEntities();
persistResource(
@ -922,7 +925,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(e).hasMessageThat().contains("serverUpdateProhibited");
}
@Test
@TestOfyAndSql
void testSuccess_serverUpdateProhibited_allowsSuperuserUpdates() throws Exception {
persistReferencedEntities();
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"));
}
@Test
@TestOfyAndSql
void testFailure_serverUpdateProhibited_notSettableWithoutSuperuser() throws Exception {
setEppInput("domain_update_add_registry_lock.xml");
persistReferencedEntities();
@ -940,7 +943,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(e).hasMessageThat().contains("serverUpdateProhibited");
}
@Test
@TestOfyAndSql
void testSuccess_serverUpdateProhibited_isSettableWithSuperuser() throws Exception {
setEppInput("domain_update_add_registry_lock.xml");
persistReferencedEntities();
@ -949,7 +952,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
}
@Test
@TestOfyAndSql
void testFailure_clientUpdateProhibited() throws Exception {
createTld("com");
setEppInput("domain_update_authinfo.xml");
@ -964,7 +967,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_serverUpdateProhibited() throws Exception {
persistReferencedEntities();
persistResource(
@ -977,7 +980,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("serverUpdateProhibited");
}
@Test
@TestOfyAndSql
void testFailure_pendingDelete() throws Exception {
persistReferencedEntities();
persistResource(
@ -991,7 +994,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("pendingDelete");
}
@Test
@TestOfyAndSql
void testFailure_duplicateContactInCommand() throws Exception {
setEppInput("domain_update_duplicate_contact.xml");
persistReferencedEntities();
@ -1000,7 +1003,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_multipleDuplicateContactInCommand() throws Exception {
setEppInput("domain_update_multiple_duplicate_contacts.xml");
persistReferencedEntities();
@ -1015,7 +1018,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_missingContactType() throws Exception {
// We need to test for missing type, but not for invalid - the schema enforces that for us.
setEppInput("domain_update_missing_contact_type.xml");
@ -1025,7 +1028,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_unauthorizedClient() throws Exception {
sessionMetadata.setClientId("NewRegistrar");
persistReferencedEntities();
@ -1034,7 +1037,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_superuserUnauthorizedClient() throws Exception {
sessionMetadata.setClientId("NewRegistrar");
persistReferencedEntities();
@ -1044,7 +1047,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
CommitMode.LIVE, UserPrivileges.SUPERUSER, loadFile("generic_success_response.xml"));
}
@Test
@TestOfyAndSql
void testFailure_notAuthorizedForTld() throws Exception {
persistResource(
loadRegistrar("TheRegistrar").asBuilder().setAllowedTlds(ImmutableSet.of()).build());
@ -1054,7 +1057,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_superuserNotAuthorizedForTld() throws Exception {
persistResource(
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"));
}
@Test
@TestOfyAndSql
void testFailure_sameNameserverAddedAndRemoved() throws Exception {
setEppInput("domain_update_add_remove_same_host.xml");
persistReferencedEntities();
@ -1082,7 +1085,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_sameContactAddedAndRemoved() throws Exception {
setEppInput("domain_update_add_remove_same_contact.xml");
persistReferencedEntities();
@ -1100,7 +1103,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_removeAdmin() throws Exception {
setEppInput("domain_update_remove_admin.xml");
persistReferencedEntities();
@ -1116,7 +1119,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_removeTech() throws Exception {
setEppInput("domain_update_remove_tech.xml");
persistReferencedEntities();
@ -1132,7 +1135,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_addPendingDeleteContact() throws Exception {
persistReferencedEntities();
persistDomain();
@ -1151,7 +1154,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("mak21");
}
@Test
@TestOfyAndSql
void testFailure_addPendingDeleteHost() throws Exception {
persistReferencedEntities();
persistDomain();
@ -1170,7 +1173,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(thrown).hasMessageThat().contains("ns2.example.foo");
}
@Test
@TestOfyAndSql
void testFailure_newRegistrantNotAllowListed() throws Exception {
persistReferencedEntities();
persistDomain();
@ -1184,7 +1187,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testFailure_addedNameserverDisallowedInTld() throws Exception {
persistReferencedEntities();
persistDomain();
@ -1199,7 +1202,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_newNameserverAllowListed() throws Exception {
setEppInput("domain_update_add_nameserver.xml");
persistReferencedEntities();
@ -1225,7 +1228,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.createVKey());
}
@Test
@TestOfyAndSql
void testSuccess_changeRegistrantAllowListed() throws Exception {
setEppInput("domain_update_registrant.xml");
persistReferencedEntities();
@ -1238,11 +1241,11 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.setAllowedFullyQualifiedHostNames(ImmutableSet.of("ns1.example.foo"))
.build());
runFlow();
assertThat(tm().loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
assertThat(loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
.isEqualTo("sh8013");
}
@Test
@TestOfyAndSql
void testSuccess_changeContactsAndRegistrant() throws Exception {
setEppInput("domain_update_contacts_and_registrant.xml");
persistReferencedEntities();
@ -1251,10 +1254,9 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
reloadResourceByForeignKey()
.getContacts()
.forEach(
contact -> {
assertThat(tm().loadByKey(contact.getContactKey()).getContactId()).isEqualTo("mak21");
});
assertThat(tm().loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
contact ->
assertThat(loadByKey(contact.getContactKey()).getContactId()).isEqualTo("mak21"));
assertThat(loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
.isEqualTo("mak21");
runFlow();
@ -1262,15 +1264,13 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
reloadResourceByForeignKey()
.getContacts()
.forEach(
contact -> {
assertThat(tm().loadByKey(contact.getContactKey()).getContactId())
.isEqualTo("sh8013");
});
assertThat(tm().loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
contact ->
assertThat(loadByKey(contact.getContactKey()).getContactId()).isEqualTo("sh8013"));
assertThat(loadByKey(reloadResourceByForeignKey().getRegistrant()).getContactId())
.isEqualTo("sh8013");
}
@Test
@TestOfyAndSql
void testSuccess_nameserverAndRegistrantAllowListed() throws Exception {
persistReferencedEntities();
persistDomain();
@ -1283,7 +1283,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
doSuccessfulTest();
}
@Test
@TestOfyAndSql
void testSuccess_tldWithNameserverAllowList_removeNameserver() throws Exception {
setEppInput("domain_update_remove_nameserver.xml");
persistReferencedEntities();
@ -1315,7 +1315,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
loadByForeignKey(HostResource.class, "ns1.example.foo", clock.nowUtc()).get()));
}
@Test
@TestOfyAndSql
void testFailure_tldWithNameserverAllowList_removeLastNameserver() throws Exception {
persistReferencedEntities();
persistDomain();
@ -1331,7 +1331,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testSuccess_domainCreateNotRestricted_doNotApplyServerProhibitedStatusCodes()
throws Exception {
persistReferencedEntities();
@ -1342,7 +1342,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.hasExactlyStatusValues(StatusValue.CLIENT_HOLD);
}
@Test
@TestOfyAndSql
void testFailure_freePremium_wrongFee() throws Exception {
setEppInput("domain_update_fee.xml", ImmutableMap.of("FEE_VERSION", "0.11"));
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
// zero.
@Test
@TestOfyAndSql
void testFailure_missingFeeOnNonFreeUpdate() throws Exception {
setEppInput("domain_update_wildcard.xml", ImmutableMap.of("DOMAIN", "non-free-update.tld"));
persistReferencedEntities();
@ -1363,7 +1363,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@Test
@TestOfyAndSql
void testIcannActivityReportField_getsLogged() throws Exception {
persistReferencedEntities();
persistDomain();
@ -1372,7 +1372,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertTldsFieldLogged("tld");
}
@Test
@TestOfyAndSql
void testSuperuserExtension_turnsOffAutorenew() throws Exception {
eppRequestSource = EppRequestSource.TOOL;
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);
}
@Test
@TestOfyAndSql
void testSuperuserExtension_turnsOnAutorenew() throws Exception {
eppRequestSource = EppRequestSource.TOOL;
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.Reason;
import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.model.domain.token.AllocationToken;
@ -59,8 +60,8 @@ public class BillingEventTest extends EntityTestCase {
super(JpaEntityCoverageCheck.ENABLED);
}
private HistoryEntry historyEntry;
private HistoryEntry historyEntry2;
private DomainHistory domainHistory;
private DomainHistory domainHistory2;
private DomainBase domain;
private BillingEvent.OneTime oneTime;
private BillingEvent.OneTime oneTimeSynthetic;
@ -73,26 +74,24 @@ public class BillingEventTest extends EntityTestCase {
void setUp() {
createTld("tld");
domain = persistActiveDomain("foo.tld");
historyEntry =
domainHistory =
persistResource(
new HistoryEntry.Builder()
.setParent(domain)
new DomainHistory.Builder()
.setDomainContent(domain)
.setModificationTime(now)
.setRequestedByRegistrar(false)
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setXmlBytes(new byte[0])
.build()
.toChildHistoryEntity());
historyEntry2 =
.build());
domainHistory2 =
persistResource(
new HistoryEntry.Builder()
.setParent(domain)
new DomainHistory.Builder()
.setDomainContent(domain)
.setModificationTime(now.plusDays(1))
.setRequestedByRegistrar(false)
.setType(HistoryEntry.Type.DOMAIN_CREATE)
.setXmlBytes(new byte[0])
.build()
.toChildHistoryEntity());
.build());
AllocationToken allocationToken =
persistResource(
@ -112,7 +111,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource(
commonInit(
new BillingEvent.OneTime.Builder()
.setParent(historyEntry)
.setParent(domainHistory)
.setReason(Reason.CREATE)
.setFlags(ImmutableSet.of(BillingEvent.Flag.ANCHOR_TENANT))
.setPeriodYears(2)
@ -125,7 +124,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource(
commonInit(
new BillingEvent.Recurring.Builder()
.setParent(historyEntry)
.setParent(domainHistory)
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
.setReason(Reason.RENEW)
.setEventTime(now.plusYears(1))
@ -134,7 +133,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource(
commonInit(
new BillingEvent.OneTime.Builder()
.setParent(historyEntry)
.setParent(domainHistory)
.setReason(Reason.CREATE)
.setFlags(
ImmutableSet.of(
@ -150,7 +149,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource(
commonInit(
new BillingEvent.Cancellation.Builder()
.setParent(historyEntry2)
.setParent(domainHistory2)
.setReason(Reason.CREATE)
.setEventTime(now.plusDays(1))
.setBillingTime(now.plusDays(5))
@ -160,7 +159,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource(
commonInit(
new BillingEvent.Cancellation.Builder()
.setParent(historyEntry2)
.setParent(domainHistory2)
.setReason(Reason.RENEW)
.setEventTime(now.plusDays(1))
.setBillingTime(now.plusYears(1).plusDays(45))
@ -171,7 +170,7 @@ public class BillingEventTest extends EntityTestCase {
persistResource(
commonInit(
new BillingEvent.Modification.Builder()
.setParent(historyEntry2)
.setParent(domainHistory2)
.setReason(Reason.CREATE)
.setCost(Money.of(USD, 1))
.setDescription("Something happened")
@ -206,13 +205,13 @@ public class BillingEventTest extends EntityTestCase {
.containsExactly(cancellationOneTime, cancellationRecurring);
assertThat(ofy().load().type(BillingEvent.Modification.class).ancestor(domain).list())
.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);
assertThat(ofy().load().type(BillingEvent.Recurring.class).ancestor(historyEntry).list())
assertThat(ofy().load().type(BillingEvent.Recurring.class).ancestor(domainHistory).list())
.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);
assertThat(ofy().load().type(BillingEvent.Modification.class).ancestor(historyEntry2).list())
assertThat(ofy().load().type(BillingEvent.Modification.class).ancestor(domainHistory2).list())
.containsExactly(modification);
}
@ -311,7 +310,8 @@ public class BillingEventTest extends EntityTestCase {
BillingEvent.Cancellation newCancellation =
BillingEvent.Cancellation.forGracePeriod(
GracePeriod.forBillingEvent(GracePeriodStatus.ADD, domain.getRepoId(), oneTime),
historyEntry2,
domainHistory2.getModificationTime(),
Key.create(domainHistory2),
"foo.tld");
// Set ID to be the same to ignore for the purposes of comparison.
assertThat(newCancellation.asBuilder().setId(cancellationOneTime.getId()).build())
@ -328,7 +328,8 @@ public class BillingEventTest extends EntityTestCase {
now.plusYears(1).plusDays(45),
"TheRegistrar",
recurring.createVKey()),
historyEntry2,
domainHistory2.getModificationTime(),
Key.create(domainHistory2),
"foo.tld");
// Set ID to be the same to ignore for the purposes of comparison.
assertThat(newCancellation.asBuilder().setId(cancellationRecurring.getId()).build())
@ -347,7 +348,8 @@ public class BillingEventTest extends EntityTestCase {
domain.getRepoId(),
now.plusDays(1),
"a registrar"),
historyEntry,
domainHistory.getModificationTime(),
Key.create(domainHistory),
"foo.tld"));
assertThat(thrown).hasMessageThat().contains("grace period without billing event");
}
@ -382,7 +384,7 @@ public class BillingEventTest extends EntityTestCase {
@TestOfyAndSql
void testDeadCodeThatDeletedScrapCommandsReference() {
assertThat(recurring.getParentKey()).isEqualTo(Key.create(historyEntry));
new BillingEvent.OneTime.Builder().setParent(Key.create(historyEntry));
assertThat(recurring.getParentKey()).isEqualTo(Key.create(domainHistory));
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 java.util.Arrays.asList;
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.Splitter;
@ -73,8 +72,6 @@ import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason;
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.domain.DesignatedContact;
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.StatusValue;
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.index.EppResourceIndex;
import google.registry.model.index.EppResourceIndexBucket;
@ -117,7 +112,6 @@ import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import google.registry.tmch.LordnTaskUtils;
import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
@ -1127,29 +1121,7 @@ public class DatabaseHelper {
/** Returns all of the history entries that are parented off the given EppResource. */
public static List<? extends HistoryEntry> getHistoryEntries(EppResource resource) {
return tm().isOfy()
? 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);
});
return HistoryEntryDao.loadHistoryObjectsForResource(resource.createVKey());
}
/**

View file

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

View file

@ -3,7 +3,7 @@
<result code="1301">
<msg>Command completed successfully; ack to dequeue</msg>
</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>
<msg>Domain example.tld was unrenewed by 3 years; now expires at 2003-06-01T00:02:00.000Z.</msg>
</msgQ>

View file

@ -6,7 +6,7 @@ class google.registry.model.UpdateAutoTimestamp {
}
class google.registry.model.billing.BillingEvent$Cancellation {
@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.persistence.BillingVKey$BillingEventVKey refOneTime;
google.registry.persistence.BillingVKey$BillingRecurrenceVKey refRecurring;
@ -27,7 +27,7 @@ enum google.registry.model.billing.BillingEvent$Flag {
}
class google.registry.model.billing.BillingEvent$Modification {
@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;
google.registry.model.billing.BillingEvent$Reason reason;
java.lang.String clientId;
@ -39,7 +39,7 @@ class google.registry.model.billing.BillingEvent$Modification {
}
class google.registry.model.billing.BillingEvent$OneTime {
@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.persistence.VKey<google.registry.model.billing.BillingEvent$Recurring> cancellationMatchingBillingEvent;
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 {
@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.common.TimeOfYear recurrenceTimeOfYear;
java.lang.String clientId;