1
0
mirror of https://github.com/google/nomulus synced 2026-04-24 02:00:50 +00:00

Remove references to contacts in domain flows (#2944)

We've moved on from contacts entirely now so the only thing we really
need to do is make sure that people don't include contacts in domain
creates or updates. This also makes auth code checking easier too,
because now the only auth code that you're allowed to provide is the
domain auth code (not a contact auth code)
This commit is contained in:
gbrodman
2026-01-29 14:30:41 -05:00
committed by GitHub
parent 71c9407f07
commit 41d26d8385
32 changed files with 95 additions and 773 deletions

View File

@@ -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();
}
}

View File

@@ -119,7 +119,6 @@ import google.registry.flows.domain.DomainFlowUtils.MalformedTcnIdException;
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 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
.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");

View File

@@ -64,7 +64,6 @@ import google.registry.model.billing.BillingBase.RenewalPriceBehavior;
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 @@ class DomainTransferApproveFlowTest
.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 @@ class DomainTransferApproveFlowTest
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 @@ class DomainTransferApproveFlowTest
}
private void doFailingTest(String commandFilename) throws Exception {
setEppLoader(commandFilename);
setEppInput(commandFilename);
// Setup done; run the test.
assertMutatingFlow(true);
runFlow();
@@ -376,7 +369,7 @@ class DomainTransferApproveFlowTest
@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 @@ class DomainTransferApproveFlowTest
"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 @@ class DomainTransferApproveFlowTest
}
@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,

View File

@@ -43,7 +43,6 @@ import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
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 @@ class DomainTransferCancelFlowTest
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 @@ class DomainTransferCancelFlowTest
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 @@ class DomainTransferCancelFlowTest
@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 @@ class DomainTransferCancelFlowTest
}
@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,

View File

@@ -20,7 +20,6 @@ import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_CREATE;
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.Flag;
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<F extends Flow, R extends EppResource>
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 @@ abstract class DomainTransferFlowTestCase<F extends Flow, R extends EppResource>
/** 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);

View File

@@ -29,7 +29,6 @@ import google.registry.flows.ResourceFlowUtils.BadAuthInfoForResourceException;
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 @@ class DomainTransferQueryFlowTest
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 @@ class DomainTransferQueryFlowTest
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 @@ class DomainTransferQueryFlowTest
"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 @@ class DomainTransferQueryFlowTest
}
@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,

View File

@@ -43,7 +43,6 @@ import google.registry.flows.ResourceFlowUtils.ResourceDoesNotExistException;
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 @@ class DomainTransferRejectFlowTest
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 @@ class DomainTransferRejectFlowTest
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 @@ class DomainTransferRejectFlowTest
@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 @@ class DomainTransferRejectFlowTest
"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 @@ class DomainTransferRejectFlowTest
}
@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,

View File

@@ -40,7 +40,6 @@ import static google.registry.testing.DatabaseHelper.loadByEntity;
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.BillingBase.RenewalPriceBehavior;
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 @@ class DomainTransferRequestFlowTest
throws Exception {
setEppInput(commandFilename, substitutions);
ImmutableSet<GracePeriod> 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 @@ class DomainTransferRequestFlowTest
eppRequestSource = EppRequestSource.TOOL;
setEppInput(commandFilename, substitutions);
ImmutableSet<GracePeriod> 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 @@ class DomainTransferRequestFlowTest
String commandFilename, UserPrivileges userPrivileges, Map<String, String> 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 @@ class DomainTransferRequestFlowTest
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 @@ class DomainTransferRequestFlowTest
// 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 @@ class DomainTransferRequestFlowTest
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 @@ class DomainTransferRequestFlowTest
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 @@ class DomainTransferRequestFlowTest
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 @@ class DomainTransferRequestFlowTest
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 @@ class DomainTransferRequestFlowTest
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 @@ class DomainTransferRequestFlowTest
@Test
void testFailure_nonexistentDomain() {
createTld("tld");
contact = persistActiveContact("jd1234");
ResourceDoesNotExistException thrown =
assertThrows(
ResourceDoesNotExistException.class,
@@ -1671,6 +1626,22 @@ class DomainTransferRequestFlowTest
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");

View File

@@ -1,20 +0,0 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<create>
<domain:create
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.tld</domain:name>
<domain:period unit="y">2</domain:period>
<domain:ns>
<domain:hostObj>ns1.example.net</domain:hostObj>
<domain:hostObj>ns2.example.net</domain:hostObj>
</domain:ns>
<domain:contact>sh8013</domain:contact>
<domain:authInfo>
<domain:pw>2fooBAR</domain:pw>
</domain:authInfo>
</domain:create>
</create>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View File

@@ -6,7 +6,7 @@
<domain:name>example.tld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -6,7 +6,7 @@
<domain:name>example.tld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -0,0 +1,15 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<transfer op="request">
<domain:transfer
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.tld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:authInfo>
<domain:pw roid="2-ROID">2fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>
<clTRID>ABC-12345</clTRID>
</command>
</epp>

View File

@@ -6,7 +6,7 @@
<domain:name>%DOMAIN%</domain:name>
<domain:period unit="y">%YEARS%</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -6,7 +6,7 @@
<domain:name>example.tld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -6,7 +6,7 @@
<domain:name>example.tld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -6,7 +6,7 @@
<domain:name>example.tld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -6,7 +6,7 @@
<domain:name>example.tld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -6,7 +6,7 @@
<domain:name>example.tld</domain:name>
<domain:period unit="y">1</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -5,7 +5,7 @@
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>example.tld</domain:name>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -6,7 +6,7 @@
<domain:name>example.tld</domain:name>
<domain:period unit="m">1</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -6,7 +6,7 @@
<domain:name>rich.example</domain:name>
<domain:period unit="y">1</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -6,7 +6,7 @@
<domain:name>%DOMAIN%</domain:name>
<domain:period unit="y">%YEARS%</domain:period>
<domain:authInfo>
<domain:pw roid="JD1234-REP">2fooBAR</domain:pw>
<domain:pw>fooBAR</domain:pw>
</domain:authInfo>
</domain:transfer>
</transfer>

View File

@@ -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