Add columns for TransferData in Domain and Contact (#577)

* Add columns for TransferData in Domain and Contact

* Rename flyway file and foreign key

* Rebase on master and address comment

* Compileable commit

* Fix unit test

* Refactor TransferServerApproveEntity

* Use tm().delete(vkeys)

* Rename transfer_period fields

* Rename client_id to registrar_id

* Rebase on master

* Resolve comment

* Rebase on master
This commit is contained in:
Shicong Huang 2020-06-09 16:39:55 -04:00 committed by GitHub
parent c154df9d2c
commit fbe613c209
33 changed files with 568 additions and 182 deletions

View file

@ -97,7 +97,7 @@ public final class ContactTransferApproveFlow implements TransactionalFlow {
ofy().save().<Object>entities(newContact, historyEntry, gainingPollMessage); ofy().save().<Object>entities(newContact, historyEntry, gainingPollMessage);
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
ofy().delete().keys(existingContact.getTransferData().getServerApproveEntities()); tm().delete(existingContact.getTransferData().getServerApproveEntities());
return responseBuilder return responseBuilder
.setResData(createTransferResponse(targetId, newContact.getTransferData())) .setResData(createTransferResponse(targetId, newContact.getTransferData()))
.build(); .build();

View file

@ -93,7 +93,7 @@ public final class ContactTransferCancelFlow implements TransactionalFlow {
ofy().save().<Object>entities(newContact, historyEntry, losingPollMessage); ofy().save().<Object>entities(newContact, historyEntry, losingPollMessage);
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
ofy().delete().keys(existingContact.getTransferData().getServerApproveEntities()); tm().delete(existingContact.getTransferData().getServerApproveEntities());
return responseBuilder return responseBuilder
.setResData(createTransferResponse(targetId, newContact.getTransferData())) .setResData(createTransferResponse(targetId, newContact.getTransferData()))
.build(); .build();

View file

@ -90,7 +90,7 @@ public final class ContactTransferRejectFlow implements TransactionalFlow {
ofy().save().<Object>entities(newContact, historyEntry, gainingPollMessage); ofy().save().<Object>entities(newContact, historyEntry, gainingPollMessage);
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
ofy().delete().keys(existingContact.getTransferData().getServerApproveEntities()); tm().delete(existingContact.getTransferData().getServerApproveEntities());
return responseBuilder return responseBuilder
.setResData(createTransferResponse(targetId, newContact.getTransferData())) .setResData(createTransferResponse(targetId, newContact.getTransferData()))
.build(); .build();

View file

@ -126,13 +126,15 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
// If the transfer is server approved, this message will be sent to the gaining registrar. */ // If the transfer is server approved, this message will be sent to the gaining registrar. */
PollMessage serverApproveGainingPollMessage = PollMessage serverApproveGainingPollMessage =
createGainingTransferPollMessage(targetId, serverApproveTransferData, historyEntry); createGainingTransferPollMessage(targetId, serverApproveTransferData, historyEntry);
TransferData pendingTransferData = serverApproveTransferData.asBuilder() TransferData pendingTransferData =
.setTransferStatus(TransferStatus.PENDING) serverApproveTransferData
.setServerApproveEntities( .asBuilder()
ImmutableSet.of( .setTransferStatus(TransferStatus.PENDING)
Key.create(serverApproveGainingPollMessage), .setServerApproveEntities(
Key.create(serverApproveLosingPollMessage))) ImmutableSet.of(
.build(); serverApproveGainingPollMessage.createVKey(),
serverApproveLosingPollMessage.createVKey()))
.build();
// When a transfer is requested, a poll message is created to notify the losing registrar. // When a transfer is requested, a poll message is created to notify the losing registrar.
PollMessage requestPollMessage = PollMessage requestPollMessage =
createLosingTransferPollMessage(targetId, pendingTransferData, historyEntry).asBuilder() createLosingTransferPollMessage(targetId, pendingTransferData, historyEntry).asBuilder()

View file

@ -214,7 +214,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
ofy().save().entities(entitiesToSave.build()); ofy().save().entities(entitiesToSave.build());
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities()); tm().delete(existingDomain.getTransferData().getServerApproveEntities());
return responseBuilder return responseBuilder
.setResData(createTransferResponse( .setResData(createTransferResponse(
targetId, newDomain.getTransferData(), newDomain.getRegistrationExpirationTime())) targetId, newDomain.getTransferData(), newDomain.getRegistrationExpirationTime()))

View file

@ -110,7 +110,7 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME); updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME);
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities()); tm().delete(existingDomain.getTransferData().getServerApproveEntities());
return responseBuilder return responseBuilder
.setResData(createTransferResponse(targetId, newDomain.getTransferData(), null)) .setResData(createTransferResponse(targetId, newDomain.getTransferData(), null))
.build(); .build();

View file

@ -112,7 +112,7 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME); updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME);
// Delete the billing event and poll messages that were written in case the transfer would have // Delete the billing event and poll messages that were written in case the transfer would have
// been implicitly server approved. // been implicitly server approved.
ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities()); tm().delete(existingDomain.getTransferData().getServerApproveEntities());
return responseBuilder return responseBuilder
.setResData(createTransferResponse(targetId, newDomain.getTransferData(), null)) .setResData(createTransferResponse(targetId, newDomain.getTransferData(), null))
.build(); .build();

View file

