diff --git a/core/src/main/java/google/registry/batch/RemoveAllDomainContactsAction.java b/core/src/main/java/google/registry/batch/RemoveAllDomainContactsAction.java deleted file mode 100644 index cfe4ab85a05..00000000000 --- a/core/src/main/java/google/registry/batch/RemoveAllDomainContactsAction.java +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright 2025 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.batch; - -import static com.google.common.net.MediaType.PLAIN_TEXT_UTF_8; -import static google.registry.flows.FlowUtils.marshalWithLenientRetry; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; -import static google.registry.util.DateTimeUtils.END_OF_TIME; -import static google.registry.util.ResourceUtils.readResourceUtf8; -import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; -import static jakarta.servlet.http.HttpServletResponse.SC_NO_CONTENT; -import static jakarta.servlet.http.HttpServletResponse.SC_OK; -import static java.nio.charset.StandardCharsets.US_ASCII; - -import com.google.common.base.Ascii; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.flogger.FluentLogger; -import com.google.common.util.concurrent.RateLimiter; -import google.registry.config.RegistryConfig.Config; -import google.registry.flows.EppController; -import google.registry.flows.EppRequestSource; -import google.registry.flows.PasswordOnlyTransportCredentials; -import google.registry.flows.StatelessRequestSessionMetadata; -import google.registry.model.contact.Contact; -import google.registry.model.domain.DesignatedContact; -import google.registry.model.domain.Domain; -import google.registry.model.eppcommon.ProtocolDefinition; -import google.registry.model.eppoutput.EppOutput; -import google.registry.persistence.VKey; -import google.registry.request.Action; -import google.registry.request.Response; -import google.registry.request.auth.Auth; -import google.registry.request.lock.LockHandler; -import jakarta.inject.Inject; -import jakarta.inject.Named; -import java.util.List; -import java.util.concurrent.Callable; -import java.util.logging.Level; -import javax.annotation.Nullable; -import org.joda.time.Duration; - -/** - * An action that removes all contacts from all active (non-deleted) domains. - * - *

This implements part 1 of phase 3 of the Minimum Dataset migration, wherein we remove all uses - * of contact objects in preparation for later removing all contact data from the system. - * - *

This runs as a singly threaded, resumable action that loads batches of domains still - * containing contacts, and runs a superuser domain update on each one to remove the contacts, - * leaving behind a record recording that update. - */ -@Action( - service = Action.Service.BACKEND, - path = RemoveAllDomainContactsAction.PATH, - method = Action.Method.POST, - auth = Auth.AUTH_ADMIN) -public class RemoveAllDomainContactsAction implements Runnable { - - public static final String PATH = "/_dr/task/removeAllDomainContacts"; - private static final String LOCK_NAME = "Remove all domain contacts"; - private static final String CONTACT_FMT = "%s"; - - private static final FluentLogger logger = FluentLogger.forEnclosingClass(); - private final EppController eppController; - private final String registryAdminClientId; - private final LockHandler lockHandler; - private final RateLimiter rateLimiter; - private final Response response; - private final String updateDomainXml; - private int successes = 0; - private int failures = 0; - - private static final int BATCH_SIZE = 10000; - - @Inject - RemoveAllDomainContactsAction( - EppController eppController, - @Config("registryAdminClientId") String registryAdminClientId, - LockHandler lockHandler, - @Named("standardRateLimiter") RateLimiter rateLimiter, - Response response) { - this.eppController = eppController; - this.registryAdminClientId = registryAdminClientId; - this.lockHandler = lockHandler; - this.rateLimiter = rateLimiter; - this.response = response; - this.updateDomainXml = - readResourceUtf8(RemoveAllDomainContactsAction.class, "domain_remove_contacts.xml"); - } - - @Override - public void run() { - response.setContentType(PLAIN_TEXT_UTF_8); - Callable runner = - () -> { - try { - runLocked(); - response.setStatus(SC_OK); - } catch (Exception e) { - logger.atSevere().withCause(e).log("Errored out during execution."); - response.setStatus(SC_INTERNAL_SERVER_ERROR); - response.setPayload(String.format("Errored out with cause: %s", e)); - } - return null; - }; - - if (!lockHandler.executeWithLocks(runner, null, Duration.standardHours(1), LOCK_NAME)) { - // Send a 200-series status code to prevent this conflicting action from retrying. - response.setStatus(SC_NO_CONTENT); - response.setPayload("Could not acquire lock; already running?"); - } - } - - private void runLocked() { - logger.atInfo().log("Removing contacts on all active domains."); - - List domainRepoIdsBatch; - do { - domainRepoIdsBatch = - tm().>transact( - () -> - tm().getEntityManager() - .createQuery( - """ - SELECT repoId FROM Domain WHERE deletionTime = :end_of_time AND NOT ( - adminContact IS NULL AND billingContact IS NULL - AND registrantContact IS NULL AND techContact IS NULL) - """) - .setParameter("end_of_time", END_OF_TIME) - .setMaxResults(BATCH_SIZE) - .getResultList()); - - for (String domainRepoId : domainRepoIdsBatch) { - rateLimiter.acquire(); - runDomainUpdateFlow(domainRepoId); - } - } while (!domainRepoIdsBatch.isEmpty()); - String msg = - String.format( - "Finished; %d domains were successfully updated and %d errored out.", - successes, failures); - logger.at(failures == 0 ? Level.INFO : Level.WARNING).log(msg); - response.setPayload(msg); - } - - private void runDomainUpdateFlow(String repoId) { - // Create a new transaction that the flow's execution will be enlisted in that loads the domain - // transactionally. This way we can ensure that nothing else has modified the domain in question - // in the intervening period since the query above found it. If a single domain update fails - // permanently, log it and move on to not block processing all the other domains. - try { - boolean success = tm().transact(() -> runDomainUpdateFlowInner(repoId)); - if (success) { - successes++; - } else { - failures++; - } - } catch (Throwable t) { - logger.atWarning().withCause(t).log( - "Failed updating domain with repoId %s; skipping.", repoId); - } - } - - /** - * Runs the actual domain update flow and returns whether the contact removals were successful. - */ - private boolean runDomainUpdateFlowInner(String repoId) { - Domain domain = tm().loadByKey(VKey.create(Domain.class, repoId)); - if (!domain.getDeletionTime().equals(END_OF_TIME)) { - // Domain has been deleted since the action began running; nothing further to be - // done here. - logger.atInfo().log("Nothing to process for deleted domain '%s'.", domain.getDomainName()); - return false; - } - logger.atInfo().log("Attempting to remove contacts on domain '%s'.", domain.getDomainName()); - - StringBuilder sb = new StringBuilder(); - ImmutableMap, Contact> contacts = - tm().loadByKeys( - domain.getContacts().stream() - .map(DesignatedContact::getContactKey) - .collect(ImmutableSet.toImmutableSet())); - - // Collect all the (non-registrant) contacts referenced by the domain and compile an EPP XML - // string that removes each one. - for (DesignatedContact designatedContact : domain.getContacts()) { - @Nullable Contact contact = contacts.get(designatedContact.getContactKey()); - if (contact == null) { - logger.atWarning().log( - "Domain '%s' referenced contact with repo ID '%s' that couldn't be" + " loaded.", - domain.getDomainName(), designatedContact.getContactKey().getKey()); - continue; - } - sb.append( - String.format( - CONTACT_FMT, - Ascii.toLowerCase(designatedContact.getType().name()), - contact.getContactId())) - .append("\n"); - } - - String compiledXml = - updateDomainXml - .replace("%DOMAIN%", domain.getDomainName()) - .replace("%CONTACTS%", sb.toString()); - EppOutput output = - eppController.handleEppCommand( - new StatelessRequestSessionMetadata( - registryAdminClientId, ProtocolDefinition.getVisibleServiceExtensionUris()), - new PasswordOnlyTransportCredentials(), - EppRequestSource.BACKEND, - false, - true, - compiledXml.getBytes(US_ASCII)); - if (output.isSuccess()) { - logger.atInfo().log( - "Successfully removed contacts from domain '%s'.", domain.getDomainName()); - } else { - logger.atWarning().log( - "Failed removing contacts from domain '%s' with error %s.", - domain.getDomainName(), new String(marshalWithLenientRetry(output), US_ASCII)); - } - return output.isSuccess(); - } -} diff --git a/core/src/main/java/google/registry/flows/FlowModule.java b/core/src/main/java/google/registry/flows/FlowModule.java index 81749ad9090..99e883d3f47 100644 --- a/core/src/main/java/google/registry/flows/FlowModule.java +++ b/core/src/main/java/google/registry/flows/FlowModule.java @@ -22,7 +22,6 @@ import dagger.Module; import dagger.Provides; import google.registry.flows.picker.FlowPicker; -import google.registry.model.contact.ContactHistory; import google.registry.model.domain.DomainHistory; import google.registry.model.domain.metadata.MetadataExtension; import google.registry.model.eppcommon.AuthInfo; @@ -267,23 +266,6 @@ B makeHistoryEntryBuilder( return builder; } - /** - * Provides a partially filled in {@link ContactHistory.Builder} - * - *

This is not marked with {@link FlowScope} so that each retry gets a fresh one. Otherwise, - * the fact that the builder is one-use would cause NPEs. - */ - @Provides - static ContactHistory.Builder provideContactHistoryBuilder( - Trid trid, - @InputXml byte[] inputXmlBytes, - @Superuser boolean isSuperuser, - @RegistrarId String registrarId, - EppInput eppInput) { - return makeHistoryEntryBuilder( - new ContactHistory.Builder(), trid, inputXmlBytes, isSuperuser, registrarId, eppInput); - } - /** * Provides a partially filled in {@link HostHistory.Builder} * diff --git a/core/src/main/java/google/registry/flows/ResourceFlowUtils.java b/core/src/main/java/google/registry/flows/ResourceFlowUtils.java index 9ceb7150cf3..c52458ac82a 100644 --- a/core/src/main/java/google/registry/flows/ResourceFlowUtils.java +++ b/core/src/main/java/google/registry/flows/ResourceFlowUtils.java @@ -16,7 +16,6 @@ import static com.google.common.collect.Sets.intersection; import static google.registry.model.EppResourceUtils.isLinked; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; @@ -37,7 +36,6 @@ import google.registry.model.EppResource.ForeignKeyedEppResource; import google.registry.model.EppResource.ResourceWithTransferData; import google.registry.model.ForeignKeyUtils; -import google.registry.model.contact.Contact; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainBase; import google.registry.model.domain.Period; @@ -124,14 +122,6 @@ public static void verifyAuthInfoPresentForResourceTransfer(Optional a } } - /** Check that the given AuthInfo is either missing or else is valid for the given resource. */ - public static void verifyOptionalAuthInfo(Optional authInfo, Contact contact) - throws EppException { - if (authInfo.isPresent()) { - verifyAuthInfo(authInfo.get(), contact); - } - } - /** Check that the given AuthInfo is either missing or else is valid for the given resource. */ public static void verifyOptionalAuthInfo(Optional authInfo, Domain domain) throws EppException { @@ -142,37 +132,14 @@ public static void verifyOptionalAuthInfo(Optional authInfo, Domain do /** Check that the given {@link AuthInfo} is valid for the given domain. */ public static void verifyAuthInfo(AuthInfo authInfo, Domain domain) throws EppException { - final String authRepoId = authInfo.getPw().getRepoId(); - String authPassword = authInfo.getPw().getValue(); - if (authRepoId == null) { - // If no roid is specified, check the password against the domain's password. - String domainPassword = domain.getAuthInfo().getPw().getValue(); - if (!domainPassword.equals(authPassword)) { - throw new BadAuthInfoForResourceException(); - } - return; - } - // The roid should match one of the contacts. - Optional> foundContact = - domain.getReferencedContacts().stream() - .filter(key -> key.getKey().equals(authRepoId)) - .findFirst(); - if (foundContact.isEmpty()) { + String authRepoId = authInfo.getPw().getRepoId(); + // Previously one could auth against a contact, but we no longer hold any contact info + if (authRepoId != null) { throw new BadAuthInfoForResourceException(); } - // Check the authInfo against the contact. - verifyAuthInfo(authInfo, tm().loadByKey(foundContact.get())); - } - - /** Check that the given {@link AuthInfo} is valid for the given contact. */ - public static void verifyAuthInfo(AuthInfo authInfo, Contact contact) throws EppException { - String authRepoId = authInfo.getPw().getRepoId(); String authPassword = authInfo.getPw().getValue(); - String contactPassword = contact.getAuthInfo().getPw().getValue(); - if (!contactPassword.equals(authPassword) - // It's unnecessary to specify a repoId on a contact auth info, but if it's there validate - // it. The usual case of this is validating a domain's auth using this method. - || (authRepoId != null && !authRepoId.equals(contact.getRepoId()))) { + String domainPassword = domain.getAuthInfo().getPw().getValue(); + if (!domainPassword.equals(authPassword)) { throw new BadAuthInfoForResourceException(); } } diff --git a/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java b/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java index bc47760546f..9aa7723ef26 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainCreateFlow.java @@ -167,7 +167,6 @@ * @error {@link DomainFlowUtils.DomainLabelBlockedByBsaException} * @error {@link DomainFlowUtils.DomainLabelTooLongException} * @error {@link DomainFlowUtils.DomainReservedException} - * @error {@link DomainFlowUtils.DuplicateContactForRoleException} * @error {@link DomainFlowUtils.EmptyDomainNamePartException} * @error {@link DomainFlowUtils.ExceedsMaxRegistrationYearsException} * @error {@link DomainFlowUtils.ExpiredClaimException} @@ -188,7 +187,6 @@ * @error {@link DomainFlowUtils.MaxSigLifeNotSupportedException} * @error {@link DomainFlowUtils.MissingBillingAccountMapException} * @error {@link DomainFlowUtils.MissingClaimsNoticeException} - * @error {@link DomainFlowUtils.MissingContactTypeException} * @error {@link DomainFlowUtils.NameserversNotAllowedForTldException} * @error {@link DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverAllowListException} * @error {@link DomainFlowUtils.PremiumNameBlockedException} @@ -221,7 +219,8 @@ public final class DomainCreateFlow implements MutatingFlow { @Inject DomainPricingLogic pricingLogic; @Inject DomainDeletionTimeCache domainDeletionTimeCache; - @Inject DomainCreateFlow() {} + @Inject + DomainCreateFlow() {} @Override public EppResponse run() throws EppException { @@ -378,12 +377,10 @@ public EppResponse run() throws EppException { .setLaunchNotice(hasClaimsNotice ? launchCreate.get().getNotice() : null) .setSmdId(signedMarkId) .setDsData(secDnsCreate.map(SecDnsCreateExtension::getDsData).orElse(null)) - .setRegistrant(command.getRegistrant()) .setAuthInfo(command.getAuthInfo()) .setDomainName(targetId) .setNameservers(command.getNameservers().stream().collect(toImmutableSet())) .setStatusValues(statuses) - .setContacts(command.getContacts()) .addGracePeriod( GracePeriod.forBillingEvent(GracePeriodStatus.ADD, repoId, createBillingEvent)) .setLordnPhase( diff --git a/core/src/main/java/google/registry/flows/domain/DomainFlowTmchUtils.java b/core/src/main/java/google/registry/flows/domain/DomainFlowTmchUtils.java index 3dcf8994dc7..f0ce2021cac 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainFlowTmchUtils.java +++ b/core/src/main/java/google/registry/flows/domain/DomainFlowTmchUtils.java @@ -157,7 +157,8 @@ public Base64RequiredForEncodedSignedMarksException() { } /** The provided mark does not match the desired domain label. */ - static class NoMarksFoundMatchingDomainException extends RequiredParameterMissingException { + public static class NoMarksFoundMatchingDomainException + extends RequiredParameterMissingException { public NoMarksFoundMatchingDomainException() { super("The provided mark does not match the desired domain label"); } 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 08da55a759a..1db88bfbe13 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/core/src/main/java/google/registry/flows/domain/DomainFlowUtils.java @@ -19,7 +19,6 @@ import static com.google.common.base.Strings.emptyToNull; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableMap.toImmutableMap; -import static com.google.common.collect.ImmutableSetMultimap.toImmutableSetMultimap; import static com.google.common.collect.Sets.difference; import static com.google.common.collect.Sets.intersection; import static com.google.common.collect.Sets.union; @@ -45,10 +44,8 @@ import static google.registry.util.DateTimeUtils.isAtOrAfter; import static google.registry.util.DateTimeUtils.leapSafeAddYears; import static google.registry.util.DomainNameUtils.ACE_PREFIX; -import static java.util.Comparator.comparing; import static java.util.stream.Collectors.joining; -import com.google.common.base.Ascii; import com.google.common.base.CharMatcher; import com.google.common.base.Joiner; import com.google.common.base.Splitter; @@ -57,9 +54,6 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import com.google.common.collect.Multimaps; import com.google.common.collect.Sets; import com.google.common.collect.Streams; import com.google.common.net.InternetDomainName; @@ -81,14 +75,12 @@ import google.registry.model.billing.BillingRecurrence; import google.registry.model.contact.Contact; import google.registry.model.domain.DesignatedContact; -import google.registry.model.domain.DesignatedContact.Type; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainCommand.Create; import google.registry.model.domain.DomainCommand.CreateOrUpdate; import google.registry.model.domain.DomainCommand.InvalidReferencesException; import google.registry.model.domain.DomainCommand.Update; import google.registry.model.domain.DomainHistory; -import google.registry.model.domain.ForeignKeyedDesignatedContact; import google.registry.model.domain.Period; import google.registry.model.domain.Period.Unit; import google.registry.model.domain.fee.BaseFee; @@ -133,10 +125,8 @@ import google.registry.tools.DigestType; import google.registry.util.Idn; import java.math.BigDecimal; -import java.util.Collection; import java.util.Comparator; import java.util.List; -import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; @@ -405,22 +395,11 @@ static Period verifyUnitIsYears(Period period) throws EppException { return period; } - /** Verify that no linked resources have disallowed statuses. */ - static void verifyNotInPendingDelete( - Set contacts, - Optional> registrant, - Set> nameservers) - throws EppException { - ImmutableList.Builder> keysToLoad = new ImmutableList.Builder<>(); - contacts.stream().map(DesignatedContact::getContactKey).forEach(keysToLoad::add); - registrant.ifPresent(keysToLoad::add); - keysToLoad.addAll(nameservers); - verifyNotInPendingDelete(EppResource.loadByCacheIfEnabled(keysToLoad.build()).values()); - } - - private static void verifyNotInPendingDelete(Iterable resources) - throws EppException { - for (EppResource resource : resources) { + /** Verify that no linked nameservers have disallowed statuses. */ + static void verifyNotInPendingDelete(ImmutableSet> nameservers) + throws StatusProhibitsOperationException { + for (EppResource resource : + EppResource.loadByCacheIfEnabled(ImmutableSet.copyOf(nameservers)).values()) { if (resource.getStatusValues().contains(StatusValue.PENDING_DELETE)) { throw new LinkedResourceInPendingDeleteProhibitsOperationException( resource.getForeignKey()); @@ -428,15 +407,6 @@ private static void verifyNotInPendingDelete(Iterable resources) } } - static void validateContactsHaveTypes(Set contacts) - throws ParameterValuePolicyErrorException { - for (DesignatedContact contact : contacts) { - if (contact.getType() == null) { - throw new MissingContactTypeException(); - } - } - } - static void validateNameserversCountForTld(String tld, InternetDomainName domainName, int count) throws EppException { // For TLDs with a nameserver allow list, all domains must have at least 1 nameserver. @@ -451,36 +421,22 @@ static void validateNameserversCountForTld(String tld, InternetDomainName domain } } - static void validateNoDuplicateContacts(Set contacts) + /** Enforces absence of contact data on creation as part of the Minimum Dataset requirements. */ + static void enforceContactAbsencesOnCreate(Create create) throws ParameterValuePolicyErrorException { - ImmutableMultimap> contactsByType = - contacts.stream() - .collect( - toImmutableSetMultimap( - DesignatedContact::getType, DesignatedContact::getContactKey)); - - // If any contact type has multiple contacts: - if (contactsByType.asMap().values().stream().anyMatch(v -> v.size() > 1)) { - // Find the duplicates. - Map>> dupeKeysMap = - Maps.filterEntries(contactsByType.asMap(), e -> e.getValue().size() > 1); - ImmutableList> dupeKeys = - dupeKeysMap.values().stream().flatMap(Collection::stream).collect(toImmutableList()); - // Load the duplicates in one batch. - Map, Contact> dupeContacts = tm().loadByKeys(dupeKeys); - ImmutableMultimap.Builder> typesMap = new ImmutableMultimap.Builder<>(); - dupeKeysMap.forEach(typesMap::putAll); - // Create an error message showing the type and contact IDs of the duplicates. - throw new DuplicateContactForRoleException( - Multimaps.transformValues(typesMap.build(), key -> dupeContacts.get(key).getContactId())); - } + enforceContactAbsences(create.getRegistrant(), create.getContacts()); } - /** - * Enforces the presence/absence of contact data on domain creates depending on the minimum data - * set migration schedule. - */ - static void validateCreateContactData( + /** 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()) { @@ -491,25 +447,6 @@ static void validateCreateContactData( } } - /** - * Enforces the presence/absence of contact data on domain updates depending on the minimum data - * set migration schedule. - */ - static void validateUpdateContactData( - Optional> existingRegistrant, - Optional> newRegistrant, - Set existingContacts, - Set newContacts) - throws ParameterValuePolicyErrorException { - // Throw if the update specifies a new registrant that is different from the existing one. - if (newRegistrant.isPresent() && !newRegistrant.equals(existingRegistrant)) { - throw new RegistrantProhibitedException(); - } - // Throw if the update specifies any new contacts that weren't already present on the domain. - if (!Sets.difference(newContacts, existingContacts).isEmpty()) { - throw new ContactsProhibitedException(); - } - } static void validateNameserversAllowedOnTld(String tld, Set fullyQualifiedHostNames) throws EppException { @@ -1032,12 +969,9 @@ public static void verifyNotInPredelegation(Tld registry, DateTime now) /** Validate the contacts and nameservers specified in a domain create command. */ static void validateCreateCommandContactsAndNameservers( Create command, Tld tld, InternetDomainName domainName) throws EppException { - verifyNotInPendingDelete( - command.getContacts(), command.getRegistrant(), command.getNameservers()); - validateContactsHaveTypes(command.getContacts()); + verifyNotInPendingDelete(command.getNameservers()); String tldStr = tld.getTldStr(); - validateNoDuplicateContacts(command.getContacts()); - validateCreateContactData(command.getRegistrant(), command.getContacts()); + enforceContactAbsencesOnCreate(command); ImmutableSet hostNames = command.getNameserverHostNames(); validateNameserversCountForTld(tldStr, domainName, hostNames.size()); validateNameserversAllowedOnTld(tldStr, hostNames); @@ -1143,17 +1077,6 @@ static FeeTransformResponseExtension createFeeCreateResponse( .build(); } - static ImmutableSet loadForeignKeyedDesignatedContacts( - ImmutableSet contacts) { - ImmutableSet.Builder builder = new ImmutableSet.Builder<>(); - for (DesignatedContact contact : contacts) { - builder.add( - ForeignKeyedDesignatedContact.create( - contact.getType(), tm().loadByKey(contact.getContactKey()).getContactId())); - } - return builder.build(); - } - /** * Returns a set of DomainTransactionRecords which negate the most recent HistoryEntry's records. * @@ -1293,32 +1216,6 @@ public BadPeriodUnitException() { } } - /** Missing type attribute for contact. */ - static class MissingContactTypeException extends ParameterValuePolicyErrorException { - public MissingContactTypeException() { - super("Missing type attribute for contact"); - } - } - - /** More than one contact for a given role is not allowed. */ - static class DuplicateContactForRoleException extends ParameterValuePolicyErrorException { - - public DuplicateContactForRoleException(Multimap dupeContactsByType) { - super( - String.format( - "More than one contact for a given role is not allowed: %s", - dupeContactsByType.asMap().entrySet().stream() - .sorted(comparing(e -> e.getKey().name())) - .map( - e -> - String.format( - "role [%s] has contacts [%s]", - Ascii.toLowerCase(e.getKey().name()), - e.getValue().stream().sorted().collect(joining(", ")))) - .collect(joining(", ")))); - } - } - /** Declared launch extension phase does not match the current registry phase. */ static class LaunchPhaseMismatchException extends ParameterValuePolicyErrorException { public LaunchPhaseMismatchException() { diff --git a/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java b/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java index 8522fe8d514..15a9b1b48c9 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainInfoFlow.java @@ -19,7 +19,6 @@ import static google.registry.flows.ResourceFlowUtils.verifyOptionalAuthInfo; import static google.registry.flows.domain.DomainFlowUtils.addSecDnsExtensionIfPresent; import static google.registry.flows.domain.DomainFlowUtils.handleFeeRequest; -import static google.registry.flows.domain.DomainFlowUtils.loadForeignKeyedDesignatedContacts; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import com.google.common.collect.ImmutableList; @@ -126,15 +125,11 @@ public EppResponse run() throws EppException { .setLastEppUpdateTime(domain.getLastEppUpdateTime()) .setRegistrationExpirationTime(domain.getRegistrationExpirationTime()) .setLastTransferTime(domain.getLastTransferTime()); - domain - .getRegistrant() - .ifPresent(r -> infoBuilder.setRegistrant(tm().loadByKey(r).getContactId())); // If authInfo is non-null, then the caller is authorized to see the full information since we // will have already verified the authInfo is valid. if (registrarId.equals(domain.getCurrentSponsorRegistrarId()) || authInfo.isPresent()) { infoBuilder - .setContacts(loadForeignKeyedDesignatedContacts(domain.getContacts())) .setSubordinateHosts( hostsRequest.requestSubordinate() ? domain.getSubordinateHosts() : null) .setCreationRegistrarId(domain.getCreationRegistrarId()) 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 fc1f494d663..1f565aca585 100644 --- a/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java +++ b/core/src/main/java/google/registry/flows/domain/DomainUpdateFlow.java @@ -29,14 +29,12 @@ 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.validateContactsHaveTypes; import static google.registry.flows.domain.DomainFlowUtils.validateDsData; import static google.registry.flows.domain.DomainFlowUtils.validateFeesAckedIfPresent; import static google.registry.flows.domain.DomainFlowUtils.validateNameserversAllowedOnTld; import static google.registry.flows.domain.DomainFlowUtils.validateNameserversCountForTld; -import static google.registry.flows.domain.DomainFlowUtils.validateNoDuplicateContacts; -import static google.registry.flows.domain.DomainFlowUtils.validateUpdateContactData; import static google.registry.flows.domain.DomainFlowUtils.verifyClientUpdateNotProhibited; import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDelete; import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_UPDATE; @@ -64,8 +62,6 @@ import google.registry.model.ImmutableObject; import google.registry.model.billing.BillingBase.Reason; import google.registry.model.billing.BillingEvent; -import google.registry.model.contact.Contact; -import google.registry.model.domain.DesignatedContact; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainCommand.Update; import google.registry.model.domain.DomainCommand.Update.AddRemove; @@ -88,7 +84,6 @@ import google.registry.model.poll.PollMessage; import google.registry.model.reporting.IcannReportingTypes.ActivityReportField; import google.registry.model.tld.Tld; -import google.registry.persistence.VKey; import jakarta.inject.Inject; import java.util.Objects; import java.util.Optional; @@ -97,8 +92,8 @@ /** * An EPP flow that updates a domain. * - *

Updates can change contacts, nameservers and delegation signer data of a domain. Updates - * cannot change the domain's name. + *

Updates can change nameservers and delegation signer data of a domain. Updates cannot change + * the domain's name. * *

Some status values (those of the form "serverSomethingProhibited") can only be applied by the * superuser. As such, adding or removing these statuses incurs a billing event. There will be only @@ -113,7 +108,6 @@ * @error {@link google.registry.flows.exceptions.OnlyToolCanPassMetadataException} * @error {@link google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException} * @error {@link google.registry.flows.exceptions.ResourceStatusProhibitsOperationException} - * @error {@link DomainFlowUtils.DuplicateContactForRoleException} * @error {@link DomainFlowUtils.EmptySecDnsUpdateException} * @error {@link DomainFlowUtils.FeesMismatchException} * @error {@link DomainFlowUtils.FeesRequiredForNonFreeOperationException} @@ -121,7 +115,6 @@ * @error {@link DomainFlowUtils.LinkedResourcesDoNotExistException} * @error {@link DomainFlowUtils.LinkedResourceInPendingDeleteProhibitsOperationException} * @error {@link DomainFlowUtils.MaxSigLifeChangeNotSupportedException} - * @error {@link DomainFlowUtils.MissingContactTypeException} * @error {@link DomainFlowUtils.NameserversNotAllowedForTldException} * @error {@link NameserversNotSpecifiedForTldWithNameserverAllowListException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException} @@ -158,7 +151,9 @@ public final class DomainUpdateFlow implements MutatingFlow { @Inject EppResponse.Builder responseBuilder; @Inject DomainUpdateFlowCustomLogic flowCustomLogic; @Inject DomainPricingLogic pricingLogic; - @Inject DomainUpdateFlow() {} + + @Inject + DomainUpdateFlow() {} @Override public EppResponse run() throws EppException { @@ -179,7 +174,7 @@ public EppResponse run() throws EppException { Domain newDomain = performUpdate(command, existingDomain, now); DomainHistory domainHistory = historyBuilder.setType(DOMAIN_UPDATE).setDomain(newDomain).build(); - validateNewState(existingDomain, newDomain); + validateNewState(newDomain); if (requiresDnsUpdate(existingDomain, newDomain)) { requestDomainDnsRefresh(targetId); } @@ -235,12 +230,7 @@ private void verifyUpdateAllowed(Update command, Domain existingDomain, DateTime eppInput.getSingleExtension(FeeUpdateCommandExtension.class); FeesAndCredits feesAndCredits = pricingLogic.getUpdatePrice(tld, targetId, now); validateFeesAckedIfPresent(feeUpdate, feesAndCredits, false); - verifyNotInPendingDelete( - add.getContacts(), - command.getInnerChange().getRegistrant(), - add.getNameservers()); - validateContactsHaveTypes(add.getContacts()); - validateContactsHaveTypes(remove.getContacts()); + verifyNotInPendingDelete(add.getNameservers()); validateNameserversAllowedOnTld(tldStr, add.getNameserverHostNames()); } @@ -250,7 +240,6 @@ private Domain performUpdate(Update command, Domain domain, DateTime now) throws Optional secDnsUpdate = eppInput.getSingleExtension(SecDnsUpdateExtension.class); verifyAddsAndRemoves(domain.getNameservers(), add.getNameservers(), remove.getNameservers()); - verifyAddsAndRemoves(domain.getContacts(), add.getContacts(), remove.getContacts()); verifyAddsAndRemoves(domain.getStatusValues(), add.getStatusValues(), remove.getStatusValues()); if (secDnsUpdate.isPresent()) { SecDnsUpdateExtension ext = secDnsUpdate.get(); @@ -260,12 +249,7 @@ private Domain performUpdate(Update command, Domain domain, DateTime now) throws ext.getRemove().map(Remove::getDsData).orElse(ImmutableSet.of())); } Change change = command.getInnerChange(); - - // We have to verify no duplicate contacts _before_ constructing the domain because it is - // illegal to construct a domain with duplicate contacts. - Sets.SetView newContacts = - union(Sets.difference(domain.getContacts(), remove.getContacts()), add.getContacts()); - validateNoDuplicateContacts(newContacts); + enforceContactAbsencesOnUpdate(command); Domain.Builder domainBuilder = domain @@ -285,9 +269,6 @@ private Domain performUpdate(Update command, Domain domain, DateTime now) throws .setLastEppUpdateRegistrarId(registrarId) .addStatusValues(add.getStatusValues()) .removeStatusValues(remove.getStatusValues()) - .removeContacts(remove.getContacts()) - .addContacts(add.getContacts()) - .setRegistrant(determineUpdatedRegistrant(change, domain)) .setAuthInfo(Optional.ofNullable(change.getAuthInfo()).orElse(domain.getAuthInfo())); if (!add.getNameservers().isEmpty()) { @@ -309,15 +290,6 @@ private Domain performUpdate(Update command, Domain domain, DateTime now) throws return domainBuilder.build(); } - private Optional> determineUpdatedRegistrant(Change change, Domain domain) { - // During or after the minimum dataset transition, allow registrant to be removed. - if (change.getRegistrantContactId().isPresent() - && change.getRegistrantContactId().get().isEmpty()) { - return Optional.empty(); - } - return change.getRegistrant().or(domain::getRegistrant); - } - /** * Checks whether the new state of the domain is valid. * @@ -325,13 +297,7 @@ private Optional> determineUpdatedRegistrant(Change change, Domain * compliant with the additions or amendments, otherwise existing data can become invalid and * cause Domain update failure. */ - private static void validateNewState(Domain existingDomain, Domain newDomain) - throws EppException { - validateUpdateContactData( - existingDomain.getRegistrant(), - newDomain.getRegistrant(), - existingDomain.getContacts(), - newDomain.getContacts()); + private static void validateNewState(Domain newDomain) throws EppException { validateDsData(newDomain.getDsData()); validateNameserversCountForTld( newDomain.getTld(), @@ -345,8 +311,8 @@ private Optional createBillingEventForStatusUpdates( Optional metadataExtension = eppInput.getSingleExtension(MetadataExtension.class); if (metadataExtension.isPresent() && metadataExtension.get().getRequestedByRegistrar()) { - for (StatusValue statusValue - : symmetricDifference(existingDomain.getStatusValues(), newDomain.getStatusValues())) { + for (StatusValue statusValue : + symmetricDifference(existingDomain.getStatusValues(), newDomain.getStatusValues())) { if (statusValue.isChargedStatus()) { // Only charge once. return Optional.of( diff --git a/core/src/main/java/google/registry/module/RequestComponent.java b/core/src/main/java/google/registry/module/RequestComponent.java index 551b05d8a41..f136150956e 100644 --- a/core/src/main/java/google/registry/module/RequestComponent.java +++ b/core/src/main/java/google/registry/module/RequestComponent.java @@ -24,7 +24,6 @@ import google.registry.batch.DeleteProberDataAction; import google.registry.batch.ExpandBillingRecurrencesAction; import google.registry.batch.RelockDomainAction; -import google.registry.batch.RemoveAllDomainContactsAction; import google.registry.batch.ResaveAllEppResourcesPipelineAction; import google.registry.batch.ResaveEntityAction; import google.registry.batch.SendExpiringCertificateNotificationEmailAction; @@ -276,8 +275,6 @@ interface RequestComponent { ReadinessProbeActionFrontend readinessProbeActionFrontend(); - RemoveAllDomainContactsAction removeAllDomainContactsAction(); - RdapAutnumAction rdapAutnumAction(); RdapDomainAction rdapDomainAction(); diff --git a/core/src/test/java/google/registry/batch/RemoveAllDomainContactsActionTest.java b/core/src/test/java/google/registry/batch/RemoveAllDomainContactsActionTest.java deleted file mode 100644 index 2d358c9e779..00000000000 --- a/core/src/test/java/google/registry/batch/RemoveAllDomainContactsActionTest.java +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2025 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.batch; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.model.common.FeatureFlag.FeatureName.MINIMUM_DATASET_CONTACTS_PROHIBITED; -import static google.registry.model.common.FeatureFlag.FeatureStatus.ACTIVE; -import static google.registry.testing.DatabaseHelper.createTld; -import static google.registry.testing.DatabaseHelper.loadByEntity; -import static google.registry.testing.DatabaseHelper.newDomain; -import static google.registry.testing.DatabaseHelper.persistActiveContact; -import static google.registry.testing.DatabaseHelper.persistResource; -import static google.registry.util.DateTimeUtils.START_OF_TIME; -import static org.mockito.Mockito.mock; - -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedMap; -import com.google.common.util.concurrent.RateLimiter; -import google.registry.flows.DaggerEppTestComponent; -import google.registry.flows.EppController; -import google.registry.flows.EppTestComponent.FakesAndMocksModule; -import google.registry.model.common.FeatureFlag; -import google.registry.model.contact.Contact; -import google.registry.model.domain.Domain; -import google.registry.persistence.transaction.JpaTestExtensions; -import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension; -import google.registry.testing.FakeClock; -import google.registry.testing.FakeLockHandler; -import google.registry.testing.FakeResponse; -import java.util.Optional; -import org.joda.time.DateTime; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -/** Unit tests for {@link RemoveAllDomainContactsAction}. */ -class RemoveAllDomainContactsActionTest { - - @RegisterExtension - final JpaIntegrationTestExtension jpa = - new JpaTestExtensions.Builder().buildIntegrationTestExtension(); - - private final FakeResponse response = new FakeResponse(); - private final RateLimiter rateLimiter = mock(RateLimiter.class); - private RemoveAllDomainContactsAction action; - - @BeforeEach - void beforeEach() { - createTld("tld"); - persistResource( - new FeatureFlag.Builder() - .setFeatureName(MINIMUM_DATASET_CONTACTS_PROHIBITED) - .setStatusMap(ImmutableSortedMap.of(START_OF_TIME, ACTIVE)) - .build()); - EppController eppController = - DaggerEppTestComponent.builder() - .fakesAndMocksModule(FakesAndMocksModule.create(new FakeClock())) - .build() - .startRequest() - .eppController(); - action = - new RemoveAllDomainContactsAction( - eppController, "NewRegistrar", new FakeLockHandler(true), rateLimiter, response); - } - - @Test - void test_removesAllContactsFromMultipleDomains_andDoesntModifyDomainThatHasNoContacts() { - Contact c1 = persistActiveContact("contact12345"); - Domain d1 = persistResource(newDomain("foo.tld", c1)); - assertThat(d1.getAllContacts()).hasSize(3); - Contact c2 = persistActiveContact("contact23456"); - Domain d2 = persistResource(newDomain("bar.tld", c2)); - assertThat(d2.getAllContacts()).hasSize(3); - Domain d3 = - persistResource( - newDomain("baz.tld") - .asBuilder() - .setRegistrant(Optional.empty()) - .setContacts(ImmutableSet.of()) - .build()); - assertThat(d3.getAllContacts()).isEmpty(); - DateTime lastUpdate = d3.getUpdateTimestamp().getTimestamp(); - - action.run(); - assertThat(loadByEntity(d1).getAllContacts()).isEmpty(); - assertThat(loadByEntity(d2).getAllContacts()).isEmpty(); - assertThat(loadByEntity(d3).getUpdateTimestamp().getTimestamp()).isEqualTo(lastUpdate); - } - - @Test - void test_removesContacts_onDomainsThatOnlyPartiallyHaveContacts() { - Contact c1 = persistActiveContact("contact12345"); - Domain d1 = - persistResource( - newDomain("foo.tld", c1).asBuilder().setContacts(ImmutableSet.of()).build()); - assertThat(d1.getAllContacts()).hasSize(1); - Contact c2 = persistActiveContact("contact23456"); - Domain d2 = - persistResource( - newDomain("bar.tld", c2).asBuilder().setRegistrant(Optional.empty()).build()); - assertThat(d2.getAllContacts()).hasSize(2); - - action.run(); - assertThat(loadByEntity(d1).getAllContacts()).isEmpty(); - assertThat(loadByEntity(d2).getAllContacts()).isEmpty(); - } -} 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 77ba1c404e9..71f93f598b1 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainCreateFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainCreateFlowTest.java @@ -119,7 +119,6 @@ import google.registry.flows.domain.DomainFlowUtils.MaxSigLifeNotSupportedException; import google.registry.flows.domain.DomainFlowUtils.MissingBillingAccountMapException; import google.registry.flows.domain.DomainFlowUtils.MissingClaimsNoticeException; -import google.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedForTldException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedForTldWithNameserverAllowListException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; @@ -1874,15 +1873,6 @@ void testSuccess_customLogicIsCalled_andSavesExtraEntity() throws Exception { .build()); } - @Test - void testFailure_missingContactType() { - // We need to test for missing type, but not for invalid - the schema enforces that for us. - setEppInput("domain_create_missing_contact_type.xml"); - persistContactsAndHosts(); - EppException thrown = assertThrows(MissingContactTypeException.class, this::runFlow); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - @Test void testFailure_minimumDataset_noRegistrantButSomeOtherContactTypes() throws Exception { setEppInput("domain_create_other_contact_types.xml"); 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 21d2a8fb2bd..aafa9387236 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferApproveFlowTest.java @@ -64,7 +64,6 @@ import google.registry.model.billing.BillingCancellation; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingRecurrence; -import google.registry.model.contact.ContactAuthInfo; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainAuthInfo; import google.registry.model.domain.DomainHistory; @@ -153,12 +152,6 @@ private void assertTransferApproved(Domain domain, DomainTransferData oldTransfe .build()); } - private void setEppLoader(String commandFilename) { - setEppInput(commandFilename); - // Replace the ROID in the xml file with the one generated in our test. - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); - } - /** * Runs a successful test, with the expectedCancellationBillingEvents parameter containing a list * of billing event builders that will be filled out with the correct HistoryEntry parent as it is @@ -184,7 +177,7 @@ private void runSuccessfulFlowWithAssertions( String expectedXmlFilename, DateTime expectedExpirationTime) throws Exception { - setEppLoader(commandFilename); + setEppInput(commandFilename); Tld registry = Tld.get(tld); domain = reloadResourceByForeignKey(); // Make sure the implicit billing event is there; it will be deleted by the flow. @@ -361,7 +354,7 @@ private void doSuccessfulTest(String tld, String commandFilename, String expecte } private void doFailingTest(String commandFilename) throws Exception { - setEppLoader(commandFilename); + setEppInput(commandFilename); // Setup done; run the test. assertMutatingFlow(true); runFlow(); @@ -376,7 +369,7 @@ void testNotLoggedIn() { @Test void testDryRun() throws Exception { - setEppLoader("domain_transfer_approve.xml"); + setEppInput("domain_transfer_approve.xml"); dryRunFlowAssertResponse(loadFile("domain_transfer_approve_response.xml")); } @@ -492,14 +485,6 @@ void testSuccess_domainAuthInfo() throws Exception { "domain_transfer_approve_response.xml"); } - @Test - void testSuccess_contactAuthInfo() throws Exception { - doSuccessfulTest( - "tld", - "domain_transfer_approve_contact_authinfo.xml", - "domain_transfer_approve_response.xml"); - } - @Test void testSuccess_autorenewBeforeTransfer() throws Exception { domain = reloadResourceByForeignKey(); @@ -619,14 +604,8 @@ void testSuccess_specifiedPriceRenewalBehavior_carriesOver() throws Exception { } @Test - void testFailure_badContactPassword() { - // Change the contact's password so it does not match the password in the file. - contact = - persistResource( - contact - .asBuilder() - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("badpassword"))) - .build()); + void testFailure_contactPassword() { + // Contact passwords cannot be provided because we don't store contacts EppException thrown = assertThrows( BadAuthInfoForResourceException.class, diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java index 81457833821..c7b62116bb8 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferCancelFlowTest.java @@ -43,7 +43,6 @@ import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.exceptions.NotPendingTransferException; import google.registry.flows.exceptions.NotTransferInitiatorException; -import google.registry.model.contact.ContactAuthInfo; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainAuthInfo; import google.registry.model.domain.DomainHistory; @@ -75,8 +74,6 @@ void beforeEach() { private void doSuccessfulTest(String commandFilename) throws Exception { setEppInput(commandFilename); - // Replace the ROID in the xml file with the one generated in our test. - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); // Make sure the implicit billing event is there; it will be deleted by the flow. // We also expect to see autorenew events for the gaining and losing registrars. assertBillingEvents( @@ -187,8 +184,6 @@ private void doSuccessfulTest(String commandFilename) throws Exception { private void doFailingTest(String commandFilename) throws Exception { setEppInput(commandFilename); - // Replace the ROID in the xml file with the one generated in our test. - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); // Setup done; run the test. assertMutatingFlow(true); runFlow(); @@ -204,7 +199,6 @@ void testNotLoggedIn() { @Test void testDryRun() throws Exception { setEppInput("domain_transfer_cancel.xml"); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); dryRunFlowAssertResponse(loadFile("domain_transfer_cancel_response.xml")); } @@ -219,19 +213,8 @@ void testSuccess_domainAuthInfo() throws Exception { } @Test - void testSuccess_contactAuthInfo() throws Exception { - doSuccessfulTest("domain_transfer_cancel_contact_authinfo.xml"); - } - - @Test - void testFailure_badContactPassword() { - // Change the contact's password so it does not match the password in the file. - contact = - persistResource( - contact - .asBuilder() - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("badpassword"))) - .build()); + void testFailure_contactPassword() { + // Contact passwords cannot be provided because we don't store contacts EppException thrown = assertThrows( BadAuthInfoForResourceException.class, diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferFlowTestCase.java b/core/src/test/java/google/registry/flows/domain/DomainTransferFlowTestCase.java index d337fb78d05..49c1dfd8b52 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferFlowTestCase.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferFlowTestCase.java @@ -20,7 +20,6 @@ import static google.registry.testing.DatabaseHelper.createBillingEventForTransfer; import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType; -import static google.registry.testing.DatabaseHelper.persistActiveContact; import static google.registry.testing.DatabaseHelper.persistDomainWithDependentResources; import static google.registry.testing.DatabaseHelper.persistDomainWithPendingTransfer; import static google.registry.testing.DatabaseHelper.persistResource; @@ -36,7 +35,6 @@ import google.registry.model.billing.BillingBase.Reason; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingRecurrence; -import google.registry.model.contact.Contact; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainHistory; import google.registry.model.eppcommon.StatusValue; @@ -72,7 +70,6 @@ abstract class DomainTransferFlowTestCase static final DateTime EXTENDED_REGISTRATION_EXPIRATION_TIME = REGISTRATION_EXPIRATION_TIME.plusYears(EXTENDED_REGISTRATION_YEARS); - protected Contact contact; protected Domain domain; Host subordinateHost; private DomainHistory historyEntryDomainCreate; @@ -104,12 +101,11 @@ static Domain persistWithPendingTransfer(Domain domain) { /** Adds a domain with no pending transfer on it. */ void setupDomain(String label, String tld) { createTld(tld); - contact = persistActiveContact("jd1234"); domain = persistDomainWithDependentResources( label, tld, - contact, + null, clock.nowUtc(), DateTime.parse("1999-04-03T22:00:00.0Z"), REGISTRATION_EXPIRATION_TIME); diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferQueryFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferQueryFlowTest.java index 7297dcdb347..523120f4ade 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferQueryFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferQueryFlowTest.java @@ -29,7 +29,6 @@ import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException; import google.registry.flows.exceptions.NoTransferHistoryToQueryException; import google.registry.flows.exceptions.NotAuthorizedToViewTransferException; -import google.registry.model.contact.ContactAuthInfo; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainAuthInfo; import google.registry.model.eppcommon.AuthInfo.PasswordAuth; @@ -52,8 +51,6 @@ void beforeEach() { private void doSuccessfulTest( String commandFilename, String expectedXmlFilename, int numPollMessages) throws Exception { setEppInput(commandFilename); - // Replace the ROID in the xml file with the one generated in our test. - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); // Setup done; run the test. assertMutatingFlow(false); runFlowAssertResponse(loadFile(expectedXmlFilename)); @@ -73,8 +70,6 @@ private void doSuccessfulTest( private void doFailingTest(String commandFilename) throws Exception { setEppInput(commandFilename); - // Replace the ROID in the xml file with the one generated in our test. - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); // Setup done; run the test. assertMutatingFlow(false); runFlow(); @@ -105,13 +100,6 @@ void testSuccess_domainAuthInfo() throws Exception { "domain_transfer_query_domain_authinfo.xml", "domain_transfer_query_response.xml", 1); } - @Test - void testSuccess_contactAuthInfo() throws Exception { - setRegistrarIdForFlow("ClientZ"); - doSuccessfulTest( - "domain_transfer_query_contact_authinfo.xml", "domain_transfer_query_response.xml", 1); - } - @Test void testSuccess_clientApproved() throws Exception { changeTransferStatus(TransferStatus.CLIENT_APPROVED); @@ -170,14 +158,7 @@ void testFailure_pendingDeleteDomain() throws Exception { } @Test - void testFailure_badContactPassword() { - // Change the contact's password so it does not match the password in the file. - contact = - persistResource( - contact - .asBuilder() - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("badpassword"))) - .build()); + void testFailure_contactPasswordNotAllowed() { EppException thrown = assertThrows( BadAuthInfoForResourceException.class, diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferRejectFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferRejectFlowTest.java index 8179c2811a6..e5ab76f612c 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferRejectFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferRejectFlowTest.java @@ -43,7 +43,6 @@ import google.registry.flows.ResourceFlowUtils.ResourceNotOwnedException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.exceptions.NotPendingTransferException; -import google.registry.model.contact.ContactAuthInfo; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainAuthInfo; import google.registry.model.domain.DomainHistory; @@ -78,7 +77,6 @@ void beforeEach() { private void doSuccessfulTest(String commandFilename, String expectedXmlFilename) throws Exception { setEppInput(commandFilename); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); // Make sure the implicit billing event is there; it will be deleted by the flow. // We also expect to see autorenew events for the gaining and losing registrars. assertBillingEvents( @@ -149,8 +147,6 @@ private void doSuccessfulTest(String commandFilename, String expectedXmlFilename private void doFailingTest(String commandFilename) throws Exception { setEppInput(commandFilename); - // Replace the ROID in the xml file with the one generated in our test. - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); // Setup done; run the test. assertMutatingFlow(true); runFlow(); @@ -171,7 +167,6 @@ void testSuccess() throws Exception { @Test void testDryRun() throws Exception { setEppInput("domain_transfer_reject.xml"); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); dryRunFlowAssertResponse(loadFile("domain_transfer_reject_response.xml")); } @@ -181,12 +176,6 @@ void testSuccess_domainAuthInfo() throws Exception { "domain_transfer_reject_domain_authinfo.xml", "domain_transfer_reject_response.xml"); } - @Test - void testSuccess_contactAuthInfo() throws Exception { - doSuccessfulTest( - "domain_transfer_reject_contact_authinfo.xml", "domain_transfer_reject_response.xml"); - } - @Test void testFailure_notAuthorizedForTld() { persistResource( @@ -209,14 +198,8 @@ void testSuccess_superuserNotAuthorizedForTld() throws Exception { } @Test - void testFailure_badContactPassword() { - // Change the contact's password so it does not match the password in the file. - contact = - persistResource( - contact - .asBuilder() - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("badpassword"))) - .build()); + void testFailure_contactPassword() { + // Contact passwords cannot be provided because we don't store contacts EppException thrown = assertThrows( BadAuthInfoForResourceException.class, diff --git a/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java index 9aaf221d65d..70ad4517e37 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainTransferRequestFlowTest.java @@ -40,7 +40,6 @@ import static google.registry.testing.DatabaseHelper.loadByKey; import static google.registry.testing.DatabaseHelper.loadByKeys; import static google.registry.testing.DatabaseHelper.loadRegistrar; -import static google.registry.testing.DatabaseHelper.persistActiveContact; import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.DomainSubject.assertAboutDomains; import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions; @@ -96,7 +95,6 @@ import google.registry.model.billing.BillingCancellation; import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingRecurrence; -import google.registry.model.contact.ContactAuthInfo; import google.registry.model.domain.Domain; import google.registry.model.domain.DomainAuthInfo; import google.registry.model.domain.DomainHistory; @@ -470,8 +468,6 @@ private void doSuccessfulTest( throws Exception { setEppInput(commandFilename, substitutions); ImmutableSet originalGracePeriods = domain.getGracePeriods(); - // Replace the ROID in the xml file with the one generated in our test. - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); // For all of the other transfer flow tests, 'now' corresponds to day 3 of the transfer, but // for the request test we want that same 'now' to be the initial request time, so we shift // the transfer timeline 3 days later by adjusting the implicit transfer time here. @@ -571,8 +567,6 @@ private void doSuccessfulSuperuserExtensionTest( eppRequestSource = EppRequestSource.TOOL; setEppInput(commandFilename, substitutions); ImmutableSet originalGracePeriods = domain.getGracePeriods(); - // Replace the ROID in the xml file with the one generated in our test. - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); // For all of the other transfer flow tests, 'now' corresponds to day 3 of the transfer, but // for the request test we want that same 'now' to be the initial request time, so we shift // the transfer timeline 3 days later by adjusting the implicit transfer time here. @@ -626,8 +620,6 @@ private void runTest( String commandFilename, UserPrivileges userPrivileges, Map substitutions) throws Exception { setEppInput(commandFilename, substitutions); - // Replace the ROID in the xml file with the one generated in our test. - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); // Setup done; run the test. assertMutatingFlow(true); runFlow(CommitMode.LIVE, userPrivileges); @@ -657,7 +649,6 @@ void testNotLoggedIn() { void testDryRun() throws Exception { setupDomain("example", "tld"); setEppInput("domain_transfer_request.xml"); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); dryRunFlowAssertResponse(loadFile("domain_transfer_request_response.xml")); } @@ -1184,7 +1175,6 @@ void testSuccess_nonPremiumRenewalPrice_isReflectedInTransferCostAndCarriesOver( // This ensures that the transfer has non-premium cost, as otherwise, the fee extension would be // required to ack the premium price. setEppInput("domain_transfer_request.xml"); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); runFlowAssertResponse(loadFile("domain_transfer_request_response.xml")); domain = loadByEntity(domain); @@ -1238,7 +1228,6 @@ void testSuccess_specifiedRenewalPrice_isReflectedInTransferCostAndCarriesOver() DateTime now = clock.nowUtc(); setEppInput("domain_transfer_request.xml"); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); runFlowAssertResponse(loadFile("domain_transfer_request_response.xml")); domain = loadByEntity(domain); @@ -1300,7 +1289,6 @@ void testSuccess_specifiedRenewalPrice_notCarriedOverForBulkPricingName() throws DateTime now = clock.nowUtc(); setEppInput("domain_transfer_request.xml"); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); runFlowAssertResponse(loadFile("domain_transfer_request_response.xml")); domain = loadByEntity(domain); @@ -1361,7 +1349,6 @@ void testSuccess_defaultRenewalPrice_carriedOverForBulkPricingName() throws Exce DateTime now = clock.nowUtc(); setEppInput("domain_transfer_request.xml"); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); runFlowAssertResponse(loadFile("domain_transfer_request_response.xml")); domain = loadByEntity(domain); @@ -1518,36 +1505,6 @@ void testFailure_noAuthInfo() { assertAboutEppExceptions().that(thrown).marshalsToXml(); } - @Test - void testFailure_badContactPassword() { - setupDomain("example", "tld"); - // Change the contact's password so it does not match the password in the file. - contact = - persistResource( - contact - .asBuilder() - .setAuthInfo(ContactAuthInfo.create(PasswordAuth.create("badpassword"))) - .build()); - EppException thrown = - assertThrows( - BadAuthInfoForResourceException.class, - () -> doFailingTest("domain_transfer_request.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - - @Test - void testFailure_badContactRepoId() { - setupDomain("example", "tld"); - // Set the contact to a different ROID, but don't persist it; this is just so the substitution - // code above will write the wrong ROID into the file. - contact = contact.asBuilder().setRepoId("DEADBEEF_TLD-ROID").build(); - EppException thrown = - assertThrows( - BadAuthInfoForResourceException.class, - () -> doFailingTest("domain_transfer_request.xml")); - assertAboutEppExceptions().that(thrown).marshalsToXml(); - } - @Test void testSuccess_clientApproved() throws Exception { setupDomain("example", "tld"); @@ -1651,7 +1608,6 @@ void testFailure_invalidDomain() throws Exception { setEppInput( "domain_transfer_request_wildcard.xml", ImmutableMap.of("YEARS", "1", "DOMAIN", "--invalid", "EXDATE", "2002-09-08T22:00:00.0Z")); - eppLoader.replaceAll("JD1234-REP", contact.getRepoId()); assertMutatingFlow(true); ResourceDoesNotExistException thrown = assertThrows( @@ -1663,7 +1619,6 @@ void testFailure_invalidDomain() throws Exception { @Test void testFailure_nonexistentDomain() { createTld("tld"); - contact = persistActiveContact("jd1234"); ResourceDoesNotExistException thrown = assertThrows( ResourceDoesNotExistException.class, @@ -1671,6 +1626,22 @@ void testFailure_nonexistentDomain() { assertThat(thrown).hasMessageThat().contains(String.format("(%s)", "example.tld")); } + @Test + void testFailure_cannotUseContactAuthInfo() { + // RFC 5731: "An OPTIONAL "roid" attribute MUST be used to identify the registrant or contact + // object if and only if the given authInfo is associated with a registrant or contact object, + // and not the domain object itself." + // + // We have no contacts, so it cannot be valid to specify a roid + setupDomain("example", "tld"); + assertAboutEppExceptions() + .that( + assertThrows( + BadAuthInfoForResourceException.class, + () -> doFailingTest("domain_transfer_request_contact_auth_info_failure.xml"))) + .marshalsToXml(); + } + @Test void testFailure_periodInMonths() { setupDomain("example", "tld"); diff --git a/core/src/test/resources/google/registry/flows/domain/domain_create_missing_contact_type.xml b/core/src/test/resources/google/registry/flows/domain/domain_create_missing_contact_type.xml deleted file mode 100644 index d78add11645..00000000000 --- a/core/src/test/resources/google/registry/flows/domain/domain_create_missing_contact_type.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - example.tld - 2 - - ns1.example.net - ns2.example.net - - sh8013 - - 2fooBAR - - - - ABC-12345 - - diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request.xml index 45f757e8c12..947ef66fc0e 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request.xml @@ -6,7 +6,7 @@ example.tld 1 - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_allocation_token.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_allocation_token.xml index 6064c60e113..d8b179f1f58 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_allocation_token.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_allocation_token.xml @@ -6,7 +6,7 @@ example.tld 1 - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_contact_auth_info_failure.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_contact_auth_info_failure.xml new file mode 100644 index 00000000000..895ec5292c6 --- /dev/null +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_contact_auth_info_failure.xml @@ -0,0 +1,15 @@ + + + + + example.tld + 1 + + 2fooBAR + + + + ABC-12345 + + diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee.xml index 32ffebcd2e2..5685179f0f0 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee.xml @@ -6,7 +6,7 @@ %DOMAIN% %YEARS% - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_applied.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_applied.xml index ace1d334e63..4f5cd08745d 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_applied.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_applied.xml @@ -6,7 +6,7 @@ example.tld 1 - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_bad_scale.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_bad_scale.xml index cb0f8e0ee73..313eb810d96 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_bad_scale.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_bad_scale.xml @@ -6,7 +6,7 @@ example.tld 1 - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_defaults.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_defaults.xml index 3c8dd64890b..a169b5bca7f 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_defaults.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_defaults.xml @@ -6,7 +6,7 @@ example.tld 1 - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_grace_period.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_grace_period.xml index 1b25e13029f..5486694d3e5 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_grace_period.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_grace_period.xml @@ -6,7 +6,7 @@ example.tld 1 - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_refundable.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_refundable.xml index 097132cc08f..17b5d2950d0 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_refundable.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_fee_refundable.xml @@ -6,7 +6,7 @@ example.tld 1 - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_missing_period.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_missing_period.xml index 0981c182f96..eb6b8266b43 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_missing_period.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_missing_period.xml @@ -5,7 +5,7 @@ xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"> example.tld - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_months.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_months.xml index f509beaee2d..e08f12f57df 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_months.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_months.xml @@ -6,7 +6,7 @@ example.tld 1 - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_premium.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_premium.xml index 2380336d297..f8d93bd9495 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_premium.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_premium.xml @@ -6,7 +6,7 @@ rich.example 1 - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_separate_fees.xml b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_separate_fees.xml index 44e733a2a43..9c6d679b4b2 100644 --- a/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_separate_fees.xml +++ b/core/src/test/resources/google/registry/flows/domain/domain_transfer_request_separate_fees.xml @@ -6,7 +6,7 @@ %DOMAIN% %YEARS% - 2fooBAR + fooBAR diff --git a/core/src/test/resources/google/registry/module/routing.txt b/core/src/test/resources/google/registry/module/routing.txt index afb28e832a1..b429eceea7b 100644 --- a/core/src/test/resources/google/registry/module/routing.txt +++ b/core/src/test/resources/google/registry/module/routing.txt @@ -46,7 +46,6 @@ BACKEND /_dr/task/readDnsRefreshRequests ReadDnsRefreshReques BACKEND /_dr/task/refreshDnsForAllDomains RefreshDnsForAllDomainsAction GET n APP ADMIN BACKEND /_dr/task/refreshDnsOnHostRename RefreshDnsOnHostRenameAction POST n APP ADMIN BACKEND /_dr/task/relockDomain RelockDomainAction POST y APP ADMIN -BACKEND /_dr/task/removeAllDomainContacts RemoveAllDomainContactsAction POST n APP ADMIN BACKEND /_dr/task/resaveAllEppResourcesPipeline ResaveAllEppResourcesPipelineAction GET n APP ADMIN BACKEND /_dr/task/resaveEntity ResaveEntityAction POST n APP ADMIN BACKEND /_dr/task/sendExpiringCertificateNotificationEmail SendExpiringCertificateNotificationEmailAction GET n APP ADMIN