mirror of
https://github.com/google/nomulus.git
synced 2025-04-29 19:47:51 +02:00
Remove ofy support from PollMessage (#1732)
Also deletes the autorenew poll message history revision id field in Domain, which is only needed to recreate the ofy key for the poll message. The column already contains null values in it, making it impossible to depend on it. The column itself will be deleted from the schema after this PR is deployed. The logic to update autorenew recurrence end time is changed accordingly: When a poll message already exists, we simply update the endtime, but when it no longer exists, i. e. when it's deleted speculatively after a transfer request, we recreate one using the history entry id that resulted in its creation (e. g. cancelled or rejected transfer). This should fix b/240984498. Though the exact reason for that bug is still unclear to me. Namely, it throws an NPE at this line during an explicit domain transfer approval: https://cs.opensource.google/nomulus/nomulus/+/master:core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java;l=603;bpv=1;bpt=0;drc=ede919d7dcdb7f209b074563b3d449ebee19118a The domain in question has a null autorenewPollMessageHistoryId, but that in itself should not have caused an NPE because we are not operating on the null pointer. On that line the only possible way to throw an NPE is for the domain itself to be null, but if that were the case, the NPE would have been thrown at line 599 where we called a method on the domain object. Regardless of the cause, with this PR we are using an explicitly provided history id and checking for its nullness before using it. If a similar issue arises again, we should have a better idea why. Lastly, the way poll message id is constructed is largely simplified in PollMessageExternalKeyConverter as a result of the removal ofy parent keys in PollMessage. This does present a possibility of failure when immediately before deployment, a registrar requests a poll message and received the old id, but by the time the registrar acks the id, the new version is deployed and therefore does not recognize the old key. The likelihood of this happening should be slim, and we could have prevented it by letting the converter recognize both the old and the new key. However, we would like to eventually phase out the old key, and in theory a registrar could ack a poll message at any time after it was requested. So, there is not a safe time by which all the old ids are acked, lest we develop some elaborate scheme to keep track of which messages were sent with an old id when requested and which of these old ids are acked. Only then can we be truly safe to phase out the old id. The benefit does not seem to warrant the effort. If a registrar does encounter a situation like this, they could open a support bug to have us manually ack the poll message for them.
This commit is contained in:
parent
aea98f4bc3
commit
cfa5699cc3
46 changed files with 188 additions and 512 deletions
|
@ -377,8 +377,7 @@ public final class DomainCreateFlow implements TransactionalFlow {
|
|||
.setIdnTableName(validateDomainNameWithIdnTables(domainName))
|
||||
.setRegistrationExpirationTime(registrationExpirationTime)
|
||||
.setAutorenewBillingEvent(autorenewBillingEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
|
||||
.setLaunchNotice(hasClaimsNotice ? launchCreate.get().getNotice() : null)
|
||||
.setSmdId(signedMarkId)
|
||||
.setDsData(secDnsCreate.map(SecDnsCreateExtension::getDsData).orElse(null))
|
||||
|
|
|
@ -263,7 +263,8 @@ public final class DomainDeleteFlow implements TransactionalFlow {
|
|||
// the updated recurring billing event, we'll need it later and can't reload it.
|
||||
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
|
||||
BillingEvent.Recurring recurringBillingEvent =
|
||||
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now);
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain, existingRecurring, now, domainHistory.getDomainHistoryId());
|
||||
// If there's a pending transfer, the gaining client's autorenew billing
|
||||
// event and poll message will already have been deleted in
|
||||
// ResourceDeleteFlow since it's listed in serverApproveEntities.
|
||||
|
|
|
@ -591,7 +591,10 @@ public class DomainFlowUtils {
|
|||
* <p>Returns the new autorenew recurring billing event.
|
||||
*/
|
||||
public static Recurring updateAutorenewRecurrenceEndTime(
|
||||
Domain domain, Recurring existingRecurring, DateTime newEndTime) {
|
||||
Domain domain,
|
||||
Recurring existingRecurring,
|
||||
DateTime newEndTime,
|
||||
@Nullable DomainHistoryId historyId) {
|
||||
Optional<PollMessage.Autorenew> autorenewPollMessage =
|
||||
tm().loadByKeyIfPresent(domain.getAutorenewPollMessage());
|
||||
|
||||
|
@ -599,20 +602,25 @@ public class DomainFlowUtils {
|
|||
// create a new one at the same id. This can happen if a transfer was requested on a domain
|
||||
// where all autorenew poll messages had already been delivered (this would cause the poll
|
||||
// message to be deleted), and then subsequently the transfer was canceled, rejected, or deleted
|
||||
// (which would cause the poll message to be recreated here).
|
||||
PollMessage.Autorenew updatedAutorenewPollMessage =
|
||||
autorenewPollMessage.isPresent()
|
||||
? autorenewPollMessage.get().asBuilder().setAutorenewEndTime(newEndTime).build()
|
||||
: newAutorenewPollMessage(domain)
|
||||
.setId((Long) domain.getAutorenewPollMessage().getSqlKey())
|
||||
.setAutorenewEndTime(newEndTime)
|
||||
.setDomainHistoryId(
|
||||
new DomainHistoryId(
|
||||
domain.getRepoId(), domain.getAutorenewPollMessageHistoryId()))
|
||||
.build();
|
||||
// (which would cause the poll message to be recreated here). In the latter case, the history id
|
||||
// of the event that created the new poll message will also be used.
|
||||
PollMessage.Autorenew updatedAutorenewPollMessage;
|
||||
if (autorenewPollMessage.isPresent()) {
|
||||
updatedAutorenewPollMessage =
|
||||
autorenewPollMessage.get().asBuilder().setAutorenewEndTime(newEndTime).build();
|
||||
} else {
|
||||
checkNotNull(
|
||||
historyId, "Cannot create a new autorenew poll message without a domain history id");
|
||||
updatedAutorenewPollMessage =
|
||||
newAutorenewPollMessage(domain)
|
||||
.setId((Long) domain.getAutorenewPollMessage().getSqlKey())
|
||||
.setAutorenewEndTime(newEndTime)
|
||||
.setDomainHistoryId(historyId)
|
||||
.build();
|
||||
}
|
||||
|
||||
// If the resultant autorenew poll message would have no poll messages to deliver, then just
|
||||
// delete it. Otherwise save it with the new end time.
|
||||
// delete it. Otherwise, save it with the new end time.
|
||||
if (isAtOrAfter(updatedAutorenewPollMessage.getEventTime(), newEndTime)) {
|
||||
autorenewPollMessage.ifPresent(autorenew -> tm().delete(autorenew));
|
||||
} else {
|
||||
|
|
|
@ -223,7 +223,11 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
|||
.build();
|
||||
// End the old autorenew billing event and poll message now. This may delete the poll message.
|
||||
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
|
||||
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now);
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain,
|
||||
existingRecurring,
|
||||
now,
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()));
|
||||
Domain newDomain =
|
||||
existingDomain
|
||||
.asBuilder()
|
||||
|
@ -231,9 +235,7 @@ public final class DomainRenewFlow implements TransactionalFlow {
|
|||
.setLastEppUpdateRegistrarId(registrarId)
|
||||
.setRegistrationExpirationTime(newExpirationTime)
|
||||
.setAutorenewBillingEvent(newAutorenewEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
newAutorenewPollMessage.createVKey(),
|
||||
newAutorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(newAutorenewPollMessage.createVKey())
|
||||
.addGracePeriod(
|
||||
GracePeriod.forBillingEvent(
|
||||
GracePeriodStatus.RENEW, existingDomain.getRepoId(), explicitRenewEvent))
|
||||
|
|
|
@ -251,8 +251,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
|
|||
.setGracePeriods(null)
|
||||
.setDeletePollMessage(null)
|
||||
.setAutorenewBillingEvent(autorenewEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
|
||||
// Clear the autorenew end time so if it had expired but is now explicitly being restored,
|
||||
// it won't immediately be deleted again.
|
||||
.setAutorenewEndTime(Optional.empty())
|
||||
|
|
|
@ -194,7 +194,11 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
|||
}
|
||||
// Close the old autorenew event and poll message at the transfer time (aka now). This may end
|
||||
// up deleting the poll message.
|
||||
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, now);
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain,
|
||||
existingRecurring,
|
||||
now,
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()));
|
||||
DateTime newExpirationTime =
|
||||
computeExDateForApprovalTime(existingDomain, now, transferData.getTransferPeriod());
|
||||
// Create a new autorenew event starting at the expiration time.
|
||||
|
@ -240,9 +244,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
|
|||
.build())
|
||||
.setRegistrationExpirationTime(newExpirationTime)
|
||||
.setAutorenewBillingEvent(autorenewEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
gainingClientAutorenewPollMessage.createVKey(),
|
||||
gainingClientAutorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(gainingClientAutorenewPollMessage.createVKey())
|
||||
// Remove all the old grace periods and add a new one for the transfer.
|
||||
.setGracePeriods(
|
||||
billingEvent
|
||||
|
|
|
@ -116,7 +116,8 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
|
|||
// 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.
|
||||
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
|
||||
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, END_OF_TIME);
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain, existingRecurring, END_OF_TIME, domainHistory.getDomainHistoryId());
|
||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||
// been implicitly server approved.
|
||||
tm().delete(existingDomain.getTransferData().getServerApproveEntities());
|
||||
|
|
|
@ -117,7 +117,8 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
|
|||
// 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.
|
||||
Recurring existingRecurring = tm().loadByKey(existingDomain.getAutorenewBillingEvent());
|
||||
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, END_OF_TIME);
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain, existingRecurring, END_OF_TIME, domainHistory.getDomainHistoryId());
|
||||
// Delete the billing event and poll messages that were written in case the transfer would have
|
||||
// been implicitly server approved.
|
||||
tm().delete(existingDomain.getTransferData().getServerApproveEntities());
|
||||
|
|
|
@ -57,6 +57,7 @@ import google.registry.model.billing.BillingEvent.Recurring;
|
|||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.DomainCommand.Transfer;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.DomainHistory.DomainHistoryId;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.domain.fee.FeeTransferCommandExtension;
|
||||
import google.registry.model.domain.fee.FeeTransformResponseExtension;
|
||||
|
@ -260,7 +261,11 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
|
|||
// 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
|
||||
// that we've created in this flow and stored in pendingTransferData.
|
||||
updateAutorenewRecurrenceEndTime(existingDomain, existingRecurring, automaticTransferTime);
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
existingDomain,
|
||||
existingRecurring,
|
||||
automaticTransferTime,
|
||||
new DomainHistoryId(domainHistoryKey.getParent().getName(), domainHistoryKey.getId()));
|
||||
Domain newDomain =
|
||||
existingDomain
|
||||
.asBuilder()
|
||||
|
|
|
@ -28,7 +28,6 @@ import google.registry.model.host.HostHistory;
|
|||
import google.registry.model.index.EppResourceIndex;
|
||||
import google.registry.model.index.EppResourceIndexBucket;
|
||||
import google.registry.model.index.ForeignKeyIndex;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.rde.RdeRevision;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
|
@ -58,9 +57,6 @@ public final class EntityClasses {
|
|||
Host.class,
|
||||
HostHistory.class,
|
||||
Lock.class,
|
||||
PollMessage.class,
|
||||
PollMessage.Autorenew.class,
|
||||
PollMessage.OneTime.class,
|
||||
RdeRevision.class,
|
||||
Registrar.class,
|
||||
ServerSecret.class);
|
||||
|
|
|
@ -90,13 +90,13 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
|
|||
@Access(AccessType.PROPERTY)
|
||||
@Column(name = "host_repo_id")
|
||||
public Set<VKey<Host>> getNsHosts() {
|
||||
return super.nsHosts;
|
||||
return nsHosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of {@link GracePeriod} associated with the domain.
|
||||
*
|
||||
* <p>This is the getter method specific for Hibernate to access the field so it is set to
|
||||
* <p>This is the getter method specific for Hibernate to access the field, so it is set to
|
||||
* private. The caller can use the public {@link #getGracePeriods()} to get the grace periods.
|
||||
*
|
||||
* <p>Note that we need to set `insertable = false, updatable = false` for @JoinColumn, otherwise
|
||||
|
@ -104,10 +104,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
|
|||
* deleting the whole entry from the table when the {@link GracePeriod} is removed from the set.
|
||||
*/
|
||||
@Access(AccessType.PROPERTY)
|
||||
@OneToMany(
|
||||
cascade = {CascadeType.ALL},
|
||||
fetch = FetchType.EAGER,
|
||||
orphanRemoval = true)
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
|
||||
@JoinColumn(
|
||||
name = "domainRepoId",
|
||||
referencedColumnName = "repoId",
|
||||
|
@ -121,7 +118,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
|
|||
/**
|
||||
* Returns the set of {@link DelegationSignerData} associated with the domain.
|
||||
*
|
||||
* <p>This is the getter method specific for Hibernate to access the field so it is set to
|
||||
* <p>This is the getter method specific for Hibernate to access the field, so it is set to
|
||||
* private. The caller can use the public {@link #getDsData()} to get the DS data.
|
||||
*
|
||||
* <p>Note that we need to set `insertable = false, updatable = false` for @JoinColumn, otherwise
|
||||
|
@ -130,10 +127,7 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
|
|||
* the set.
|
||||
*/
|
||||
@Access(AccessType.PROPERTY)
|
||||
@OneToMany(
|
||||
cascade = {CascadeType.ALL},
|
||||
fetch = FetchType.EAGER,
|
||||
orphanRemoval = true)
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
|
||||
@JoinColumn(
|
||||
name = "domainRepoId",
|
||||
referencedColumnName = "repoId",
|
||||
|
@ -182,10 +176,9 @@ public class Domain extends DomainBase implements ForeignKeyedEppResource {
|
|||
}
|
||||
|
||||
public Builder copyFrom(DomainBase domainBase) {
|
||||
this.getInstance().copyUpdateTimestamp(domainBase);
|
||||
return this.setAuthInfo(domainBase.getAuthInfo())
|
||||
.setAutorenewPollMessage(
|
||||
domainBase.getAutorenewPollMessage(), domainBase.getAutorenewPollMessageHistoryId())
|
||||
getInstance().copyUpdateTimestamp(domainBase);
|
||||
return setAuthInfo(domainBase.getAuthInfo())
|
||||
.setAutorenewPollMessage(domainBase.getAutorenewPollMessage())
|
||||
.setAutorenewBillingEvent(domainBase.getAutorenewBillingEvent())
|
||||
.setAutorenewEndTime(domainBase.getAutorenewEndTime())
|
||||
.setContacts(domainBase.getContacts())
|
||||
|
|
|
@ -216,13 +216,6 @@ public class DomainBase extends EppResource
|
|||
@Column(name = "autorenew_poll_message_id")
|
||||
VKey<PollMessage.Autorenew> autorenewPollMessage;
|
||||
|
||||
/**
|
||||
* History record for the autorenew poll message.
|
||||
*
|
||||
* <p>Here so we can restore the original ofy key from sql.
|
||||
*/
|
||||
@Ignore Long autorenewPollMessageHistoryId;
|
||||
|
||||
/** The unexpired grace periods for this domain (some of which may not be active yet). */
|
||||
@Transient Set<GracePeriod> gracePeriods;
|
||||
|
||||
|
@ -322,10 +315,6 @@ public class DomainBase extends EppResource
|
|||
return autorenewPollMessage;
|
||||
}
|
||||
|
||||
public Long getAutorenewPollMessageHistoryId() {
|
||||
return autorenewPollMessageHistoryId;
|
||||
}
|
||||
|
||||
public ImmutableSet<GracePeriod> getGracePeriods() {
|
||||
return nullToEmptyImmutableCopy(gracePeriods);
|
||||
}
|
||||
|
@ -509,9 +498,7 @@ public class DomainBase extends EppResource
|
|||
// Set the speculatively-written new autorenew events as the domain's autorenew
|
||||
// events.
|
||||
.setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent())
|
||||
.setAutorenewPollMessage(
|
||||
transferData.getServerApproveAutorenewPollMessage(),
|
||||
transferData.getServerApproveAutorenewPollMessageHistoryId());
|
||||
.setAutorenewPollMessage(transferData.getServerApproveAutorenewPollMessage());
|
||||
if (transferData.getTransferPeriod().getValue() == 1) {
|
||||
// Set the grace period using a key to the prescheduled transfer billing event. Not using
|
||||
// GracePeriod.forBillingEvent() here in order to avoid the actual Datastore fetch.
|
||||
|
@ -886,11 +873,8 @@ public class DomainBase extends EppResource
|
|||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
public B setAutorenewPollMessage(
|
||||
@Nullable VKey<PollMessage.Autorenew> autorenewPollMessage,
|
||||
@Nullable Long autorenewPollMessageHistoryId) {
|
||||
public B setAutorenewPollMessage(@Nullable VKey<PollMessage.Autorenew> autorenewPollMessage) {
|
||||
getInstance().autorenewPollMessage = autorenewPollMessage;
|
||||
getInstance().autorenewPollMessageHistoryId = autorenewPollMessageHistoryId;
|
||||
return thisCastToDerived();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,18 +20,12 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
|||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.annotation.Entity;
|
||||
import com.googlecode.objectify.annotation.EntitySubclass;
|
||||
import com.googlecode.objectify.annotation.Id;
|
||||
import com.googlecode.objectify.annotation.Ignore;
|
||||
import com.googlecode.objectify.annotation.Index;
|
||||
import google.registry.model.Buildable;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.UnsafeSerializable;
|
||||
import google.registry.model.annotations.ExternalMessagingName;
|
||||
import google.registry.model.annotations.ReportedOn;
|
||||
import google.registry.model.annotations.OfyIdAllocation;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactHistory.ContactHistoryId;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
|
@ -55,16 +49,19 @@ import google.registry.persistence.VKey;
|
|||
import google.registry.persistence.WithLongVKey;
|
||||
import google.registry.util.NullIgnoringCollectionBuilder;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.persistence.AttributeOverride;
|
||||
import javax.persistence.AttributeOverrides;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.InheritanceType;
|
||||
import javax.persistence.PostLoad;
|
||||
import javax.persistence.Table;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
|
@ -76,10 +73,10 @@ import org.joda.time.DateTime;
|
|||
* retained for historical purposes, poll messages are truly deleted once they have been delivered
|
||||
* and ACKed.
|
||||
*
|
||||
* <p>Poll messages are parented off of the {@link HistoryEntry} that resulted in their creation.
|
||||
* This means that poll messages are contained in the Datastore entity group of the parent {@link
|
||||
* EppResource} (which can be a domain, contact, or host). It is thus possible to perform a strongly
|
||||
* consistent query to find all poll messages associated with a given EPP resource.
|
||||
* <p>Poll messages have a reference to the revision id of the {@link HistoryEntry} that resulted in
|
||||
* their creation or re-creation, in case of transfer cancellation/rejection. The revision ids are
|
||||
* not used directly by the Java code, but their presence in the database makes it easier to
|
||||
* diagnose potential issues related to poll messages.
|
||||
*
|
||||
* <p>Poll messages are identified externally by registrars using the format defined in {@link
|
||||
* PollMessageExternalKeyConverter}.
|
||||
|
@ -88,16 +85,10 @@ import org.joda.time.DateTime;
|
|||
* Command</a>
|
||||
*/
|
||||
@Entity
|
||||
@ReportedOn
|
||||
@ExternalMessagingName("message")
|
||||
@javax.persistence.Entity
|
||||
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
|
||||
@DiscriminatorColumn(name = "type")
|
||||
@javax.persistence.Table(
|
||||
indexes = {
|
||||
@javax.persistence.Index(columnList = "registrar_id"),
|
||||
@javax.persistence.Index(columnList = "eventTime")
|
||||
})
|
||||
@Table(indexes = {@Index(columnList = "registrar_id"), @Index(columnList = "eventTime")})
|
||||
public abstract class PollMessage extends ImmutableObject
|
||||
implements Buildable, TransferServerApproveEntity, UnsafeSerializable {
|
||||
|
||||
|
@ -108,9 +99,9 @@ public abstract class PollMessage extends ImmutableObject
|
|||
HOST(3L, Host.class);
|
||||
|
||||
private final long id;
|
||||
private final Class<?> clazz;
|
||||
private final Class<? extends EppResource> clazz;
|
||||
|
||||
Type(long id, Class<?> clazz) {
|
||||
Type(long id, Class<? extends EppResource> clazz) {
|
||||
this.id = id;
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
@ -124,58 +115,40 @@ public abstract class PollMessage extends ImmutableObject
|
|||
}
|
||||
|
||||
/** Returns the class of the underlying resource for the poll message type. */
|
||||
public Class<?> getResourceClass() {
|
||||
public Class<? extends EppResource> getResourceClass() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type specified by the identifer, {@code Optional.empty()} if the id is out of
|
||||
* range.
|
||||
*/
|
||||
public static Optional<Type> fromId(long id) {
|
||||
for (Type val : values()) {
|
||||
if (val.id == id) {
|
||||
return Optional.of(val);
|
||||
}
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/** Entity id. */
|
||||
@Id
|
||||
@javax.persistence.Id
|
||||
@OfyIdAllocation
|
||||
@Column(name = "poll_message_id")
|
||||
Long id;
|
||||
|
||||
/** The registrar that this poll message will be delivered to. */
|
||||
@Index
|
||||
@Column(name = "registrar_id", nullable = false)
|
||||
String clientId;
|
||||
|
||||
/** The time when the poll message should be delivered. May be in the future. */
|
||||
@Index
|
||||
@Column(nullable = false)
|
||||
DateTime eventTime;
|
||||
|
||||
/** Human readable message that will be returned with this poll message. */
|
||||
/** Human-readable message that will be returned with this poll message. */
|
||||
@Column(name = "message")
|
||||
String msg;
|
||||
|
||||
// TODO(b/456803336): Replace these fields with {Domain,Contact,Host}HistoryId objects.
|
||||
String domainRepoId;
|
||||
|
||||
@Ignore String domainRepoId;
|
||||
String contactRepoId;
|
||||
|
||||
@Ignore String contactRepoId;
|
||||
String hostRepoId;
|
||||
|
||||
@Ignore String hostRepoId;
|
||||
Long domainHistoryRevisionId;
|
||||
|
||||
@Ignore Long domainHistoryRevisionId;
|
||||
Long contactHistoryRevisionId;
|
||||
|
||||
@Ignore Long contactHistoryRevisionId;
|
||||
|
||||
@Ignore Long hostHistoryRevisionId;
|
||||
Long hostHistoryRevisionId;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
|
@ -228,32 +201,22 @@ public abstract class PollMessage extends ImmutableObject
|
|||
* the resource.
|
||||
*/
|
||||
public String getResourceName() {
|
||||
return domainRepoId != null
|
||||
? domainRepoId
|
||||
: (contactRepoId != null ? contactRepoId : hostRepoId);
|
||||
return domainRepoId != null ? domainRepoId : contactRepoId != null ? contactRepoId : hostRepoId;
|
||||
}
|
||||
|
||||
/** Gets the underlying history revision id, regardless of the type of the resource. */
|
||||
public Long getHistoryRevisionId() {
|
||||
return domainHistoryRevisionId != null
|
||||
? domainHistoryRevisionId
|
||||
: (contactHistoryRevisionId != null ? contactHistoryRevisionId : hostHistoryRevisionId);
|
||||
: contactHistoryRevisionId != null ? contactHistoryRevisionId : hostHistoryRevisionId;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return domainRepoId != null ? Type.DOMAIN : (contactRepoId != null ? Type.CONTACT : Type.HOST);
|
||||
return domainRepoId != null ? Type.DOMAIN : contactRepoId != null ? Type.CONTACT : Type.HOST;
|
||||
}
|
||||
|
||||
public abstract ImmutableList<ResponseData> getResponseData();
|
||||
|
||||
@Override
|
||||
public abstract VKey<? extends PollMessage> createVKey();
|
||||
|
||||
/** Static VKey factory method for use by VKeyTranslatorFactory. */
|
||||
public static VKey<PollMessage> createVKey(Key<PollMessage> key) {
|
||||
return VKey.create(PollMessage.class, key.getId(), key);
|
||||
}
|
||||
|
||||
/** Override Buildable.asBuilder() to give this method stronger typing. */
|
||||
@Override
|
||||
public abstract Builder<?, ?> asBuilder();
|
||||
|
@ -318,9 +281,11 @@ public abstract class PollMessage extends ImmutableObject
|
|||
// Set the appropriate field based on the history entry type.
|
||||
if (history instanceof DomainHistory) {
|
||||
return setDomainHistoryId(((DomainHistory) history).getDomainHistoryId());
|
||||
} else if (history instanceof ContactHistory) {
|
||||
}
|
||||
if (history instanceof ContactHistory) {
|
||||
return setContactHistoryId(((ContactHistory) history).getContactHistoryId());
|
||||
} else if (history instanceof HostHistory) {
|
||||
}
|
||||
if (history instanceof HostHistory) {
|
||||
return setHostHistoryId(((HostHistory) history).getHostHistoryId());
|
||||
}
|
||||
return thisCastToDerived();
|
||||
|
@ -330,7 +295,7 @@ public abstract class PollMessage extends ImmutableObject
|
|||
* Given an array containing pairs of objects, verifies that both members of exactly one of the
|
||||
* pairs is non-null.
|
||||
*/
|
||||
private boolean exactlyOnePairNonNull(Object... pairs) {
|
||||
private static boolean exactlyOnePairNonNull(Object... pairs) {
|
||||
int count = 0;
|
||||
checkArgument(pairs.length % 2 == 0, "Odd number of arguments provided.");
|
||||
for (int i = 0; i < pairs.length; i += 2) {
|
||||
|
@ -360,9 +325,9 @@ public abstract class PollMessage extends ImmutableObject
|
|||
instance.contactHistoryRevisionId,
|
||||
instance.hostRepoId,
|
||||
instance.hostHistoryRevisionId),
|
||||
"the repo id and history revision id must be defined for exactly one of domain, "
|
||||
+ "contact or host: "
|
||||
+ instance);
|
||||
"The repo id and history revision id must be defined for exactly one of domain, "
|
||||
+ "contact or host: %s",
|
||||
instance);
|
||||
return super.build();
|
||||
}
|
||||
}
|
||||
|
@ -372,13 +337,11 @@ public abstract class PollMessage extends ImmutableObject
|
|||
*
|
||||
* <p>One-time poll messages are deleted from Datastore once they have been delivered and ACKed.
|
||||
*/
|
||||
@EntitySubclass(index = false)
|
||||
@javax.persistence.Entity
|
||||
@Entity
|
||||
@DiscriminatorValue("ONE_TIME")
|
||||
@WithLongVKey(compositeKey = true)
|
||||
public static class OneTime extends PollMessage {
|
||||
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(
|
||||
|
@ -399,7 +362,6 @@ public abstract class PollMessage extends ImmutableObject
|
|||
})
|
||||
PendingActionNotificationResponse pendingActionNotificationResponse;
|
||||
|
||||
@Ignore
|
||||
@Embedded
|
||||
@AttributeOverrides({
|
||||
@AttributeOverride(
|
||||
|
@ -420,35 +382,21 @@ public abstract class PollMessage extends ImmutableObject
|
|||
})
|
||||
TransferResponse transferResponse;
|
||||
|
||||
@Ignore
|
||||
@Column(name = "transfer_response_domain_name")
|
||||
String fullyQualifiedDomainName;
|
||||
|
||||
@Ignore
|
||||
@Column(name = "transfer_response_domain_expiration_time")
|
||||
DateTime extendedRegistrationExpirationTime;
|
||||
|
||||
@Ignore
|
||||
@Column(name = "transfer_response_contact_id")
|
||||
String contactId;
|
||||
|
||||
@Ignore
|
||||
@Column(name = "transfer_response_host_id")
|
||||
String hostId;
|
||||
|
||||
@Override
|
||||
public VKey<OneTime> createVKey() {
|
||||
return VKey.create(OneTime.class, getId(), Key.create(this));
|
||||
}
|
||||
|
||||
/** Converts an unspecialized VKey<PollMessage> to a VKey of the derived class. */
|
||||
public static @Nullable VKey<OneTime> convertVKey(@Nullable VKey<? extends PollMessage> key) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
Key<OneTime> ofyKey =
|
||||
Key.create(key.getOfyKey().getParent(), OneTime.class, key.getOfyKey().getId());
|
||||
return VKey.create(OneTime.class, key.getSqlKey(), ofyKey);
|
||||
return VKey.createSql(OneTime.class, getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -525,8 +473,7 @@ public abstract class PollMessage extends ImmutableObject
|
|||
/** A builder for {@link OneTime} since it is immutable. */
|
||||
public static class Builder extends PollMessage.Builder<OneTime, Builder> {
|
||||
|
||||
public Builder() {
|
||||
}
|
||||
public Builder() {}
|
||||
|
||||
private Builder(OneTime instance) {
|
||||
super(instance);
|
||||
|
@ -587,14 +534,13 @@ public abstract class PollMessage extends ImmutableObject
|
|||
}
|
||||
|
||||
/**
|
||||
* An auto-renew poll message which recurs annually.
|
||||
* An autorenew poll message which recurs annually.
|
||||
*
|
||||
* <p>Auto-renew poll messages are not deleted until the registration of their parent domain has
|
||||
* been canceled, because there will always be a speculative renewal for next year until that
|
||||
* happens.
|
||||
*/
|
||||
@EntitySubclass(index = false)
|
||||
@javax.persistence.Entity
|
||||
@Entity
|
||||
@DiscriminatorValue("AUTORENEW")
|
||||
@WithLongVKey(compositeKey = true)
|
||||
public static class Autorenew extends PollMessage {
|
||||
|
@ -604,7 +550,6 @@ public abstract class PollMessage extends ImmutableObject
|
|||
String targetId;
|
||||
|
||||
/** The autorenew recurs annually between {@link #eventTime} and this time. */
|
||||
@Index
|
||||
DateTime autorenewEndTime;
|
||||
|
||||
public String getTargetId() {
|
||||
|
@ -617,25 +562,14 @@ public abstract class PollMessage extends ImmutableObject
|
|||
|
||||
@Override
|
||||
public VKey<Autorenew> createVKey() {
|
||||
return VKey.create(Autorenew.class, getId(), Key.create(this));
|
||||
}
|
||||
|
||||
/** Converts an unspecialized VKey<PollMessage> to a VKey of the derived class. */
|
||||
public static @Nullable VKey<Autorenew> convertVKey(VKey<? extends PollMessage> key) {
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
Key<Autorenew> ofyKey =
|
||||
Key.create(key.getOfyKey().getParent(), Autorenew.class, key.getOfyKey().getId());
|
||||
return VKey.create(Autorenew.class, key.getSqlKey(), ofyKey);
|
||||
return VKey.createSql(Autorenew.class, getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImmutableList<ResponseData> getResponseData() {
|
||||
// Note that the event time is when the auto-renew occured, so the expiration time in the
|
||||
// Note that the event time is when the autorenew occurred, so the expiration time in the
|
||||
// response should be 1 year past that, since it denotes the new expiration time.
|
||||
return ImmutableList.of(
|
||||
DomainRenewData.create(getTargetId(), getEventTime().plusYears(1)));
|
||||
return ImmutableList.of(DomainRenewData.create(getTargetId(), getEventTime().plusYears(1)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,48 +14,38 @@
|
|||
|
||||
package google.registry.model.poll;
|
||||
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A converter between external key strings for {@link PollMessage}s (i.e. what registrars use to
|
||||
* identify and ACK them) and Datastore keys to the resource.
|
||||
* identify and ACK them) and {@link VKey}s to the resource.
|
||||
*
|
||||
* <p>The format of the key string is A-B-C-D-E-F as follows:
|
||||
* <p>The format of the key string is A-B as follows:
|
||||
*
|
||||
* <pre>
|
||||
* A = EppResource.typeId (decimal)
|
||||
* B = EppResource.repoId prefix (STRING)
|
||||
* C = EppResource.repoId suffix (STRING)
|
||||
* D = HistoryEntry.id (decimal)
|
||||
* E = PollMessage.id (decimal)
|
||||
* F = PollMessage.eventTime (decimal, year only)
|
||||
* A = PollMessage.id (decimal)
|
||||
* B = PollMessage.eventTime (decimal, year only)
|
||||
* </pre>
|
||||
*
|
||||
* <p>A typical poll message ID might thus look like: 1-FE0F22-TLD-10071463070-10072612074-2018
|
||||
* <p>A typical poll message ID might thus look like: 10072612074-2018
|
||||
*/
|
||||
public class PollMessageExternalKeyConverter {
|
||||
public final class PollMessageExternalKeyConverter {
|
||||
|
||||
/** An exception thrown when an external key cannot be parsed. */
|
||||
public static class PollMessageExternalKeyParseException extends RuntimeException {}
|
||||
public static class PollMessageExternalKeyParseException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 9026397649048831777L;
|
||||
}
|
||||
|
||||
/** Returns an external poll message ID for the given poll message. */
|
||||
public static String makePollMessageExternalId(PollMessage pollMessage) {
|
||||
return String.format(
|
||||
"%d-%s-%d-%d-%d",
|
||||
pollMessage.getType().getId(),
|
||||
pollMessage.getResourceName(),
|
||||
pollMessage.getHistoryRevisionId(),
|
||||
pollMessage.getId(),
|
||||
pollMessage.getEventTime().getYear());
|
||||
return String.format("%d-%d", pollMessage.getId(), pollMessage.getEventTime().getYear());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Objectify Key to a PollMessage corresponding with the external ID.
|
||||
* Returns a {@link VKey} to a {@link PollMessage} corresponding with the external ID.
|
||||
*
|
||||
* <p>Note that the year field that is included at the end of the poll message isn't actually used
|
||||
* for anything; it exists solely to create unique externally visible IDs for autorenews. We thus
|
||||
|
@ -66,26 +56,13 @@ public class PollMessageExternalKeyConverter {
|
|||
*/
|
||||
public static VKey<PollMessage> parsePollMessageExternalId(String externalKey) {
|
||||
List<String> idComponents = Splitter.on('-').splitToList(externalKey);
|
||||
if (idComponents.size() != 6) {
|
||||
if (idComponents.size() != 2) {
|
||||
throw new PollMessageExternalKeyParseException();
|
||||
}
|
||||
try {
|
||||
Class<?> resourceClazz =
|
||||
PollMessage.Type.fromId(Long.parseLong(idComponents.get(0)))
|
||||
.orElseThrow(() -> new PollMessageExternalKeyParseException())
|
||||
.getResourceClass();
|
||||
return VKey.from(
|
||||
Key.create(
|
||||
Key.create(
|
||||
Key.create(
|
||||
null,
|
||||
resourceClazz,
|
||||
String.format("%s-%s", idComponents.get(1), idComponents.get(2))),
|
||||
HistoryEntry.class,
|
||||
Long.parseLong(idComponents.get(3))),
|
||||
PollMessage.class,
|
||||
Long.parseLong(idComponents.get(4))));
|
||||
// Note that idComponents.get(5) is entirely ignored; we never use the year field internally.
|
||||
Long id = Long.parseLong(idComponents.get(0));
|
||||
return VKey.createSql(PollMessage.class, id);
|
||||
// Note that idComponents.get(1) is entirely ignored; we never use the year field internally.
|
||||
} catch (NumberFormatException e) {
|
||||
throw new PollMessageExternalKeyParseException();
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ import org.joda.time.DateTime;
|
|||
* <p>This removes years off a domain's registration period. Note that the expiration time cannot be
|
||||
* set to prior than the present. Reversal of the charges for these years (if desired) must happen
|
||||
* out of band, as they may already have been billed out and thus cannot and won't be reversed in
|
||||
* Datastore.
|
||||
* the database.
|
||||
*/
|
||||
@Parameters(separators = " =", commandDescription = "Unrenew a domain.")
|
||||
@NonFinalForTesting
|
||||
|
@ -217,7 +217,8 @@ class UnrenewDomainCommand extends ConfirmingCommand implements CommandWithRemot
|
|||
.build();
|
||||
// End the old autorenew billing event and poll message now.
|
||||
Recurring existingRecurring = tm().loadByKey(domain.getAutorenewBillingEvent());
|
||||
updateAutorenewRecurrenceEndTime(domain, existingRecurring, now);
|
||||
updateAutorenewRecurrenceEndTime(
|
||||
domain, existingRecurring, now, domainHistory.getDomainHistoryId());
|
||||
Domain newDomain =
|
||||
domain
|
||||
.asBuilder()
|
||||
|
@ -225,9 +226,7 @@ class UnrenewDomainCommand extends ConfirmingCommand implements CommandWithRemot
|
|||
.setLastEppUpdateTime(now)
|
||||
.setLastEppUpdateRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
.setAutorenewBillingEvent(newAutorenewEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
newAutorenewPollMessage.createVKey(),
|
||||
newAutorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(newAutorenewPollMessage.createVKey())
|
||||
.build();
|
||||
// In order to do it'll need to write out a new HistoryEntry (likely of type SYNTHETIC), a new
|
||||
// autorenew billing event and poll message, and a new one time poll message at the present time
|
||||
|
|
|
@ -179,8 +179,7 @@ class DeleteExpiredDomainsActionTest {
|
|||
.asBuilder()
|
||||
.setAutorenewEndTime(Optional.of(clock.nowUtc().minusDays(10)))
|
||||
.setAutorenewBillingEvent(autorenewBillingEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
|
||||
.build());
|
||||
|
||||
return pendingExpirationDomain;
|
||||
|
|
|
@ -95,7 +95,7 @@ class EppLifecycleContactTest extends EppTestCase {
|
|||
.hasCommandName("PollRequest")
|
||||
.and()
|
||||
.hasStatus(SUCCESS_WITH_ACK_MESSAGE);
|
||||
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "2-1-ROID-3-6-2000"))
|
||||
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "6-2000"))
|
||||
.atTime("2000-06-08T22:02:00Z")
|
||||
.hasResponse("poll_ack_response_empty.xml");
|
||||
assertThat(getRecordedEppMetric())
|
||||
|
|
|
@ -747,11 +747,11 @@ class EppLifecycleDomainTest extends EppTestCase {
|
|||
.hasResponse(
|
||||
"poll_response_autorenew.xml",
|
||||
ImmutableMap.of(
|
||||
"ID", "1-B-EXAMPLE-12-15-2002",
|
||||
"ID", "15-2002",
|
||||
"QDATE", "2002-06-01T00:04:00Z",
|
||||
"DOMAIN", "fakesite.example",
|
||||
"EXDATE", "2003-06-01T00:04:00Z"));
|
||||
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-B-EXAMPLE-12-15-2002"))
|
||||
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "15-2002"))
|
||||
.atTime("2002-07-01T00:02:00Z")
|
||||
.hasResponse("poll_ack_response_empty.xml");
|
||||
|
||||
|
@ -765,13 +765,13 @@ class EppLifecycleDomainTest extends EppTestCase {
|
|||
.hasResponse(
|
||||
"poll_response_autorenew.xml",
|
||||
ImmutableMap.of(
|
||||
"ID", "1-B-EXAMPLE-12-15-2003", // Note -- Year is different from previous ID.
|
||||
"ID", "15-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-B-EXAMPLE-12-15-2003"))
|
||||
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "15-2003"))
|
||||
.atTime("2003-07-01T00:05:05Z")
|
||||
.hasResponse("poll_ack_response_empty.xml");
|
||||
assertThatCommand("poll.xml")
|
||||
|
@ -801,7 +801,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-B-EXAMPLE-18-24-2001";
|
||||
String messageId = "24-2001";
|
||||
assertThatCommand("poll.xml")
|
||||
.atTime("2001-01-01T00:01:00Z")
|
||||
.hasResponse("poll_response_domain_transfer_request.xml", ImmutableMap.of("ID", messageId));
|
||||
|
@ -810,7 +810,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-B-EXAMPLE-18-23-2001";
|
||||
messageId = "23-2001";
|
||||
assertThatCommand("poll.xml")
|
||||
.atTime("2001-01-06T00:01:00Z")
|
||||
.hasResponse(
|
||||
|
@ -822,7 +822,7 @@ class EppLifecycleDomainTest extends EppTestCase {
|
|||
assertThatLogoutSucceeds();
|
||||
|
||||
// Also expect a server approval poll message to the winner, with the transfer request trid.
|
||||
messageId = "1-B-EXAMPLE-18-22-2001";
|
||||
messageId = "22-2001";
|
||||
assertThatLoginSucceeds("TheRegistrar", "password2");
|
||||
assertThatCommand("poll.xml")
|
||||
.atTime("2001-01-06T00:02:00Z")
|
||||
|
|
|
@ -147,8 +147,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
|
|||
domain
|
||||
.asBuilder()
|
||||
.setAutorenewBillingEvent(autorenewBillingEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
|
||||
.build());
|
||||
|
||||
assertTransactionalFlow(true);
|
||||
|
@ -214,8 +213,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
|
|||
"TheRegistrar",
|
||||
autorenewBillingEvent.createVKey())))
|
||||
.setAutorenewBillingEvent(autorenewBillingEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
|
||||
.build());
|
||||
assertTransactionalFlow(true);
|
||||
}
|
||||
|
|
|
@ -181,9 +181,7 @@ class DomainRenewFlowTest extends ResourceFlowTestCase<DomainRenewFlow, Domain>
|
|||
.setRegistrationExpirationTime(expirationTime)
|
||||
.setStatusValues(ImmutableSet.copyOf(statusValues))
|
||||
.setAutorenewBillingEvent(autorenewEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
autorenewPollMessage.createVKey(),
|
||||
autorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
|
||||
.build();
|
||||
persistResources(
|
||||
ImmutableSet.of(
|
||||
|
|
|
@ -162,7 +162,7 @@ class DomainTransferCancelFlowTest
|
|||
.setEventTime(originalExpirationTime)
|
||||
.setAutorenewEndTime(END_OF_TIME)
|
||||
.setMsg("Domain was auto-renewed.")
|
||||
.setHistoryEntry(getOnlyHistoryEntryOfType(domain, DOMAIN_CREATE))
|
||||
.setHistoryEntry(getOnlyHistoryEntryOfType(domain, DOMAIN_TRANSFER_CANCEL))
|
||||
.build(),
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setRegistrarId("TheRegistrar")
|
||||
|
|
|
@ -47,7 +47,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
|||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2011"));
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-2011"));
|
||||
clock.setTo(DateTime.parse("2011-01-02T01:01:01Z"));
|
||||
setRegistrarIdForFlow("NewRegistrar");
|
||||
createTld("example");
|
||||
|
@ -87,7 +87,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
|||
|
||||
@Test
|
||||
void testSuccess_contactPollMessage() throws Exception {
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3-2011"));
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-2011"));
|
||||
persistResource(
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setId(MESSAGE_ID)
|
||||
|
@ -102,7 +102,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
|||
|
||||
@Test
|
||||
void testFailure_contactPollMessage_withIncorrectYearField() throws Exception {
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3-1999"));
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-1999"));
|
||||
persistResource(
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setId(MESSAGE_ID)
|
||||
|
@ -124,7 +124,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
|||
|
||||
@Test
|
||||
void testSuccess_recentActiveAutorenew() throws Exception {
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2010"));
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-2010"));
|
||||
persistAutorenewPollMessage(clock.nowUtc().minusMonths(6), END_OF_TIME);
|
||||
assertTransactionalFlow(true);
|
||||
runFlowAssertResponse(loadFile("poll_ack_response_empty.xml"));
|
||||
|
@ -132,7 +132,7 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
|||
|
||||
@Test
|
||||
void testSuccess_oldActiveAutorenew() throws Exception {
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2009"));
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-2009"));
|
||||
persistAutorenewPollMessage(clock.nowUtc().minusYears(2), END_OF_TIME);
|
||||
// Create three other messages to be queued for retrieval to get our count right, since the poll
|
||||
// ack response wants there to be 4 messages in the queue when the ack comes back.
|
||||
|
@ -141,14 +141,12 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
|||
}
|
||||
assertTransactionalFlow(true);
|
||||
runFlowAssertResponse(
|
||||
loadFile(
|
||||
"poll_ack_response.xml",
|
||||
ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2009", "COUNT", "4")));
|
||||
loadFile("poll_ack_response.xml", ImmutableMap.of("MSGID", "3-2009", "COUNT", "4")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_oldInactiveAutorenew() throws Exception {
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2010"));
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3-2010"));
|
||||
persistAutorenewPollMessage(clock.nowUtc().minusMonths(6), clock.nowUtc());
|
||||
assertTransactionalFlow(true);
|
||||
runFlowAssertResponse(loadFile("poll_ack_response_empty.xml"));
|
||||
|
@ -162,35 +160,33 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
|||
}
|
||||
assertTransactionalFlow(true);
|
||||
runFlowAssertResponse(
|
||||
loadFile(
|
||||
"poll_ack_response.xml",
|
||||
ImmutableMap.of("MSGID", "1-3-EXAMPLE-4-3-2011", "COUNT", "4")));
|
||||
loadFile("poll_ack_response.xml", ImmutableMap.of("MSGID", "3-2011", "COUNT", "4")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_noSuchMessage() throws Exception {
|
||||
assertTransactionalFlow(true);
|
||||
Exception e = assertThrows(MessageDoesNotExistException.class, this::runFlow);
|
||||
assertThat(e).hasMessageThat().contains(String.format("(1-3-EXAMPLE-4-%d-2011)", MESSAGE_ID));
|
||||
assertThat(e).hasMessageThat().contains(String.format("(%d-2011)", MESSAGE_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_invalidId_tooFewComponents() throws Exception {
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1-2-3"));
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "1"));
|
||||
assertTransactionalFlow(true);
|
||||
assertThrows(InvalidMessageIdException.class, this::runFlow);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_invalidId_tooManyComponents() throws Exception {
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3-1999-2007"));
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-1999-2007"));
|
||||
assertTransactionalFlow(true);
|
||||
assertThrows(InvalidMessageIdException.class, this::runFlow);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_contactPollMessage_withMissingYearField() throws Exception {
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "2-2-ROID-4-3"));
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "3"));
|
||||
persistResource(
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setId(MESSAGE_ID)
|
||||
|
@ -210,13 +206,6 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
|||
assertThrows(InvalidMessageIdException.class, this::runFlow);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_invalidEppResourceClassId() throws Exception {
|
||||
setEppInput("poll_ack.xml", ImmutableMap.of("MSGID", "999-1-1-1"));
|
||||
assertTransactionalFlow(true);
|
||||
assertThrows(InvalidMessageIdException.class, this::runFlow);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_missingId() throws Exception {
|
||||
setEppInput("poll_ack_missing_id.xml");
|
||||
|
@ -250,6 +239,6 @@ class PollAckFlowTest extends FlowTestCase<PollAckFlow> {
|
|||
.build());
|
||||
assertTransactionalFlow(true);
|
||||
Exception e = assertThrows(MessageDoesNotExistException.class, this::runFlow);
|
||||
assertThat(e).hasMessageThat().contains(String.format("(1-3-EXAMPLE-4-%d-2011)", MESSAGE_ID));
|
||||
assertThat(e).hasMessageThat().contains(String.format("(%d-2011)", MESSAGE_ID));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import google.registry.model.index.EppResourceIndexBucket;
|
|||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyContactIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyDomainIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.rde.RdeRevision;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
|
@ -63,7 +62,6 @@ public class ClassPathManagerTest {
|
|||
assertThat(ClassPathManager.getClass("Lock")).isEqualTo(Lock.class);
|
||||
assertThat(ClassPathManager.getClass("Domain")).isEqualTo(Domain.class);
|
||||
assertThat(ClassPathManager.getClass("HistoryEntry")).isEqualTo(HistoryEntry.class);
|
||||
assertThat(ClassPathManager.getClass("PollMessage")).isEqualTo(PollMessage.class);
|
||||
assertThat(ClassPathManager.getClass("ForeignKeyHostIndex"))
|
||||
.isEqualTo(ForeignKeyHostIndex.class);
|
||||
assertThat(ClassPathManager.getClass("ServerSecret")).isEqualTo(ServerSecret.class);
|
||||
|
@ -117,7 +115,6 @@ public class ClassPathManagerTest {
|
|||
assertThat(ClassPathManager.getClassName(Lock.class)).isEqualTo("Lock");
|
||||
assertThat(ClassPathManager.getClassName(Domain.class)).isEqualTo("Domain");
|
||||
assertThat(ClassPathManager.getClassName(HistoryEntry.class)).isEqualTo("HistoryEntry");
|
||||
assertThat(ClassPathManager.getClassName(PollMessage.class)).isEqualTo("PollMessage");
|
||||
assertThat(ClassPathManager.getClassName(ForeignKeyHostIndex.class))
|
||||
.isEqualTo("ForeignKeyHostIndex");
|
||||
assertThat(ClassPathManager.getClassName(ServerSecret.class)).isEqualTo("ServerSecret");
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
package google.registry.model.domain;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.flows.domain.DomainTransferUtils.createPendingTransferData;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.model.domain.token.AllocationToken.TokenStatus.NOT_STARTED;
|
||||
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
|
||||
|
@ -40,11 +39,8 @@ 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.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.common.EntityGroupRoot;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DesignatedContact.Type;
|
||||
import google.registry.model.domain.Period.Unit;
|
||||
import google.registry.model.domain.launch.LaunchNotice;
|
||||
import google.registry.model.domain.rgp.GracePeriodStatus;
|
||||
import google.registry.model.domain.secdns.DelegationSignerData;
|
||||
|
@ -52,7 +48,6 @@ import google.registry.model.domain.token.AllocationToken;
|
|||
import google.registry.model.domain.token.AllocationToken.TokenStatus;
|
||||
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
|
||||
import google.registry.model.eppcommon.StatusValue;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.host.Host;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
|
@ -503,8 +498,7 @@ public class DomainSqlTest {
|
|||
domain
|
||||
.asBuilder()
|
||||
.setAutorenewBillingEvent(billEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
|
||||
.setDeletePollMessage(deletePollMessage.createVKey())
|
||||
.setTransferData(transferData)
|
||||
.setGracePeriods(gracePeriods)
|
||||
|
@ -549,147 +543,10 @@ public class DomainSqlTest {
|
|||
assertThat(persisted.getGracePeriods()).isEqualTo(gracePeriods);
|
||||
}
|
||||
|
||||
@Test
|
||||
void persistDomainWithLegacyVKeys() {
|
||||
createTld("com");
|
||||
historyEntry =
|
||||
new DomainHistory.Builder()
|
||||
.setId(100L)
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setPeriod(Period.create(1, Period.Unit.YEARS))
|
||||
.setModificationTime(DateTime.now(UTC))
|
||||
.setDomainRepoId("4-COM")
|
||||
.setRegistrarId("registrar1")
|
||||
// These are non-null, but I don't think some tests set them.
|
||||
.setReason("felt like it")
|
||||
.setRequestedByRegistrar(false)
|
||||
.setXmlBytes(new byte[0])
|
||||
.build();
|
||||
BillingEvent.Recurring billEvent =
|
||||
new BillingEvent.Recurring.Builder()
|
||||
.setId(200L)
|
||||
.setReason(Reason.RENEW)
|
||||
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
|
||||
.setTargetId("example.com")
|
||||
.setRegistrarId("registrar1")
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setRecurrenceEndTime(END_OF_TIME)
|
||||
.setDomainHistory(historyEntry)
|
||||
.build();
|
||||
PollMessage.Autorenew autorenewPollMessage =
|
||||
new PollMessage.Autorenew.Builder()
|
||||
.setId(300L)
|
||||
.setRegistrarId("registrar1")
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setHistoryEntry(historyEntry)
|
||||
.build();
|
||||
PollMessage.OneTime deletePollMessage =
|
||||
new PollMessage.OneTime.Builder()
|
||||
.setId(400L)
|
||||
.setRegistrarId("registrar1")
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setHistoryEntry(historyEntry)
|
||||
.build();
|
||||
BillingEvent.OneTime oneTimeBillingEvent =
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setId(500L)
|
||||
// Use SERVER_STATUS so we don't have to add a period.
|
||||
.setReason(Reason.SERVER_STATUS)
|
||||
.setTargetId("example.com")
|
||||
.setRegistrarId("registrar1")
|
||||
.setBillingTime(DateTime.now(UTC))
|
||||
.setCost(Money.of(USD, 100))
|
||||
.setEventTime(DateTime.now(UTC).plusYears(1))
|
||||
.setDomainHistory(historyEntry)
|
||||
.build();
|
||||
DomainTransferData transferData =
|
||||
createPendingTransferData(
|
||||
domain.getRepoId(),
|
||||
historyEntry.getId(),
|
||||
new DomainTransferData.Builder()
|
||||
.setTransferRequestTrid(Trid.create("foo", "bar"))
|
||||
.setTransferRequestTime(fakeClock.nowUtc())
|
||||
.setGainingRegistrarId("registrar2")
|
||||
.setLosingRegistrarId("registrar1")
|
||||
.setPendingTransferExpirationTime(fakeClock.nowUtc().plusDays(1)),
|
||||
ImmutableSet.of(oneTimeBillingEvent, billEvent, autorenewPollMessage),
|
||||
Period.create(0, Unit.YEARS));
|
||||
gracePeriods =
|
||||
ImmutableSet.of(
|
||||
GracePeriod.create(
|
||||
GracePeriodStatus.ADD,
|
||||
"4-COM",
|
||||
END_OF_TIME,
|
||||
"registrar1",
|
||||
oneTimeBillingEvent.createVKey()),
|
||||
GracePeriod.createForRecurring(
|
||||
GracePeriodStatus.AUTO_RENEW,
|
||||
"4-COM",
|
||||
END_OF_TIME,
|
||||
"registrar1",
|
||||
billEvent.createVKey()));
|
||||
|
||||
domain =
|
||||
domain
|
||||
.asBuilder()
|
||||
.setAutorenewBillingEvent(Recurring.createVKey(billEvent.getId()))
|
||||
.setAutorenewPollMessage(
|
||||
createLegacyVKey(PollMessage.Autorenew.class, autorenewPollMessage.getId()),
|
||||
autorenewPollMessage.getHistoryRevisionId())
|
||||
.setDeletePollMessage(
|
||||
createLegacyVKey(PollMessage.OneTime.class, deletePollMessage.getId()))
|
||||
.setTransferData(transferData)
|
||||
.setGracePeriods(gracePeriods)
|
||||
.build();
|
||||
historyEntry = historyEntry.asBuilder().setDomain(domain).build();
|
||||
insertInDb(
|
||||
contact,
|
||||
contact2,
|
||||
host,
|
||||
historyEntry,
|
||||
autorenewPollMessage,
|
||||
billEvent,
|
||||
deletePollMessage,
|
||||
oneTimeBillingEvent,
|
||||
domain);
|
||||
|
||||
// Store the existing BillingRecurrence VKey. This happens after the event has been persisted.
|
||||
Domain persisted = loadByKey(domain.createVKey());
|
||||
|
||||
// Verify that the domain data has been persisted.
|
||||
// dsData still isn't persisted. gracePeriods appears to have the same values but for some
|
||||
// reason is showing up as different.
|
||||
assertEqualDomainExcept(persisted, "creationTime", "dsData", "gracePeriods");
|
||||
|
||||
// Verify that the DomainBase object from the history record sets the fields correctly.
|
||||
DomainHistory persistedHistoryEntry = loadByKey(historyEntry.createVKey());
|
||||
assertThat(persistedHistoryEntry.getDomainBase().get().getAutorenewPollMessage())
|
||||
.isEqualTo(domain.getAutorenewPollMessage());
|
||||
assertThat(persistedHistoryEntry.getDomainBase().get().getAutorenewBillingEvent())
|
||||
.isEqualTo(domain.getAutorenewBillingEvent());
|
||||
assertThat(persistedHistoryEntry.getDomainBase().get().getDeletePollMessage())
|
||||
.isEqualTo(domain.getDeletePollMessage());
|
||||
DomainTransferData persistedTransferData =
|
||||
persistedHistoryEntry.getDomainBase().get().getTransferData();
|
||||
DomainTransferData originalTransferData = domain.getTransferData();
|
||||
assertThat(persistedTransferData.getServerApproveBillingEvent())
|
||||
.isEqualTo(originalTransferData.getServerApproveBillingEvent());
|
||||
assertThat(persistedTransferData.getServerApproveAutorenewEvent())
|
||||
.isEqualTo(originalTransferData.getServerApproveAutorenewEvent());
|
||||
assertThat(persistedTransferData.getServerApproveAutorenewPollMessage())
|
||||
.isEqualTo(originalTransferData.getServerApproveAutorenewPollMessage());
|
||||
assertThat(domain.getGracePeriods()).isEqualTo(gracePeriods);
|
||||
}
|
||||
|
||||
private <T> VKey<T> createKey(Class<T> clazz, String name) {
|
||||
return VKey.create(clazz, name, Key.create(clazz, name));
|
||||
}
|
||||
|
||||
private <T> VKey<T> createLegacyVKey(Class<T> clazz, long id) {
|
||||
return VKey.create(
|
||||
clazz, id, Key.create(Key.create(EntityGroupRoot.class, "per-tld"), clazz, id));
|
||||
}
|
||||
|
||||
private void assertEqualDomainExcept(Domain thatDomain, String... excepts) {
|
||||
ImmutableList<String> moreExcepts =
|
||||
new ImmutableList.Builder<String>()
|
||||
|
|
|
@ -41,7 +41,6 @@ import com.google.common.collect.ImmutableSortedMap;
|
|||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Ordering;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.ImmutableObject;
|
||||
import google.registry.model.ImmutableObjectSubject;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
|
@ -114,7 +113,7 @@ public class DomainTest {
|
|||
oneTimeBillKey =
|
||||
persistResource(
|
||||
new BillingEvent.OneTime.Builder()
|
||||
// Use SERVER_STATUS so we don't have to add a period.
|
||||
// Use SERVER_STATUS, so we don't have to add a period.
|
||||
.setReason(Reason.SERVER_STATUS)
|
||||
.setTargetId(domain.getDomainName())
|
||||
.setRegistrarId(domain.getCurrentSponsorRegistrarId())
|
||||
|
@ -140,7 +139,7 @@ public class DomainTest {
|
|||
BillingEvent.OneTime oneTimeBill =
|
||||
new BillingEvent.OneTime.Builder()
|
||||
.setId(500L)
|
||||
// Use SERVER_STATUS so we don't have to add a period.
|
||||
// Use SERVER_STATUS, so we don't have to add a period.
|
||||
.setReason(Reason.SERVER_STATUS)
|
||||
.setTargetId("example.com")
|
||||
.setRegistrarId("registrar1")
|
||||
|
@ -163,10 +162,8 @@ public class DomainTest {
|
|||
.build();
|
||||
insertInDb(historyEntry, oneTimeBill, recurringBill);
|
||||
recurringBillKey = recurringBill.createVKey();
|
||||
VKey<PollMessage.Autorenew> autorenewPollKey =
|
||||
VKey.from(Key.create(Key.create(domainHistory), PollMessage.Autorenew.class, 3));
|
||||
VKey<PollMessage.OneTime> onetimePollKey =
|
||||
VKey.from(Key.create(Key.create(domainHistory), PollMessage.OneTime.class, 1));
|
||||
VKey<PollMessage.Autorenew> autorenewPollKey = VKey.createSql(PollMessage.Autorenew.class, 3L);
|
||||
VKey<PollMessage.OneTime> onetimePollKey = VKey.createSql(PollMessage.OneTime.class, 1L);
|
||||
// Set up a new persisted domain entity.
|
||||
domain =
|
||||
persistResource(
|
||||
|
@ -215,7 +212,7 @@ public class DomainTest {
|
|||
.build())
|
||||
.setDeletePollMessage(onetimePollKey)
|
||||
.setAutorenewBillingEvent(recurringBillKey)
|
||||
.setAutorenewPollMessage(autorenewPollKey, historyEntry.getId())
|
||||
.setAutorenewPollMessage(autorenewPollKey)
|
||||
.setSmdId("smdid")
|
||||
.addGracePeriod(
|
||||
GracePeriod.create(
|
||||
|
@ -849,7 +846,7 @@ public class DomainTest {
|
|||
|
||||
@Test
|
||||
void testClone_transferDuringAutorenew() {
|
||||
// When the domain is an an autorenew grace period, we should not extend the registration
|
||||
// When the domain is an autorenew grace period, we should not extend the registration
|
||||
// expiration by a further year--it should just be whatever the autorenew was
|
||||
DateTime now = DateTime.now(UTC);
|
||||
DateTime transferExpirationTime = now.minusDays(1);
|
||||
|
|
|
@ -46,7 +46,7 @@ public class PollMessageExternalKeyConverterTest {
|
|||
public final AppEngineExtension appEngine = AppEngineExtension.builder().withCloudSql().build();
|
||||
|
||||
private HistoryEntry historyEntry;
|
||||
private FakeClock clock = new FakeClock(DateTime.parse("2007-07-07T01:01:01Z"));
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2007-07-07T01:01:01Z"));
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
|
@ -77,8 +77,8 @@ public class PollMessageExternalKeyConverterTest {
|
|||
.setMsg("Test poll message")
|
||||
.setHistoryEntry(historyEntry)
|
||||
.build());
|
||||
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("1-2-FOOBAR-4-5-2007");
|
||||
assertVKeysEqual(parsePollMessageExternalId("1-2-FOOBAR-4-5-2007"), pollMessage.createVKey());
|
||||
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("5-2007");
|
||||
assertVKeysEqual(parsePollMessageExternalId("5-2007"), pollMessage.createVKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -94,8 +94,8 @@ public class PollMessageExternalKeyConverterTest {
|
|||
.setMsg("Test poll message")
|
||||
.setHistoryEntry(historyEntry)
|
||||
.build());
|
||||
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("2-5-ROID-6-7-2007");
|
||||
assertVKeysEqual(parsePollMessageExternalId("2-5-ROID-6-7-2007"), pollMessage.createVKey());
|
||||
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("7-2007");
|
||||
assertVKeysEqual(parsePollMessageExternalId("7-2007"), pollMessage.createVKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -111,46 +111,25 @@ public class PollMessageExternalKeyConverterTest {
|
|||
.setMsg("Test poll message")
|
||||
.setHistoryEntry(historyEntry)
|
||||
.build());
|
||||
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("3-5-ROID-6-7-2007");
|
||||
assertVKeysEqual(parsePollMessageExternalId("3-5-ROID-6-7-2007"), pollMessage.createVKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_missingYearField() {
|
||||
assertThrows(
|
||||
PollMessageExternalKeyParseException.class,
|
||||
() -> parsePollMessageExternalId("1-2-FOOBAR-4-5"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_invalidEppResourceTypeId() {
|
||||
// Populate the testdata correctly as for 1-2-FOOBAR-4-5 so we know that the only thing that
|
||||
// is wrong here is the EppResourceTypeId.
|
||||
testSuccess_domain();
|
||||
assertThrows(
|
||||
PollMessageExternalKeyParseException.class,
|
||||
() -> parsePollMessageExternalId("4-2-FOOBAR-4-5-2007"));
|
||||
assertThat(makePollMessageExternalId(pollMessage)).isEqualTo("7-2007");
|
||||
assertVKeysEqual(parsePollMessageExternalId("7-2007"), pollMessage.createVKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_tooFewComponentParts() {
|
||||
assertThrows(
|
||||
PollMessageExternalKeyParseException.class,
|
||||
() -> parsePollMessageExternalId("1-3-EXAMPLE"));
|
||||
assertThrows(PollMessageExternalKeyParseException.class, () -> parsePollMessageExternalId("1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_tooManyComponentParts() {
|
||||
assertThrows(
|
||||
PollMessageExternalKeyParseException.class,
|
||||
() -> parsePollMessageExternalId("1-3-EXAMPLE-4-5-2007-2009"));
|
||||
PollMessageExternalKeyParseException.class, () -> parsePollMessageExternalId("1-3-2009"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFailure_nonNumericIds() {
|
||||
assertThrows(
|
||||
PollMessageExternalKeyParseException.class,
|
||||
() -> parsePollMessageExternalId("A-B-FOOBAR-D-E-F"));
|
||||
PollMessageExternalKeyParseException.class, () -> parsePollMessageExternalId("A-2007"));
|
||||
}
|
||||
|
||||
// We may have VKeys of slightly varying types, e.g. VKey<PollMessage> (superclass) and
|
||||
|
|
|
@ -18,16 +18,13 @@ import static com.google.common.truth.Truth.assertThat;
|
|||
import static org.joda.time.DateTimeZone.UTC;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.model.billing.BillingEvent;
|
||||
import google.registry.model.billing.BillingEvent.Cancellation;
|
||||
import google.registry.model.billing.BillingEvent.OneTime;
|
||||
import google.registry.model.billing.BillingEvent.Recurring;
|
||||
import google.registry.model.domain.Domain;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.poll.PollMessage;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.testing.AppEngineExtension;
|
||||
import org.joda.time.DateTime;
|
||||
|
@ -51,21 +48,11 @@ public class TransferDataTest {
|
|||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
Key<HistoryEntry> historyEntryKey =
|
||||
Key.create(Key.create(Domain.class, "4-TLD"), HistoryEntry.class, 1356L);
|
||||
transferBillingEventKey = OneTime.createVKey(12345L);
|
||||
otherServerApproveBillingEventKey = Cancellation.createVKey(2468L);
|
||||
recurringBillingEventKey = Recurring.createVKey(13579L);
|
||||
autorenewPollMessageKey =
|
||||
VKey.create(
|
||||
PollMessage.Autorenew.class,
|
||||
67890L,
|
||||
Key.create(historyEntryKey, PollMessage.Autorenew.class, 67890L));
|
||||
otherServerApprovePollMessageKey =
|
||||
VKey.create(
|
||||
PollMessage.OneTime.class,
|
||||
314159L,
|
||||
Key.create(historyEntryKey, PollMessage.OneTime.class, 314159L));
|
||||
autorenewPollMessageKey = VKey.createSql(PollMessage.Autorenew.class, 67890L);
|
||||
otherServerApprovePollMessageKey = VKey.createSql(PollMessage.OneTime.class, 314159L);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -334,8 +334,7 @@ public class DomainToXjcConverterTest {
|
|||
.setMsg("Domain was auto-renewed.")
|
||||
.setHistoryEntry(domainHistory)
|
||||
.build())
|
||||
.createVKey(),
|
||||
domainHistory.getId())
|
||||
.createVKey())
|
||||
.setTransferData(
|
||||
new DomainTransferData.Builder()
|
||||
.setGainingRegistrarId("NewRegistrar")
|
||||
|
|
|
@ -175,8 +175,7 @@ final class RdeFixtures {
|
|||
.setMsg("Domain was auto-renewed.")
|
||||
.setHistoryEntry(historyEntry)
|
||||
.build())
|
||||
.createVKey(),
|
||||
historyEntry.getId())
|
||||
.createVKey())
|
||||
.setTransferData(
|
||||
new DomainTransferData.Builder()
|
||||
.setGainingRegistrarId("gaining")
|
||||
|
|
|
@ -667,8 +667,7 @@ public class DatabaseHelper {
|
|||
domain
|
||||
.asBuilder()
|
||||
.setAutorenewBillingEvent(autorenewEvent.createVKey())
|
||||
.setAutorenewPollMessage(
|
||||
autorenewPollMessage.createVKey(), autorenewPollMessage.getHistoryRevisionId())
|
||||
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
|
||||
.build());
|
||||
}
|
||||
|
||||
|
|
|
@ -77,10 +77,10 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
|
|||
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3, pm4)).values())
|
||||
.containsExactly(futurePollMessage);
|
||||
assertInStdout(
|
||||
"1-FSDGS-TLD-2406-624-2013,2013-05-01T22:33:44.000Z,ninelives",
|
||||
"1-FSDGS-TLD-2406-316-2014,2014-01-01T22:33:44.000Z,foobar",
|
||||
"1-FSDGS-TLD-2406-791-2015,2015-01-08T22:33:44.000Z,ginger");
|
||||
assertNotInStdout("1-FSDGS-TLD-2406-123-2015,2015-09-01T22:33:44.000Z,notme");
|
||||
"624-2013,2013-05-01T22:33:44.000Z,ninelives",
|
||||
"316-2014,2014-01-01T22:33:44.000Z,foobar",
|
||||
"791-2015,2015-01-08T22:33:44.000Z,ginger");
|
||||
assertNotInStdout("123-2015,2015-09-01T22:33:44.000Z,notme");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -105,9 +105,9 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
|
|||
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3)).values())
|
||||
.containsExactly(resaved);
|
||||
assertInStdout(
|
||||
"1-FSDGS-TLD-2406-625-2011,2011-04-15T22:33:44.000Z,autorenew",
|
||||
"1-FSDGS-TLD-2406-624-2013,2013-05-01T22:33:44.000Z,ninelives",
|
||||
"1-FSDGS-TLD-2406-316-2014,2014-01-01T22:33:44.000Z,foobar");
|
||||
"625-2011,2011-04-15T22:33:44.000Z,autorenew",
|
||||
"624-2013,2013-05-01T22:33:44.000Z,ninelives",
|
||||
"316-2014,2014-01-01T22:33:44.000Z,foobar");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -130,9 +130,9 @@ public class AckPollMessagesCommandTest extends CommandTestCase<AckPollMessagesC
|
|||
runCommand("-c", "TheRegistrar");
|
||||
assertThat(loadByKeysIfPresent(ImmutableList.of(pm1, pm2, pm3))).isEmpty();
|
||||
assertInStdout(
|
||||
"1-FSDGS-TLD-2406-625-2011,2011-04-15T22:33:44.000Z,autorenew",
|
||||
"1-FSDGS-TLD-2406-624-2013,2013-05-01T22:33:44.000Z,ninelives",
|
||||
"1-FSDGS-TLD-2406-316-2014,2014-01-01T22:33:44.000Z,foobar");
|
||||
"625-2011,2011-04-15T22:33:44.000Z,autorenew",
|
||||
"624-2013,2013-05-01T22:33:44.000Z,ninelives",
|
||||
"316-2014,2014-01-01T22:33:44.000Z,foobar");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -115,7 +115,7 @@ class EppLifecycleToolsTest extends EppTestCase {
|
|||
.atTime("2001-06-08T00:00:00Z")
|
||||
.hasResponse("poll_response_unrenew.xml");
|
||||
|
||||
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-7-TLD-20-21-2001"))
|
||||
assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "21-2001"))
|
||||
.atTime("2001-06-08T00:00:01Z")
|
||||
.hasResponse("poll_ack_response_empty.xml");
|
||||
|
||||
|
@ -136,7 +136,7 @@ class EppLifecycleToolsTest extends EppTestCase {
|
|||
.hasResponse(
|
||||
"poll_response_autorenew.xml",
|
||||
ImmutableMap.of(
|
||||
"ID", "1-7-TLD-20-23-2003",
|
||||
"ID", "23-2003",
|
||||
"QDATE", "2003-06-01T00:02:00Z",
|
||||
"DOMAIN", "example.tld",
|
||||
"EXDATE", "2004-06-01T00:02:00Z"));
|
||||
|
|
|
@ -155,7 +155,6 @@ public class UnrenewDomainCommandTest extends CommandTestCase<UnrenewDomainComma
|
|||
.build()));
|
||||
|
||||
// Check that fields on domain were updated correctly.
|
||||
assertThat(domain.getAutorenewPollMessageHistoryId()).isEqualTo(synthetic.getId());
|
||||
assertThat(domain.getRegistrationExpirationTime()).isEqualTo(newExpirationTime);
|
||||
assertThat(domain.getLastEppUpdateTime()).isEqualTo(unrenewTime);
|
||||
assertThat(domain.getLastEppUpdateRegistrarId()).isEqualTo("TheRegistrar");
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="1-3-EXAMPLE-5-6-2011">
|
||||
<msgQ count="1" id="6-2011">
|
||||
<qDate>2011-01-02T01:01:01Z</qDate>
|
||||
<msg>Domain test.example was deleted by registry administrator with final deletion effective: 2011-01-02T00:56:01.008Z</msg>
|
||||
</msgQ>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="1-3-EXAMPLE-5-6-2011">
|
||||
<msgQ count="1" id="6-2011">
|
||||
<qDate>2011-01-01T01:01:01Z</qDate>
|
||||
<msg>Domain was auto-renewed.</msg>
|
||||
</msgQ>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="2-2-ROID-5-6-2011">
|
||||
<msgQ count="1" id="6-2011">
|
||||
<qDate>2011-01-01T01:01:01Z</qDate>
|
||||
<msg>Deleted contact jd1234</msg>
|
||||
</msgQ>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="2-2-ROID-5-3-2010">
|
||||
<msgQ count="1" id="3-2010">
|
||||
<qDate>2010-12-28T01:01:01Z</qDate>
|
||||
<msg>Transfer requested.</msg>
|
||||
</msgQ>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="1-3-EXAMPLE-5-6-2011">
|
||||
<msgQ count="1" id="6-2011">
|
||||
<qDate>2011-01-01T01:01:01Z</qDate>
|
||||
<msg>Domain deleted.</msg>
|
||||
</msgQ>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="1-3-EXAMPLE-5-6-2011">
|
||||
<msgQ count="1" id="6-2011">
|
||||
<qDate>2011-01-01T01:01:01Z</qDate>
|
||||
<msg>Transfer approved.</msg>
|
||||
</msgQ>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="1-3-EXAMPLE-5-6-2011">
|
||||
<msgQ count="1" id="6-2011">
|
||||
<qDate>2011-01-01T01:01:01Z</qDate>
|
||||
<msg>Transfer approved.</msg>
|
||||
</msgQ>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="3-4-ROID-5-6-2011">
|
||||
<msgQ count="1" id="6-2011">
|
||||
<qDate>2011-01-01T01:01:01Z</qDate>
|
||||
<msg>Deleted host ns1.test.example</msg>
|
||||
</msgQ>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="2-1-ROID-3-6-2000">
|
||||
<msgQ count="1" id="6-2000">
|
||||
<qDate>2000-06-08T22:00:00Z</qDate>
|
||||
<msg>Transfer requested.</msg>
|
||||
</msgQ>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="1-7-TLD-14-16-2000">
|
||||
<msgQ count="1" id="16-2000">
|
||||
<qDate>2000-06-02T13:00:00Z</qDate>
|
||||
<msg>The registry administrator has added the status(es) [serverHold].
|
||||
</msg>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<result code="1301">
|
||||
<msg>Command completed successfully; ack to dequeue</msg>
|
||||
</result>
|
||||
<msgQ count="1" id="1-7-TLD-20-21-2001">
|
||||
<msgQ count="1" id="21-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>
|
||||
|
|
|
@ -359,26 +359,6 @@ class google.registry.model.index.ForeignKeyIndex$ForeignKeyHostIndex {
|
|||
google.registry.persistence.VKey<E> topReference;
|
||||
org.joda.time.DateTime deletionTime;
|
||||
}
|
||||
class google.registry.model.poll.PollMessage {
|
||||
@Id java.lang.Long id;
|
||||
java.lang.String clientId;
|
||||
java.lang.String msg;
|
||||
org.joda.time.DateTime eventTime;
|
||||
}
|
||||
class google.registry.model.poll.PollMessage$Autorenew {
|
||||
@Id java.lang.Long id;
|
||||
java.lang.String clientId;
|
||||
java.lang.String msg;
|
||||
java.lang.String targetId;
|
||||
org.joda.time.DateTime autorenewEndTime;
|
||||
org.joda.time.DateTime eventTime;
|
||||
}
|
||||
class google.registry.model.poll.PollMessage$OneTime {
|
||||
@Id java.lang.Long id;
|
||||
java.lang.String clientId;
|
||||
java.lang.String msg;
|
||||
org.joda.time.DateTime eventTime;
|
||||
}
|
||||
class google.registry.model.rde.RdeRevision {
|
||||
@Id java.lang.String id;
|
||||
int revision;
|
||||
|
|
|
@ -270,7 +270,6 @@
|
|||
billing_recurrence_id int8,
|
||||
autorenew_end_time timestamptz,
|
||||
autorenew_poll_message_id int8,
|
||||
autorenew_poll_message_history_id int8,
|
||||
billing_contact text,
|
||||
current_package_token text,
|
||||
deletion_poll_message_id int8,
|
||||
|
@ -340,7 +339,6 @@
|
|||
billing_recurrence_id int8,
|
||||
autorenew_end_time timestamptz,
|
||||
autorenew_poll_message_id int8,
|
||||
autorenew_poll_message_history_id int8,
|
||||
billing_contact text,
|
||||
current_package_token text,
|
||||
deletion_poll_message_id int8,
|
||||
|
|
Loading…
Add table
Reference in a new issue