@ -20,7 +20,6 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag; import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason; import google.registry.model.billing.BillingEvent.Reason;
@ -37,6 +36,7 @@ import google.registry.model.transfer.TransferData;
import google.registry.model.transfer.TransferData.TransferServerApproveEntity; import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
import google.registry.model.transfer.TransferResponse.DomainTransferResponse; import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
import google.registry.model.transfer.TransferStatus; import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.joda.money.Money; import org.joda.money.Money;
@ -52,37 +52,34 @@ public final class DomainTransferUtils {
TransferData.Builder transferDataBuilder, TransferData.Builder transferDataBuilder,
ImmutableSet<TransferServerApproveEntity> serverApproveEntities, ImmutableSet<TransferServerApproveEntity> serverApproveEntities,
Period transferPeriod) { Period transferPeriod) {
ImmutableSet.Builder<Key<? extends TransferServerApproveEntity>> serverApproveEntityKeys = ImmutableSet.Builder<VKey<? extends TransferServerApproveEntity>> serverApproveEntityKeys =
new ImmutableSet.Builder<>(); new ImmutableSet.Builder<>();
for (TransferServerApproveEntity entity : serverApproveEntities) { for (TransferServerApproveEntity entity : serverApproveEntities) {
serverApproveEntityKeys.add(Key.create(entity)); serverApproveEntityKeys.add(entity.createVKey());
} }
if (transferPeriod.getValue() != 0) { if (transferPeriod.getValue() != 0) {
// Unless superuser sets period to 0, add a transfer billing event. // Unless superuser sets period to 0, add a transfer billing event.
transferDataBuilder.setServerApproveBillingEvent( transferDataBuilder.setServerApproveBillingEvent(
Key.create( serverApproveEntities.stream()
serverApproveEntities .filter(BillingEvent.OneTime.class::isInstance)
.stream() .map(BillingEvent.OneTime.class::cast)
.filter(BillingEvent.OneTime.class::isInstance) .collect(onlyElement())
.map(BillingEvent.OneTime.class::cast) .createVKey());
.collect(onlyElement())));
} }
return transferDataBuilder return transferDataBuilder
.setTransferStatus(TransferStatus.PENDING) .setTransferStatus(TransferStatus.PENDING)
.setServerApproveAutorenewEvent( .setServerApproveAutorenewEvent(
Key.create( serverApproveEntities.stream()
serverApproveEntities .filter(BillingEvent.Recurring.class::isInstance)
.stream() .map(BillingEvent.Recurring.class::cast)
.filter(BillingEvent.Recurring.class::isInstance) .collect(onlyElement())
.map(BillingEvent.Recurring.class::cast) .createVKey())
.collect(onlyElement())))
.setServerApproveAutorenewPollMessage( .setServerApproveAutorenewPollMessage(
Key.create( serverApproveEntities.stream()
serverApproveEntities .filter(PollMessage.Autorenew.class::isInstance)
.stream() .map(PollMessage.Autorenew.class::cast)
.filter(PollMessage.Autorenew.class::isInstance) .collect(onlyElement())
.map(PollMessage.Autorenew.class::cast) .createVKey())
.collect(onlyElement())))
.setServerApproveEntities(serverApproveEntityKeys.build()) .setServerApproveEntities(serverApproveEntityKeys.build())
.setTransferPeriod(transferPeriod) .setTransferPeriod(transferPeriod)
.build(); .build();

View file

@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -114,7 +115,7 @@ public final class ResourceTransferUtils {
R resource, R newResource, DateTime now, HistoryEntry historyEntry) { R resource, R newResource, DateTime now, HistoryEntry historyEntry) {
if (resource.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) { if (resource.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) {
TransferData oldTransferData = resource.getTransferData(); TransferData oldTransferData = resource.getTransferData();
ofy().delete().keys(oldTransferData.getServerApproveEntities()); tm().delete(oldTransferData.getServerApproveEntities());
ofy() ofy()
.save() .save()
.entity( .entity(

View file

@ -345,6 +345,7 @@ public abstract class BillingEvent extends ImmutableObject
return Optional.ofNullable(allocationToken); return Optional.ofNullable(allocationToken);
} }
@Override
public VKey<OneTime> createVKey() { public VKey<OneTime> createVKey() {
return VKey.createOfy(getClass(), Key.create(this)); return VKey.createOfy(getClass(), Key.create(this));
} }
@ -482,6 +483,7 @@ public abstract class BillingEvent extends ImmutableObject
return recurrenceTimeOfYear; return recurrenceTimeOfYear;
} }
@Override
public VKey<Recurring> createVKey() { public VKey<Recurring> createVKey() {
return VKey.createOfy(getClass(), Key.create(this)); return VKey.createOfy(getClass(), Key.create(this));
} }
@ -603,6 +605,7 @@ public abstract class BillingEvent extends ImmutableObject
return builder.build(); return builder.build();
} }
@Override
public VKey<Cancellation> createVKey() { public VKey<Cancellation> createVKey() {
return VKey.createOfy(getClass(), Key.create(this)); return VKey.createOfy(getClass(), Key.create(this));
} }
@ -682,6 +685,11 @@ public abstract class BillingEvent extends ImmutableObject
return new Builder(clone(this)); return new Builder(clone(this));
} }
@Override
public VKey<Modification> createVKey() {
return VKey.createOfy(this.getClass(), Key.create(this));
}
/** /**
* Create a new Modification billing event which is a refund of the given OneTime billing event * Create a new Modification billing event which is a refund of the given OneTime billing event
* and that is parented off the given HistoryEntry. * and that is parented off the given HistoryEntry.

View file

@ -41,7 +41,6 @@ import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides; import javax.persistence.AttributeOverrides;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Embedded; import javax.persistence.Embedded;
import javax.persistence.Transient;
import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElement;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -171,8 +170,7 @@ public class ContactResource extends EppResource
ContactAuthInfo authInfo; ContactAuthInfo authInfo;
/** Data about any pending or past transfers on this contact. */ /** Data about any pending or past transfers on this contact. */
// TODO(b/153363295): Figure out how to persist transfer data TransferData transferData;
@Transient TransferData transferData;
/** /**
* The time that this resource was last transferred. * The time that this resource was last transferred.

View file

@ -253,7 +253,7 @@ public class DomainBase extends EppResource
String smdId; String smdId;
/** Data about any pending or past transfers on this domain. */ /** Data about any pending or past transfers on this domain. */
@Transient TransferData transferData; TransferData transferData;
/** /**
* The time that this resource was last transferred. * The time that this resource was last transferred.
@ -438,8 +438,14 @@ public class DomainBase extends EppResource
.setRegistrationExpirationTime(expirationDate) .setRegistrationExpirationTime(expirationDate)
// Set the speculatively-written new autorenew events as the domain's autorenew // Set the speculatively-written new autorenew events as the domain's autorenew
// events. // events.
.setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent()) .setAutorenewBillingEvent(
.setAutorenewPollMessage(transferData.getServerApproveAutorenewPollMessage()); transferData.getServerApproveAutorenewEvent() == null
? null
: transferData.getServerApproveAutorenewEvent().getOfyKey())
.setAutorenewPollMessage(
transferData.getServerApproveAutorenewPollMessage() == null
? null
: transferData.getServerApproveAutorenewPollMessage().getOfyKey());
if (transferData.getTransferPeriod().getValue() == 1) { if (transferData.getTransferPeriod().getValue() == 1) {
// Set the grace period using a key to the prescheduled transfer billing event. Not using // 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. // GracePeriod.forBillingEvent() here in order to avoid the actual Datastore fetch.
@ -450,7 +456,9 @@ public class DomainBase extends EppResource
transferExpirationTime.plus( transferExpirationTime.plus(
Registry.get(getTld()).getTransferGracePeriodLength()), Registry.get(getTld()).getTransferGracePeriodLength()),
transferData.getGainingClientId(), transferData.getGainingClientId(),
transferData.getServerApproveBillingEvent()))); transferData.getServerApproveBillingEvent() == null
? null
: transferData.getServerApproveBillingEvent().getOfyKey())));
} else { } else {
// There won't be a billing event, so we don't need a grace period // There won't be a billing event, so we don't need a grace period
builder.setGracePeriods(ImmutableSet.of()); builder.setGracePeriods(ImmutableSet.of());

View file

@ -16,6 +16,8 @@ package google.registry.model.domain;
import com.googlecode.objectify.annotation.Embed; import com.googlecode.objectify.annotation.Embed;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlEnumValue;
import javax.xml.bind.annotation.XmlValue; import javax.xml.bind.annotation.XmlValue;
@ -25,6 +27,7 @@ import javax.xml.bind.annotation.XmlValue;
@javax.persistence.Embeddable @javax.persistence.Embeddable
public class Period extends ImmutableObject { public class Period extends ImmutableObject {
@Enumerated(EnumType.STRING)
@XmlAttribute @XmlAttribute
Unit unit; Unit unit;

View file

@ -43,6 +43,7 @@ import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
import google.registry.model.transfer.TransferResponse; import google.registry.model.transfer.TransferResponse;
import google.registry.model.transfer.TransferResponse.ContactTransferResponse; import google.registry.model.transfer.TransferResponse.ContactTransferResponse;
import google.registry.model.transfer.TransferResponse.DomainTransferResponse; import google.registry.model.transfer.TransferResponse.DomainTransferResponse;
import google.registry.persistence.VKey;
import google.registry.persistence.WithLongVKey; import google.registry.persistence.WithLongVKey;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -150,6 +151,9 @@ public abstract class PollMessage extends ImmutableObject
public abstract ImmutableList<ResponseData> getResponseData(); public abstract ImmutableList<ResponseData> getResponseData();
@Override
public abstract VKey<? extends PollMessage> createVKey();
/** Override Buildable.asBuilder() to give this method stronger typing. */ /** Override Buildable.asBuilder() to give this method stronger typing. */
@Override @Override
public abstract Builder<?, ?> asBuilder(); public abstract Builder<?, ?> asBuilder();
@ -291,6 +295,11 @@ public abstract class PollMessage extends ImmutableObject
@Column(name = "transfer_response_contact_id") @Column(name = "transfer_response_contact_id")
String contactId; String contactId;
@Override
public VKey<OneTime> createVKey() {
return VKey.createOfy(this.getClass(), Key.create(this));
}
@Override @Override
public Builder asBuilder() { public Builder asBuilder() {
return new Builder(clone(this)); return new Builder(clone(this));
@ -387,6 +396,11 @@ public abstract class PollMessage extends ImmutableObject
return autorenewEndTime; return autorenewEndTime;
} }
@Override
public VKey<Autorenew> createVKey() {
return VKey.createOfy(this.getClass(), Key.create(this));
}
@Override @Override
public ImmutableList<ResponseData> getResponseData() { 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 auto-renew occured, so the expiration time in the

View file

@ -16,6 +16,7 @@ package google.registry.model.transfer;
import google.registry.model.Buildable.GenericBuilder; import google.registry.model.Buildable.GenericBuilder;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import javax.persistence.Column;
import javax.persistence.EnumType; import javax.persistence.EnumType;
import javax.persistence.Enumerated; import javax.persistence.Enumerated;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;
@ -38,6 +39,7 @@ public abstract class BaseTransferObject extends ImmutableObject {
/** The gaining registrar of the current or last transfer. Can be null if never transferred. */ /** The gaining registrar of the current or last transfer. Can be null if never transferred. */
@XmlElement(name = "reID") @XmlElement(name = "reID")
@Column(name = "transfer_gaining_registrar_id")
String gainingClientId; String gainingClientId;
/** The time that the last transfer was requested. Can be null if never transferred. */ /** The time that the last transfer was requested. Can be null if never transferred. */
@ -46,6 +48,7 @@ public abstract class BaseTransferObject extends ImmutableObject {
/** The losing registrar of the current or last transfer. Can be null if never transferred. */ /** The losing registrar of the current or last transfer. Can be null if never transferred. */
@XmlElement(name = "acID") @XmlElement(name = "acID")
@Column(name = "transfer_losing_registrar_id")
String losingClientId; String losingClientId;
/** /**
@ -54,6 +57,7 @@ public abstract class BaseTransferObject extends ImmutableObject {
* this holds the time that the last pending transfer ended. Can be null if never transferred. * this holds the time that the last pending transfer ended. Can be null if never transferred.
*/ */
@XmlElement(name = "acDate") @XmlElement(name = "acDate")
@Column(name = "transfer_pending_expiration_time")
DateTime pendingTransferExpirationTime; DateTime pendingTransferExpirationTime;
public TransferStatus getTransferStatus() { public TransferStatus getTransferStatus() {

View file

@ -17,8 +17,8 @@ package google.registry.model.transfer;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Embed; import com.googlecode.objectify.annotation.Embed;
import com.googlecode.objectify.annotation.Ignore;
import com.googlecode.objectify.annotation.IgnoreSave; import com.googlecode.objectify.annotation.IgnoreSave;
import com.googlecode.objectify.annotation.Unindex; import com.googlecode.objectify.annotation.Unindex;
import com.googlecode.objectify.condition.IfNull; import com.googlecode.objectify.condition.IfNull;
@ -29,10 +29,14 @@ import google.registry.model.domain.Period;
import google.registry.model.domain.Period.Unit; import google.registry.model.domain.Period.Unit;
import google.registry.model.eppcommon.Trid; import google.registry.model.eppcommon.Trid;
import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage;
import google.registry.persistence.VKey;
import java.util.Set; import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.persistence.ElementCollection; import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded; import javax.persistence.Embedded;
import javax.persistence.Transient;
import org.joda.time.DateTime; import org.joda.time.DateTime;
/** /**
@ -47,7 +51,16 @@ public class TransferData extends BaseTransferObject implements Buildable {
public static final TransferData EMPTY = new TransferData(); public static final TransferData EMPTY = new TransferData();
/** The transaction id of the most recent transfer request (or null if there never was one). */ /** The transaction id of the most recent transfer request (or null if there never was one). */
@Embedded Trid transferRequestTrid; @Embedded
@AttributeOverrides({
@AttributeOverride(
name = "serverTransactionId",
column = @Column(name = "transfer_server_txn_id")),
@AttributeOverride(
name = "clientTransactionId",
column = @Column(name = "transfer_client_txn_id"))
})
Trid transferRequestTrid;
/** /**
* The period to extend the registration upon completion of the transfer. * The period to extend the registration upon completion of the transfer.
@ -55,23 +68,29 @@ public class TransferData extends BaseTransferObject implements Buildable {
* <p>By default, domain transfers are for one year. This can be changed to zero by using the * <p>By default, domain transfers are for one year. This can be changed to zero by using the
* superuser EPP extension. * superuser EPP extension.
*/ */
@Embedded Period transferPeriod = Period.create(1, Unit.YEARS); @Embedded
@AttributeOverrides({
@AttributeOverride(name = "unit", column = @Column(name = "transfer_renew_period_unit")),
@AttributeOverride(name = "value", column = @Column(name = "transfer_renew_period_value"))
})
Period transferPeriod = Period.create(1, Unit.YEARS);
/** /**
* The registration expiration time resulting from the approval - speculative or actual - of the * The registration expiration time resulting from the approval - speculative or actual - of the
* most recent transfer request, applicable for domains only. * most recent transfer request, applicable for domains only.
* *
* <p>For pending transfers, this is the expiration time that will take effect under a projected * <p>For pending transfers, this is the expiration time that will take effect under a projected
* server approval. For approved transfers, this is the actual expiration time of the domain as * server approval. For approved transfers, this is the actual expiration time of the domain as of
* of the moment of transfer completion. For rejected or cancelled transfers, this field will be * the moment of transfer completion. For rejected or cancelled transfers, this field will be
* reset to null. * reset to null.
* *
* <p>Note that even when this field is set, it does not necessarily mean that the post-transfer * <p>Note that even when this field is set, it does not necessarily mean that the post-transfer
* domain has a new expiration time. Superuser transfers may not include a bundled 1 year renewal * domain has a new expiration time. Superuser transfers may not include a bundled 1 year renewal
* at all, or even when a renewal is bundled, for a transfer during the autorenew grace period the * at all, or even when a renewal is bundled, for a transfer during the autorenew grace period the
* bundled renewal simply subsumes the recent autorenewal, resulting in the same expiration time. * bundled renewal simply subsumes the recent autorenewal, resulting in the same expiration time.
*/ */
// TODO(b/36405140): backfill this field for existing domains to which it should apply. // TODO(b/36405140): backfill this field for existing domains to which it should apply.
@Column(name = "transfer_registration_expiration_time")
DateTime transferredRegistrationExpirationTime; DateTime transferredRegistrationExpirationTime;
/** /**
@ -83,18 +102,35 @@ public class TransferData extends BaseTransferObject implements Buildable {
* pending transfer is explicitly approved, rejected or cancelled, the referenced entities should * pending transfer is explicitly approved, rejected or cancelled, the referenced entities should
* be deleted. * be deleted.
*/ */
@Transient
@IgnoreSave(IfNull.class) @IgnoreSave(IfNull.class)
@ElementCollection Set<VKey<? extends TransferServerApproveEntity>> serverApproveEntities;
Set<Key<? extends TransferServerApproveEntity>> serverApproveEntities;
// The following 3 fields are the replacement for serverApproveEntities in Cloud SQL.
// TODO(shicong): Add getter/setter for these 3 fields and use them in the application code.
@Ignore
@Column(name = "transfer_gaining_poll_message_id")
Long gainingTransferPollMessageId;
@Ignore
@Column(name = "transfer_losing_poll_message_id")
Long losingTransferPollMessageId;
@Ignore
@Column(name = "transfer_billing_cancellation_id")
Long billingCancellationId;
/** /**
* The regular one-time billing event that will be charged for a server-approved transfer. * The regular one-time billing event that will be charged for a server-approved transfer.
* *
* <p>This field should be null if there is not currently a pending transfer or if the object * <p>This field should be null if there is not currently a pending transfer or if the object
* being transferred is not a domain. * being transferred is not a domain.
*
* <p>TODO(b/158230654) Remove unused columns for TransferData in Contact table.
*/ */
@IgnoreSave(IfNull.class) @IgnoreSave(IfNull.class)
Key<BillingEvent.OneTime> serverApproveBillingEvent; @Column(name = "transfer_billing_event_id")
VKey<BillingEvent.OneTime> serverApproveBillingEvent;
/** /**
* The autorenew billing event that should be associated with this resource after the transfer. * The autorenew billing event that should be associated with this resource after the transfer.
@ -103,7 +139,8 @@ public class TransferData extends BaseTransferObject implements Buildable {
* being transferred is not a domain. * being transferred is not a domain.
*/ */
@IgnoreSave(IfNull.class) @IgnoreSave(IfNull.class)
Key<BillingEvent.Recurring> serverApproveAutorenewEvent; @Column(name = "transfer_billing_recurrence_id")
VKey<BillingEvent.Recurring> serverApproveAutorenewEvent;
/** /**
* The autorenew poll message that should be associated with this resource after the transfer. * The autorenew poll message that should be associated with this resource after the transfer.
@ -112,7 +149,8 @@ public class TransferData extends BaseTransferObject implements Buildable {
* being transferred is not a domain. * being transferred is not a domain.
*/ */
@IgnoreSave(IfNull.class) @IgnoreSave(IfNull.class)
Key<PollMessage.Autorenew> serverApproveAutorenewPollMessage; @Column(name = "transfer_autorenew_poll_message_id")
VKey<PollMessage.Autorenew> serverApproveAutorenewPollMessage;
@Nullable @Nullable
public Trid getTransferRequestTrid() { public Trid getTransferRequestTrid() {
@ -128,22 +166,22 @@ public class TransferData extends BaseTransferObject implements Buildable {
return transferredRegistrationExpirationTime; return transferredRegistrationExpirationTime;
} }
public ImmutableSet<Key<? extends TransferServerApproveEntity>> getServerApproveEntities() { public ImmutableSet<VKey<? extends TransferServerApproveEntity>> getServerApproveEntities() {
return nullToEmptyImmutableCopy(serverApproveEntities); return nullToEmptyImmutableCopy(serverApproveEntities);
} }
@Nullable @Nullable
public Key<BillingEvent.OneTime> getServerApproveBillingEvent() { public VKey<BillingEvent.OneTime> getServerApproveBillingEvent() {
return serverApproveBillingEvent; return serverApproveBillingEvent;
} }
@Nullable @Nullable
public Key<BillingEvent.Recurring> getServerApproveAutorenewEvent() { public VKey<BillingEvent.Recurring> getServerApproveAutorenewEvent() {
return serverApproveAutorenewEvent; return serverApproveAutorenewEvent;
} }
@Nullable @Nullable
public Key<PollMessage.Autorenew> getServerApproveAutorenewPollMessage() { public VKey<PollMessage.Autorenew> getServerApproveAutorenewPollMessage() {
return serverApproveAutorenewPollMessage; return serverApproveAutorenewPollMessage;
} }
@ -202,25 +240,25 @@ public class TransferData extends BaseTransferObject implements Buildable {
} }
public Builder setServerApproveEntities( public Builder setServerApproveEntities(
ImmutableSet<Key<? extends TransferServerApproveEntity>> serverApproveEntities) { ImmutableSet<VKey<? extends TransferServerApproveEntity>> serverApproveEntities) {
getInstance().serverApproveEntities = serverApproveEntities; getInstance().serverApproveEntities = serverApproveEntities;
return this; return this;
} }
public Builder setServerApproveBillingEvent( public Builder setServerApproveBillingEvent(
Key<BillingEvent.OneTime> serverApproveBillingEvent) { VKey<BillingEvent.OneTime> serverApproveBillingEvent) {
getInstance().serverApproveBillingEvent = serverApproveBillingEvent; getInstance().serverApproveBillingEvent = serverApproveBillingEvent;
return this; return this;
} }
public Builder setServerApproveAutorenewEvent( public Builder setServerApproveAutorenewEvent(
Key<BillingEvent.Recurring> serverApproveAutorenewEvent) { VKey<BillingEvent.Recurring> serverApproveAutorenewEvent) {
getInstance().serverApproveAutorenewEvent = serverApproveAutorenewEvent; getInstance().serverApproveAutorenewEvent = serverApproveAutorenewEvent;
return this; return this;
} }
public Builder setServerApproveAutorenewPollMessage( public Builder setServerApproveAutorenewPollMessage(
Key<PollMessage.Autorenew> serverApproveAutorenewPollMessage) { VKey<PollMessage.Autorenew> serverApproveAutorenewPollMessage) {
getInstance().serverApproveAutorenewPollMessage = serverApproveAutorenewPollMessage; getInstance().serverApproveAutorenewPollMessage = serverApproveAutorenewPollMessage;
return this; return this;
} }
@ -230,5 +268,7 @@ public class TransferData extends BaseTransferObject implements Buildable {
* Marker interface for objects that are written in anticipation of a server approval, and * Marker interface for objects that are written in anticipation of a server approval, and
* therefore need to be deleted under any other outcome. * therefore need to be deleted under any other outcome.
*/ */
public interface TransferServerApproveEntity {} public interface TransferServerApproveEntity {
VKey<? extends TransferServerApproveEntity> createVKey();
}
} }

View file

@ -17,6 +17,7 @@ package google.registry.persistence;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
import com.googlecode.objectify.Key;
import google.registry.model.ImmutableObject; import google.registry.model.ImmutableObject;
import java.util.Optional; import java.util.Optional;
@ -57,6 +58,23 @@ public class VKey<T> extends ImmutableObject {
return new VKey(kind, ofyKey, null); return new VKey(kind, ofyKey, null);
} }
/**
* Creates a {@link VKey} which only contains the ofy primary key by specifying the id of the
* {@link Key}.
*/
public static <T> VKey<T> createOfy(Class<? extends T> kind, long id) {
return createOfy(kind, Key.create(kind, id));
}
/**
* Creates a {@link VKey} which only contains the ofy primary key by specifying the name of the
* {@link Key}.
*/
public static <T> VKey<T> createOfy(Class<? extends T> kind, String name) {
checkArgumentNotNull(kind, "name must not be null");
return createOfy(kind, Key.create(kind, name));
}
/** Creates a {@link VKey} which only contains both sql and ofy primary key. */ /** Creates a {@link VKey} which only contains both sql and ofy primary key. */
public static <T> VKey<T> create( public static <T> VKey<T> create(
Class<? extends T> kind, Object sqlKey, com.googlecode.objectify.Key ofyKey) { Class<? extends T> kind, Object sqlKey, com.googlecode.objectify.Key ofyKey) {

View file

@ -0,0 +1,37 @@
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.persistence.converter;
import google.registry.model.transfer.TransferData.TransferServerApproveEntity;
import google.registry.persistence.VKey;
import java.util.Set;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
/** {@link AttributeConverter} for {@link Set}. */
@Converter(autoApply = true)
public class TransferServerApproveEntitySetConverter
extends StringSetConverterBase<VKey<? extends TransferServerApproveEntity>> {
@Override
String toString(VKey<? extends TransferServerApproveEntity> element) {
return String.valueOf(element.getSqlKey());
}
@Override
VKey<? extends TransferServerApproveEntity> fromString(String value) {
return VKey.createSql(TransferServerApproveEntity.class, Long.parseLong(value));
}
}

View file

@ -56,15 +56,18 @@
<class>google.registry.persistence.converter.StringListConverter</class> <class>google.registry.persistence.converter.StringListConverter</class>
<class>google.registry.persistence.converter.StringSetConverter</class> <class>google.registry.persistence.converter.StringSetConverter</class>
<class>google.registry.persistence.converter.TldStateTransitionConverter</class> <class>google.registry.persistence.converter.TldStateTransitionConverter</class>
<class>google.registry.persistence.converter.TransferServerApproveEntitySetConverter</class>
<class>google.registry.persistence.converter.UpdateAutoTimestampConverter</class> <class>google.registry.persistence.converter.UpdateAutoTimestampConverter</class>
<class>google.registry.persistence.converter.ZonedDateTimeConverter</class> <class>google.registry.persistence.converter.ZonedDateTimeConverter</class>
<!-- Generated converters for VKey --> <!-- Generated converters for VKey -->
<class>google.registry.model.billing.VKeyConverter_BillingEvent</class> <class>google.registry.model.billing.VKeyConverter_BillingEvent</class>
<class>google.registry.model.domain.VKeyConverter_DomainBase</class> <class>google.registry.model.domain.VKeyConverter_DomainBase</class>
<class>google.registry.model.contact.VKeyConverter_ContactResource</class>
<class>google.registry.model.domain.token.VKeyConverter_AllocationToken</class> <class>google.registry.model.domain.token.VKeyConverter_AllocationToken</class>
<class>google.registry.model.host.VKeyConverter_HostResource</class> <class>google.registry.model.host.VKeyConverter_HostResource</class>
<class>google.registry.model.contact.VKeyConverter_ContactResource</class> <class>google.registry.model.poll.VKeyConverter_Autorenew</class>
<class>google.registry.model.poll.VKeyConverter_OneTime</class>
<!-- TODO(weiminyu): check out application-layer validation. --> <!-- TODO(weiminyu): check out application-layer validation. -->
<validation-mode>NONE</validation-mode> <validation-mode>NONE</validation-mode>

View file

@ -52,6 +52,7 @@ import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferData;
import google.registry.model.transfer.TransferStatus; import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -129,9 +130,13 @@ public class ContactTransferRequestFlowTest
// poll messages, the approval notice ones for gaining and losing registrars. // poll messages, the approval notice ones for gaining and losing registrars.
assertPollMessagesEqual( assertPollMessagesEqual(
Iterables.filter( Iterables.filter(
ofy().load() ofy()
.load()
// Use toArray() to coerce the type to something keys() will accept. // Use toArray() to coerce the type to something keys() will accept.
.keys(contact.getTransferData().getServerApproveEntities().toArray(new Key<?>[]{})) .keys(
contact.getTransferData().getServerApproveEntities().stream()
.map(VKey::getOfyKey)
.toArray(Key[]::new))
.values(), .values(),
PollMessage.class), PollMessage.class),
ImmutableList.of(gainingApproveMessage, losingApproveMessage)); ImmutableList.of(gainingApproveMessage, losingApproveMessage));

View file

@ -93,6 +93,7 @@ import google.registry.model.reporting.HistoryEntry;
import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferData;
import google.registry.model.transfer.TransferResponse; import google.registry.model.transfer.TransferResponse;
import google.registry.model.transfer.TransferStatus; import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import google.registry.testing.TaskQueueHelper.TaskMatcher; import google.registry.testing.TaskQueueHelper.TaskMatcher;
import java.util.Map; import java.util.Map;
import org.joda.money.Money; import org.joda.money.Money;
@ -668,13 +669,24 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow,
.setPendingTransferExpirationTime(clock.nowUtc()) .setPendingTransferExpirationTime(clock.nowUtc())
.build()); .build());
// The server-approve entities should all be deleted. // The server-approve entities should all be deleted.
assertThat(ofy().load().key(oldTransferData.getServerApproveBillingEvent()).now()).isNull(); assertThat(ofy().load().key(oldTransferData.getServerApproveBillingEvent().getOfyKey()).now())
assertThat(ofy().load().key(oldTransferData.getServerApproveAutorenewEvent()).now()).isNull(); .isNull();
assertThat(ofy().load().key(oldTransferData.getServerApproveAutorenewPollMessage()).now()) assertThat(ofy().load().key(oldTransferData.getServerApproveAutorenewEvent().getOfyKey()).now())
.isNull();
assertThat(
ofy()
.load()
.key(oldTransferData.getServerApproveAutorenewPollMessage().getOfyKey())
.now())
.isNull(); .isNull();
assertThat(oldTransferData.getServerApproveEntities()).isNotEmpty(); // Just a sanity check. assertThat(oldTransferData.getServerApproveEntities()).isNotEmpty(); // Just a sanity check.
assertThat( assertThat(
ofy().load().keys(oldTransferData.getServerApproveEntities().toArray(new Key<?>[] {}))) ofy()
.load()
.keys(
oldTransferData.getServerApproveEntities().stream()
.map(VKey::getOfyKey)
.toArray(Key[]::new)))
.isEmpty(); .isEmpty();
} }

View file

@ -27,6 +27,7 @@ import static google.registry.model.registry.Registry.TldState.QUIET_PERIOD;
import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL; import static google.registry.model.reporting.DomainTransactionRecord.TransactionReportField.TRANSFER_SUCCESSFUL;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE;
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_TRANSFER_REQUEST;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatastoreHelper.assertBillingEvents; import static google.registry.testing.DatastoreHelper.assertBillingEvents;
import static google.registry.testing.DatastoreHelper.assertBillingEventsEqual; import static google.registry.testing.DatastoreHelper.assertBillingEventsEqual;
import static google.registry.testing.DatastoreHelper.assertPollMessagesEqual; import static google.registry.testing.DatastoreHelper.assertPollMessagesEqual;
@ -290,13 +291,13 @@ public class DomainTransferRequestFlowTest
// Assert that the domain's TransferData server-approve billing events match the above. // Assert that the domain's TransferData server-approve billing events match the above.
if (expectTransferBillingEvent) { if (expectTransferBillingEvent) {
assertBillingEventsEqual( assertBillingEventsEqual(
ofy().load().key(domain.getTransferData().getServerApproveBillingEvent()).now(), tm().load(domain.getTransferData().getServerApproveBillingEvent()),
optionalTransferBillingEvent.get()); optionalTransferBillingEvent.get());
} else { } else {
assertThat(domain.getTransferData().getServerApproveBillingEvent()).isNull(); assertThat(domain.getTransferData().getServerApproveBillingEvent()).isNull();
} }
assertBillingEventsEqual( assertBillingEventsEqual(
ofy().load().key(domain.getTransferData().getServerApproveAutorenewEvent()).now(), tm().load(domain.getTransferData().getServerApproveAutorenewEvent()),
gainingClientAutorenew); gainingClientAutorenew);
// Assert that the full set of server-approve billing events is exactly the extra ones plus // Assert that the full set of server-approve billing events is exactly the extra ones plus
// the transfer billing event (if present) and the gaining client autorenew. // the transfer billing event (if present) and the gaining client autorenew.
@ -309,7 +310,10 @@ public class DomainTransferRequestFlowTest
ofy() ofy()
.load() .load()
// Use toArray() to coerce the type to something keys() will accept. // Use toArray() to coerce the type to something keys() will accept.
.keys(domain.getTransferData().getServerApproveEntities().toArray(new Key<?>[] {})) .keys(
domain.getTransferData().getServerApproveEntities().stream()
.map(VKey::getOfyKey)
.toArray(Key[]::new))
.values(), .values(),
BillingEvent.class), BillingEvent.class),
Sets.union(expectedServeApproveBillingEvents, extraBillingEvents)); Sets.union(expectedServeApproveBillingEvents, extraBillingEvents));
@ -410,7 +414,7 @@ public class DomainTransferRequestFlowTest
// Assert that the poll messages show up in the TransferData server approve entities. // Assert that the poll messages show up in the TransferData server approve entities.
assertPollMessagesEqual( assertPollMessagesEqual(
ofy().load().key(domain.getTransferData().getServerApproveAutorenewPollMessage()).now(), tm().load(domain.getTransferData().getServerApproveAutorenewPollMessage()),
autorenewPollMessage); autorenewPollMessage);
// Assert that the full set of server-approve poll messages is exactly the server approve // Assert that the full set of server-approve poll messages is exactly the server approve
// OneTime messages to gaining and losing registrars plus the gaining client autorenew. // OneTime messages to gaining and losing registrars plus the gaining client autorenew.
@ -419,7 +423,10 @@ public class DomainTransferRequestFlowTest
ofy() ofy()
.load() .load()
// Use toArray() to coerce the type to something keys() will accept. // Use toArray() to coerce the type to something keys() will accept.
.keys(domain.getTransferData().getServerApproveEntities().toArray(new Key<?>[] {})) .keys(
domain.getTransferData().getServerApproveEntities().stream()
.map(VKey::getOfyKey)
.toArray(Key[]::new))
.values(), .values(),
PollMessage.class), PollMessage.class),
ImmutableList.of( ImmutableList.of(

View file

@ -29,7 +29,6 @@ import static org.junit.Assert.assertThrows;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.EntityTestCase; import google.registry.model.EntityTestCase;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
import google.registry.model.contact.Disclose.PostalInfoChoice; import google.registry.model.contact.Disclose.PostalInfoChoice;
@ -114,7 +113,7 @@ public class ContactResourceTest extends EntityTestCase {
.setLosingClientId("losing") .setLosingClientId("losing")
.setPendingTransferExpirationTime(fakeClock.nowUtc()) .setPendingTransferExpirationTime(fakeClock.nowUtc())
.setServerApproveEntities( .setServerApproveEntities(
ImmutableSet.of(Key.create(BillingEvent.OneTime.class, 1))) ImmutableSet.of(VKey.createOfy(BillingEvent.OneTime.class, 1)))
.setTransferRequestTime(fakeClock.nowUtc()) .setTransferRequestTime(fakeClock.nowUtc())
.setTransferStatus(TransferStatus.SERVER_APPROVED) .setTransferStatus(TransferStatus.SERVER_APPROVED)
.setTransferRequestTrid(Trid.create("client-trid", "server-trid")) .setTransferRequestTrid(Trid.create("client-trid", "server-trid"))
@ -134,6 +133,8 @@ public class ContactResourceTest extends EntityTestCase {
saveRegistrar("registrar1"); saveRegistrar("registrar1");
saveRegistrar("registrar2"); saveRegistrar("registrar2");
saveRegistrar("registrar3"); saveRegistrar("registrar3");
saveRegistrar("gaining");
saveRegistrar("losing");
jpaTm().transact(() -> jpaTm().saveNew(originalContact)); jpaTm().transact(() -> jpaTm().saveNew(originalContact));
ContactResource persisted = ContactResource persisted =
jpaTm() jpaTm()
@ -141,15 +142,17 @@ public class ContactResourceTest extends EntityTestCase {
() -> () ->
jpaTm() jpaTm()
.load(VKey.createSql(ContactResource.class, originalContact.getRepoId()))); .load(VKey.createSql(ContactResource.class, originalContact.getRepoId())));
// TODO(b/153378849): Remove the hard code for postal info after resolving the issue that
// @PostLoad doesn't work in Address
ContactResource fixed = ContactResource fixed =
originalContact originalContact
.asBuilder() .asBuilder()
.setCreationTime(persisted.getCreationTime()) .setCreationTime(persisted.getCreationTime())
.setInternationalizedPostalInfo(persisted.getInternationalizedPostalInfo()) .setTransferData(
.setLocalizedPostalInfo(persisted.getLocalizedPostalInfo()) originalContact
.setTransferData(null) .getTransferData()
.asBuilder()
.setServerApproveEntities(null)
.build())
.build(); .build();
assertThat(persisted).isEqualTo(fixed); assertThat(persisted).isEqualTo(fixed);
} }

View file

@ -138,10 +138,16 @@ public class DomainBaseTest extends EntityTestCase {
.setLosingClientId("losing") .setLosingClientId("losing")
.setPendingTransferExpirationTime(fakeClock.nowUtc()) .setPendingTransferExpirationTime(fakeClock.nowUtc())
.setServerApproveEntities( .setServerApproveEntities(
ImmutableSet.of(oneTimeBillKey, recurringBillKey, autorenewPollKey)) ImmutableSet.of(
.setServerApproveBillingEvent(oneTimeBillKey) VKey.createOfy(BillingEvent.OneTime.class, oneTimeBillKey),
.setServerApproveAutorenewEvent(recurringBillKey) VKey.createOfy(BillingEvent.Recurring.class, recurringBillKey),
.setServerApproveAutorenewPollMessage(autorenewPollKey) VKey.createOfy(PollMessage.Autorenew.class, autorenewPollKey)))
.setServerApproveBillingEvent(
VKey.createOfy(BillingEvent.OneTime.class, oneTimeBillKey))
.setServerApproveAutorenewEvent(
VKey.createOfy(BillingEvent.Recurring.class, recurringBillKey))
.setServerApproveAutorenewPollMessage(
VKey.createOfy(PollMessage.Autorenew.class, autorenewPollKey))
.setTransferRequestTime(fakeClock.nowUtc().plusDays(1)) .setTransferRequestTime(fakeClock.nowUtc().plusDays(1))
.setTransferStatus(TransferStatus.SERVER_APPROVED) .setTransferStatus(TransferStatus.SERVER_APPROVED)
.setTransferRequestTrid(Trid.create("client-trid", "server-trid")) .setTransferRequestTrid(Trid.create("client-trid", "server-trid"))
@ -363,8 +369,8 @@ public class DomainBaseTest extends EntityTestCase {
.setTransferRequestTime(fakeClock.nowUtc().minusDays(4)) .setTransferRequestTime(fakeClock.nowUtc().minusDays(4))
.setPendingTransferExpirationTime(fakeClock.nowUtc().plusDays(1)) .setPendingTransferExpirationTime(fakeClock.nowUtc().plusDays(1))
.setGainingClientId("winner") .setGainingClientId("winner")
.setServerApproveBillingEvent(Key.create(transferBillingEvent)) .setServerApproveBillingEvent(transferBillingEvent.createVKey())
.setServerApproveEntities(ImmutableSet.of(Key.create(transferBillingEvent))) .setServerApproveEntities(ImmutableSet.of(transferBillingEvent.createVKey()))
.build()) .build())
.addGracePeriod( .addGracePeriod(
// Okay for billing event to be null since the point of this grace period is just // Okay for billing event to be null since the point of this grace period is just
@ -375,7 +381,7 @@ public class DomainBaseTest extends EntityTestCase {
DomainBase afterTransfer = domain.cloneProjectedAtTime(fakeClock.nowUtc().plusDays(1)); DomainBase afterTransfer = domain.cloneProjectedAtTime(fakeClock.nowUtc().plusDays(1));
DateTime newExpirationTime = oldExpirationTime.plusYears(1); DateTime newExpirationTime = oldExpirationTime.plusYears(1);
Key<BillingEvent.Recurring> serverApproveAutorenewEvent = Key<BillingEvent.Recurring> serverApproveAutorenewEvent =
domain.getTransferData().getServerApproveAutorenewEvent(); domain.getTransferData().getServerApproveAutorenewEvent().getOfyKey();
assertTransferred(afterTransfer, newExpirationTime, serverApproveAutorenewEvent); assertTransferred(afterTransfer, newExpirationTime, serverApproveAutorenewEvent);
assertThat(afterTransfer.getGracePeriods()) assertThat(afterTransfer.getGracePeriods())
.containsExactly( .containsExactly(
@ -746,8 +752,10 @@ public class DomainBaseTest extends EntityTestCase {
.setPendingTransferExpirationTime(transferExpirationTime) .setPendingTransferExpirationTime(transferExpirationTime)
.setTransferStatus(TransferStatus.PENDING) .setTransferStatus(TransferStatus.PENDING)
.setGainingClientId("TheRegistrar") .setGainingClientId("TheRegistrar")
.setServerApproveAutorenewEvent(recurringBillKey) .setServerApproveAutorenewEvent(
.setServerApproveBillingEvent(oneTimeBillKey) VKey.createOfy(BillingEvent.Recurring.class, recurringBillKey))
.setServerApproveBillingEvent(
VKey.createOfy(BillingEvent.OneTime.class, oneTimeBillKey))
.build(); .build();
domain = domain =
persistResource( persistResource(

View file

@ -26,7 +26,6 @@ import static org.junit.Assert.assertThrows;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.net.InetAddresses; import com.google.common.net.InetAddresses;
import com.googlecode.objectify.Key;
import google.registry.model.EntityTestCase; import google.registry.model.EntityTestCase;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
@ -34,6 +33,7 @@ import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid; import google.registry.model.eppcommon.Trid;
import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferData;
import google.registry.model.transfer.TransferStatus; import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -63,7 +63,7 @@ public class HostResourceTest extends EntityTestCase {
.setLosingClientId("losing") .setLosingClientId("losing")
.setPendingTransferExpirationTime(fakeClock.nowUtc()) .setPendingTransferExpirationTime(fakeClock.nowUtc())
.setServerApproveEntities( .setServerApproveEntities(
ImmutableSet.of(Key.create(BillingEvent.OneTime.class, 1))) ImmutableSet.of(VKey.createOfy(BillingEvent.OneTime.class, 1)))
.setTransferRequestTime(fakeClock.nowUtc()) .setTransferRequestTime(fakeClock.nowUtc())
.setTransferStatus(TransferStatus.SERVER_APPROVED) .setTransferStatus(TransferStatus.SERVER_APPROVED)
.setTransferRequestTrid(Trid.create("client-trid", "server-trid")) .setTransferRequestTrid(Trid.create("client-trid", "server-trid"))

View file

@ -18,11 +18,11 @@ import static com.google.common.truth.Truth.assertThat;
import static org.joda.time.DateTimeZone.UTC; import static org.joda.time.DateTimeZone.UTC;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
import google.registry.model.domain.Period; import google.registry.model.domain.Period;
import google.registry.model.eppcommon.Trid; import google.registry.model.eppcommon.Trid;
import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage;
import google.registry.persistence.VKey;
import google.registry.testing.AppEngineRule; import google.registry.testing.AppEngineRule;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.Before; import org.junit.Before;
@ -40,19 +40,19 @@ public class TransferDataTest {
private final DateTime now = DateTime.now(UTC); private final DateTime now = DateTime.now(UTC);
private Key<BillingEvent.OneTime> transferBillingEventKey; private VKey<BillingEvent.OneTime> transferBillingEventKey;
private Key<BillingEvent.Cancellation> otherServerApproveBillingEventKey; private VKey<BillingEvent.Cancellation> otherServerApproveBillingEventKey;
private Key<BillingEvent.Recurring> recurringBillingEventKey; private VKey<BillingEvent.Recurring> recurringBillingEventKey;
private Key<PollMessage.Autorenew> autorenewPollMessageKey; private VKey<PollMessage.Autorenew> autorenewPollMessageKey;
private Key<PollMessage.OneTime> otherServerApprovePollMessageKey; private VKey<PollMessage.OneTime> otherServerApprovePollMessageKey;
@Before @Before
public void setUp() { public void setUp() {
transferBillingEventKey = Key.create(BillingEvent.OneTime.class, 12345); transferBillingEventKey = VKey.createOfy(BillingEvent.OneTime.class, 12345);
otherServerApproveBillingEventKey = Key.create(BillingEvent.Cancellation.class, 2468); otherServerApproveBillingEventKey = VKey.createOfy(BillingEvent.Cancellation.class, 2468);
recurringBillingEventKey = Key.create(BillingEvent.Recurring.class, 13579); recurringBillingEventKey = VKey.createOfy(BillingEvent.Recurring.class, 13579);
autorenewPollMessageKey = Key.create(PollMessage.Autorenew.class, 67890); autorenewPollMessageKey = VKey.createOfy(PollMessage.Autorenew.class, 67890);
otherServerApprovePollMessageKey = Key.create(PollMessage.OneTime.class, 314159); otherServerApprovePollMessageKey = VKey.createOfy(PollMessage.OneTime.class, 314159);
} }
@Test @Test
@ -67,7 +67,8 @@ public class TransferDataTest {
.setTransferPeriod(Period.create(5, Period.Unit.YEARS)) .setTransferPeriod(Period.create(5, Period.Unit.YEARS))
.build(); .build();
TransferData fullTransferData = TransferData fullTransferData =
constantTransferData.asBuilder() constantTransferData
.asBuilder()
.setPendingTransferExpirationTime(now) .setPendingTransferExpirationTime(now)
.setTransferStatus(TransferStatus.PENDING) .setTransferStatus(TransferStatus.PENDING)
.setServerApproveEntities( .setServerApproveEntities(

View file

@ -332,10 +332,9 @@ public class DomainBaseToXjcConverterTest {
.setGainingClientId("gaining") .setGainingClientId("gaining")
.setLosingClientId("losing") .setLosingClientId("losing")
.setPendingTransferExpirationTime(DateTime.parse("1925-04-20T00:00:00Z")) .setPendingTransferExpirationTime(DateTime.parse("1925-04-20T00:00:00Z"))
.setServerApproveBillingEvent(Key.create(billingEvent)) .setServerApproveBillingEvent(billingEvent.createVKey())
.setServerApproveAutorenewEvent( .setServerApproveAutorenewEvent(
Key.create( persistResource(
persistResource(
new BillingEvent.Recurring.Builder() new BillingEvent.Recurring.Builder()
.setReason(Reason.RENEW) .setReason(Reason.RENEW)
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) .setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
@ -344,10 +343,10 @@ public class DomainBaseToXjcConverterTest {
.setEventTime(END_OF_TIME) .setEventTime(END_OF_TIME)
.setRecurrenceEndTime(END_OF_TIME) .setRecurrenceEndTime(END_OF_TIME)
.setParent(historyEntry) .setParent(historyEntry)
.build()))) .build())
.createVKey())
.setServerApproveAutorenewPollMessage( .setServerApproveAutorenewPollMessage(
Key.create( persistResource(
persistResource(
new Autorenew.Builder() new Autorenew.Builder()
.setTargetId("example.xn--q9jyb4c") .setTargetId("example.xn--q9jyb4c")
.setClientId("TheRegistrar") .setClientId("TheRegistrar")
@ -355,8 +354,9 @@ public class DomainBaseToXjcConverterTest {
.setAutorenewEndTime(END_OF_TIME) .setAutorenewEndTime(END_OF_TIME)
.setMsg("Domain was auto-renewed.") .setMsg("Domain was auto-renewed.")
.setParent(historyEntry) .setParent(historyEntry)
.build()))) .build())
.setServerApproveEntities(ImmutableSet.of(Key.create(billingEvent))) .createVKey())
.setServerApproveEntities(ImmutableSet.of(billingEvent.createVKey()))
.setTransferRequestTime(DateTime.parse("1919-01-01T00:00:00Z")) .setTransferRequestTime(DateTime.parse("1919-01-01T00:00:00Z"))
.setTransferStatus(TransferStatus.PENDING) .setTransferStatus(TransferStatus.PENDING)
.setTransferredRegistrationExpirationTime( .setTransferredRegistrationExpirationTime(

View file

@ -174,10 +174,9 @@ final class RdeFixtures {
.setGainingClientId("gaining") .setGainingClientId("gaining")
.setLosingClientId("losing") .setLosingClientId("losing")
.setPendingTransferExpirationTime(DateTime.parse("1993-04-20T00:00:00Z")) .setPendingTransferExpirationTime(DateTime.parse("1993-04-20T00:00:00Z"))
.setServerApproveBillingEvent(Key.create(billingEvent)) .setServerApproveBillingEvent(billingEvent.createVKey())
.setServerApproveAutorenewEvent( .setServerApproveAutorenewEvent(
Key.create( persistResource(
persistResource(
new BillingEvent.Recurring.Builder() new BillingEvent.Recurring.Builder()
.setReason(Reason.RENEW) .setReason(Reason.RENEW)
.setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) .setFlags(ImmutableSet.of(Flag.AUTO_RENEW))
@ -186,10 +185,10 @@ final class RdeFixtures {
.setEventTime(END_OF_TIME) .setEventTime(END_OF_TIME)
.setRecurrenceEndTime(END_OF_TIME) .setRecurrenceEndTime(END_OF_TIME)
.setParent(historyEntry) .setParent(historyEntry)
.build()))) .build())
.createVKey())
.setServerApproveAutorenewPollMessage( .setServerApproveAutorenewPollMessage(
Key.create( persistResource(
persistResource(
new Autorenew.Builder() new Autorenew.Builder()
.setTargetId("example." + tld) .setTargetId("example." + tld)
.setClientId("TheRegistrar") .setClientId("TheRegistrar")
@ -197,8 +196,9 @@ final class RdeFixtures {
.setAutorenewEndTime(END_OF_TIME) .setAutorenewEndTime(END_OF_TIME)
.setMsg("Domain was auto-renewed.") .setMsg("Domain was auto-renewed.")
.setParent(historyEntry) .setParent(historyEntry)
.build()))) .build())
.setServerApproveEntities(ImmutableSet.of(Key.create(billingEvent))) .createVKey())
.setServerApproveEntities(ImmutableSet.of(billingEvent.createVKey()))
.setTransferRequestTime(DateTime.parse("1991-01-01T00:00:00Z")) .setTransferRequestTime(DateTime.parse("1991-01-01T00:00:00Z"))
.setTransferStatus(TransferStatus.PENDING) .setTransferStatus(TransferStatus.PENDING)
.setTransferredRegistrationExpirationTime( .setTransferredRegistrationExpirationTime(

View file

@ -443,32 +443,37 @@ public class DatastoreHelper {
.setParent(contact) .setParent(contact)
.build()); .build());
return persistResource( return persistResource(
contact.asBuilder() contact
.asBuilder()
.setPersistedCurrentSponsorClientId("TheRegistrar") .setPersistedCurrentSponsorClientId("TheRegistrar")
.addStatusValue(StatusValue.PENDING_TRANSFER) .addStatusValue(StatusValue.PENDING_TRANSFER)
.setTransferData(createTransferDataBuilder(requestTime, expirationTime) .setTransferData(
createTransferDataBuilder(requestTime, expirationTime)
.setPendingTransferExpirationTime(now.plus(getContactAutomaticTransferLength())) .setPendingTransferExpirationTime(now.plus(getContactAutomaticTransferLength()))
.setServerApproveEntities( .setServerApproveEntities(
ImmutableSet.of( ImmutableSet.of(
// Pretend it's 3 days since the request // Pretend it's 3 days since the request
Key.create(persistResource( persistResource(
createPollMessageForImplicitTransfer( createPollMessageForImplicitTransfer(
contact, contact,
historyEntryContactTransfer, historyEntryContactTransfer,
"NewRegistrar", "NewRegistrar",
requestTime, requestTime,
expirationTime, expirationTime,
null))), null))
Key.create(persistResource( .createVKey(),
createPollMessageForImplicitTransfer( persistResource(
contact, createPollMessageForImplicitTransfer(
historyEntryContactTransfer, contact,
"TheRegistrar", historyEntryContactTransfer,
requestTime, "TheRegistrar",
expirationTime, requestTime,
null))))) expirationTime,
.setTransferRequestTrid(Trid.create("transferClient-trid", "transferServer-trid")) null))
.build()) .createVKey()))
.setTransferRequestTrid(
Trid.create("transferClient-trid", "transferServer-trid"))
.build())
.build()); .build());
} }
@ -585,38 +590,46 @@ public class DatastoreHelper {
} }
TransferData.Builder transferDataBuilder = TransferData.Builder transferDataBuilder =
createTransferDataBuilder(requestTime, expirationTime); createTransferDataBuilder(requestTime, expirationTime);
return persistResource(domain.asBuilder() return persistResource(
.setPersistedCurrentSponsorClientId("TheRegistrar") domain
.addStatusValue(StatusValue.PENDING_TRANSFER) .asBuilder()
.setTransferData(transferDataBuilder .setPersistedCurrentSponsorClientId("TheRegistrar")
.setPendingTransferExpirationTime(expirationTime) .addStatusValue(StatusValue.PENDING_TRANSFER)
.setTransferredRegistrationExpirationTime(extendedRegistrationExpirationTime) .setTransferData(
.setServerApproveBillingEvent(Key.create(transferBillingEvent)) transferDataBuilder
.setServerApproveAutorenewEvent(Key.create(gainingClientAutorenewEvent)) .setPendingTransferExpirationTime(expirationTime)
.setServerApproveAutorenewPollMessage(Key.create(gainingClientAutorenewPollMessage)) .setTransferredRegistrationExpirationTime(extendedRegistrationExpirationTime)
.setServerApproveEntities(ImmutableSet.of( .setServerApproveBillingEvent(transferBillingEvent.createVKey())
Key.create(transferBillingEvent), .setServerApproveAutorenewEvent(gainingClientAutorenewEvent.createVKey())
Key.create(gainingClientAutorenewEvent), .setServerApproveAutorenewPollMessage(
Key.create(gainingClientAutorenewPollMessage), gainingClientAutorenewPollMessage.createVKey())
Key.create(persistResource( .setServerApproveEntities(
createPollMessageForImplicitTransfer( ImmutableSet.of(
domain, transferBillingEvent.createVKey(),
historyEntryDomainTransfer, gainingClientAutorenewEvent.createVKey(),
"NewRegistrar", gainingClientAutorenewPollMessage.createVKey(),
requestTime, persistResource(
expirationTime, createPollMessageForImplicitTransfer(
extendedRegistrationExpirationTime))), domain,
Key.create(persistResource( historyEntryDomainTransfer,
createPollMessageForImplicitTransfer( "NewRegistrar",
domain, requestTime,
historyEntryDomainTransfer, expirationTime,
"TheRegistrar", extendedRegistrationExpirationTime))
requestTime, .createVKey(),
expirationTime, persistResource(
extendedRegistrationExpirationTime))))) createPollMessageForImplicitTransfer(
.setTransferRequestTrid(Trid.create("transferClient-trid", "transferServer-trid")) domain,
.build()) historyEntryDomainTransfer,
.build()); "TheRegistrar",
requestTime,
expirationTime,
extendedRegistrationExpirationTime))
.createVKey()))
.setTransferRequestTrid(
Trid.create("transferClient-trid", "transferServer-trid"))
.build())
.build());
} }
/** Persists and returns a {@link Registrar} with the specified attributes. */ /** Persists and returns a {@link Registrar} with the specified attributes. */

View file

@ -716,15 +716,15 @@ class google.registry.model.tmch.TmchCrl {
org.joda.time.DateTime updated; org.joda.time.DateTime updated;
} }
class google.registry.model.transfer.TransferData { class google.registry.model.transfer.TransferData {
com.googlecode.objectify.Key<google.registry.model.billing.BillingEvent$OneTime> serverApproveBillingEvent;
com.googlecode.objectify.Key<google.registry.model.billing.BillingEvent$Recurring> serverApproveAutorenewEvent;
com.googlecode.objectify.Key<google.registry.model.poll.PollMessage$Autorenew> serverApproveAutorenewPollMessage;
google.registry.model.domain.Period transferPeriod; google.registry.model.domain.Period transferPeriod;
google.registry.model.eppcommon.Trid transferRequestTrid; google.registry.model.eppcommon.Trid transferRequestTrid;
google.registry.model.transfer.TransferStatus transferStatus; google.registry.model.transfer.TransferStatus transferStatus;
google.registry.persistence.VKey<google.registry.model.billing.BillingEvent$OneTime> serverApproveBillingEvent;
google.registry.persistence.VKey<google.registry.model.billing.BillingEvent$Recurring> serverApproveAutorenewEvent;
google.registry.persistence.VKey<google.registry.model.poll.PollMessage$Autorenew> serverApproveAutorenewPollMessage;
java.lang.String gainingClientId; java.lang.String gainingClientId;
java.lang.String losingClientId; java.lang.String losingClientId;
java.util.Set<com.googlecode.objectify.Key<? extends google.registry.model.transfer.TransferData$TransferServerApproveEntity>> serverApproveEntities; java.util.Set<google.registry.persistence.VKey<? extends google.registry.model.transfer.TransferData$TransferServerApproveEntity>> serverApproveEntities;
org.joda.time.DateTime pendingTransferExpirationTime; org.joda.time.DateTime pendingTransferExpirationTime;
org.joda.time.DateTime transferRequestTime; org.joda.time.DateTime transferRequestTime;
org.joda.time.DateTime transferredRegistrationExpirationTime; org.joda.time.DateTime transferredRegistrationExpirationTime;

View file

@ -0,0 +1,84 @@
-- Copyright 2020 The Nomulus Authors. All Rights Reserved.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
alter table "Contact"
add column transfer_gaining_poll_message_id int8,
add column transfer_losing_poll_message_id int8,
add column transfer_billing_cancellation_id int8,
add column transfer_billing_event_id int8,
add column transfer_billing_recurrence_id int8,
add column transfer_autorenew_poll_message_id int8,
add column transfer_renew_period_unit text,
add column transfer_renew_period_value int4,
add column transfer_client_txn_id text,
add column transfer_server_txn_id text,
add column transfer_registration_expiration_time timestamptz,
add column transfer_gaining_registrar_id text,
add column transfer_losing_registrar_id text,
add column transfer_pending_expiration_time timestamptz,
add column transfer_request_time timestamptz,
add column transfer_status text;
alter table "Domain"
add column transfer_gaining_poll_message_id int8,
add column transfer_losing_poll_message_id int8,
add column transfer_billing_cancellation_id int8,
add column transfer_billing_event_id int8,
add column transfer_billing_recurrence_id int8,
add column transfer_autorenew_poll_message_id int8,
add column transfer_renew_period_unit text,
add column transfer_renew_period_value int4,
add column transfer_client_txn_id text,
add column transfer_server_txn_id text,
add column transfer_registration_expiration_time timestamptz,
add column transfer_gaining_registrar_id text,
add column transfer_losing_registrar_id text,
add column transfer_pending_expiration_time timestamptz,
add column transfer_request_time timestamptz,
add column transfer_status text;
alter table if exists "Contact"
add constraint fk_contact_transfer_gaining_registrar_id
foreign key (transfer_gaining_registrar_id)
references "Registrar";
alter table if exists "Contact"
add constraint fk_contact_transfer_losing_registrar_id
foreign key (transfer_losing_registrar_id)
references "Registrar";
alter table if exists "Domain"
add constraint fk_domain_transfer_gaining_registrar_id
foreign key (transfer_gaining_registrar_id)
references "Registrar";
alter table if exists "Domain"
add constraint fk_domain_transfer_losing_registrar_id
foreign key (transfer_losing_registrar_id)
references "Registrar";
alter table if exists "Domain"
add constraint fk_domain_transfer_billing_cancellation_id
foreign key (transfer_billing_cancellation_id)
references "BillingCancellation";
alter table if exists "Domain"
add constraint fk_domain_transfer_billing_event_id
foreign key (transfer_billing_event_id)
references "BillingEvent";
alter table if exists "Domain"
add constraint fk_domain_transfer_billing_recurrence_id
foreign key (transfer_billing_recurrence_id)
references "BillingRecurrence";

View file

@ -118,6 +118,22 @@
addr_local_org text, addr_local_org text,
addr_local_type text, addr_local_type text,
search_name text, search_name text,
transfer_billing_cancellation_id int8,
transfer_gaining_poll_message_id int8,
transfer_losing_poll_message_id int8,
transfer_billing_recurrence_id int8,
transfer_autorenew_poll_message_id int8,
transfer_billing_event_id int8,
transfer_renew_period_unit text,
transfer_renew_period_value int4,
transfer_client_txn_id text,
transfer_server_txn_id text,
transfer_registration_expiration_time timestamptz,
transfer_gaining_registrar_id text,
transfer_losing_registrar_id text,
transfer_pending_expiration_time timestamptz,
transfer_request_time timestamptz,
transfer_status text,
voice_phone_extension text, voice_phone_extension text,
voice_phone_number text, voice_phone_number text,
primary key (repo_id) primary key (repo_id)
@ -165,6 +181,22 @@
subordinate_hosts text[], subordinate_hosts text[],
tech_contact text, tech_contact text,
tld text, tld text,
transfer_billing_cancellation_id int8,
transfer_gaining_poll_message_id int8,
transfer_losing_poll_message_id int8,
transfer_billing_recurrence_id int8,
transfer_autorenew_poll_message_id int8,
transfer_billing_event_id int8,
transfer_renew_period_unit text,
transfer_renew_period_value int4,
transfer_client_txn_id text,
transfer_server_txn_id text,
transfer_registration_expiration_time timestamptz,
transfer_gaining_registrar_id text,
transfer_losing_registrar_id text,
transfer_pending_expiration_time timestamptz,
transfer_request_time timestamptz,
transfer_status text,
primary key (repo_id) primary key (repo_id)
); );

View file

@ -241,7 +241,23 @@ CREATE TABLE public."Contact" (
addr_local_type text, addr_local_type text,
search_name text, search_name text,
voice_phone_extension text, voice_phone_extension text,
voice_phone_number text voice_phone_number text,
transfer_gaining_poll_message_id bigint,
transfer_losing_poll_message_id bigint,
transfer_billing_cancellation_id bigint,
transfer_billing_event_id bigint,
transfer_billing_recurrence_id bigint,
transfer_autorenew_poll_message_id bigint,
transfer_renew_period_unit text,
transfer_renew_period_value integer,
transfer_client_txn_id text,
transfer_server_txn_id text,
transfer_registration_expiration_time timestamp with time zone,
transfer_gaining_registrar_id text,
transfer_losing_registrar_id text,
transfer_pending_expiration_time timestamp with time zone,
transfer_request_time timestamp with time zone,
transfer_status text
); );
@ -286,7 +302,23 @@ CREATE TABLE public."Domain" (
admin_contact text, admin_contact text,
billing_contact text, billing_contact text,
registrant_contact text, registrant_contact text,
tech_contact text tech_contact text,
transfer_gaining_poll_message_id bigint,
transfer_losing_poll_message_id bigint,
transfer_billing_cancellation_id bigint,
transfer_billing_event_id bigint,
transfer_billing_recurrence_id bigint,
transfer_autorenew_poll_message_id bigint,
transfer_renew_period_unit text,
transfer_renew_period_value integer,
transfer_client_txn_id text,
transfer_server_txn_id text,
transfer_registration_expiration_time timestamp with time zone,
transfer_gaining_registrar_id text,
transfer_losing_registrar_id text,
transfer_pending_expiration_time timestamp with time zone,
transfer_request_time timestamp with time zone,
transfer_status text
); );
@ -1127,6 +1159,22 @@ ALTER TABLE ONLY public."BillingRecurrence"
ADD CONSTRAINT fk_billing_recurrence_client_id FOREIGN KEY (client_id) REFERENCES public."Registrar"(client_id); ADD CONSTRAINT fk_billing_recurrence_client_id FOREIGN KEY (client_id) REFERENCES public."Registrar"(client_id);
--
-- Name: Contact fk_contact_transfer_gaining_registrar_id; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."Contact"
ADD CONSTRAINT fk_contact_transfer_gaining_registrar_id FOREIGN KEY (transfer_gaining_registrar_id) REFERENCES public."Registrar"(client_id);
--
-- Name: Contact fk_contact_transfer_losing_registrar_id; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."Contact"
ADD CONSTRAINT fk_contact_transfer_losing_registrar_id FOREIGN KEY (transfer_losing_registrar_id) REFERENCES public."Registrar"(client_id);
-- --
-- Name: Domain fk_domain_admin_contact; Type: FK CONSTRAINT; Schema: public; Owner: - -- Name: Domain fk_domain_admin_contact; Type: FK CONSTRAINT; Schema: public; Owner: -
-- --
@ -1159,6 +1207,46 @@ ALTER TABLE ONLY public."Domain"
ADD CONSTRAINT fk_domain_tech_contact FOREIGN KEY (tech_contact) REFERENCES public."Contact"(repo_id); ADD CONSTRAINT fk_domain_tech_contact FOREIGN KEY (tech_contact) REFERENCES public."Contact"(repo_id);
--
-- Name: Domain fk_domain_transfer_billing_cancellation_id; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."Domain"
ADD CONSTRAINT fk_domain_transfer_billing_cancellation_id FOREIGN KEY (transfer_billing_cancellation_id) REFERENCES public."BillingCancellation"(billing_cancellation_id);
--
-- Name: Domain fk_domain_transfer_billing_event_id; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."Domain"
ADD CONSTRAINT fk_domain_transfer_billing_event_id FOREIGN KEY (transfer_billing_event_id) REFERENCES public."BillingEvent"(billing_event_id);
--
-- Name: Domain fk_domain_transfer_billing_recurrence_id; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."Domain"
ADD CONSTRAINT fk_domain_transfer_billing_recurrence_id FOREIGN KEY (transfer_billing_recurrence_id) REFERENCES public."BillingRecurrence"(billing_recurrence_id);
--
-- Name: Domain fk_domain_transfer_gaining_registrar_id; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."Domain"
ADD CONSTRAINT fk_domain_transfer_gaining_registrar_id FOREIGN KEY (transfer_gaining_registrar_id) REFERENCES public."Registrar"(client_id);
--
-- Name: Domain fk_domain_transfer_losing_registrar_id; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."Domain"
ADD CONSTRAINT fk_domain_transfer_losing_registrar_id FOREIGN KEY (transfer_losing_registrar_id) REFERENCES public."Registrar"(client_id);
-- --
-- Name: DomainHost fk_domainhost_host_valid; Type: FK CONSTRAINT; Schema: public; Owner: - -- Name: DomainHost fk_domainhost_host_valid; Type: FK CONSTRAINT; Schema: public; Owner: -
-- --