From 6a3ea198478952a632fd40a4ff3b6b66c7e3eb43 Mon Sep 17 00:00:00 2001 From: Gus Brodman Date: Thu, 19 Feb 2026 15:07:51 -0500 Subject: [PATCH] Remove Contact and ContactHistory Java objects and related code This doesn't remove everything -- there are still other contact-related objects that we'll need to remove (e.g. ContactPendingActionNotificationResponse) and simplifications we'll need to make (e.g. only domains can be transferred now, so all transfer data can move there instead of being generic) But this removes the bulk of the remaining contact-related code. We'll keep around the XML request objects, since it's still nice to route them to the appropriate (exception-throwing but logging) flow class. --- .../flows/domain/DomainFlowUtils.java | 31 -- .../flows/domain/DomainUpdateFlow.java | 3 - .../registry/model/ForeignKeyUtils.java | 2 - .../registry/model/contact/Contact.java | 96 ----- .../registry/model/contact/ContactBase.java | 388 ------------------ .../model/contact/ContactCommand.java | 21 +- .../model/contact/ContactHistory.java | 102 ----- .../model/contact/ContactPhoneNumber.java | 8 +- .../model/domain/DesignatedContact.java | 80 ---- .../google/registry/model/domain/Domain.java | 2 - .../registry/model/domain/DomainBase.java | 139 +------ .../registry/model/domain/DomainCommand.java | 24 -- .../domain/ForeignKeyedDesignatedContact.java | 29 +- .../registry/model/eppcommon/StatusValue.java | 4 - .../google/registry/persistence/VKey.java | 3 +- .../google/registry/rde/RdeStagingAction.java | 5 +- .../registry/tools/CommandUtilities.java | 2 - .../main/resources/META-INF/persistence.xml | 3 - .../beam/common/RegistryJpaReadTest.java | 1 - .../registry/beam/rde/RdePipelineTest.java | 5 - .../flows/domain/DomainCreateFlowTest.java | 3 - .../flows/domain/DomainInfoFlowTest.java | 15 - .../flows/domain/DomainUpdateFlowTest.java | 9 +- .../registry/model/contact/ContactTest.java | 227 ---------- .../registry/model/domain/DomainTest.java | 11 - .../registry/model/eppinput/EppInputTest.java | 12 - .../model/history/ContactHistoryTest.java | 145 ------- .../rde/DomainToXjcConverterTest.java | 9 - .../integration/SqlIntegrationTestSuite.java | 4 - .../registry/testing/DatabaseHelper.java | 23 +- .../sql/er_diagram/brief_er_diagram.html | 4 +- .../sql/er_diagram/full_er_diagram.html | 4 +- .../sql/schema/db-schema.sql.generated | 161 -------- 33 files changed, 50 insertions(+), 1525 deletions(-) delete mode 100644 core/src/main/java/google/registry/model/contact/Contact.java delete mode 100644 core/src/main/java/google/registry/model/contact/ContactBase.java delete mode 100644 core/src/main/java/google/registry/model/contact/ContactHistory.java delete mode 100644 core/src/main/java/google/registry/model/domain/DesignatedContact.java delete mode 100644 core/src/test/java/google/registry/model/contact/ContactTest.java delete mode 100644 core/src/test/java/google/registry/model/history/ContactHistoryTest.java diff --git a/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java b/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java index 90fa4c2e595..0b4a20d9769 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java @@ -67,14 +67,11 @@ import google.registry.flows.EppException.RequiredParameterMissingException; import google.registry.flows.EppException.StatusProhibitsOperationException; import google.registry.flows.EppException.UnimplementedOptionException; -import google.registry.flows.exceptions.ContactsProhibitedException; import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException; import google.registry.model.EppResource; import google.registry.model.billing.BillingBase.Flag; import google.registry.model.billing.BillingBase.Reason; import google.registry.model.billing.BillingRecurrence; -import google.registry.model.contact.Contact; -import google.registry.model.domain.DesignatedContact; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainCommand.Create; import google.registry.model.domain.DomainCommand.CreateOrUpdate; @@ -421,33 +418,6 @@ static void validateNameserversCountForTld(String tld, InternetDomainName domain } } - /** Enforces absence of contact data on creation as part of the Minimum Dataset requirements. */ - static void enforceContactAbsencesOnCreate(Create create) - throws ParameterValuePolicyErrorException { - enforceContactAbsences(create.getRegistrant(), create.getContacts()); - } - - /** Enforces absence of contact data on update as part of the Minimum Dataset requirements. */ - static void enforceContactAbsencesOnUpdate(Update update) - throws ParameterValuePolicyErrorException { - Set allDesignatedContacts = - Sets.union(update.getInnerAdd().getContacts(), update.getInnerRemove().getContacts()); - enforceContactAbsences(update.getInnerChange().getRegistrant(), allDesignatedContacts); - } - - /** Enforces the absence of contact data as part of the Minimum Dataset requirements. */ - static void enforceContactAbsences( - Optional> registrant, Set contacts) - throws ParameterValuePolicyErrorException { - if (registrant.isPresent()) { - throw new RegistrantProhibitedException(); - } - if (!contacts.isEmpty()) { - throw new ContactsProhibitedException(); - } - } - - static void validateNameserversAllowedOnTld(String tld, Set fullyQualifiedHostNames) throws EppException { ImmutableSet allowedHostNames = Tld.get(tld).getAllowedFullyQualifiedHostNames(); @@ -971,7 +941,6 @@ static void validateCreateCommandContactsAndNameservers( Create command, Tld tld, InternetDomainName domainName) throws EppException { verifyNotInPendingDelete(command.getNameservers()); String tldStr = tld.getTldStr(); - enforceContactAbsencesOnCreate(command); ImmutableSet hostNames = command.getNameserverHostNames(); validateNameserversCountForTld(tldStr, domainName, hostNames.size()); validateNameserversAllowedOnTld(tldStr, hostNames); 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 1f565aca585..16f89e57b82 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java @@ -29,7 +29,6 @@ import static google.registry.flows.ResourceFlowUtils.verifyResourceOwnership; import static google.registry.flows.domain.DomainFlowUtils.checkAllowedAccessToTld; import static google.registry.flows.domain.DomainFlowUtils.cloneAndLinkReferences; -import static google.registry.flows.domain.DomainFlowUtils.enforceContactAbsencesOnUpdate; import static google.registry.flows.domain.DomainFlowUtils.updateDsData; import static google.registry.flows.domain.DomainFlowUtils.validateDsData; import static google.registry.flows.domain.DomainFlowUtils.validateFeesAckedIfPresent; @@ -249,8 +248,6 @@ private Domain performUpdate(Update command, Domain domain, DateTime now) throws ext.getRemove().map(Remove::getDsData).orElse(ImmutableSet.of())); } Change change = command.getInnerChange(); - enforceContactAbsencesOnUpdate(command); - Domain.Builder domainBuilder = domain .asBuilder() diff --git a/core/src/main/java/google/registry/model/ForeignKeyUtils.java b/core/src/main/java/google/registry/model/ForeignKeyUtils.java index e00d07a0be9..9a0b08006e0 100644 --- a/core/src/main/java/google/registry/model/ForeignKeyUtils.java +++ b/core/src/main/java/google/registry/model/ForeignKeyUtils.java @@ -29,7 +29,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import google.registry.config.RegistryConfig; -import google.registry.model.contact.Contact; import google.registry.model.domain.Domain; import google.registry.model.host.Host; import google.registry.persistence.VKey; @@ -60,7 +59,6 @@ private ForeignKeyUtils() {} private static final ImmutableMap, String> RESOURCE_TYPE_TO_FK_PROPERTY = ImmutableMap.of( - Contact.class, "contactId", Domain.class, "domainName", Host.class, "hostName"); diff --git a/core/src/main/java/google/registry/model/contact/Contact.java b/core/src/main/java/google/registry/model/contact/Contact.java deleted file mode 100644 index f8218247192..00000000000 --- a/core/src/main/java/google/registry/model/contact/Contact.java +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2017 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.model.contact; - -import google.registry.model.EppResource.ForeignKeyedEppResource; -import google.registry.model.annotations.ExternalMessagingName; -import google.registry.persistence.VKey; -import google.registry.persistence.WithVKey; -import jakarta.persistence.Access; -import jakarta.persistence.AccessType; -import jakarta.persistence.Entity; -import jakarta.persistence.Id; -import jakarta.persistence.Index; -import jakarta.persistence.Table; - -/** - * A persistable contact resource including mutable and non-mutable fields. - * - * @see RFC 5733 - */ -@Entity -@Table( - name = "Contact", - indexes = { - @Index(columnList = "creationTime"), - @Index(columnList = "currentSponsorRegistrarId"), - @Index(columnList = "deletionTime"), - @Index(columnList = "contactId"), - @Index(columnList = "searchName") - }) -@ExternalMessagingName("contact") -@WithVKey(String.class) -@Access(AccessType.FIELD) -public class Contact extends ContactBase implements ForeignKeyedEppResource { - - @Override - public VKey createVKey() { - return VKey.create(Contact.class, getRepoId()); - } - - @Override - @Id - @Access(AccessType.PROPERTY) - public String getRepoId() { - return super.getRepoId(); - } - - @Override - public Builder asBuilder() { - return new Builder(clone(this)); - } - - /** A builder for constructing {@link Contact}, since it is immutable. */ - public static class Builder extends ContactBase.Builder { - - public Builder() {} - - private Builder(Contact instance) { - super(instance); - } - - public Builder copyFrom(ContactBase contactBase) { - return this.setAuthInfo(contactBase.getAuthInfo()) - .setContactId(contactBase.getContactId()) - .setCreationRegistrarId(contactBase.getCreationRegistrarId()) - .setCreationTime(contactBase.getCreationTime()) - .setDeletionTime(contactBase.getDeletionTime()) - .setDisclose(contactBase.getDisclose()) - .setEmailAddress(contactBase.getEmailAddress()) - .setFaxNumber(contactBase.getFaxNumber()) - .setInternationalizedPostalInfo(contactBase.getInternationalizedPostalInfo()) - .setLastTransferTime(contactBase.getLastTransferTime()) - .setLastEppUpdateRegistrarId(contactBase.getLastEppUpdateRegistrarId()) - .setLastEppUpdateTime(contactBase.getLastEppUpdateTime()) - .setLocalizedPostalInfo(contactBase.getLocalizedPostalInfo()) - .setPersistedCurrentSponsorRegistrarId( - contactBase.getPersistedCurrentSponsorRegistrarId()) - .setRepoId(contactBase.getRepoId()) - .setStatusValues(contactBase.getStatusValues()) - .setTransferData(contactBase.getTransferData()) - .setVoiceNumber(contactBase.getVoiceNumber()); - } - } -} diff --git a/core/src/main/java/google/registry/model/contact/ContactBase.java b/core/src/main/java/google/registry/model/contact/ContactBase.java deleted file mode 100644 index fb7d5b6535e..00000000000 --- a/core/src/main/java/google/registry/model/contact/ContactBase.java +++ /dev/null @@ -1,388 +0,0 @@ -// 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.model.contact; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.collect.ImmutableList.toImmutableList; - -import com.google.common.collect.ImmutableList; -import google.registry.model.EppResource; -import google.registry.model.EppResource.ResourceWithTransferData; -import google.registry.model.transfer.ContactTransferData; -import google.registry.persistence.VKey; -import jakarta.persistence.Access; -import jakarta.persistence.AccessType; -import jakarta.persistence.AttributeOverride; -import jakarta.persistence.AttributeOverrides; -import jakarta.persistence.Column; -import jakarta.persistence.Embeddable; -import jakarta.persistence.Embedded; -import jakarta.persistence.MappedSuperclass; -import jakarta.xml.bind.annotation.XmlElement; -import java.util.Objects; -import java.util.Optional; -import java.util.stream.Stream; -import org.joda.time.DateTime; - -/** - * A persistable contact resource including mutable and non-mutable fields. - * - *

