diff --git a/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java b/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java index 6ebea8cd8ec..0ffa2d687a9 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactCreateFlow.java @@ -86,6 +86,7 @@ public EppResponse run() throws EppException { .setEmailAddress(command.getEmail()) .setInternationalizedPostalInfo(command.getInternationalizedPostalInfo()) .setLocalizedPostalInfo(command.getLocalizedPostalInfo()) + .setLastUpdateTimeViaEpp(now) .build(); validateAsciiPostalInfo(newContact.getInternationalizedPostalInfo()); validateContactAgainstPolicy(newContact); diff --git a/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java b/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java index 5983783ee33..20e70d61857 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactDeleteFlow.java @@ -103,7 +103,13 @@ public EppResponse run() throws EppException { : existingContact; // Wipe out PII on contact deletion. newContact = - newContact.asBuilder().wipeOut().setStatusValues(null).setDeletionTime(now).build(); + newContact + .asBuilder() + .wipeOut() + .setStatusValues(null) + .setDeletionTime(now) + .setLastUpdateTimeViaEpp(now) + .build(); ContactHistory contactHistory = historyBuilder.setType(Type.CONTACT_DELETE).setContact(newContact).build(); handlePendingTransferOnDelete(existingContact, newContact, now, contactHistory); diff --git a/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java b/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java index 63d51051648..a0bf0a2fd49 100644 --- a/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java +++ b/core/src/main/java/google/registry/flows/contact/ContactUpdateFlow.java @@ -129,6 +129,7 @@ public EppResponse run() throws EppException { Contact newContact = builder .setLastEppUpdateTime(now) + .setLastUpdateTimeViaEpp(now) .setLastEppUpdateRegistrarId(registrarId) .setAuthInfo(preferFirst(change.getAuthInfo(), existingContact.getAuthInfo())) .setDisclose(preferFirst(change.getDisclose(), existingContact.getDisclose())) diff --git a/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java b/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java index a8301c8bd2f..2fa112d6009 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java @@ -386,6 +386,7 @@ public EppResponse run() throws EppException { .setCreationRegistrarId(registrarId) .setPersistedCurrentSponsorRegistrarId(registrarId) .setRepoId(repoId) + .setLastUpdateTimeViaEpp(now) .setIdnTableName(validateDomainNameWithIdnTables(domainName)) .setRegistrationExpirationTime(registrationExpirationTime) .setAutorenewBillingEvent(autorenewBillingEvent.createVKey()) diff --git a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java index 13c17c6cc01..9b654c5d220 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainDeleteFlow.java @@ -159,7 +159,10 @@ public EppResponse run() throws EppException { } else { builder = existingDomain.asBuilder(); } - builder.setLastEppUpdateTime(now).setLastEppUpdateRegistrarId(registrarId); + builder + .setLastEppUpdateTime(now) + .setLastUpdateTimeViaEpp(now) + .setLastEppUpdateRegistrarId(registrarId); Duration redemptionGracePeriodLength = tld.getRedemptionGracePeriodLength(); Duration pendingDeleteLength = tld.getPendingDeleteLength(); Optional domainDeleteSuperuserExtension = diff --git a/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java b/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java index f56d43cc783..49280f98a88 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainRenewFlow.java @@ -244,6 +244,7 @@ public EppResponse run() throws EppException { existingDomain .asBuilder() .setLastEppUpdateTime(now) + .setLastUpdateTimeViaEpp(now) .setLastEppUpdateRegistrarId(registrarId) .setRegistrationExpirationTime(newExpirationTime) .setAutorenewBillingEvent(newAutorenewEvent.createVKey()) diff --git a/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java b/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java index d19cb8b4720..78af10338cb 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainRestoreRequestFlow.java @@ -247,6 +247,7 @@ private static Domain performRestore( // it won't immediately be deleted again. .setAutorenewEndTime(Optional.empty()) .setLastEppUpdateTime(now) + .setLastUpdateTimeViaEpp(now) .setLastEppUpdateRegistrarId(registrarId) .build(); } 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 dcf210ad679..a316bcbc013 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferApproveFlow.java @@ -257,6 +257,7 @@ public EppResponse run() throws EppException { GracePeriodStatus.TRANSFER, existingDomain.getRepoId(), event))) .orElseGet(ImmutableSet::of)) .setLastEppUpdateTime(now) + .setLastUpdateTimeViaEpp(now) .setLastEppUpdateRegistrarId(registrarId) // Even if the existing domain had a bulk token, that bulk token should be removed // on transfer diff --git a/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java b/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java index d9aed6315d1..7dd02865739 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainTransferRequestFlow.java @@ -284,6 +284,7 @@ public EppResponse run() throws EppException { .setTransferData(pendingTransferData) .addStatusValue(StatusValue.PENDING_TRANSFER) .setLastEppUpdateTime(now) + .setLastUpdateTimeViaEpp(now) .setLastEppUpdateRegistrarId(gainingClientId) .build(); DomainHistory domainHistory = buildDomainHistory(newDomain, tld, now, period); diff --git a/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java b/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java index f12dda3e3c5..cf9a282ea64 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java @@ -273,6 +273,7 @@ private Domain performUpdate(Update command, Domain domain, DateTime now) throws secDnsUpdate.get()) : domain.getDsData()) .setLastEppUpdateTime(now) + .setLastUpdateTimeViaEpp(now) .setLastEppUpdateRegistrarId(registrarId) .addStatusValues(add.getStatusValues()) .removeStatusValues(remove.getStatusValues()) diff --git a/core/src/main/java/google/registry/model/EppResource.java b/core/src/main/java/google/registry/model/EppResource.java index efe736792cb..9852cffc891 100644 --- a/core/src/main/java/google/registry/model/EppResource.java +++ b/core/src/main/java/google/registry/model/EppResource.java @@ -34,6 +34,7 @@ import com.google.gson.annotations.Expose; import google.registry.config.RegistryConfig; import google.registry.model.eppcommon.StatusValue; +import google.registry.model.reporting.HistoryEntry; import google.registry.model.transfer.TransferData; import google.registry.persistence.VKey; import google.registry.util.NonFinalForTesting; @@ -129,9 +130,24 @@ public abstract class EppResource extends UpdateAutoTimestampEntity implements B *

This does not refer to the last delta made on this object, which might include out-of-band * edits; it only includes EPP-visible modifications such as {@literal }. Can be null if * the resource has never been modified. + * + *

This field reflects the last update that is visible in EPP requests, not necessarily + * when the last EPP request was made on this entity. For that, see {@link #lastUpdateTimeViaEpp}. */ @Expose DateTime lastEppUpdateTime; + /** + * The time that this resource was last updated via an EPP request. + * + *

This will usually be the same as {@link #lastEppUpdateTime} but not always, as that field + * can be modified by automated events such as grace period expirations or autorenews. There + * should always be exactly one {@link HistoryEntry} object corresponding to this time. + * + *

This field exists to track when (if) the EppResource becomes out of sync with the + * corresponding most-recent {@link HistoryEntry} object. + */ + DateTime lastUpdateTimeViaEpp; + /** Status values associated with this resource. */ @Expose Set statuses; @@ -164,6 +180,10 @@ public DateTime getLastEppUpdateTime() { return lastEppUpdateTime; } + public DateTime getLastUpdateTimeViaEpp() { + return lastUpdateTimeViaEpp; + } + public String getLastEppUpdateRegistrarId() { return lastEppUpdateRegistrarId; } @@ -281,6 +301,12 @@ public B setLastEppUpdateTime(DateTime lastEppUpdateTime) { return thisCastToDerived(); } + /** Set the time when this resource was updated by an EPP request. */ + public B setLastUpdateTimeViaEpp(DateTime lastUpdateTimeViaEpp) { + getInstance().lastUpdateTimeViaEpp = lastUpdateTimeViaEpp; + return thisCastToDerived(); + } + /** Set the registrar who last performed a {@literal } on this resource. */ public B setLastEppUpdateRegistrarId(String lastEppUpdateRegistrarId) { getInstance().lastEppUpdateRegistrarId = lastEppUpdateRegistrarId; diff --git a/core/src/main/java/google/registry/model/ResourceTransferUtils.java b/core/src/main/java/google/registry/model/ResourceTransferUtils.java index 0288ad39e93..cb9fc9b6f4f 100644 --- a/core/src/main/java/google/registry/model/ResourceTransferUtils.java +++ b/core/src/main/java/google/registry/model/ResourceTransferUtils.java @@ -145,14 +145,14 @@ B resolvePendingTransfer(R resource, TransferStatus transferStatus, DateTime now return builder .removeStatusValue(StatusValue.PENDING_TRANSFER) + .setLastUpdateTimeViaEpp(now) .setTransferData( - (TransferData) - resource - .getTransferData() - .copyConstantFieldsToBuilder() - .setTransferStatus(transferStatus) - .setPendingTransferExpirationTime(checkNotNull(now)) - .build()); + resource + .getTransferData() + .copyConstantFieldsToBuilder() + .setTransferStatus(transferStatus) + .setPendingTransferExpirationTime(checkNotNull(now)) + .build()); } /** diff --git a/core/src/main/java/google/registry/model/contact/Contact.java b/core/src/main/java/google/registry/model/contact/Contact.java index 4b389709470..e385a72f9d8 100644 --- a/core/src/main/java/google/registry/model/contact/Contact.java +++ b/core/src/main/java/google/registry/model/contact/Contact.java @@ -90,6 +90,7 @@ public Builder copyFrom(ContactBase contactBase) { .setLastTransferTime(contactBase.getLastTransferTime()) .setLastEppUpdateRegistrarId(contactBase.getLastEppUpdateRegistrarId()) .setLastEppUpdateTime(contactBase.getLastEppUpdateTime()) + .setLastUpdateTimeViaEpp(contactBase.getLastUpdateTimeViaEpp()) .setLocalizedPostalInfo(contactBase.getLocalizedPostalInfo()) .setPersistedCurrentSponsorRegistrarId( contactBase.getPersistedCurrentSponsorRegistrarId()) diff --git a/core/src/main/java/google/registry/model/domain/Domain.java b/core/src/main/java/google/registry/model/domain/Domain.java index d92e030c712..04f7b858a5f 100644 --- a/core/src/main/java/google/registry/model/domain/Domain.java +++ b/core/src/main/java/google/registry/model/domain/Domain.java @@ -191,6 +191,7 @@ public Builder copyFrom(DomainBase domainBase) { .setLaunchNotice(domainBase.getLaunchNotice()) .setLastEppUpdateRegistrarId(domainBase.getLastEppUpdateRegistrarId()) .setLastEppUpdateTime(domainBase.getLastEppUpdateTime()) + .setLastUpdateTimeViaEpp(domainBase.getLastUpdateTimeViaEpp()) .setNameservers(domainBase.getNameservers()) .setPersistedCurrentSponsorRegistrarId(domainBase.getPersistedCurrentSponsorRegistrarId()) .setRegistrant(domainBase.getRegistrant()) diff --git a/core/src/main/java/google/registry/model/host/Host.java b/core/src/main/java/google/registry/model/host/Host.java index 0ee095cf28e..8e664ac67f9 100644 --- a/core/src/main/java/google/registry/model/host/Host.java +++ b/core/src/main/java/google/registry/model/host/Host.java @@ -91,6 +91,7 @@ public Builder copyFrom(HostBase hostBase) { .setLastSuperordinateChange(hostBase.getLastSuperordinateChange()) .setLastEppUpdateRegistrarId(hostBase.getLastEppUpdateRegistrarId()) .setLastEppUpdateTime(hostBase.getLastEppUpdateTime()) + .setLastUpdateTimeViaEpp(hostBase.getLastUpdateTimeViaEpp()) .setPersistedCurrentSponsorRegistrarId(hostBase.getPersistedCurrentSponsorRegistrarId()) .setRepoId(hostBase.getRepoId()) .setSuperordinateDomain(hostBase.getSuperordinateDomain()) diff --git a/db/src/main/resources/sql/er_diagram/brief_er_diagram.html b/db/src/main/resources/sql/er_diagram/brief_er_diagram.html index e0d05bbfc4d..c8c9d9d74fb 100644 --- a/db/src/main/resources/sql/er_diagram/brief_er_diagram.html +++ b/db/src/main/resources/sql/er_diagram/brief_er_diagram.html @@ -261,7 +261,7 @@

System Information

generated on - 2024-05-01 21:04:48.5296048 + 2024-05-02 20:18:24.185031041 last flyway file @@ -277,11 +277,11 @@

System Information

SchemaCrawler_Diagram - generated by - SchemaCrawler 16.10.1 - generated on - 2024-05-01 21:04:48.5296048 - + generated by + SchemaCrawler 16.10.1 + generated on + 2024-05-02 20:18:24.185031041 + allocationtoken_a08ccbef diff --git a/db/src/main/resources/sql/er_diagram/full_er_diagram.html b/db/src/main/resources/sql/er_diagram/full_er_diagram.html index 85675f080d7..213c4a97eeb 100644 --- a/db/src/main/resources/sql/er_diagram/full_er_diagram.html +++ b/db/src/main/resources/sql/er_diagram/full_er_diagram.html @@ -261,7 +261,7 @@ <h2>System Information</h2> </tr> <tr> <td class="property_name">generated on</td> - <td class="property_value">2024-05-01 21:04:45.792776047</td> + <td class="property_value">2024-05-02 20:18:21.247959871</td> </tr> <tr> <td class="property_name">last flyway file</td> @@ -280,7 +280,7 @@ <h2>System Information</h2> <text text-anchor="start" x="4443.5" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00">generated by</text> <text text-anchor="start" x="4526.5" y="-29.8" font-family="Helvetica,sans-Serif" font-size="14.00">SchemaCrawler 16.10.1</text> <text text-anchor="start" x="4442.5" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">generated on</text> - <text text-anchor="start" x="4526.5" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">2024-05-01 21:04:45.792776047</text> + <text text-anchor="start" x="4526.5" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">2024-05-02 20:18:21.247959871</text> <polygon fill="none" stroke="#888888" points="4439,-4 4439,-44 4726,-44 4726,-4 4439,-4" /> <!-- allocationtoken_a08ccbef --> <g id="node1" class="node"> <title> 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 5e0a3dbfe6c..86ac142f53c 100644 --- a/db/src/main/resources/sql/schema/db-schema.sql.generated +++ b/db/src/main/resources/sql/schema/db-schema.sql.generated @@ -153,6 +153,7 @@ deletion_time timestamptz, last_epp_update_registrar_id text, last_epp_update_time timestamptz, + last_update_time_via_epp timestamptz, statuses text[], auth_info_repo_id text, auth_info_value text, @@ -273,6 +274,7 @@ deletion_time timestamptz, last_epp_update_registrar_id text, last_epp_update_time timestamptz, + last_update_time_via_epp timestamptz, statuses text[], update_timestamp timestamptz, primary key (contact_repo_id, history_revision_id) @@ -314,6 +316,7 @@ deletion_time timestamptz, last_epp_update_registrar_id text, last_epp_update_time timestamptz, + last_update_time_via_epp timestamptz, statuses text[], admin_contact text, auth_info_repo_id text, @@ -436,6 +439,7 @@ deletion_time timestamptz, last_epp_update_registrar_id text, last_epp_update_time timestamptz, + last_update_time_via_epp timestamptz, statuses text[], update_timestamp timestamptz, primary key (domain_repo_id, history_revision_id) @@ -496,6 +500,7 @@ deletion_time timestamptz, last_epp_update_registrar_id text, last_epp_update_time timestamptz, + last_update_time_via_epp timestamptz, statuses text[], host_name text, inet_addresses text[], @@ -528,6 +533,7 @@ deletion_time timestamptz, last_epp_update_registrar_id text, last_epp_update_time timestamptz, + last_update_time_via_epp timestamptz, statuses text[], update_timestamp timestamptz, primary key (host_repo_id, history_revision_id)