diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java index ab8dd92f7..d6d8c8e63 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferApproveFlow.java @@ -97,7 +97,7 @@ public final class ContactTransferApproveFlow implements TransactionalFlow { ofy().save().entities(newContact, historyEntry, gainingPollMessage); // Delete the billing event and poll messages that were written in case the transfer would have // been implicitly server approved. - ofy().delete().keys(existingContact.getTransferData().getServerApproveEntities()); + tm().delete(existingContact.getTransferData().getServerApproveEntities()); return responseBuilder .setResData(createTransferResponse(targetId, newContact.getTransferData())) .build(); diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java index fc0c797ce..aba875007 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferCancelFlow.java @@ -93,7 +93,7 @@ public final class ContactTransferCancelFlow implements TransactionalFlow { ofy().save().entities(newContact, historyEntry, losingPollMessage); // Delete the billing event and poll messages that were written in case the transfer would have // been implicitly server approved. - ofy().delete().keys(existingContact.getTransferData().getServerApproveEntities()); + tm().delete(existingContact.getTransferData().getServerApproveEntities()); return responseBuilder .setResData(createTransferResponse(targetId, newContact.getTransferData())) .build(); diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java index 64311ee09..6b7af9fa9 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferRejectFlow.java @@ -90,7 +90,7 @@ public final class ContactTransferRejectFlow implements TransactionalFlow { ofy().save().entities(newContact, historyEntry, gainingPollMessage); // Delete the billing event and poll messages that were written in case the transfer would have // been implicitly server approved. - ofy().delete().keys(existingContact.getTransferData().getServerApproveEntities()); + tm().delete(existingContact.getTransferData().getServerApproveEntities()); return responseBuilder .setResData(createTransferResponse(targetId, newContact.getTransferData())) .build(); diff --git a/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java b/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java index f256352d6..51eb43bf7 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactTransferRequestFlow.java @@ -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. */ PollMessage serverApproveGainingPollMessage = createGainingTransferPollMessage(targetId, serverApproveTransferData, historyEntry); - TransferData pendingTransferData = serverApproveTransferData.asBuilder() - .setTransferStatus(TransferStatus.PENDING) - .setServerApproveEntities( - ImmutableSet.of( - Key.create(serverApproveGainingPollMessage), - Key.create(serverApproveLosingPollMessage))) - .build(); + TransferData pendingTransferData = + serverApproveTransferData + .asBuilder() + .setTransferStatus(TransferStatus.PENDING) + .setServerApproveEntities( + ImmutableSet.of( + serverApproveGainingPollMessage.createVKey(), + serverApproveLosingPollMessage.createVKey())) + .build(); // When a transfer is requested, a poll message is created to notify the losing registrar. PollMessage requestPollMessage = createLosingTransferPollMessage(targetId, pendingTransferData, historyEntry).asBuilder() diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java index 9d51b8c7f..5096b989d 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java @@ -214,7 +214,7 @@ public final class DomainTransferApproveFlow implements TransactionalFlow { ofy().save().entities(entitiesToSave.build()); // Delete the billing event and poll messages that were written in case the transfer would have // been implicitly server approved. - ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities()); + tm().delete(existingDomain.getTransferData().getServerApproveEntities()); return responseBuilder .setResData(createTransferResponse( targetId, newDomain.getTransferData(), newDomain.getRegistrationExpirationTime())) diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferCancelFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferCancelFlow.java index 7543d2cd9..8a8fa1d07 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferCancelFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferCancelFlow.java @@ -110,7 +110,7 @@ public final class DomainTransferCancelFlow implements TransactionalFlow { updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME); // Delete the billing event and poll messages that were written in case the transfer would have // been implicitly server approved. - ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities()); + tm().delete(existingDomain.getTransferData().getServerApproveEntities()); return responseBuilder .setResData(createTransferResponse(targetId, newDomain.getTransferData(), null)) .build(); diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java index bf7093410..f5a35974b 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferRejectFlow.java @@ -112,7 +112,7 @@ public final class DomainTransferRejectFlow implements TransactionalFlow { updateAutorenewRecurrenceEndTime(existingDomain, END_OF_TIME); // Delete the billing event and poll messages that were written in case the transfer would have // been implicitly server approved. - ofy().delete().keys(existingDomain.getTransferData().getServerApproveEntities()); + tm().delete(existingDomain.getTransferData().getServerApproveEntities()); return responseBuilder .setResData(createTransferResponse(targetId, newDomain.getTransferData(), null)) .build(); diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferUtils.java b/core/src/main/java/google/registry/flows/domain/DomainTransferUtils.java index 49bab34c4..baad641c3 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferUtils.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferUtils.java @@ -20,7 +20,6 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import com.googlecode.objectify.Key; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent.Flag; import google.registry.model.billing.BillingEvent.Reason; @@ -37,6 +36,7 @@ import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferData.TransferServerApproveEntity; import google.registry.model.transfer.TransferResponse.DomainTransferResponse; import google.registry.model.transfer.TransferStatus; +import google.registry.persistence.VKey; import java.util.Optional; import javax.annotation.Nullable; import org.joda.money.Money; @@ -52,37 +52,34 @@ public final class DomainTransferUtils { TransferData.Builder transferDataBuilder, ImmutableSet serverApproveEntities, Period transferPeriod) { - ImmutableSet.Builder> serverApproveEntityKeys = + ImmutableSet.Builder> serverApproveEntityKeys = new ImmutableSet.Builder<>(); for (TransferServerApproveEntity entity : serverApproveEntities) { - serverApproveEntityKeys.add(Key.create(entity)); + serverApproveEntityKeys.add(entity.createVKey()); } if (transferPeriod.getValue() != 0) { // Unless superuser sets period to 0, add a transfer billing event. transferDataBuilder.setServerApproveBillingEvent( - Key.create( - serverApproveEntities - .stream() - .filter(BillingEvent.OneTime.class::isInstance) - .map(BillingEvent.OneTime.class::cast) - .collect(onlyElement()))); + serverApproveEntities.stream() + .filter(BillingEvent.OneTime.class::isInstance) + .map(BillingEvent.OneTime.class::cast) + .collect(onlyElement()) + .createVKey()); } return transferDataBuilder .setTransferStatus(TransferStatus.PENDING) .setServerApproveAutorenewEvent( - Key.create( - serverApproveEntities - .stream() - .filter(BillingEvent.Recurring.class::isInstance) - .map(BillingEvent.Recurring.class::cast) - .collect(onlyElement()))) + serverApproveEntities.stream() + .filter(BillingEvent.Recurring.class::isInstance) + .map(BillingEvent.Recurring.class::cast) + .collect(onlyElement()) + .createVKey()) .setServerApproveAutorenewPollMessage( - Key.create( - serverApproveEntities - .stream() - .filter(PollMessage.Autorenew.class::isInstance) - .map(PollMessage.Autorenew.class::cast) - .collect(onlyElement()))) + serverApproveEntities.stream() + .filter(PollMessage.Autorenew.class::isInstance) + .map(PollMessage.Autorenew.class::cast) + .collect(onlyElement()) + .createVKey()) .setServerApproveEntities(serverApproveEntityKeys.build()) .setTransferPeriod(transferPeriod) .build(); diff --git a/core/src/main/java/google/registry/model/ResourceTransferUtils.java b/core/src/main/java/google/registry/model/ResourceTransferUtils.java index 169d7cc5f..e5ccd8f24 100644 --- a/core/src/main/java/google/registry/model/ResourceTransferUtils.java +++ b/core/src/main/java/google/registry/model/ResourceTransferUtils.java @@ -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.checkState; 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.ImmutableSet; @@ -114,7 +115,7 @@ public final class ResourceTransferUtils { R resource, R newResource, DateTime now, HistoryEntry historyEntry) { if (resource.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) { TransferData oldTransferData = resource.getTransferData(); - ofy().delete().keys(oldTransferData.getServerApproveEntities()); + tm().delete(oldTransferData.getServerApproveEntities()); ofy() .save() .entity( diff --git a/core/src/main/java/google/registry/model/billing/BillingEvent.java b/core/src/main/java/google/registry/model/billing/BillingEvent.java index 7184e60c0..5fe81c82e 100644 --- a/core/src/main/java/google/registry/model/billing/BillingEvent.java +++ b/core/src/main/java/google/registry/model/billing/BillingEvent.java @@ -345,6 +345,7 @@ public abstract class BillingEvent extends ImmutableObject return Optional.ofNullable(allocationToken); } + @Override public VKey createVKey() { return VKey.createOfy(getClass(), Key.create(this)); } @@ -482,6 +483,7 @@ public abstract class BillingEvent extends ImmutableObject return recurrenceTimeOfYear; } + @Override public VKey createVKey() { return VKey.createOfy(getClass(), Key.create(this)); } @@ -603,6 +605,7 @@ public abstract class BillingEvent extends ImmutableObject return builder.build(); } + @Override public VKey createVKey() { return VKey.createOfy(getClass(), Key.create(this)); } @@ -682,6 +685,11 @@ public abstract class BillingEvent extends ImmutableObject return new Builder(clone(this)); } + @Override + public VKey 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 * and that is parented off the given HistoryEntry. diff --git a/core/src/main/java/google/registry/model/contact/ContactResource.java b/core/src/main/java/google/registry/model/contact/ContactResource.java index de1308c1d..ef5fb0562 100644 --- a/core/src/main/java/google/registry/model/contact/ContactResource.java +++ b/core/src/main/java/google/registry/model/contact/ContactResource.java @@ -41,7 +41,6 @@ import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; import javax.persistence.Column; import javax.persistence.Embedded; -import javax.persistence.Transient; import javax.xml.bind.annotation.XmlElement; import org.joda.time.DateTime; @@ -171,8 +170,7 @@ public class ContactResource extends EppResource ContactAuthInfo authInfo; /** Data about any pending or past transfers on this contact. */ - // TODO(b/153363295): Figure out how to persist transfer data - @Transient TransferData transferData; + TransferData transferData; /** * The time that this resource was last transferred. diff --git a/core/src/main/java/google/registry/model/domain/DomainBase.java b/core/src/main/java/google/registry/model/domain/DomainBase.java index bc37c4d93..04d8f6ffe 100644 --- a/core/src/main/java/google/registry/model/domain/DomainBase.java +++ b/core/src/main/java/google/registry/model/domain/DomainBase.java @@ -253,7 +253,7 @@ public class DomainBase extends EppResource String smdId; /** Data about any pending or past transfers on this domain. */ - @Transient TransferData transferData; + TransferData transferData; /** * The time that this resource was last transferred. @@ -438,8 +438,14 @@ public class DomainBase extends EppResource .setRegistrationExpirationTime(expirationDate) // Set the speculatively-written new autorenew events as the domain's autorenew // events. - .setAutorenewBillingEvent(transferData.getServerApproveAutorenewEvent()) - .setAutorenewPollMessage(transferData.getServerApproveAutorenewPollMessage()); + .setAutorenewBillingEvent( + transferData.getServerApproveAutorenewEvent() == null + ? null + : transferData.getServerApproveAutorenewEvent().getOfyKey()) + .setAutorenewPollMessage( + transferData.getServerApproveAutorenewPollMessage() == null + ? null + : transferData.getServerApproveAutorenewPollMessage().getOfyKey()); 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. @@ -450,7 +456,9 @@ public class DomainBase extends EppResource transferExpirationTime.plus( Registry.get(getTld()).getTransferGracePeriodLength()), transferData.getGainingClientId(), - transferData.getServerApproveBillingEvent()))); + transferData.getServerApproveBillingEvent() == null + ? null + : transferData.getServerApproveBillingEvent().getOfyKey()))); } else { // There won't be a billing event, so we don't need a grace period builder.setGracePeriods(ImmutableSet.of()); diff --git a/core/src/main/java/google/registry/model/domain/Period.java b/core/src/main/java/google/registry/model/domain/Period.java index 9a98f0cc4..9960acc38 100644 --- a/core/src/main/java/google/registry/model/domain/Period.java +++ b/core/src/main/java/google/registry/model/domain/Period.java @@ -16,6 +16,8 @@ package google.registry.model.domain; import com.googlecode.objectify.annotation.Embed; import google.registry.model.ImmutableObject; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlEnumValue; import javax.xml.bind.annotation.XmlValue; @@ -25,6 +27,7 @@ import javax.xml.bind.annotation.XmlValue; @javax.persistence.Embeddable public class Period extends ImmutableObject { + @Enumerated(EnumType.STRING) @XmlAttribute Unit unit; diff --git a/core/src/main/java/google/registry/model/poll/PollMessage.java b/core/src/main/java/google/registry/model/poll/PollMessage.java index 3976941cd..c26a09302 100644 --- a/core/src/main/java/google/registry/model/poll/PollMessage.java +++ b/core/src/main/java/google/registry/model/poll/PollMessage.java @@ -43,6 +43,7 @@ import google.registry.model.transfer.TransferData.TransferServerApproveEntity; import google.registry.model.transfer.TransferResponse; import google.registry.model.transfer.TransferResponse.ContactTransferResponse; import google.registry.model.transfer.TransferResponse.DomainTransferResponse; +import google.registry.persistence.VKey; import google.registry.persistence.WithLongVKey; import java.util.List; import java.util.Optional; @@ -150,6 +151,9 @@ public abstract class PollMessage extends ImmutableObject public abstract ImmutableList getResponseData(); + @Override + public abstract VKey createVKey(); + /** Override Buildable.asBuilder() to give this method stronger typing. */ @Override public abstract Builder asBuilder(); @@ -291,6 +295,11 @@ public abstract class PollMessage extends ImmutableObject @Column(name = "transfer_response_contact_id") String contactId; + @Override + public VKey createVKey() { + return VKey.createOfy(this.getClass(), Key.create(this)); + } + @Override public Builder asBuilder() { return new Builder(clone(this)); @@ -387,6 +396,11 @@ public abstract class PollMessage extends ImmutableObject return autorenewEndTime; } + @Override + public VKey createVKey() { + return VKey.createOfy(this.getClass(), Key.create(this)); + } + @Override public ImmutableList getResponseData() { // Note that the event time is when the auto-renew occured, so the expiration time in the diff --git a/core/src/main/java/google/registry/model/transfer/BaseTransferObject.java b/core/src/main/java/google/registry/model/transfer/BaseTransferObject.java index 09807b336..a6e2f1939 100644 --- a/core/src/main/java/google/registry/model/transfer/BaseTransferObject.java +++ b/core/src/main/java/google/registry/model/transfer/BaseTransferObject.java @@ -16,6 +16,7 @@ package google.registry.model.transfer; import google.registry.model.Buildable.GenericBuilder; import google.registry.model.ImmutableObject; +import javax.persistence.Column; import javax.persistence.EnumType; import javax.persistence.Enumerated; 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. */ @XmlElement(name = "reID") + @Column(name = "transfer_gaining_registrar_id") String gainingClientId; /** 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. */ @XmlElement(name = "acID") + @Column(name = "transfer_losing_registrar_id") 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. */ @XmlElement(name = "acDate") + @Column(name = "transfer_pending_expiration_time") DateTime pendingTransferExpirationTime; public TransferStatus getTransferStatus() { diff --git a/core/src/main/java/google/registry/model/transfer/TransferData.java b/core/src/main/java/google/registry/model/transfer/TransferData.java index 89ab9fbea..442bebbfc 100644 --- a/core/src/main/java/google/registry/model/transfer/TransferData.java +++ b/core/src/main/java/google/registry/model/transfer/TransferData.java @@ -17,8 +17,8 @@ package google.registry.model.transfer; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import com.google.common.collect.ImmutableSet; -import com.googlecode.objectify.Key; import com.googlecode.objectify.annotation.Embed; +import com.googlecode.objectify.annotation.Ignore; import com.googlecode.objectify.annotation.IgnoreSave; import com.googlecode.objectify.annotation.Unindex; 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.eppcommon.Trid; import google.registry.model.poll.PollMessage; +import google.registry.persistence.VKey; import java.util.Set; 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.Transient; import org.joda.time.DateTime; /** @@ -47,7 +51,16 @@ public class TransferData extends BaseTransferObject implements Buildable { public static final TransferData EMPTY = new TransferData(); /** 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. @@ -55,23 +68,29 @@ public class TransferData extends BaseTransferObject implements Buildable { *

By default, domain transfers are for one year. This can be changed to zero by using the * 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 * most recent transfer request, applicable for domains only. * *

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 - * of the moment of transfer completion. For rejected or cancelled transfers, this field will be + * server approval. For approved transfers, this is the actual expiration time of the domain as of + * the moment of transfer completion. For rejected or cancelled transfers, this field will be * reset to null. * *

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 * 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. + @Column(name = "transfer_registration_expiration_time") 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 * be deleted. */ + @Transient @IgnoreSave(IfNull.class) - @ElementCollection - Set> serverApproveEntities; + Set> 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. * *

This field should be null if there is not currently a pending transfer or if the object * being transferred is not a domain. + * + *

TODO(b/158230654) Remove unused columns for TransferData in Contact table. */ @IgnoreSave(IfNull.class) - Key serverApproveBillingEvent; + @Column(name = "transfer_billing_event_id") + VKey serverApproveBillingEvent; /** * 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. */ @IgnoreSave(IfNull.class) - Key serverApproveAutorenewEvent; + @Column(name = "transfer_billing_recurrence_id") + VKey serverApproveAutorenewEvent; /** * 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. */ @IgnoreSave(IfNull.class) - Key serverApproveAutorenewPollMessage; + @Column(name = "transfer_autorenew_poll_message_id") + VKey serverApproveAutorenewPollMessage; @Nullable public Trid getTransferRequestTrid() { @@ -128,22 +166,22 @@ public class TransferData extends BaseTransferObject implements Buildable { return transferredRegistrationExpirationTime; } - public ImmutableSet> getServerApproveEntities() { + public ImmutableSet> getServerApproveEntities() { return nullToEmptyImmutableCopy(serverApproveEntities); } @Nullable - public Key getServerApproveBillingEvent() { + public VKey getServerApproveBillingEvent() { return serverApproveBillingEvent; } @Nullable - public Key getServerApproveAutorenewEvent() { + public VKey getServerApproveAutorenewEvent() { return serverApproveAutorenewEvent; } @Nullable - public Key getServerApproveAutorenewPollMessage() { + public VKey getServerApproveAutorenewPollMessage() { return serverApproveAutorenewPollMessage; } @@ -202,25 +240,25 @@ public class TransferData extends BaseTransferObject implements Buildable { } public Builder setServerApproveEntities( - ImmutableSet> serverApproveEntities) { + ImmutableSet> serverApproveEntities) { getInstance().serverApproveEntities = serverApproveEntities; return this; } public Builder setServerApproveBillingEvent( - Key serverApproveBillingEvent) { + VKey serverApproveBillingEvent) { getInstance().serverApproveBillingEvent = serverApproveBillingEvent; return this; } public Builder setServerApproveAutorenewEvent( - Key serverApproveAutorenewEvent) { + VKey serverApproveAutorenewEvent) { getInstance().serverApproveAutorenewEvent = serverApproveAutorenewEvent; return this; } public Builder setServerApproveAutorenewPollMessage( - Key serverApproveAutorenewPollMessage) { + VKey serverApproveAutorenewPollMessage) { getInstance().serverApproveAutorenewPollMessage = serverApproveAutorenewPollMessage; 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 * therefore need to be deleted under any other outcome. */ - public interface TransferServerApproveEntity {} + public interface TransferServerApproveEntity { + VKey createVKey(); + } } diff --git a/core/src/main/java/google/registry/persistence/VKey.java b/core/src/main/java/google/registry/persistence/VKey.java index ff985e9a6..06404fb66 100644 --- a/core/src/main/java/google/registry/persistence/VKey.java +++ b/core/src/main/java/google/registry/persistence/VKey.java @@ -17,6 +17,7 @@ package google.registry.persistence; import static com.google.common.base.Preconditions.checkState; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; +import com.googlecode.objectify.Key; import google.registry.model.ImmutableObject; import java.util.Optional; @@ -57,6 +58,23 @@ public class VKey extends ImmutableObject { 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 VKey createOfy(Class 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 VKey createOfy(Class 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. */ public static VKey create( Class kind, Object sqlKey, com.googlecode.objectify.Key ofyKey) { diff --git a/core/src/main/java/google/registry/persistence/converter/TransferServerApproveEntitySetConverter.java b/core/src/main/java/google/registry/persistence/converter/TransferServerApproveEntitySetConverter.java new file mode 100644 index 000000000..67f1f6a22 --- /dev/null +++ b/core/src/main/java/google/registry/persistence/converter/TransferServerApproveEntitySetConverter.java @@ -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> { + + @Override + String toString(VKey element) { + return String.valueOf(element.getSqlKey()); + } + + @Override + VKey fromString(String value) { + return VKey.createSql(TransferServerApproveEntity.class, Long.parseLong(value)); + } +} diff --git a/core/src/main/resources/META-INF/persistence.xml b/core/src/main/resources/META-INF/persistence.xml index 7f413cc12..8c3317f42 100644 --- a/core/src/main/resources/META-INF/persistence.xml +++ b/core/src/main/resources/META-INF/persistence.xml @@ -56,15 +56,18 @@ google.registry.persistence.converter.StringListConverter google.registry.persistence.converter.StringSetConverter google.registry.persistence.converter.TldStateTransitionConverter + google.registry.persistence.converter.TransferServerApproveEntitySetConverter google.registry.persistence.converter.UpdateAutoTimestampConverter google.registry.persistence.converter.ZonedDateTimeConverter google.registry.model.billing.VKeyConverter_BillingEvent google.registry.model.domain.VKeyConverter_DomainBase + google.registry.model.contact.VKeyConverter_ContactResource google.registry.model.domain.token.VKeyConverter_AllocationToken google.registry.model.host.VKeyConverter_HostResource - google.registry.model.contact.VKeyConverter_ContactResource + google.registry.model.poll.VKeyConverter_Autorenew + google.registry.model.poll.VKeyConverter_OneTime NONE diff --git a/core/src/test/java/google/registry/flows/contact/ContactTransferRequestFlowTest.java b/core/src/test/java/google/registry/flows/contact/ContactTransferRequestFlowTest.java index 0bff7d139..bcc0dbaec 100644 --- a/core/src/test/java/google/registry/flows/contact/ContactTransferRequestFlowTest.java +++ b/core/src/test/java/google/registry/flows/contact/ContactTransferRequestFlowTest.java @@ -52,6 +52,7 @@ import google.registry.model.poll.PollMessage; import google.registry.model.reporting.HistoryEntry; import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferStatus; +import google.registry.persistence.VKey; import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; @@ -129,9 +130,13 @@ public class ContactTransferRequestFlowTest // poll messages, the approval notice ones for gaining and losing registrars. assertPollMessagesEqual( Iterables.filter( - ofy().load() + ofy() + .load() // 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(), PollMessage.class), ImmutableList.of(gainingApproveMessage, losingApproveMessage)); diff --git a/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java index a1643daf9..88f6c8398 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainDeleteFlowTest.java @@ -93,6 +93,7 @@ import google.registry.model.reporting.HistoryEntry; import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferResponse; import google.registry.model.transfer.TransferStatus; +import google.registry.persistence.VKey; import google.registry.testing.TaskQueueHelper.TaskMatcher; import java.util.Map; import org.joda.money.Money; @@ -668,13 +669,24 @@ public class DomainDeleteFlowTest extends ResourceFlowTestCase[] {}))) + ofy() + .load() + .keys( + oldTransferData.getServerApproveEntities().stream() + .map(VKey::getOfyKey) + .toArray(Key[]::new))) .isEmpty(); } diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java index a263ea38a..3877cbebf 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java @@ -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.HistoryEntry.Type.DOMAIN_CREATE; 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.assertBillingEventsEqual; 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. if (expectTransferBillingEvent) { assertBillingEventsEqual( - ofy().load().key(domain.getTransferData().getServerApproveBillingEvent()).now(), + tm().load(domain.getTransferData().getServerApproveBillingEvent()), optionalTransferBillingEvent.get()); } else { assertThat(domain.getTransferData().getServerApproveBillingEvent()).isNull(); } assertBillingEventsEqual( - ofy().load().key(domain.getTransferData().getServerApproveAutorenewEvent()).now(), + tm().load(domain.getTransferData().getServerApproveAutorenewEvent()), gainingClientAutorenew); // 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. @@ -309,7 +310,10 @@ public class DomainTransferRequestFlowTest ofy() .load() // 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(), BillingEvent.class), Sets.union(expectedServeApproveBillingEvents, extraBillingEvents)); @@ -410,7 +414,7 @@ public class DomainTransferRequestFlowTest // Assert that the poll messages show up in the TransferData server approve entities. assertPollMessagesEqual( - ofy().load().key(domain.getTransferData().getServerApproveAutorenewPollMessage()).now(), + tm().load(domain.getTransferData().getServerApproveAutorenewPollMessage()), autorenewPollMessage); // 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. @@ -419,7 +423,10 @@ public class DomainTransferRequestFlowTest ofy() .load() // 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(), PollMessage.class), ImmutableList.of( diff --git a/core/src/test/java/google/registry/model/contact/ContactResourceTest.java b/core/src/test/java/google/registry/model/contact/ContactResourceTest.java index 799057faf..b745a0f11 100644 --- a/core/src/test/java/google/registry/model/contact/ContactResourceTest.java +++ b/core/src/test/java/google/registry/model/contact/ContactResourceTest.java @@ -29,7 +29,6 @@ import static org.junit.Assert.assertThrows; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import com.googlecode.objectify.Key; import google.registry.model.EntityTestCase; import google.registry.model.billing.BillingEvent; import google.registry.model.contact.Disclose.PostalInfoChoice; @@ -114,7 +113,7 @@ public class ContactResourceTest extends EntityTestCase { .setLosingClientId("losing") .setPendingTransferExpirationTime(fakeClock.nowUtc()) .setServerApproveEntities( - ImmutableSet.of(Key.create(BillingEvent.OneTime.class, 1))) + ImmutableSet.of(VKey.createOfy(BillingEvent.OneTime.class, 1))) .setTransferRequestTime(fakeClock.nowUtc()) .setTransferStatus(TransferStatus.SERVER_APPROVED) .setTransferRequestTrid(Trid.create("client-trid", "server-trid")) @@ -134,6 +133,8 @@ public class ContactResourceTest extends EntityTestCase { saveRegistrar("registrar1"); saveRegistrar("registrar2"); saveRegistrar("registrar3"); + saveRegistrar("gaining"); + saveRegistrar("losing"); jpaTm().transact(() -> jpaTm().saveNew(originalContact)); ContactResource persisted = jpaTm() @@ -141,15 +142,17 @@ public class ContactResourceTest extends EntityTestCase { () -> jpaTm() .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 = originalContact .asBuilder() .setCreationTime(persisted.getCreationTime()) - .setInternationalizedPostalInfo(persisted.getInternationalizedPostalInfo()) - .setLocalizedPostalInfo(persisted.getLocalizedPostalInfo()) - .setTransferData(null) + .setTransferData( + originalContact + .getTransferData() + .asBuilder() + .setServerApproveEntities(null) + .build()) .build(); assertThat(persisted).isEqualTo(fixed); } diff --git a/core/src/test/java/google/registry/model/domain/DomainBaseTest.java b/core/src/test/java/google/registry/model/domain/DomainBaseTest.java index ab4d65914..5488b063c 100644 --- a/core/src/test/java/google/registry/model/domain/DomainBaseTest.java +++ b/core/src/test/java/google/registry/model/domain/DomainBaseTest.java @@ -138,10 +138,16 @@ public class DomainBaseTest extends EntityTestCase { .setLosingClientId("losing") .setPendingTransferExpirationTime(fakeClock.nowUtc()) .setServerApproveEntities( - ImmutableSet.of(oneTimeBillKey, recurringBillKey, autorenewPollKey)) - .setServerApproveBillingEvent(oneTimeBillKey) - .setServerApproveAutorenewEvent(recurringBillKey) - .setServerApproveAutorenewPollMessage(autorenewPollKey) + ImmutableSet.of( + VKey.createOfy(BillingEvent.OneTime.class, oneTimeBillKey), + VKey.createOfy(BillingEvent.Recurring.class, recurringBillKey), + 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)) .setTransferStatus(TransferStatus.SERVER_APPROVED) .setTransferRequestTrid(Trid.create("client-trid", "server-trid")) @@ -363,8 +369,8 @@ public class DomainBaseTest extends EntityTestCase { .setTransferRequestTime(fakeClock.nowUtc().minusDays(4)) .setPendingTransferExpirationTime(fakeClock.nowUtc().plusDays(1)) .setGainingClientId("winner") - .setServerApproveBillingEvent(Key.create(transferBillingEvent)) - .setServerApproveEntities(ImmutableSet.of(Key.create(transferBillingEvent))) + .setServerApproveBillingEvent(transferBillingEvent.createVKey()) + .setServerApproveEntities(ImmutableSet.of(transferBillingEvent.createVKey())) .build()) .addGracePeriod( // 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)); DateTime newExpirationTime = oldExpirationTime.plusYears(1); Key serverApproveAutorenewEvent = - domain.getTransferData().getServerApproveAutorenewEvent(); + domain.getTransferData().getServerApproveAutorenewEvent().getOfyKey(); assertTransferred(afterTransfer, newExpirationTime, serverApproveAutorenewEvent); assertThat(afterTransfer.getGracePeriods()) .containsExactly( @@ -746,8 +752,10 @@ public class DomainBaseTest extends EntityTestCase { .setPendingTransferExpirationTime(transferExpirationTime) .setTransferStatus(TransferStatus.PENDING) .setGainingClientId("TheRegistrar") - .setServerApproveAutorenewEvent(recurringBillKey) - .setServerApproveBillingEvent(oneTimeBillKey) + .setServerApproveAutorenewEvent( + VKey.createOfy(BillingEvent.Recurring.class, recurringBillKey)) + .setServerApproveBillingEvent( + VKey.createOfy(BillingEvent.OneTime.class, oneTimeBillKey)) .build(); domain = persistResource( diff --git a/core/src/test/java/google/registry/model/host/HostResourceTest.java b/core/src/test/java/google/registry/model/host/HostResourceTest.java index 8fa6e798b..482fd0392 100644 --- a/core/src/test/java/google/registry/model/host/HostResourceTest.java +++ b/core/src/test/java/google/registry/model/host/HostResourceTest.java @@ -26,7 +26,6 @@ import static org.junit.Assert.assertThrows; import com.google.common.collect.ImmutableSet; import com.google.common.net.InetAddresses; -import com.googlecode.objectify.Key; import google.registry.model.EntityTestCase; import google.registry.model.billing.BillingEvent; 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.transfer.TransferData; import google.registry.model.transfer.TransferStatus; +import google.registry.persistence.VKey; import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; @@ -63,7 +63,7 @@ public class HostResourceTest extends EntityTestCase { .setLosingClientId("losing") .setPendingTransferExpirationTime(fakeClock.nowUtc()) .setServerApproveEntities( - ImmutableSet.of(Key.create(BillingEvent.OneTime.class, 1))) + ImmutableSet.of(VKey.createOfy(BillingEvent.OneTime.class, 1))) .setTransferRequestTime(fakeClock.nowUtc()) .setTransferStatus(TransferStatus.SERVER_APPROVED) .setTransferRequestTrid(Trid.create("client-trid", "server-trid")) diff --git a/core/src/test/java/google/registry/model/transfer/TransferDataTest.java b/core/src/test/java/google/registry/model/transfer/TransferDataTest.java index 6e20a932f..32fa85c11 100644 --- a/core/src/test/java/google/registry/model/transfer/TransferDataTest.java +++ b/core/src/test/java/google/registry/model/transfer/TransferDataTest.java @@ -18,11 +18,11 @@ 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.domain.Period; import google.registry.model.eppcommon.Trid; import google.registry.model.poll.PollMessage; +import google.registry.persistence.VKey; import google.registry.testing.AppEngineRule; import org.joda.time.DateTime; import org.junit.Before; @@ -40,19 +40,19 @@ public class TransferDataTest { private final DateTime now = DateTime.now(UTC); - private Key transferBillingEventKey; - private Key otherServerApproveBillingEventKey; - private Key recurringBillingEventKey; - private Key autorenewPollMessageKey; - private Key otherServerApprovePollMessageKey; + private VKey transferBillingEventKey; + private VKey otherServerApproveBillingEventKey; + private VKey recurringBillingEventKey; + private VKey autorenewPollMessageKey; + private VKey otherServerApprovePollMessageKey; @Before public void setUp() { - transferBillingEventKey = Key.create(BillingEvent.OneTime.class, 12345); - otherServerApproveBillingEventKey = Key.create(BillingEvent.Cancellation.class, 2468); - recurringBillingEventKey = Key.create(BillingEvent.Recurring.class, 13579); - autorenewPollMessageKey = Key.create(PollMessage.Autorenew.class, 67890); - otherServerApprovePollMessageKey = Key.create(PollMessage.OneTime.class, 314159); + transferBillingEventKey = VKey.createOfy(BillingEvent.OneTime.class, 12345); + otherServerApproveBillingEventKey = VKey.createOfy(BillingEvent.Cancellation.class, 2468); + recurringBillingEventKey = VKey.createOfy(BillingEvent.Recurring.class, 13579); + autorenewPollMessageKey = VKey.createOfy(PollMessage.Autorenew.class, 67890); + otherServerApprovePollMessageKey = VKey.createOfy(PollMessage.OneTime.class, 314159); } @Test @@ -67,7 +67,8 @@ public class TransferDataTest { .setTransferPeriod(Period.create(5, Period.Unit.YEARS)) .build(); TransferData fullTransferData = - constantTransferData.asBuilder() + constantTransferData + .asBuilder() .setPendingTransferExpirationTime(now) .setTransferStatus(TransferStatus.PENDING) .setServerApproveEntities( diff --git a/core/src/test/java/google/registry/rde/DomainBaseToXjcConverterTest.java b/core/src/test/java/google/registry/rde/DomainBaseToXjcConverterTest.java index d0d82f8a9..64f125024 100644 --- a/core/src/test/java/google/registry/rde/DomainBaseToXjcConverterTest.java +++ b/core/src/test/java/google/registry/rde/DomainBaseToXjcConverterTest.java @@ -332,10 +332,9 @@ public class DomainBaseToXjcConverterTest { .setGainingClientId("gaining") .setLosingClientId("losing") .setPendingTransferExpirationTime(DateTime.parse("1925-04-20T00:00:00Z")) - .setServerApproveBillingEvent(Key.create(billingEvent)) + .setServerApproveBillingEvent(billingEvent.createVKey()) .setServerApproveAutorenewEvent( - Key.create( - persistResource( + persistResource( new BillingEvent.Recurring.Builder() .setReason(Reason.RENEW) .setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) @@ -344,10 +343,10 @@ public class DomainBaseToXjcConverterTest { .setEventTime(END_OF_TIME) .setRecurrenceEndTime(END_OF_TIME) .setParent(historyEntry) - .build()))) + .build()) + .createVKey()) .setServerApproveAutorenewPollMessage( - Key.create( - persistResource( + persistResource( new Autorenew.Builder() .setTargetId("example.xn--q9jyb4c") .setClientId("TheRegistrar") @@ -355,8 +354,9 @@ public class DomainBaseToXjcConverterTest { .setAutorenewEndTime(END_OF_TIME) .setMsg("Domain was auto-renewed.") .setParent(historyEntry) - .build()))) - .setServerApproveEntities(ImmutableSet.of(Key.create(billingEvent))) + .build()) + .createVKey()) + .setServerApproveEntities(ImmutableSet.of(billingEvent.createVKey())) .setTransferRequestTime(DateTime.parse("1919-01-01T00:00:00Z")) .setTransferStatus(TransferStatus.PENDING) .setTransferredRegistrationExpirationTime( diff --git a/core/src/test/java/google/registry/rde/RdeFixtures.java b/core/src/test/java/google/registry/rde/RdeFixtures.java index 7a46b2a81..1f46f040f 100644 --- a/core/src/test/java/google/registry/rde/RdeFixtures.java +++ b/core/src/test/java/google/registry/rde/RdeFixtures.java @@ -174,10 +174,9 @@ final class RdeFixtures { .setGainingClientId("gaining") .setLosingClientId("losing") .setPendingTransferExpirationTime(DateTime.parse("1993-04-20T00:00:00Z")) - .setServerApproveBillingEvent(Key.create(billingEvent)) + .setServerApproveBillingEvent(billingEvent.createVKey()) .setServerApproveAutorenewEvent( - Key.create( - persistResource( + persistResource( new BillingEvent.Recurring.Builder() .setReason(Reason.RENEW) .setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) @@ -186,10 +185,10 @@ final class RdeFixtures { .setEventTime(END_OF_TIME) .setRecurrenceEndTime(END_OF_TIME) .setParent(historyEntry) - .build()))) + .build()) + .createVKey()) .setServerApproveAutorenewPollMessage( - Key.create( - persistResource( + persistResource( new Autorenew.Builder() .setTargetId("example." + tld) .setClientId("TheRegistrar") @@ -197,8 +196,9 @@ final class RdeFixtures { .setAutorenewEndTime(END_OF_TIME) .setMsg("Domain was auto-renewed.") .setParent(historyEntry) - .build()))) - .setServerApproveEntities(ImmutableSet.of(Key.create(billingEvent))) + .build()) + .createVKey()) + .setServerApproveEntities(ImmutableSet.of(billingEvent.createVKey())) .setTransferRequestTime(DateTime.parse("1991-01-01T00:00:00Z")) .setTransferStatus(TransferStatus.PENDING) .setTransferredRegistrationExpirationTime( diff --git a/core/src/test/java/google/registry/testing/DatastoreHelper.java b/core/src/test/java/google/registry/testing/DatastoreHelper.java index 0353f4efa..14d0b5464 100644 --- a/core/src/test/java/google/registry/testing/DatastoreHelper.java +++ b/core/src/test/java/google/registry/testing/DatastoreHelper.java @@ -443,32 +443,37 @@ public class DatastoreHelper { .setParent(contact) .build()); return persistResource( - contact.asBuilder() + contact + .asBuilder() .setPersistedCurrentSponsorClientId("TheRegistrar") .addStatusValue(StatusValue.PENDING_TRANSFER) - .setTransferData(createTransferDataBuilder(requestTime, expirationTime) + .setTransferData( + createTransferDataBuilder(requestTime, expirationTime) .setPendingTransferExpirationTime(now.plus(getContactAutomaticTransferLength())) - .setServerApproveEntities( - ImmutableSet.of( - // Pretend it's 3 days since the request - Key.create(persistResource( - createPollMessageForImplicitTransfer( - contact, - historyEntryContactTransfer, - "NewRegistrar", - requestTime, - expirationTime, - null))), - Key.create(persistResource( - createPollMessageForImplicitTransfer( - contact, - historyEntryContactTransfer, - "TheRegistrar", - requestTime, - expirationTime, - null))))) - .setTransferRequestTrid(Trid.create("transferClient-trid", "transferServer-trid")) - .build()) + .setServerApproveEntities( + ImmutableSet.of( + // Pretend it's 3 days since the request + persistResource( + createPollMessageForImplicitTransfer( + contact, + historyEntryContactTransfer, + "NewRegistrar", + requestTime, + expirationTime, + null)) + .createVKey(), + persistResource( + createPollMessageForImplicitTransfer( + contact, + historyEntryContactTransfer, + "TheRegistrar", + requestTime, + expirationTime, + null)) + .createVKey())) + .setTransferRequestTrid( + Trid.create("transferClient-trid", "transferServer-trid")) + .build()) .build()); } @@ -585,38 +590,46 @@ public class DatastoreHelper { } TransferData.Builder transferDataBuilder = createTransferDataBuilder(requestTime, expirationTime); - return persistResource(domain.asBuilder() - .setPersistedCurrentSponsorClientId("TheRegistrar") - .addStatusValue(StatusValue.PENDING_TRANSFER) - .setTransferData(transferDataBuilder - .setPendingTransferExpirationTime(expirationTime) - .setTransferredRegistrationExpirationTime(extendedRegistrationExpirationTime) - .setServerApproveBillingEvent(Key.create(transferBillingEvent)) - .setServerApproveAutorenewEvent(Key.create(gainingClientAutorenewEvent)) - .setServerApproveAutorenewPollMessage(Key.create(gainingClientAutorenewPollMessage)) - .setServerApproveEntities(ImmutableSet.of( - Key.create(transferBillingEvent), - Key.create(gainingClientAutorenewEvent), - Key.create(gainingClientAutorenewPollMessage), - Key.create(persistResource( - createPollMessageForImplicitTransfer( - domain, - historyEntryDomainTransfer, - "NewRegistrar", - requestTime, - expirationTime, - extendedRegistrationExpirationTime))), - Key.create(persistResource( - createPollMessageForImplicitTransfer( - domain, - historyEntryDomainTransfer, - "TheRegistrar", - requestTime, - expirationTime, - extendedRegistrationExpirationTime))))) - .setTransferRequestTrid(Trid.create("transferClient-trid", "transferServer-trid")) - .build()) - .build()); + return persistResource( + domain + .asBuilder() + .setPersistedCurrentSponsorClientId("TheRegistrar") + .addStatusValue(StatusValue.PENDING_TRANSFER) + .setTransferData( + transferDataBuilder + .setPendingTransferExpirationTime(expirationTime) + .setTransferredRegistrationExpirationTime(extendedRegistrationExpirationTime) + .setServerApproveBillingEvent(transferBillingEvent.createVKey()) + .setServerApproveAutorenewEvent(gainingClientAutorenewEvent.createVKey()) + .setServerApproveAutorenewPollMessage( + gainingClientAutorenewPollMessage.createVKey()) + .setServerApproveEntities( + ImmutableSet.of( + transferBillingEvent.createVKey(), + gainingClientAutorenewEvent.createVKey(), + gainingClientAutorenewPollMessage.createVKey(), + persistResource( + createPollMessageForImplicitTransfer( + domain, + historyEntryDomainTransfer, + "NewRegistrar", + requestTime, + expirationTime, + extendedRegistrationExpirationTime)) + .createVKey(), + persistResource( + createPollMessageForImplicitTransfer( + domain, + historyEntryDomainTransfer, + "TheRegistrar", + requestTime, + expirationTime, + extendedRegistrationExpirationTime)) + .createVKey())) + .setTransferRequestTrid( + Trid.create("transferClient-trid", "transferServer-trid")) + .build()) + .build()); } /** Persists and returns a {@link Registrar} with the specified attributes. */ diff --git a/core/src/test/resources/google/registry/model/schema.txt b/core/src/test/resources/google/registry/model/schema.txt index 63d95eef4..fc924a49c 100644 --- a/core/src/test/resources/google/registry/model/schema.txt +++ b/core/src/test/resources/google/registry/model/schema.txt @@ -716,15 +716,15 @@ class google.registry.model.tmch.TmchCrl { org.joda.time.DateTime updated; } class google.registry.model.transfer.TransferData { - com.googlecode.objectify.Key serverApproveBillingEvent; - com.googlecode.objectify.Key serverApproveAutorenewEvent; - com.googlecode.objectify.Key serverApproveAutorenewPollMessage; google.registry.model.domain.Period transferPeriod; google.registry.model.eppcommon.Trid transferRequestTrid; google.registry.model.transfer.TransferStatus transferStatus; + google.registry.persistence.VKey serverApproveBillingEvent; + google.registry.persistence.VKey serverApproveAutorenewEvent; + google.registry.persistence.VKey serverApproveAutorenewPollMessage; java.lang.String gainingClientId; java.lang.String losingClientId; - java.util.Set> serverApproveEntities; + java.util.Set> serverApproveEntities; org.joda.time.DateTime pendingTransferExpirationTime; org.joda.time.DateTime transferRequestTime; org.joda.time.DateTime transferredRegistrationExpirationTime; diff --git a/db/src/main/resources/sql/flyway/V29__add_columns_for_transfer_data.sql b/db/src/main/resources/sql/flyway/V29__add_columns_for_transfer_data.sql new file mode 100644 index 000000000..27e290a4e --- /dev/null +++ b/db/src/main/resources/sql/flyway/V29__add_columns_for_transfer_data.sql @@ -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"; diff --git a/db/src/main/resources/sql/schema/db-schema.sql.generated b/db/src/main/resources/sql/schema/db-schema.sql.generated index 496c1123a..b581dcbab 100644 --- a/db/src/main/resources/sql/schema/db-schema.sql.generated +++ b/db/src/main/resources/sql/schema/db-schema.sql.generated @@ -118,6 +118,22 @@ addr_local_org text, addr_local_type 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_number text, primary key (repo_id) @@ -165,6 +181,22 @@ subordinate_hosts text[], tech_contact 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) ); diff --git a/db/src/main/resources/sql/schema/nomulus.golden.sql b/db/src/main/resources/sql/schema/nomulus.golden.sql index 598e84165..ad8e5a102 100644 --- a/db/src/main/resources/sql/schema/nomulus.golden.sql +++ b/db/src/main/resources/sql/schema/nomulus.golden.sql @@ -241,7 +241,23 @@ CREATE TABLE public."Contact" ( addr_local_type text, search_name 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, billing_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); +-- +-- 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: - -- @@ -1159,6 +1207,46 @@ ALTER TABLE ONLY public."Domain" 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: - --