This class deliberately does not include an {@link jakarta.persistence.Id} so that any - * foreign-keyed fields can refer to the proper parent entity's ID, whether we're storing this in - * the DB itself or as part of another entity - * - * @see RFC 5733 - */ -@MappedSuperclass -@Embeddable -@Access(AccessType.FIELD) -public class ContactBase extends EppResource - implements ResourceWithTransferData { - - /** - * Unique identifier for this contact. - * - *

This is only unique in the sense that for any given lifetime specified as the time range - * from (creationTime, deletionTime) there can only be one contact in the database with this id. - * However, there can be many contacts with the same id and non-overlapping lifetimes. - */ - String contactId; - - /** - * Localized postal info for the contact. All contained values must be representable in the 7-bit - * US-ASCII character set. Personal info; cleared by {@link Contact.Builder#wipeOut}. - */ - @Embedded - @AttributeOverrides({ - @AttributeOverride(name = "name", column = @Column(name = "addr_local_name")), - @AttributeOverride(name = "org", column = @Column(name = "addr_local_org")), - @AttributeOverride(name = "type", column = @Column(name = "addr_local_type")), - @AttributeOverride( - name = "address.streetLine1", - column = @Column(name = "addr_local_street_line1")), - @AttributeOverride( - name = "address.streetLine2", - column = @Column(name = "addr_local_street_line2")), - @AttributeOverride( - name = "address.streetLine3", - column = @Column(name = "addr_local_street_line3")), - @AttributeOverride(name = "address.city", column = @Column(name = "addr_local_city")), - @AttributeOverride(name = "address.state", column = @Column(name = "addr_local_state")), - @AttributeOverride(name = "address.zip", column = @Column(name = "addr_local_zip")), - @AttributeOverride( - name = "address.countryCode", - column = @Column(name = "addr_local_country_code")) - }) - PostalInfo localizedPostalInfo; - - /** - * Internationalized postal info for the contact. Personal info; cleared by {@link - * Contact.Builder#wipeOut}. - */ - @Embedded - @AttributeOverrides({ - @AttributeOverride(name = "name", column = @Column(name = "addr_i18n_name")), - @AttributeOverride(name = "org", column = @Column(name = "addr_i18n_org")), - @AttributeOverride(name = "type", column = @Column(name = "addr_i18n_type")), - @AttributeOverride( - name = "address.streetLine1", - column = @Column(name = "addr_i18n_street_line1")), - @AttributeOverride( - name = "address.streetLine2", - column = @Column(name = "addr_i18n_street_line2")), - @AttributeOverride( - name = "address.streetLine3", - column = @Column(name = "addr_i18n_street_line3")), - @AttributeOverride(name = "address.city", column = @Column(name = "addr_i18n_city")), - @AttributeOverride(name = "address.state", column = @Column(name = "addr_i18n_state")), - @AttributeOverride(name = "address.zip", column = @Column(name = "addr_i18n_zip")), - @AttributeOverride( - name = "address.countryCode", - column = @Column(name = "addr_i18n_country_code")) - }) - PostalInfo internationalizedPostalInfo; - - /** - * Contact name used for name searches. This is set automatically to be the internationalized - * postal name, or if null, the localized postal name, or if that is null as well, null. Personal - * info; cleared by {@link Contact.Builder#wipeOut}. - */ - String searchName; - - /** Contact’s voice number. Personal info; cleared by {@link Contact.Builder#wipeOut}. */ - @Embedded - @AttributeOverrides({ - @AttributeOverride(name = "phoneNumber", column = @Column(name = "voice_phone_number")), - @AttributeOverride(name = "extension", column = @Column(name = "voice_phone_extension")), - }) - ContactPhoneNumber voice; - - /** Contact’s fax number. Personal info; cleared by {@link Contact.Builder#wipeOut}. */ - @Embedded - @AttributeOverrides({ - @AttributeOverride(name = "phoneNumber", column = @Column(name = "fax_phone_number")), - @AttributeOverride(name = "extension", column = @Column(name = "fax_phone_extension")), - }) - ContactPhoneNumber fax; - - /** Contact’s email address. Personal info; cleared by {@link Contact.Builder#wipeOut}. */ - String email; - - /** Authorization info (aka transfer secret) of the contact. */ - @Embedded - @AttributeOverrides({ - @AttributeOverride(name = "pw.value", column = @Column(name = "auth_info_value")), - @AttributeOverride(name = "pw.repoId", column = @Column(name = "auth_info_repo_id")), - }) - ContactAuthInfo authInfo; - - /** Data about any pending or past transfers on this contact. */ - ContactTransferData transferData; - - /** - * The time that this resource was last transferred. - * - *

Can be null if the resource has never been transferred. - */ - DateTime lastTransferTime; - - // If any new fields are added which contain personal information, make sure they are cleared by - // the wipeOut() function, so that data is not kept around for deleted contacts. - - /** Disclosure policy. */ - @Embedded - @AttributeOverrides({ - @AttributeOverride(name = "name", column = @Column(name = "disclose_types_name")), - @AttributeOverride(name = "org", column = @Column(name = "disclose_types_org")), - @AttributeOverride(name = "addr", column = @Column(name = "disclose_types_addr")), - @AttributeOverride(name = "flag", column = @Column(name = "disclose_mode_flag")), - @AttributeOverride(name = "voice.marked", column = @Column(name = "disclose_show_voice")), - @AttributeOverride(name = "fax.marked", column = @Column(name = "disclose_show_fax")), - @AttributeOverride(name = "email.marked", column = @Column(name = "disclose_show_email")) - }) - Disclose disclose; - - @Override - public VKey createVKey() { - throw new UnsupportedOperationException( - "ContactBase is not an actual persisted entity you can create a key to;" - + " use Contact instead"); - } - - public String getContactId() { - return contactId; - } - - public PostalInfo getLocalizedPostalInfo() { - return localizedPostalInfo; - } - - public PostalInfo getInternationalizedPostalInfo() { - return internationalizedPostalInfo; - } - - public String getSearchName() { - return searchName; - } - - public ContactPhoneNumber getVoiceNumber() { - return voice; - } - - public ContactPhoneNumber getFaxNumber() { - return fax; - } - - public String getEmailAddress() { - return email; - } - - public ContactAuthInfo getAuthInfo() { - return authInfo; - } - - public Disclose getDisclose() { - return disclose; - } - - public String getCurrentSponsorRegistrarId() { - return getPersistedCurrentSponsorRegistrarId(); - } - - @Override - public ContactTransferData getTransferData() { - return Optional.ofNullable(transferData).orElse(ContactTransferData.EMPTY); - } - - @Override - public DateTime getLastTransferTime() { - return lastTransferTime; - } - - @Override - public String getForeignKey() { - return contactId; - } - - /** - * Postal info for the contact. - * - *

The XML marshalling expects the {@link PostalInfo} objects in a list, but we can't actually - * persist them directly due to legacy reasons (Objectify can't handle collections of embedded - * objects that themselves contain collections, and there's a list of streets inside). This method - * transforms the persisted format to the XML format for marshalling. - */ - @XmlElement(name = "postalInfo") - public ImmutableList getPostalInfosAsList() { - return Stream.of(localizedPostalInfo, internationalizedPostalInfo) - .filter(Objects::nonNull) - .collect(toImmutableList()); - } - - @Override - public ContactBase cloneProjectedAtTime(DateTime now) { - // Contacts no longer exist and thus do not need to be projected - return this; - } - - @Override - public Builder asBuilder() { - return new Builder<>(clone(this)); - } - - /** A builder for constructing {@link Contact}, since it is immutable. */ - public static class Builder> - extends EppResource.Builder implements BuilderWithTransferData { - - public Builder() {} - - protected Builder(T instance) { - super(instance); - } - - public B setContactId(String contactId) { - getInstance().contactId = contactId; - return thisCastToDerived(); - } - - public B setLocalizedPostalInfo(PostalInfo localizedPostalInfo) { - checkArgument( - localizedPostalInfo == null - || PostalInfo.Type.LOCALIZED.equals(localizedPostalInfo.getType())); - getInstance().localizedPostalInfo = localizedPostalInfo; - return thisCastToDerived(); - } - - public B setInternationalizedPostalInfo(PostalInfo internationalizedPostalInfo) { - checkArgument( - internationalizedPostalInfo == null - || PostalInfo.Type.INTERNATIONALIZED.equals(internationalizedPostalInfo.getType())); - getInstance().internationalizedPostalInfo = internationalizedPostalInfo; - return thisCastToDerived(); - } - - public B overlayLocalizedPostalInfo(PostalInfo localizedPostalInfo) { - return setLocalizedPostalInfo( - getInstance().localizedPostalInfo == null - ? localizedPostalInfo - : getInstance().localizedPostalInfo.overlay(localizedPostalInfo)); - } - - public B overlayInternationalizedPostalInfo(PostalInfo internationalizedPostalInfo) { - return setInternationalizedPostalInfo( - getInstance().internationalizedPostalInfo == null - ? internationalizedPostalInfo - : getInstance().internationalizedPostalInfo.overlay(internationalizedPostalInfo)); - } - - public B setVoiceNumber(ContactPhoneNumber voiceNumber) { - if (voiceNumber != null && voiceNumber.hasNullFields()) { - voiceNumber = null; - } - getInstance().voice = voiceNumber; - return thisCastToDerived(); - } - - public B setFaxNumber(ContactPhoneNumber faxNumber) { - if (faxNumber != null && faxNumber.hasNullFields()) { - faxNumber = null; - } - getInstance().fax = faxNumber; - return thisCastToDerived(); - } - - public B setEmailAddress(String emailAddress) { - getInstance().email = emailAddress; - return thisCastToDerived(); - } - - public B setAuthInfo(ContactAuthInfo authInfo) { - getInstance().authInfo = authInfo; - return thisCastToDerived(); - } - - public B setDisclose(Disclose disclose) { - getInstance().disclose = disclose; - return thisCastToDerived(); - } - - @Override - public B setTransferData(ContactTransferData transferData) { - getInstance().transferData = transferData; - return thisCastToDerived(); - } - - @Override - public B setLastTransferTime(DateTime lastTransferTime) { - getInstance().lastTransferTime = lastTransferTime; - return thisCastToDerived(); - } - - /** - * Remove all personally identifying information about a contact. - * - *

This should be used when deleting a contact so that the soft-deleted entity doesn't - * contain information that the registrant requested to be deleted. - */ - public B wipeOut() { - setEmailAddress(null); - setFaxNumber(null); - setInternationalizedPostalInfo(null); - setLocalizedPostalInfo(null); - setVoiceNumber(null); - return thisCastToDerived(); - } - - @Override - public T build() { - T instance = getInstance(); - // If TransferData is totally empty, set it to null. - if (ContactTransferData.EMPTY.equals(instance.transferData)) { - setTransferData(null); - } - // Set the searchName using the internationalized and localized postal info names. - if ((instance.internationalizedPostalInfo != null) - && (instance.internationalizedPostalInfo.getName() != null)) { - instance.searchName = instance.internationalizedPostalInfo.getName(); - } else if ((instance.localizedPostalInfo != null) - && (instance.localizedPostalInfo.getName() != null)) { - instance.searchName = instance.localizedPostalInfo.getName(); - } else { - instance.searchName = null; - } - return super.build(); - } - } -} diff --git a/core/src/main/java/google/registry/model/contact/ContactCommand.java b/core/src/main/java/google/registry/model/contact/ContactCommand.java index be0639d7f8f..9aaabacd4ed 100644 --- a/core/src/main/java/google/registry/model/contact/ContactCommand.java +++ b/core/src/main/java/google/registry/model/contact/ContactCommand.java @@ -18,6 +18,7 @@ import static google.registry.util.CollectionUtils.nullToEmpty; import com.google.common.collect.Maps; +import google.registry.model.EppResource; import google.registry.model.ImmutableObject; import google.registry.model.contact.PostalInfo.Type; import google.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand; @@ -34,13 +35,13 @@ import java.util.List; import java.util.Map; -/** A collection of {@link Contact} commands. */ +/** A collection of (vestigial) Contact commands. */ public class ContactCommand { /** The fields on "chgType" from RFC5733. */ @XmlTransient public static class ContactCreateOrChange extends ImmutableObject - implements ResourceCreateOrChange { + implements ResourceCreateOrChange> { /** Postal info for the contact. */ List postalInfo; @@ -111,13 +112,13 @@ public ContactAuthInfo getAuthInfo() { } /** - * A create command for a {@link Contact}, mapping "createType" from RFC5733}. */ @XmlType(propOrder = {"contactId", "postalInfo", "voice", "fax", "email", "authInfo", "disclose"}) @XmlRootElement public static class Create extends ContactCreateOrChange - implements SingleResourceCommand, ResourceCreateOrChange { + implements SingleResourceCommand, ResourceCreateOrChange> { /** * Unique identifier for this contact. * @@ -139,29 +140,29 @@ public ContactAuthInfo getAuthInfo() { } } - /** A delete command for a {@link Contact}. */ + /** A delete command for a (vestigial) Contact. */ @XmlRootElement public static class Delete extends AbstractSingleResourceCommand {} - /** An info request for a {@link Contact}. */ + /** An info request for a (vestigial) Contact. */ @XmlRootElement @XmlType(propOrder = {"targetId", "authInfo"}) public static class Info extends AbstractContactAuthCommand {} - /** A check request for {@link Contact}. */ + /** A check request for (vestigial) Contact. */ @XmlRootElement public static class Check extends ResourceCheck {} - /** A transfer operation for a {@link Contact}. */ + /** A transfer operation for a (vestigial) Contact. */ @XmlRootElement @XmlType(propOrder = {"targetId", "authInfo"}) public static class Transfer extends AbstractContactAuthCommand {} - /** An update to a {@link Contact}. */ + /** An update to a (vestigial) Contact. */ @XmlRootElement @XmlType(propOrder = {"targetId", "innerAdd", "innerRemove", "innerChange"}) public static class Update - extends ResourceUpdate { + extends ResourceUpdate, Update.Change> { @XmlElement(name = "chg") protected Change innerChange; diff --git a/core/src/main/java/google/registry/model/contact/ContactHistory.java b/core/src/main/java/google/registry/model/contact/ContactHistory.java deleted file mode 100644 index 9750233f75b..00000000000 --- a/core/src/main/java/google/registry/model/contact/ContactHistory.java +++ /dev/null @@ -1,102 +0,0 @@ -// 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.model.contact; - -import google.registry.model.EppResource; -import google.registry.model.reporting.HistoryEntry; -import google.registry.persistence.VKey; -import jakarta.persistence.Access; -import jakarta.persistence.AccessType; -import jakarta.persistence.AttributeOverride; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.Index; -import jakarta.persistence.Table; -import java.util.Optional; -import javax.annotation.Nullable; - -/** - * A persisted history entry representing an EPP modification to a contact. - * - *

In addition to the general history fields (e.g. action time, registrar ID) we also persist a - * copy of the contact entity at this point in time. We persist a raw {@link ContactBase} so that - * the foreign-keyed fields in that class can refer to this object. - */ -@Entity -@Table( - indexes = { - @Index(columnList = "creationTime"), - @Index(columnList = "historyRegistrarId"), - @Index(columnList = "historyType"), - @Index(columnList = "historyModificationTime") - }) -@AttributeOverride(name = "repoId", column = @Column(name = "contactRepoId")) -@Access(AccessType.FIELD) -public class ContactHistory extends HistoryEntry { - - // Store ContactBase instead of Contact, so we don't pick up its @Id - // @Nullable for the sake of pre-Registry-3.0 history objects - @Nullable ContactBase resource; - - @Override - protected ContactBase getResource() { - return resource; - } - - /** - * The values of all the fields on the {@link ContactBase} object after the action represented by - * this history object was executed. - * - *

Will be absent for objects created prior to the Registry 3.0 SQL migration. - */ - public Optional getContactBase() { - return Optional.ofNullable(resource); - } - - /** Creates a {@link VKey} instance for this entity. */ - @Override - public VKey createVKey() { - return VKey.create(ContactHistory.class, getHistoryEntryId()); - } - - @Override - public Optional getResourceAtPointInTime() { - return getContactBase().map(contactBase -> new Contact.Builder().copyFrom(contactBase).build()); - } - - @Override - public Builder asBuilder() { - return new Builder(clone(this)); - } - - public static class Builder extends HistoryEntry.Builder { - - public Builder() {} - - public Builder(ContactHistory instance) { - super(instance); - } - - public Builder setContact(ContactBase contactBase) { - getInstance().resource = contactBase; - return setRepoId(contactBase); - } - - public Builder wipeOutPii() { - getInstance().resource = getInstance().resource.asBuilder().wipeOut().build(); - return this; - } - } -} diff --git a/core/src/main/java/google/registry/model/contact/ContactPhoneNumber.java b/core/src/main/java/google/registry/model/contact/ContactPhoneNumber.java index bd8bf1c8826..711072521fe 100644 --- a/core/src/main/java/google/registry/model/contact/ContactPhoneNumber.java +++ b/core/src/main/java/google/registry/model/contact/ContactPhoneNumber.java @@ -20,11 +20,9 @@ /** * EPP Contact Phone Number * - *

This class is embedded inside a {@link Contact} hold the phone number of an EPP contact. The - * fields are all defined in the parent class {@link PhoneNumber}, but the subclass is still - * necessary to pick up the contact namespace. - * - * @see Contact + *

This class is embedded inside a (vestigial) Contact to hold the phone number of an EPP + * contact. The fields are all defined in the parent class {@link PhoneNumber}, but the subclass is + * still necessary to pick up the contact namespace. */ @Embeddable public class ContactPhoneNumber extends PhoneNumber { diff --git a/core/src/main/java/google/registry/model/domain/DesignatedContact.java b/core/src/main/java/google/registry/model/domain/DesignatedContact.java deleted file mode 100644 index 45394a6a376..00000000000 --- a/core/src/main/java/google/registry/model/domain/DesignatedContact.java +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2017 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.model.domain; - -import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; - -import google.registry.model.ImmutableObject; -import google.registry.model.UnsafeSerializable; -import google.registry.model.contact.Contact; -import google.registry.persistence.VKey; -import jakarta.persistence.Embeddable; -import jakarta.xml.bind.annotation.XmlEnumValue; - -/** - * Persisted type for storing a domain's contact associations. - * - *

A contact association on a domain consists of the contact key and the contact "type", which is - * the designated role of this contact with respect to this domain. When converting to and from EPP - * XML, we use {@link ForeignKeyedDesignatedContact} to replace the contact's primary key with its - * foreign key, since that is what EPP exposes. - * - *

Note one could in principle store contact foreign keys here in addition to keys, unlike the - * situation with hosts where client-side renames would make that data stale. However, we sometimes - * rename contacts internally ourselves, and it's easier to use the same model for both cases. - * - *

This entity type is not persisted in Cloud SQL. The different roles are represented as - * separate fields in the Domain table. - * - * @see RFC 5731 - EPP Domain Name Mapping - * - Contact and Client Identifiers - */ -@Embeddable -public class DesignatedContact extends ImmutableObject implements UnsafeSerializable { - - /** - * XML type for contact types. This can be either: {@code "admin"}, {@code "billing"}, or - * {@code "tech"} and corresponds to {@code contactAttrType} in {@code domain-1.0.xsd}. - */ - public enum Type { - @XmlEnumValue("admin") - ADMIN, - @XmlEnumValue("billing") - BILLING, - @XmlEnumValue("tech") - TECH, - /** The registrant type is not reflected in XML and exists only for internal use. */ - REGISTRANT - } - - public static DesignatedContact create(Type type, VKey contact) { - DesignatedContact instance = new DesignatedContact(); - instance.type = type; - instance.contactVKey = checkArgumentNotNull(contact, "Must specify contact key"); - return instance; - } - - Type type; - - VKey contactVKey; - - public Type getType() { - return type; - } - - public VKey getContactKey() { - return contactVKey; - } -} 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 01b9c388436..f5ca447fee2 100644 --- a/core/src/main/java/google/registry/model/domain/Domain.java +++ b/core/src/main/java/google/registry/model/domain/Domain.java @@ -178,7 +178,6 @@ public Builder copyFrom(DomainBase domainBase) { .setAutorenewPollMessage(domainBase.getAutorenewPollMessage()) .setAutorenewBillingEvent(domainBase.getAutorenewBillingEvent()) .setAutorenewEndTime(domainBase.getAutorenewEndTime()) - .setContacts(domainBase.getContacts()) .setCreationRegistrarId(domainBase.getCreationRegistrarId()) .setCreationTime(domainBase.getCreationTime()) .setDomainName(domainBase.getDomainName()) @@ -193,7 +192,6 @@ public Builder copyFrom(DomainBase domainBase) { .setLastEppUpdateTime(domainBase.getLastEppUpdateTime()) .setNameservers(domainBase.getNameservers()) .setPersistedCurrentSponsorRegistrarId(domainBase.getPersistedCurrentSponsorRegistrarId()) - .setRegistrant(domainBase.getRegistrant()) .setRegistrationExpirationTime(domainBase.getRegistrationExpirationTime()) .setRepoId(domainBase.getRepoId()) .setSmdId(domainBase.getSmdId()) 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 1f95249f018..6c753c4581d 100644 --- a/core/src/main/java/google/registry/model/domain/DomainBase.java +++ b/core/src/main/java/google/registry/model/domain/DomainBase.java @@ -45,8 +45,6 @@ import google.registry.model.EppResource; import google.registry.model.EppResource.ResourceWithTransferData; import google.registry.model.billing.BillingRecurrence; -import google.registry.model.contact.Contact; -import google.registry.model.domain.DesignatedContact.Type; import google.registry.model.domain.launch.LaunchNotice; import google.registry.model.domain.rgp.GracePeriodStatus; import google.registry.model.domain.secdns.DomainDsData; @@ -79,10 +77,8 @@ import jakarta.persistence.MappedSuperclass; import jakarta.persistence.Transient; import java.util.HashSet; -import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.function.Predicate; import javax.annotation.Nullable; import org.hibernate.collection.spi.PersistentSet; import org.joda.time.DateTime; @@ -131,12 +127,12 @@ public class DomainBase extends EppResource /** References to hosts that are the nameservers for the domain. */ @Expose @Transient Set> nsHosts; - /** Contacts. */ - @Expose @Nullable VKey adminContact; + /** Contacts keys are kept around for vestigial purposes for now. */ + @Expose @Nullable String adminContact; - @Expose @Nullable VKey billingContact; - @Expose @Nullable VKey techContact; - @Expose @Nullable VKey registrantContact; + @Expose @Nullable String billingContact; + @Expose @Nullable String techContact; + @Expose @Nullable String registrantContact; /** Authorization info (aka transfer secret) of the domain. */ @Embedded @@ -586,120 +582,21 @@ public ImmutableSortedSet loadNameserverHostNames() { .collect(toImmutableSortedSet(Ordering.natural()))); } - /** A key to the registrant who registered this domain. */ - public Optional> getRegistrant() { - return Optional.ofNullable(registrantContact); - } - - public Optional> getAdminContact() { - return Optional.ofNullable(adminContact); - } - - public Optional> getBillingContact() { - return Optional.ofNullable(billingContact); - } - - public Optional> getTechContact() { - return Optional.ofNullable(techContact); - } - - /** - * Associated contacts for the domain (other than registrant). - * - *

Note: This can be an empty set if no contacts are present for the domain. - */ - public ImmutableSet getContacts() { - return getAllContacts(false); - } - - /** - * Gets all associated contacts for the domain, including the registrant. - * - *

Note: This can be an empty set if no contacts are present for the domain. - */ - public ImmutableSet getAllContacts() { - return getAllContacts(true); - } - @Nullable public DomainAuthInfo getAuthInfo() { return authInfo; } - /** - * Returns all referenced contacts from this domain. - * - *

Note: This can be an empty set if no contacts are present for the domain. - */ - public ImmutableSet> getReferencedContacts() { - return nullToEmptyImmutableCopy(getAllContacts(true)).stream() - .map(DesignatedContact::getContactKey) - .filter(Objects::nonNull) - .collect(toImmutableSet()); - } - - private ImmutableSet getAllContacts(boolean includeRegistrant) { - ImmutableSet.Builder builder = new ImmutableSet.Builder<>(); - if (includeRegistrant) { - getRegistrant().ifPresent(c -> builder.add(DesignatedContact.create(Type.REGISTRANT, c))); - } - getAdminContact().ifPresent(c -> builder.add(DesignatedContact.create(Type.ADMIN, c))); - getBillingContact().ifPresent(c -> builder.add(DesignatedContact.create(Type.BILLING, c))); - getTechContact().ifPresent(c -> builder.add(DesignatedContact.create(Type.TECH, c))); - return builder.build(); - } - public String getTld() { return tld; } - /** - * Sets the individual contact fields from {@code contacts}. - * - *

The registrant field is only set if {@code includeRegistrant} is true, as this field needs - * to be set in some circumstances but not in others. - */ - void setContactFields(Set contacts, boolean includeRegistrant) { - // Set the individual contact fields. - billingContact = null; - techContact = null; - adminContact = null; - if (includeRegistrant) { - registrantContact = null; - } - HashSet contactsDiscovered = new HashSet<>(); - for (DesignatedContact contact : contacts) { - checkArgument( - !contactsDiscovered.contains(contact.getType()), - "Duplicate contact type %s in designated contact set.", - contact.getType()); - contactsDiscovered.add(contact.getType()); - switch (contact.getType()) { - case BILLING -> billingContact = contact.getContactKey(); - case TECH -> techContact = contact.getContactKey(); - case ADMIN -> adminContact = contact.getContactKey(); - case REGISTRANT -> { - if (includeRegistrant) { - registrantContact = contact.getContactKey(); - } - } - default -> - throw new IllegalArgumentException( - "Unknown contact resource type: " + contact.getType()); - } - } - } - @Override public VKey createVKey() { throw new UnsupportedOperationException( "DomainBase is not an actual persisted entity you can create a key to; use Domain instead"); } - /** Predicate to determine if a given {@link DesignatedContact} is the registrant. */ - static final Predicate IS_REGISTRANT = - (DesignatedContact contact) -> Type.REGISTRANT.equals(contact.type); - /** An override of {@link EppResource#asBuilder} with tighter typing. */ @Override public Builder asBuilder() { @@ -764,12 +661,6 @@ public B setDsData(ImmutableSet dsData) { return thisCastToDerived(); } - public B setRegistrant(Optional> registrant) { - // Set the registrant field specifically. - getInstance().registrantContact = registrant.orElse(null); - return thisCastToDerived(); - } - public B setAuthInfo(DomainAuthInfo authInfo) { getInstance().authInfo = authInfo; return thisCastToDerived(); @@ -805,26 +696,6 @@ public B removeNameservers(ImmutableSet> nameservers) { ImmutableSet.copyOf(difference(getInstance().getNameservers(), nameservers))); } - public B setContacts(DesignatedContact contact) { - return setContacts(ImmutableSet.of(contact)); - } - - public B setContacts(ImmutableSet contacts) { - checkArgument(contacts.stream().noneMatch(IS_REGISTRANT), "Registrant cannot be a contact"); - - // Set the individual fields. - getInstance().setContactFields(contacts, false); - return thisCastToDerived(); - } - - public B addContacts(ImmutableSet contacts) { - return setContacts(ImmutableSet.copyOf(Sets.union(getInstance().getContacts(), contacts))); - } - - public B removeContacts(ImmutableSet contacts) { - return setContacts(ImmutableSet.copyOf(difference(getInstance().getContacts(), contacts))); - } - public B setLaunchNotice(LaunchNotice launchNotice) { getInstance().launchNotice = launchNotice; return thisCastToDerived(); diff --git a/core/src/main/java/google/registry/model/domain/DomainCommand.java b/core/src/main/java/google/registry/model/domain/DomainCommand.java index 2900060c37a..d8b73c504e1 100644 --- a/core/src/main/java/google/registry/model/domain/DomainCommand.java +++ b/core/src/main/java/google/registry/model/domain/DomainCommand.java @@ -30,7 +30,6 @@ import google.registry.flows.exceptions.ContactsProhibitedException; import google.registry.model.ForeignKeyUtils; import google.registry.model.ImmutableObject; -import google.registry.model.contact.Contact; import google.registry.model.eppinput.ResourceCommand.AbstractSingleResourceCommand; import google.registry.model.eppinput.ResourceCommand.ResourceCheck; import google.registry.model.eppinput.ResourceCommand.ResourceCreateOrChange; @@ -79,9 +78,6 @@ public static class DomainCreateOrChange extends Immut @Nullable String registrantContactId; - /** A resolved key to the registrant who registered this domain. */ - @Nullable @XmlTransient VKey registrant; - /** Authorization info (aka transfer secret) of the domain. */ DomainAuthInfo authInfo; @@ -89,10 +85,6 @@ public Optional getRegistrantContactId() { return Optional.ofNullable(registrantContactId); } - public Optional> getRegistrant() { - return Optional.ofNullable(registrant); - } - public DomainAuthInfo getAuthInfo() { return authInfo; } @@ -131,10 +123,6 @@ public static class Create extends DomainCreateOrChange @XmlElement(name = "contact") Set foreignKeyedDesignatedContacts; - /** Resolved keys to associated contacts for the domain (other than registrant). */ - @XmlTransient - Set contacts; - /** The period that this domain's state was set to last for (e.g. 1-10 years). */ Period period; @@ -159,10 +147,6 @@ public ImmutableSet> getNameservers() { return nullToEmptyImmutableCopy(nameservers); } - public ImmutableSet getContacts() { - return nullToEmptyImmutableCopy(contacts); - } - @Override public DomainAuthInfo getAuthInfo() { return authInfo; @@ -340,10 +324,6 @@ public static class AddRemove extends ResourceUpdate.AddRemove { @XmlElement(name = "contact") Set foreignKeyedDesignatedContacts; - /** Resolved keys to associated contacts for the domain (other than registrant). */ - @XmlTransient - Set contacts; - public ImmutableSet getNameserverHostNames() { return nullSafeImmutableCopy(nameserverHostNames); } @@ -352,10 +332,6 @@ public ImmutableSet> getNameservers() { return nullToEmptyImmutableCopy(nameservers); } - public ImmutableSet getContacts() { - return nullToEmptyImmutableCopy(contacts); - } - /** Creates a copy of this {@link AddRemove} with hard links to hosts and contacts. */ private AddRemove cloneAndLinkReferences(DateTime now) throws InvalidReferencesException, ContactsProhibitedException { diff --git a/core/src/main/java/google/registry/model/domain/ForeignKeyedDesignatedContact.java b/core/src/main/java/google/registry/model/domain/ForeignKeyedDesignatedContact.java index 32a2d80cf91..989e6000ff4 100644 --- a/core/src/main/java/google/registry/model/domain/ForeignKeyedDesignatedContact.java +++ b/core/src/main/java/google/registry/model/domain/ForeignKeyedDesignatedContact.java @@ -16,27 +16,42 @@ import google.registry.model.ImmutableObject; import jakarta.xml.bind.annotation.XmlAttribute; +import jakarta.xml.bind.annotation.XmlEnumValue; import jakarta.xml.bind.annotation.XmlValue; /** - * EPP-XML-serializable equivalent of {@link DesignatedContact}. + * Vestigial EPP-XML-serializable equivalent of a contact. * - *

This type is used on the wire for EPP XML, where only the contact ID (foreign key) is exposed. - * This is converted to and from the persisted type, {@link DesignatedContact}, which stores the - * primary key instead of the foreign key. + *

This type was used on the wire for EPP XML, where only the contact ID (foreign key) was + * exposed. * * @see RFC 5731 - EPP Domain Name Mapping * - Contact and Client Identifiers */ public class ForeignKeyedDesignatedContact extends ImmutableObject { + + /** + * XML type for contact types. This can be either: {@code "admin"}, {@code "billing"}, or {@code + * "tech"} and corresponds to {@code contactAttrType} in {@code domain-1.0.xsd}. + */ + public enum Type { + @XmlEnumValue("admin") + ADMIN, + @XmlEnumValue("billing") + BILLING, + @XmlEnumValue("tech") + TECH, + /** The registrant type is not reflected in XML and exists only for internal use. */ + REGISTRANT + } + @XmlAttribute(required = true) - DesignatedContact.Type type; + Type type; @XmlValue String contactId; - public static ForeignKeyedDesignatedContact create( - DesignatedContact.Type type, String contactId) { + public static ForeignKeyedDesignatedContact create(Type type, String contactId) { ForeignKeyedDesignatedContact instance = new ForeignKeyedDesignatedContact(); instance.type = type; instance.contactId = contactId; diff --git a/core/src/main/java/google/registry/model/eppcommon/StatusValue.java b/core/src/main/java/google/registry/model/eppcommon/StatusValue.java index 1b89bdff754..ae748f76132 100644 --- a/core/src/main/java/google/registry/model/eppcommon/StatusValue.java +++ b/core/src/main/java/google/registry/model/eppcommon/StatusValue.java @@ -22,8 +22,6 @@ import google.registry.model.EppResource; import google.registry.model.adapters.EnumToAttributeAdapter.EppEnum; import google.registry.model.adapters.StatusValueAdapter; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactBase; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainBase; import google.registry.model.host.Host; @@ -130,8 +128,6 @@ public enum StatusValue implements EppEnum { /** Enum to help clearly list which resource types a status value is allowed to be present on. */ private enum AllowedOn { ALL( - Contact.class, - ContactBase.class, Domain.class, DomainBase.class, Host.class, diff --git a/core/src/main/java/google/registry/persistence/VKey.java b/core/src/main/java/google/registry/persistence/VKey.java index e1a65b9951a..84506d8e9b0 100644 --- a/core/src/main/java/google/registry/persistence/VKey.java +++ b/core/src/main/java/google/registry/persistence/VKey.java @@ -27,7 +27,6 @@ import com.google.gson.annotations.Expose; import google.registry.model.EppResource; import google.registry.model.ImmutableObject; -import google.registry.model.contact.Contact; import google.registry.model.domain.Domain; import google.registry.model.host.Host; import google.registry.util.SerializeUtils; @@ -51,7 +50,7 @@ public class VKey extends ImmutableObject implements Serializable { private static final String DELIMITER = "@"; private static final ImmutableMap> EPP_RESOURCE_CLASS_MAP = - ImmutableList.of(Domain.class, Host.class, Contact.class).stream() + ImmutableList.of(Domain.class, Host.class).stream() .collect(toImmutableMap(Class::getSimpleName, identity())); // The primary key for the referenced entity. diff --git a/core/src/main/java/google/registry/rde/RdeStagingAction.java b/core/src/main/java/google/registry/rde/RdeStagingAction.java index 79c85243efa..890e892a31b 100644 --- a/core/src/main/java/google/registry/rde/RdeStagingAction.java +++ b/core/src/main/java/google/registry/rde/RdeStagingAction.java @@ -44,7 +44,6 @@ import google.registry.keyring.api.KeyModule.Key; import google.registry.model.common.Cursor; import google.registry.model.common.Cursor.CursorType; -import google.registry.model.contact.Contact; import google.registry.model.domain.Domain; import google.registry.model.host.Host; import google.registry.model.rde.RdeMode; @@ -80,8 +79,8 @@ * type and loads the embedded resource from it, which is then projected to watermark time to * account for things like pending transfer. * - *

Only {@link Contact}s and {@link Host}s that are referenced by an included {@link Domain} will - * be included in the corresponding pending deposit. + *

Only {@link Host}s that are referenced by an included {@link Domain} will be included in the + * corresponding pending deposit. * *

{@link Registrar} entities, both active and inactive, are included in all deposits. They are * not rewound point-in-time. diff --git a/core/src/main/java/google/registry/tools/CommandUtilities.java b/core/src/main/java/google/registry/tools/CommandUtilities.java index ad00c76c151..3f851c1adb4 100644 --- a/core/src/main/java/google/registry/tools/CommandUtilities.java +++ b/core/src/main/java/google/registry/tools/CommandUtilities.java @@ -19,7 +19,6 @@ import com.google.common.base.Ascii; import google.registry.model.EppResource; import google.registry.model.ForeignKeyUtils; -import google.registry.model.contact.Contact; import google.registry.model.domain.Domain; import google.registry.model.host.Host; import google.registry.persistence.VKey; @@ -30,7 +29,6 @@ class CommandUtilities { /** A useful parameter enum for commands that operate on {@link EppResource} objects. */ public enum ResourceType { - CONTACT(Contact.class), HOST(Host.class), DOMAIN(Domain.class); diff --git a/core/src/main/resources/META-INF/persistence.xml b/core/src/main/resources/META-INF/persistence.xml index 8bf8f9ff74a..ac9911bf531 100644 --- a/core/src/main/resources/META-INF/persistence.xml +++ b/core/src/main/resources/META-INF/persistence.xml @@ -51,8 +51,6 @@ google.registry.model.console.ConsoleUpdateHistory google.registry.model.console.PasswordResetRequest google.registry.model.console.User - google.registry.model.contact.ContactHistory - google.registry.model.contact.Contact google.registry.model.domain.Domain google.registry.model.domain.DomainHistory google.registry.model.domain.GracePeriod @@ -94,7 +92,6 @@ google.registry.model.billing.VKeyConverter_BillingCancellation google.registry.model.billing.VKeyConverter_BillingEvent google.registry.model.billing.VKeyConverter_BillingRecurrence - google.registry.model.contact.VKeyConverter_Contact google.registry.model.domain.VKeyConverter_Domain google.registry.model.domain.token.VKeyConverter_AllocationToken google.registry.model.host.VKeyConverter_Host diff --git a/core/src/test/java/google/registry/beam/common/RegistryJpaReadTest.java b/core/src/test/java/google/registry/beam/common/RegistryJpaReadTest.java index d1b822871fa..2d39c1cb77f 100644 --- a/core/src/test/java/google/registry/beam/common/RegistryJpaReadTest.java +++ b/core/src/test/java/google/registry/beam/common/RegistryJpaReadTest.java @@ -185,7 +185,6 @@ private void setupForJoinQuery() { StatusValue.SERVER_UPDATE_PROHIBITED, StatusValue.SERVER_RENEW_PROHIBITED, StatusValue.SERVER_HOLD)) - .setContacts(ImmutableSet.of()) .setSubordinateHosts(ImmutableSet.of("ns1.example.com")) .setPersistedCurrentSponsorRegistrarId(registrar.getRegistrarId()) .setRegistrationExpirationTime(fakeClock.nowUtc().plusYears(1)) diff --git a/core/src/test/java/google/registry/beam/rde/RdePipelineTest.java b/core/src/test/java/google/registry/beam/rde/RdePipelineTest.java index dd9459608da..761a5019444 100644 --- a/core/src/test/java/google/registry/beam/rde/RdePipelineTest.java +++ b/core/src/test/java/google/registry/beam/rde/RdePipelineTest.java @@ -81,7 +81,6 @@ import google.registry.testing.FakeClock; import google.registry.testing.FakeKeyringModule; import java.io.IOException; -import java.util.Optional; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -239,8 +238,6 @@ void beforeEach() throws Exception { newDomain("hello.soy") .asBuilder() .addNameserver(host1.createVKey()) - .setRegistrant(Optional.empty()) - .setContacts(ImmutableSet.of()) .build()); persistDomainHistory(helloDomain); persistHostHistory(persistActiveHost("not-used-subordinate.hello.soy")); @@ -253,8 +250,6 @@ void beforeEach() throws Exception { newDomain("kitty.fun") .asBuilder() .addNameservers(ImmutableSet.of(host1.createVKey(), host2.createVKey())) - .setRegistrant(Optional.empty()) - .setContacts(ImmutableSet.of()) .build()); persistDomainHistory(kittyDomain); // Should not appear because the TLD is not included in a pending deposit. diff --git a/core/src/test/java/google/registry/flows/domain/DomainCreateFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainCreateFlowTest.java index dea882b200f..238eb6e17f0 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainCreateFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainCreateFlowTest.java @@ -50,7 +50,6 @@ import static google.registry.testing.DatabaseHelper.loadAllOf; import static google.registry.testing.DatabaseHelper.loadRegistrar; import static google.registry.testing.DatabaseHelper.newHost; -import static google.registry.testing.DatabaseHelper.persistActiveContact; import static google.registry.testing.DatabaseHelper.persistActiveDomain; import static google.registry.testing.DatabaseHelper.persistActiveHost; import static google.registry.testing.DatabaseHelper.persistReservedList; @@ -1869,7 +1868,6 @@ void testSuccess_customLogicIsCalled_andSavesExtraEntity() throws Exception { @Test void testFailure_minimumDataset_noRegistrantButSomeOtherContactTypes() throws Exception { - persistActiveContact("sh8013"); setEppInput("domain_create_other_contact_types.xml"); persistHosts(); EppException thrown = assertThrows(ContactsProhibitedException.class, this::runFlow); @@ -1878,7 +1876,6 @@ void testFailure_minimumDataset_noRegistrantButSomeOtherContactTypes() throws Ex @Test void testFailure_minimumDataset_registrantNotPermitted() throws Exception { - persistActiveContact("jd1234"); setEppInput("domain_create_has_registrant_contact.xml"); persistHosts(); EppException thrown = assertThrows(RegistrantProhibitedException.class, this::runFlow); diff --git a/core/src/test/java/google/registry/flows/domain/DomainInfoFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainInfoFlowTest.java index fc8103e5b64..9d597700504 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainInfoFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainInfoFlowTest.java @@ -73,7 +73,6 @@ import google.registry.persistence.transaction.JpaTransactionManagerExtension; import google.registry.testing.DatabaseHelper; import google.registry.xml.ValidationMode; -import java.util.Optional; import java.util.regex.Pattern; import javax.annotation.Nullable; import org.joda.money.Money; @@ -214,23 +213,9 @@ void testSuccess_allHosts() throws Exception { doSuccessfulTest("domain_info_response.xml"); } - @Test - void testSuccess_noRegistrant() throws Exception { - persistTestEntities(false); - domain = persistResource(domain.asBuilder().setRegistrant(Optional.empty()).build()); - doSuccessfulTest("domain_info_response_no_registrant.xml", false); - } - @Test void testSuccess_noContacts() throws Exception { persistTestEntities(false); - domain = - persistResource( - domain - .asBuilder() - .setRegistrant(Optional.empty()) - .setContacts(ImmutableSet.of()) - .build()); doSuccessfulTest("domain_info_response_no_contacts.xml", false); } diff --git a/core/src/test/java/google/registry/flows/domain/DomainUpdateFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainUpdateFlowTest.java index a83ed8ef19b..ca0a26e0528 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainUpdateFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainUpdateFlowTest.java @@ -42,7 +42,6 @@ import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType; import static google.registry.testing.DatabaseHelper.getPollMessages; import static google.registry.testing.DatabaseHelper.loadRegistrar; -import static google.registry.testing.DatabaseHelper.persistActiveContact; import static google.registry.testing.DatabaseHelper.persistActiveDomain; import static google.registry.testing.DatabaseHelper.persistActiveHost; import static google.registry.testing.DatabaseHelper.persistActiveSubordinateHost; @@ -272,7 +271,6 @@ void testSuccess_inQuietPeriod() throws Exception { @Test void testFailure_minimumDataset_whenAddingNewContacts() throws Exception { - persistActiveContact("mak21"); // This EPP adds a new technical contact mak21 that wasn't already present. setEppInput("domain_update_empty_registrant.xml"); persistReferencedEntities(); @@ -1375,13 +1373,8 @@ void testFailure_removeNonexistentStatusValue() throws Exception { @Test void testFailure_minimumDataset_addingNewRegistrantFails() throws Exception { - persistActiveContact("sh8013"); persistReferencedEntities(); - persistResource( - DatabaseHelper.newDomain(getUniqueIdFromCommand()) - .asBuilder() - .setRegistrant(Optional.empty()) - .build()); + persistResource(DatabaseHelper.newDomain(getUniqueIdFromCommand())); // This EPP sets the registrant to sh8013, whereas in our test setup it is absent. setEppInput("domain_update_registrant.xml"); RegistrantProhibitedException thrown = diff --git a/core/src/test/java/google/registry/model/contact/ContactTest.java b/core/src/test/java/google/registry/model/contact/ContactTest.java deleted file mode 100644 index c5b44e5bdde..00000000000 --- a/core/src/test/java/google/registry/model/contact/ContactTest.java +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2017 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.model.contact; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects; -import static google.registry.testing.DatabaseHelper.cloneAndSetAutoTimestamps; -import static google.registry.testing.DatabaseHelper.createTld; -import static google.registry.testing.DatabaseHelper.loadByEntity; -import static google.registry.testing.DatabaseHelper.persistResource; -import static google.registry.testing.SqlHelper.assertThrowForeignKeyViolation; -import static google.registry.util.DateTimeUtils.END_OF_TIME; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import google.registry.model.EntityTestCase; -import google.registry.model.ForeignKeyUtils; -import google.registry.model.contact.Disclose.PostalInfoChoice; -import google.registry.model.contact.PostalInfo.Type; -import google.registry.model.eppcommon.AuthInfo.PasswordAuth; -import google.registry.model.eppcommon.PresenceMarker; -import google.registry.model.eppcommon.StatusValue; -import google.registry.model.eppcommon.Trid; -import google.registry.model.transfer.ContactTransferData; -import google.registry.model.transfer.TransferStatus; -import google.registry.util.SerializeUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -/** Unit tests for {@link Contact}. */ -public class ContactTest extends EntityTestCase { - - private Contact originalContact; - private Contact contact; - - ContactTest() { - super(JpaEntityCoverageCheck.ENABLED); - } - - @BeforeEach - void setUp() { - createTld("foobar"); - originalContact = - new Contact.Builder() - .setContactId("contact_id") - .setRepoId("1-FOOBAR") - .setCreationRegistrarId("TheRegistrar") - .setLastEppUpdateTime(fakeClock.nowUtc()) - .setLastEppUpdateRegistrarId("NewRegistrar") - .setLastTransferTime(fakeClock.nowUtc()) - .setPersistedCurrentSponsorRegistrarId("NewRegistrar") - .setLocalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.LOCALIZED) - .setAddress( - new ContactAddress.Builder() - .setStreet(ImmutableList.of("111 8th Ave", "4th Floor")) - .setCity("New York") - .setState("NY") - .setZip("10011") - .setCountryCode("US") - .build()) - .build()) - .setInternationalizedPostalInfo( - new PostalInfo.Builder() - .setType(Type.INTERNATIONALIZED) - .setAddress( - new ContactAddress.Builder() - .setStreet(ImmutableList.of("111 8th Ave", "4th Floor")) - .setCity("New York") - .setState("NY") - .setZip("10011") - .setCountryCode("US") - .build()) - .build()) - .setVoiceNumber(new ContactPhoneNumber.Builder().setPhoneNumber("867-5309").build()) - .setFaxNumber( - new ContactPhoneNumber.Builder() - .setPhoneNumber("867-5309") - .setExtension("1000") - .build()) - .setEmailAddress("jenny@example.com") - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("passw0rd"))) - .setDisclose( - new Disclose.Builder() - .setVoice(new PresenceMarker()) - .setEmail(new PresenceMarker()) - .setFax(new PresenceMarker()) - .setFlag(true) - .setAddrs(ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED))) - .setNames(ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED))) - .setOrgs(ImmutableList.of(PostalInfoChoice.create(Type.INTERNATIONALIZED))) - .build()) - .setStatusValues(ImmutableSet.of(StatusValue.OK)) - .setTransferData( - new ContactTransferData.Builder() - .setGainingRegistrarId("TheRegistrar") - .setLosingRegistrarId("NewRegistrar") - .setPendingTransferExpirationTime(fakeClock.nowUtc()) - .setTransferRequestTime(fakeClock.nowUtc()) - .setTransferStatus(TransferStatus.SERVER_APPROVED) - .setTransferRequestTrid(Trid.create("client-trid", "server-trid")) - .build()) - .build(); - // Set up a new persisted Contact entity. - contact = persistResource(cloneAndSetAutoTimestamps(originalContact)); - } - - @Test - void testContactBaseToContact() { - assertAboutImmutableObjects() - .that(new Contact.Builder().copyFrom(contact).build()) - .isEqualExceptFields(contact, "updateTimestamp", "revisions"); - } - - @Test - void testCloudSqlPersistence_failWhenViolateForeignKeyConstraint() { - assertThrowForeignKeyViolation( - () -> - persistResource( - originalContact - .asBuilder() - .setRepoId("2-FOOBAR") - .setCreationRegistrarId("nonexistent-registrar") - .build())); - } - - @Test - void testCloudSqlPersistence_succeed() { - Contact persisted = loadByEntity(originalContact); - Contact fixed = - originalContact - .asBuilder() - .setCreationTime(persisted.getCreationTime()) - .setTransferData( - originalContact - .getTransferData() - .asBuilder() - .setServerApproveEntities(null, null, null) - .build()) - .build(); - assertAboutImmutableObjects().that(persisted).isEqualExceptFields(fixed, "updateTimestamp"); - } - - @Test - void testPersistence() { - assertThat( - ForeignKeyUtils.loadResource( - Contact.class, contact.getForeignKey(), fakeClock.nowUtc())) - .hasValue(contact); - } - - @Test - void testSerializable() { - Contact persisted = - ForeignKeyUtils.loadResource(Contact.class, contact.getForeignKey(), fakeClock.nowUtc()) - .get(); - assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted); - } - - @Test - void testEmptyStringsBecomeNull() { - assertThat(new Contact.Builder().setContactId(null).build().getContactId()).isNull(); - assertThat(new Contact.Builder().setContactId("").build().getContactId()).isNull(); - assertThat(new Contact.Builder().setContactId(" ").build().getContactId()).isNotNull(); - // Nested ImmutableObjects should also be fixed - assertThat( - new Contact.Builder() - .setInternationalizedPostalInfo( - new PostalInfo.Builder().setType(Type.INTERNATIONALIZED).setName(null).build()) - .build() - .getInternationalizedPostalInfo() - .getName()) - .isNull(); - assertThat( - new Contact.Builder() - .setInternationalizedPostalInfo( - new PostalInfo.Builder().setType(Type.INTERNATIONALIZED).setName("").build()) - .build() - .getInternationalizedPostalInfo() - .getName()) - .isNull(); - assertThat( - new Contact.Builder() - .setInternationalizedPostalInfo( - new PostalInfo.Builder().setType(Type.INTERNATIONALIZED).setName(" ").build()) - .build() - .getInternationalizedPostalInfo() - .getName()) - .isNotNull(); - } - - @Test - void testEmptyTransferDataBecomesNull() { - Contact withNull = new Contact.Builder().setTransferData(null).build(); - Contact withEmpty = withNull.asBuilder().setTransferData(ContactTransferData.EMPTY).build(); - assertThat(withNull).isEqualTo(withEmpty); - assertThat(withEmpty.transferData).isNull(); - } - - @Test - void testSetCreationTime_cantBeCalledTwice() { - IllegalStateException thrown = - assertThrows( - IllegalStateException.class, () -> contact.asBuilder().setCreationTime(END_OF_TIME)); - assertThat(thrown).hasMessageThat().contains("creationTime can only be set once"); - } - - @Test - void testToHydratedString_notCircular() { - // If there are circular references, this will overflow the stack. - contact.toHydratedString(); - } -} diff --git a/core/src/test/java/google/registry/model/domain/DomainTest.java b/core/src/test/java/google/registry/model/domain/DomainTest.java index 01083ab68f8..e6e81d9a1df 100644 --- a/core/src/test/java/google/registry/model/domain/DomainTest.java +++ b/core/src/test/java/google/registry/model/domain/DomainTest.java @@ -236,17 +236,6 @@ void testPersistence() { .hasValue(domain); } - @Test - void testRegistrantNotRequired() { - persistResource(domain.asBuilder().setRegistrant(Optional.empty()).build()); - String foreignKey = domain.getForeignKey(); - assertThat( - ForeignKeyUtils.loadResource(Domain.class, foreignKey, fakeClock.nowUtc()) - .get() - .getRegistrant()) - .isEmpty(); - } - @Test void testEmptyStringsBecomeNull() { assertThat( diff --git a/core/src/test/java/google/registry/model/eppinput/EppInputTest.java b/core/src/test/java/google/registry/model/eppinput/EppInputTest.java index 43da2566a85..ac7e14bfef4 100644 --- a/core/src/test/java/google/registry/model/eppinput/EppInputTest.java +++ b/core/src/test/java/google/registry/model/eppinput/EppInputTest.java @@ -19,7 +19,6 @@ import static google.registry.testing.TestDataHelper.loadBytes; import static org.junit.jupiter.api.Assertions.assertThrows; -import google.registry.model.contact.ContactTest; import google.registry.model.domain.DomainTest; import google.registry.model.eppinput.EppInput.InnerCommand; import google.registry.model.eppinput.EppInput.Login; @@ -29,17 +28,6 @@ /** Unit tests for {@link EppInput}. */ class EppInputTest { - @Test - void testUnmarshalling_contactInfo() throws Exception { - EppInput input = - unmarshal(EppInput.class, loadBytes(ContactTest.class, "contact_info.xml").read()); - assertThat(input.getCommandWrapper().getClTrid()).hasValue("ABC-12345"); - assertThat(input.getCommandType()).isEqualTo("info"); - assertThat(input.getResourceType()).hasValue("contact"); - assertThat(input.getSingleTargetId()).hasValue("sh8013"); - assertThat(input.getTargetIds()).containsExactly("sh8013"); - } - @Test void testUnmarshalling_domainCheck() throws Exception { EppInput input = diff --git a/core/src/test/java/google/registry/model/history/ContactHistoryTest.java b/core/src/test/java/google/registry/model/history/ContactHistoryTest.java deleted file mode 100644 index 5b4641cc93c..00000000000 --- a/core/src/test/java/google/registry/model/history/ContactHistoryTest.java +++ /dev/null @@ -1,145 +0,0 @@ -// 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.model.history; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; -import static google.registry.testing.DatabaseHelper.loadByEntity; -import static google.registry.testing.DatabaseHelper.newContactWithRoid; -import static google.registry.testing.DatabaseHelper.persistResource; -import static java.nio.charset.StandardCharsets.UTF_8; - -import com.google.common.collect.ImmutableList; -import google.registry.model.EntityTestCase; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactAddress; -import google.registry.model.contact.ContactBase; -import google.registry.model.contact.ContactHistory; -import google.registry.model.contact.ContactPhoneNumber; -import google.registry.model.contact.PostalInfo; -import google.registry.model.eppcommon.Trid; -import google.registry.model.reporting.HistoryEntry; -import google.registry.util.SerializeUtils; -import org.junit.jupiter.api.Test; - -/** Tests for {@link ContactHistory}. */ -public class ContactHistoryTest extends EntityTestCase { - - ContactHistoryTest() { - super(JpaEntityCoverageCheck.ENABLED); - } - - @Test - void testPersistence() { - Contact contact = newContactWithRoid("contactId", "contact1"); - persistResource(contact); - Contact contactFromDb = loadByEntity(contact); - ContactHistory contactHistory = createContactHistory(contactFromDb); - persistResource(contactHistory); - tm().transact( - () -> { - ContactHistory fromDatabase = tm().loadByKey(contactHistory.createVKey()); - assertContactHistoriesEqual(fromDatabase, contactHistory); - assertThat(fromDatabase.getRepoId()).isEqualTo(contactHistory.getRepoId()); - }); - } - - @Test - void testSerializable() { - Contact contact = newContactWithRoid("contactId", "contact1"); - persistResource(contact); - Contact contactFromDb = loadByEntity(contact); - ContactHistory contactHistory = createContactHistory(contactFromDb); - persistResource(contactHistory); - ContactHistory fromDatabase = tm().transact(() -> tm().loadByKey(contactHistory.createVKey())); - assertThat(SerializeUtils.serializeDeserialize(fromDatabase)).isEqualTo(fromDatabase); - } - - @Test - void testWipeOutPii_assertsAllPiiFieldsAreNull() { - ContactHistory originalEntity = - createContactHistory( - new Contact.Builder() - .setRepoId("1-FOOBAR") - .setLocalizedPostalInfo( - new PostalInfo.Builder() - .setType(PostalInfo.Type.LOCALIZED) - .setAddress( - new ContactAddress.Builder() - .setStreet(ImmutableList.of("111 8th Ave", "4th Floor")) - .setCity("New York") - .setState("NY") - .setZip("10011") - .setCountryCode("US") - .build()) - .build()) - .setInternationalizedPostalInfo( - new PostalInfo.Builder() - .setType(PostalInfo.Type.INTERNATIONALIZED) - .setAddress( - new ContactAddress.Builder() - .setStreet(ImmutableList.of("111 8th Ave", "4th Floor")) - .setCity("New York") - .setState("NY") - .setZip("10011") - .setCountryCode("US") - .build()) - .build()) - .setVoiceNumber(new ContactPhoneNumber.Builder().setPhoneNumber("867-5309").build()) - .setFaxNumber( - new ContactPhoneNumber.Builder() - .setPhoneNumber("867-5309") - .setExtension("1000") - .build()) - .setEmailAddress("test@example.com") - .build()); - - assertThat(originalEntity.getContactBase().get().getEmailAddress()).isNotNull(); - assertThat(originalEntity.getContactBase().get().getLocalizedPostalInfo()).isNotNull(); - assertThat(originalEntity.getContactBase().get().getInternationalizedPostalInfo()).isNotNull(); - assertThat(originalEntity.getContactBase().get().getVoiceNumber()).isNotNull(); - assertThat(originalEntity.getContactBase().get().getFaxNumber()).isNotNull(); - - ContactHistory wipedEntity = originalEntity.asBuilder().wipeOutPii().build(); - - assertThat(wipedEntity.getContactBase().get().getEmailAddress()).isNull(); - assertThat(wipedEntity.getContactBase().get().getLocalizedPostalInfo()).isNull(); - assertThat(wipedEntity.getContactBase().get().getInternationalizedPostalInfo()).isNull(); - assertThat(wipedEntity.getContactBase().get().getVoiceNumber()).isNull(); - assertThat(wipedEntity.getContactBase().get().getFaxNumber()).isNull(); - } - - private ContactHistory createContactHistory(ContactBase contact) { - return new ContactHistory.Builder() - .setType(HistoryEntry.Type.HOST_CREATE) - .setXmlBytes("".getBytes(UTF_8)) - .setModificationTime(fakeClock.nowUtc()) - .setRegistrarId("TheRegistrar") - .setTrid(Trid.create("ABC-123", "server-trid")) - .setBySuperuser(false) - .setReason("reason") - .setRequestedByRegistrar(true) - .setContact(contact) - .build(); - } - - static void assertContactHistoriesEqual(ContactHistory one, ContactHistory two) { - assertAboutImmutableObjects().that(one).isEqualExceptFields(two, "resource"); - assertAboutImmutableObjects() - .that(one.getContactBase().get()) - .isEqualExceptFields(two.getContactBase().get()); - } -} diff --git a/core/src/test/java/google/registry/rde/DomainToXjcConverterTest.java b/core/src/test/java/google/registry/rde/DomainToXjcConverterTest.java index f27a68f0a7e..c1593c97e24 100644 --- a/core/src/test/java/google/registry/rde/DomainToXjcConverterTest.java +++ b/core/src/test/java/google/registry/rde/DomainToXjcConverterTest.java @@ -14,11 +14,9 @@ package google.registry.rde; -import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.io.BaseEncoding.base16; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.persistEppResource; import static google.registry.testing.DatabaseHelper.persistResource; @@ -34,7 +32,6 @@ import google.registry.model.billing.BillingBase.Reason; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingRecurrence; -import google.registry.model.domain.DesignatedContact; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainAuthInfo; import google.registry.model.domain.DomainHistory; @@ -198,12 +195,6 @@ void testMarshalThin() throws Exception { @Test void testConvertAbsentContacts() throws XmlException { Domain domain = makeDomain(clock); - tm().transact( - () -> - tm().delete( - domain.getAllContacts().stream() - .map(DesignatedContact::getContactKey) - .collect(toImmutableSet()))); XjcRdeDomain bean = DomainToXjcConverter.convertDomain(domain, RdeMode.FULL); assertThat(bean.getRegistrant()).isNull(); assertThat(bean.getContacts()).isEmpty(); diff --git a/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java b/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java index e73fe70740a..c92c8888875 100644 --- a/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java +++ b/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java @@ -27,11 +27,9 @@ import google.registry.model.console.ConsoleUpdateHistoryTest; import google.registry.model.console.PasswordResetRequestTest; import google.registry.model.console.UserTest; -import google.registry.model.contact.ContactTest; import google.registry.model.domain.DomainSqlTest; import google.registry.model.domain.token.AllocationTokenTest; import google.registry.model.domain.token.BulkPricingPackageTest; -import google.registry.model.history.ContactHistoryTest; import google.registry.model.history.DomainHistoryTest; import google.registry.model.history.HostHistoryTest; import google.registry.model.poll.PollMessageTest; @@ -96,8 +94,6 @@ BulkPricingPackageTest.class, ClaimsListDaoTest.class, ConsoleUpdateHistoryTest.class, - ContactHistoryTest.class, - ContactTest.class, CursorTest.class, DnsRefreshRequestTest.class, DomainSqlTest.class, diff --git a/core/src/test/java/google/registry/testing/DatabaseHelper.java b/core/src/test/java/google/registry/testing/DatabaseHelper.java index efeec12560c..a31841dd1f6 100644 --- a/core/src/test/java/google/registry/testing/DatabaseHelper.java +++ b/core/src/test/java/google/registry/testing/DatabaseHelper.java @@ -73,8 +73,6 @@ import google.registry.model.console.GlobalRole; import google.registry.model.console.User; import google.registry.model.console.UserRoles; -import google.registry.model.contact.Contact; -import google.registry.model.contact.ContactAuthInfo; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainAuthInfo; import google.registry.model.domain.DomainBase; @@ -182,17 +180,6 @@ public static Domain newDomain(String domainName, String repoId) { .build(); } - public static Contact newContactWithRoid(String contactId, String repoId) { - return new Contact.Builder() - .setRepoId(repoId) - .setContactId(contactId) - .setCreationRegistrarId("TheRegistrar") - .setPersistedCurrentSponsorRegistrarId("TheRegistrar") - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("2fooBAR"))) - .setCreationTimeForTest(START_OF_TIME) - .build(); - } - public static Tld newTld(String tld, String roidSuffix) { return newTld(tld, roidSuffix, ImmutableSortedMap.of(START_OF_TIME, GENERAL_AVAILABILITY)); } @@ -232,10 +219,6 @@ private static Tld setupTld( .build(); } - public static Contact persistActiveContact(String contactId) { - return persistResource(newContactWithRoid(contactId, generateNewHostRoid())); - } - public static Host persistActiveHost(String hostName) { return persistResource(newHost(hostName)); } @@ -1019,11 +1002,7 @@ public static T getOnlyHistoryEntryOfType( } private static HistoryEntry.Type getHistoryEntryType(EppResource resource) { - if (resource instanceof Contact) { - return resource.getRepoId() != null - ? HistoryEntry.Type.CONTACT_CREATE - : HistoryEntry.Type.CONTACT_UPDATE; - } else if (resource instanceof Host) { + if (resource instanceof Host) { return resource.getRepoId() != null ? HistoryEntry.Type.HOST_CREATE : HistoryEntry.Type.HOST_UPDATE; 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 1775d101e20..4ac5fafc8e2 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 - 2026-01-01 02:43:24 + 2026-02-20 05:51:31 last flyway file @@ -273,7 +273,7 @@

System Information

 

- SchemaCrawler_Diagram generated by SchemaCrawler 16.27.1 generated on 2026-01-01 02:43:24 + SchemaCrawler_Diagram generated by SchemaCrawler 16.27.1 generated on 2026-02-20 05:51:31 allocationtoken_a08ccbef public."AllocationToken" [table] token text not null domain_name text redemption_domain_repo_id text token_type text 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 3f31e3b6252..25cdad423da 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 @@

System Information

generated on - 2026-01-01 02:43:21 + 2026-02-20 05:51:28 last flyway file @@ -273,7 +273,7 @@

System Information

 

- SchemaCrawler_Diagram generated by SchemaCrawler 16.27.1 generated on 2026-01-01 02:43:21 + SchemaCrawler_Diagram generated by SchemaCrawler 16.27.1 generated on 2026-02-20 05:51:28 allocationtoken_a08ccbef public."AllocationToken" [table] token text not null update_timestamp timestamptz allowed_registrar_ids _text allowed_tlds _text creation_time timestamptz not null discount_fraction float8(17, 17) not null discount_premiums bool not null discount_years int4 not null domain_name text redemption_domain_repo_id text token_status_transitions hstore token_type text redemption_domain_history_id int8 renewal_price_behavior text not null registration_behavior text not null allowed_epp_actions _text renewal_price_amount numeric(19, 2) renewal_price_currency text discount_price_amount numeric(19, 2) discount_price_currency text 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 b75a1d74ead..40ad0778489 100644 --- a/db/src/main/resources/sql/schema/db-schema.sql.generated +++ b/db/src/main/resources/sql/schema/db-schema.sql.generated @@ -145,140 +145,6 @@ primary key (revision_id) ); - create table "Contact" ( - repo_id text not null, - update_timestamp timestamp(6) with time zone, - creation_registrar_id text, - creation_time timestamp(6) with time zone, - current_sponsor_registrar_id text, - deletion_time timestamp(6) with time zone, - last_epp_update_registrar_id text, - last_epp_update_time timestamp(6) with time zone, - statuses text[], - auth_info_repo_id text, - auth_info_value text, - contact_id text, - disclose_types_addr text[], - disclose_show_email boolean, - disclose_show_fax boolean, - disclose_mode_flag boolean, - disclose_types_name text[], - disclose_types_org text[], - disclose_show_voice boolean, - email text, - fax_phone_extension text, - fax_phone_number text, - addr_i18n_city text, - addr_i18n_country_code text, - addr_i18n_state text, - addr_i18n_street_line1 text, - addr_i18n_street_line2 text, - addr_i18n_street_line3 text, - addr_i18n_zip text, - addr_i18n_name text, - addr_i18n_org text, - addr_i18n_type text check (addr_i18n_type in ('LOCALIZED','INTERNATIONALIZED')), - last_transfer_time timestamp(6) with time zone, - addr_local_city text, - addr_local_country_code text, - addr_local_state text, - addr_local_street_line1 text, - addr_local_street_line2 text, - addr_local_street_line3 text, - addr_local_zip text, - addr_local_name text, - addr_local_org text, - addr_local_type text check (addr_local_type in ('LOCALIZED','INTERNATIONALIZED')), - search_name text, - transfer_history_entry_id bigint, - transfer_poll_message_id_1 bigint, - transfer_poll_message_id_2 bigint, - transfer_poll_message_id_3 bigint, - transfer_repo_id text, - transfer_client_txn_id text, - transfer_server_txn_id text, - transfer_gaining_registrar_id text, - transfer_losing_registrar_id text, - transfer_pending_expiration_time timestamp(6) with time zone, - transfer_request_time timestamp(6) with time zone, - transfer_status text check (transfer_status in ('CLIENT_APPROVED','CLIENT_CANCELLED','CLIENT_REJECTED','PENDING','SERVER_APPROVED','SERVER_CANCELLED')), - voice_phone_extension text, - voice_phone_number text, - primary key (repo_id) - ); - - create table "ContactHistory" ( - contact_repo_id text not null, - history_revision_id bigint not null, - history_by_superuser boolean not null, - history_registrar_id text, - history_modification_time timestamp(6) with time zone not null, - history_reason text, - history_requested_by_registrar boolean, - history_client_transaction_id text, - history_server_transaction_id text, - history_type text not null check (history_type in ('CONTACT_CREATE','CONTACT_DELETE','CONTACT_DELETE_FAILURE','CONTACT_PENDING_DELETE','CONTACT_TRANSFER_APPROVE','CONTACT_TRANSFER_CANCEL','CONTACT_TRANSFER_REJECT','CONTACT_TRANSFER_REQUEST','CONTACT_UPDATE','DOMAIN_ALLOCATE','DOMAIN_AUTORENEW','DOMAIN_CREATE','DOMAIN_DELETE','DOMAIN_RENEW','DOMAIN_RESTORE','DOMAIN_TRANSFER_APPROVE','DOMAIN_TRANSFER_CANCEL','DOMAIN_TRANSFER_REJECT','DOMAIN_TRANSFER_REQUEST','DOMAIN_UPDATE','HOST_CREATE','HOST_DELETE','HOST_DELETE_FAILURE','HOST_PENDING_DELETE','HOST_UPDATE','RDE_IMPORT','SYNTHETIC')), - history_xml_bytes bytea, - auth_info_repo_id text, - auth_info_value text, - contact_id text, - disclose_types_addr text[], - disclose_show_email boolean, - disclose_show_fax boolean, - disclose_mode_flag boolean, - disclose_types_name text[], - disclose_types_org text[], - disclose_show_voice boolean, - email text, - fax_phone_extension text, - fax_phone_number text, - addr_i18n_city text, - addr_i18n_country_code text, - addr_i18n_state text, - addr_i18n_street_line1 text, - addr_i18n_street_line2 text, - addr_i18n_street_line3 text, - addr_i18n_zip text, - addr_i18n_name text, - addr_i18n_org text, - addr_i18n_type text check (addr_i18n_type in ('LOCALIZED','INTERNATIONALIZED')), - last_transfer_time timestamp(6) with time zone, - addr_local_city text, - addr_local_country_code text, - addr_local_state text, - addr_local_street_line1 text, - addr_local_street_line2 text, - addr_local_street_line3 text, - addr_local_zip text, - addr_local_name text, - addr_local_org text, - addr_local_type text check (addr_local_type in ('LOCALIZED','INTERNATIONALIZED')), - search_name text, - transfer_history_entry_id bigint, - transfer_poll_message_id_1 bigint, - transfer_poll_message_id_2 bigint, - transfer_poll_message_id_3 bigint, - transfer_repo_id text, - transfer_client_txn_id text, - transfer_server_txn_id text, - transfer_gaining_registrar_id text, - transfer_losing_registrar_id text, - transfer_pending_expiration_time timestamp(6) with time zone, - transfer_request_time timestamp(6) with time zone, - transfer_status text check (transfer_status in ('CLIENT_APPROVED','CLIENT_CANCELLED','CLIENT_REJECTED','PENDING','SERVER_APPROVED','SERVER_CANCELLED')), - voice_phone_extension text, - voice_phone_number text, - creation_registrar_id text, - creation_time timestamp(6) with time zone, - current_sponsor_registrar_id text, - deletion_time timestamp(6) with time zone, - last_epp_update_registrar_id text, - last_epp_update_time timestamp(6) with time zone, - statuses text[], - update_timestamp timestamp(6) with time zone, - primary key (contact_repo_id, history_revision_id) - ); - create table "Cursor" ( scope text not null, type text not null check (type in ('BRDA','RDE_REPORT','RDE_STAGING','RDE_UPLOAD','RDE_UPLOAD_SFTP','RECURRING_BILLING','SYNC_REGISTRAR_SHEET','ICANN_UPLOAD_TX','ICANN_UPLOAD_ACTIVITY')), @@ -915,33 +781,6 @@ create index idx_console_update_history_modification_time on "ConsoleUpdateHistory" (modification_time); - create index IDX3y752kr9uh4kh6uig54vemx0l - on "Contact" (creation_time); - - create index IDXtm415d6fe1rr35stm33s5mg18 - on "Contact" (current_sponsor_registrar_id); - - create index IDXn1f711wicdnooa2mqb7g1m55o - on "Contact" (deletion_time); - - create index IDXoqd7n4hbx86hvlgkilq75olas - on "Contact" (contact_id); - - create index IDX1p3esngcwwu6hstyua6itn6ff - on "Contact" (search_name); - - create index IDXo1xdtpij2yryh0skxe9v91sep - on "ContactHistory" (creation_time); - - create index IDXhp33wybmb6tbpr1bq7ttwk8je - on "ContactHistory" (history_registrar_id); - - create index IDX9q53px6r302ftgisqifmc6put - on "ContactHistory" (history_type); - - create index IDXsudwswtwqnfnx2o1hx4s0k0g5 - on "ContactHistory" (history_modification_time); - create index IDXhlqqd5uy98cjyos72d81x9j95 on "DelegationSignerData" (domain_repo_id);