diff --git a/core/src/main/java/google/registry/model/domain/DomainContent.java b/core/src/main/java/google/registry/model/domain/DomainContent.java index d538a19b3..a395add00 100644 --- a/core/src/main/java/google/registry/model/domain/DomainContent.java +++ b/core/src/main/java/google/registry/model/domain/DomainContent.java @@ -24,6 +24,7 @@ import static com.google.common.collect.Sets.intersection; import static google.registry.model.EppResourceUtils.projectResourceOntoBuilderAtTime; import static google.registry.model.EppResourceUtils.setAutomaticTransferSuccessProperties; import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; import static google.registry.util.CollectionUtils.forceEmptyToNull; import static google.registry.util.CollectionUtils.nullToEmpty; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; @@ -378,6 +379,25 @@ public class DomainContent extends EppResource } } + /** + * Callback to delete grace periods and DelegationSignerData records prior to domain delete. + * + *

See {@link google.registry.schema.replay.ReplaySpecializer}. + */ + public static void beforeSqlDelete(VKey key) { + // Delete all grace periods associated with the domain. + jpaTm() + .getEntityManager() + .createQuery("DELETE FROM GracePeriod WHERE domain_repo_id = :repo_id") + .setParameter("repo_id", key.getSqlKey()) + .executeUpdate(); + jpaTm() + .getEntityManager() + .createQuery("DELETE FROM DelegationSignerData WHERE domain_repo_id = :repo_id") + .setParameter("repo_id", key.getSqlKey()) + .executeUpdate(); + } + public static VKey restoreOfyFrom(Key domainKey, VKey key, Long historyId) { if (historyId == null) { // This is a legacy key (or a null key, in which case this works too) diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java index 485c28a33..0bf31de3e 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java @@ -25,6 +25,7 @@ import static google.registry.persistence.transaction.TransactionManagerFactory. import static google.registry.testing.DatabaseHelper.assertBillingEventsForResource; import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.deleteResource; +import static google.registry.testing.DatabaseHelper.getBillingEvents; import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType; import static google.registry.testing.DatabaseHelper.getOnlyPollMessage; import static google.registry.testing.DatabaseHelper.getPollMessages; @@ -71,18 +72,25 @@ import google.registry.model.transfer.DomainTransferData; import google.registry.model.transfer.TransferResponse.DomainTransferResponse; import google.registry.model.transfer.TransferStatus; import google.registry.persistence.VKey; +import google.registry.testing.ReplayExtension; import java.util.Arrays; import java.util.stream.Stream; import org.joda.money.Money; import org.joda.time.DateTime; import org.joda.time.Duration; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; /** Unit tests for {@link DomainTransferApproveFlow}. */ class DomainTransferApproveFlowTest extends DomainTransferFlowTestCase { + @Order(value = Order.DEFAULT - 2) + @RegisterExtension + final ReplayExtension replayExtension = ReplayExtension.createWithCompare(clock); + @BeforeEach void setUp() { setEppInput("domain_transfer_approve.xml"); @@ -521,7 +529,24 @@ class DomainTransferApproveFlowTest @Test void testFailure_nonexistentDomain() throws Exception { - deleteResource(domain); + Iterable billingEvents = getBillingEvents(); + Iterable historyEntries = tm().loadAllOf(HistoryEntry.class); + Iterable pollMessages = tm().loadAllOf(PollMessage.class); + tm().transact( + () -> { + deleteResource(domain); + for (BillingEvent event : billingEvents) { + deleteResource(event); + } + for (PollMessage pollMessage : pollMessages) { + deleteResource(pollMessage); + } + deleteResource(subordinateHost); + for (HistoryEntry hist : historyEntries) { + deleteResource(hist); + } + }); + ResourceDoesNotExistException thrown = assertThrows( ResourceDoesNotExistException.class, diff --git a/core/src/test/java/google/registry/testing/DatabaseHelper.java b/core/src/test/java/google/registry/testing/DatabaseHelper.java index bc8c6958e..feed9ca31 100644 --- a/core/src/test/java/google/registry/testing/DatabaseHelper.java +++ b/core/src/test/java/google/registry/testing/DatabaseHelper.java @@ -766,7 +766,7 @@ public class DatabaseHelper { return newRegistrars.build(); } - private static Iterable getBillingEvents() { + public static Iterable getBillingEvents() { return transactIfJpaTm( () -> Iterables.concat( 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 5b814152e..4dbd103de 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,11 +261,11 @@ td.section { generated on - 2021-02-25 19:33:39.25711 + 2021-03-04 16:08:40.773463 last flyway file - V86__third_poll_message.sql + V87__fix_super_domain_fk.sql @@ -274,19 +274,19 @@ td.section { SchemaCrawler_Diagram - + generated by - + SchemaCrawler 16.10.1 - + generated on - - 2021-02-25 19:33:39.25711 + + 2021-03-04 16:08:40.773463 - + 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 cb48aaaf3..db8f8a8e5 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,11 +261,11 @@ td.section {
generated on - 2021-02-25 19:33:37.35689 + 2021-03-04 16:08:38.771681
last flyway file - V86__third_poll_message.sql + V87__fix_super_domain_fk.sql
@@ -274,19 +274,19 @@ td.section { SchemaCrawler_Diagram - + generated by - + SchemaCrawler 16.10.1 - + generated on - - 2021-02-25 19:33:37.35689 + + 2021-03-04 16:08:38.771681 - + allocationtoken_a08ccbef diff --git a/db/src/main/resources/sql/flyway.txt b/db/src/main/resources/sql/flyway.txt index c5e90092b..8025bc0b7 100644 --- a/db/src/main/resources/sql/flyway.txt +++ b/db/src/main/resources/sql/flyway.txt @@ -84,3 +84,4 @@ V83__add_indexes_on_domainhost.sql V84__add_vkey_columns_in_billing_cancellation.sql V85__add_required_columns_in_transfer_data.sql V86__third_poll_message.sql +V87__fix_super_domain_fk.sql diff --git a/db/src/main/resources/sql/flyway/V87__fix_super_domain_fk.sql b/db/src/main/resources/sql/flyway/V87__fix_super_domain_fk.sql new file mode 100644 index 000000000..bc16cbb72 --- /dev/null +++ b/db/src/main/resources/sql/flyway/V87__fix_super_domain_fk.sql @@ -0,0 +1,20 @@ +-- Copyright 2021 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 "Host" DROP CONSTRAINT fk_host_superordinate_domain; +ALTER TABLE if exists "Host" + ADD CONSTRAINT fk_host_superordinate_domain + FOREIGN KEY (superordinate_domain) + REFERENCES "Domain"(repo_id) + DEFERRABLE INITIALLY DEFERRED; diff --git a/db/src/main/resources/sql/schema/nomulus.golden.sql b/db/src/main/resources/sql/schema/nomulus.golden.sql index 4cee96a79..d4a1784d3 100644 --- a/db/src/main/resources/sql/schema/nomulus.golden.sql +++ b/db/src/main/resources/sql/schema/nomulus.golden.sql @@ -2198,7 +2198,7 @@ ALTER TABLE ONLY public."Host" -- ALTER TABLE ONLY public."Host" - ADD CONSTRAINT fk_host_superordinate_domain FOREIGN KEY (superordinate_domain) REFERENCES public."Domain"(repo_id); + ADD CONSTRAINT fk_host_superordinate_domain FOREIGN KEY (superordinate_domain) REFERENCES public."Domain"(repo_id) DEFERRABLE INITIALLY DEFERRED; --