From daa7ab3bfad7222d7db4e4c5fd022f7a644ce24a Mon Sep 17 00:00:00 2001
From: gbrodman
Date: Tue, 29 Apr 2025 13:32:29 -0400
Subject: [PATCH] Disable primary-contact editing in console (#2745)
This is necessary because we'll use primary-contact emails as a way of
resetting passwords.
In the UI, don't allow editing of email address for primary contacts,
and don't allow addition/removal of the primary contact field
post-creation.
In the backend, make sure that all emails previously added still exist.
---
.../app/settings/contact/contact.component.ts | 6 +-
.../app/settings/contact/contact.service.ts | 2 +-
.../contact/contactDetails.component.html | 17 +-
.../contact/contactDetails.component.ts | 11 ++
.../console/settings/ContactAction.java | 18 ++
.../console/settings/ContactActionTest.java | 169 ++++++++++--------
.../webdriver/ConsoleScreenshotTest.java | 11 +-
.../registry/webdriver/WebDriverTestCase.java | 30 ----
8 files changed, 147 insertions(+), 117 deletions(-)
delete mode 100644 core/src/test/java/google/registry/webdriver/WebDriverTestCase.java
diff --git a/console-webapp/src/app/settings/contact/contact.component.ts b/console-webapp/src/app/settings/contact/contact.component.ts
index 74d3dd4da..cc23a7c3b 100644
--- a/console-webapp/src/app/settings/contact/contact.component.ts
+++ b/console-webapp/src/app/settings/contact/contact.component.ts
@@ -16,11 +16,7 @@ import { Component, effect, ViewEncapsulation } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';
import { take } from 'rxjs';
import { RegistrarService } from 'src/app/registrar/registrar.service';
-import {
- ContactService,
- contactTypeToViewReadyContact,
- ViewReadyContact,
-} from './contact.service';
+import { ContactService, ViewReadyContact } from './contact.service';
@Component({
selector: 'app-contact',
diff --git a/console-webapp/src/app/settings/contact/contact.service.ts b/console-webapp/src/app/settings/contact/contact.service.ts
index b042a86a9..8936553d7 100644
--- a/console-webapp/src/app/settings/contact/contact.service.ts
+++ b/console-webapp/src/app/settings/contact/contact.service.ts
@@ -83,7 +83,7 @@ export class ContactService {
: contactTypeToViewReadyContact({
emailAddress: '',
name: '',
- types: ['ADMIN'],
+ types: ['TECH'],
faxNumber: '',
phoneNumber: '',
registrarId: '',
diff --git a/console-webapp/src/app/settings/contact/contactDetails.component.html b/console-webapp/src/app/settings/contact/contactDetails.component.html
index 1a6041603..d621920f5 100644
--- a/console-webapp/src/app/settings/contact/contactDetails.component.html
+++ b/console-webapp/src/app/settings/contact/contactDetails.component.html
@@ -56,6 +56,7 @@
[required]="true"
[(ngModel)]="contactService.contactInEdit.emailAddress"
[ngModelOptions]="{ standalone: true }"
+ [disabled]="emailAddressIsDisabled()"
/>
@@ -85,14 +86,18 @@
errorRequired to select at least one
-
- {{ contactType.value }}
-
+
+ {{ contactType.value }}
+
+
diff --git a/console-webapp/src/app/settings/contact/contactDetails.component.ts b/console-webapp/src/app/settings/contact/contactDetails.component.ts
index 8ab347ba2..0a24ad460 100644
--- a/console-webapp/src/app/settings/contact/contactDetails.component.ts
+++ b/console-webapp/src/app/settings/contact/contactDetails.component.ts
@@ -82,6 +82,10 @@ export class ContactDetailsComponent {
});
}
+ shouldDisplayCheckbox(type: string) {
+ return type !== 'ADMIN' || this.checkboxIsChecked(type);
+ }
+
checkboxIsChecked(type: string) {
return this.contactService.contactInEdit.types.includes(
type as contactType
@@ -89,6 +93,9 @@ export class ContactDetailsComponent {
}
checkboxIsDisabled(type: string) {
+ if (type === 'ADMIN') {
+ return true;
+ }
return (
this.contactService.contactInEdit.types.length === 1 &&
this.contactService.contactInEdit.types[0] === (type as contactType)
@@ -105,4 +112,8 @@ export class ContactDetailsComponent {
);
}
}
+
+ emailAddressIsDisabled() {
+ return this.contactService.contactInEdit.types.includes('ADMIN');
+ }
}
diff --git a/core/src/main/java/google/registry/ui/server/console/settings/ContactAction.java b/core/src/main/java/google/registry/ui/server/console/settings/ContactAction.java
index 83336f3bb..322e62460 100644
--- a/core/src/main/java/google/registry/ui/server/console/settings/ContactAction.java
+++ b/core/src/main/java/google/registry/ui/server/console/settings/ContactAction.java
@@ -169,6 +169,7 @@ public class ContactAction extends ConsoleApiAction {
throw new ContactRequirementException(t);
}
}
+ enforcePrimaryContactRestrictions(oldContactsByType, newContactsByType);
ensurePhoneNumberNotRemovedForContactTypes(oldContactsByType, newContactsByType, Type.TECH);
Optional domainWhoisAbuseContact =
getDomainWhoisVisibleAbuseContact(updatedContacts);
@@ -187,6 +188,23 @@ public class ContactAction extends ConsoleApiAction {
checkContactRegistryLockRequirements(existingContacts, updatedContacts);
}
+ private static void enforcePrimaryContactRestrictions(
+ Multimap oldContactsByType,
+ Multimap newContactsByType) {
+ ImmutableSet oldAdminEmails =
+ oldContactsByType.get(Type.ADMIN).stream()
+ .map(RegistrarPoc::getEmailAddress)
+ .collect(toImmutableSet());
+ ImmutableSet newAdminEmails =
+ newContactsByType.get(Type.ADMIN).stream()
+ .map(RegistrarPoc::getEmailAddress)
+ .collect(toImmutableSet());
+ if (!newAdminEmails.containsAll(oldAdminEmails)) {
+ throw new ContactRequirementException(
+ "Cannot remove or change the email address of primary contacts");
+ }
+ }
+
private static void checkContactRegistryLockRequirements(
ImmutableSet existingContacts, ImmutableSet updatedContacts) {
// Any contact(s) with new passwords must be allowed to set them
diff --git a/core/src/test/java/google/registry/ui/server/console/settings/ContactActionTest.java b/core/src/test/java/google/registry/ui/server/console/settings/ContactActionTest.java
index 378f5d521..e5137c918 100644
--- a/core/src/test/java/google/registry/ui/server/console/settings/ContactActionTest.java
+++ b/core/src/test/java/google/registry/ui/server/console/settings/ContactActionTest.java
@@ -18,6 +18,7 @@ import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.registrar.RegistrarPoc.Type.ABUSE;
import static google.registry.model.registrar.RegistrarPoc.Type.ADMIN;
+import static google.registry.model.registrar.RegistrarPoc.Type.MARKETING;
import static google.registry.model.registrar.RegistrarPoc.Type.TECH;
import static google.registry.testing.DatabaseHelper.createAdminUser;
import static google.registry.testing.DatabaseHelper.insertInDb;
@@ -70,8 +71,9 @@ class ContactActionTest {
private Registrar testRegistrar;
private ConsoleApiParams consoleApiParams;
- private RegistrarPoc testRegistrarPoc1;
- private RegistrarPoc testRegistrarPoc2;
+ private RegistrarPoc adminPoc;
+ private RegistrarPoc techPoc;
+ private RegistrarPoc marketingPoc;
private static final Gson GSON = RequestModule.provideGson();
@@ -82,7 +84,7 @@ class ContactActionTest {
@BeforeEach
void beforeEach() {
testRegistrar = saveRegistrar("registrarId");
- testRegistrarPoc1 =
+ adminPoc =
new RegistrarPoc.Builder()
.setRegistrar(testRegistrar)
.setName("Test Registrar 1")
@@ -94,19 +96,32 @@ class ContactActionTest {
.setVisibleInWhoisAsTech(false)
.setVisibleInDomainWhoisAsAbuse(false)
.build();
- testRegistrarPoc2 =
- testRegistrarPoc1
+ techPoc =
+ adminPoc
.asBuilder()
.setName("Test Registrar 2")
+ .setTypes(ImmutableSet.of(TECH))
+ .setVisibleInWhoisAsTech(true)
+ .setVisibleInWhoisAsAdmin(false)
.setEmailAddress("test.registrar2@example.com")
.setPhoneNumber("+1.1234567890")
.setFaxNumber("+1.1234567891")
.build();
+ marketingPoc =
+ adminPoc
+ .asBuilder()
+ .setName("Test Registrar 3")
+ .setTypes(ImmutableSet.of(MARKETING))
+ .setVisibleInWhoisAsAdmin(false)
+ .setEmailAddress("test.registrar3@example.com")
+ .setPhoneNumber("+1.1238675309")
+ .setFaxNumber("+1.1238675309")
+ .build();
}
@Test
void testSuccess_getContactInfo() throws IOException {
- insertInDb(testRegistrarPoc1);
+ insertInDb(adminPoc);
ContactAction action =
createAction(
Action.Method.GET,
@@ -120,13 +135,13 @@ class ContactActionTest {
@Test
void testSuccess_noOp() throws IOException {
- insertInDb(testRegistrarPoc1);
+ insertInDb(adminPoc);
ContactAction action =
createAction(
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1);
+ adminPoc);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
verify(consoleApiParams.sendEmailUtils().gmailClient, never()).sendEmail(any());
@@ -134,8 +149,8 @@ class ContactActionTest {
@Test
void testSuccess_onlyContactsWithNonEmptyType() throws IOException {
- testRegistrarPoc1 = testRegistrarPoc1.asBuilder().setTypes(ImmutableSet.of()).build();
- insertInDb(testRegistrarPoc1);
+ adminPoc = adminPoc.asBuilder().setTypes(ImmutableSet.of()).build();
+ insertInDb(adminPoc);
ContactAction action =
createAction(
Action.Method.GET,
@@ -148,14 +163,14 @@ class ContactActionTest {
@Test
void testSuccess_postCreateContactInfo() throws IOException {
- insertInDb(testRegistrarPoc1);
+ insertInDb(adminPoc);
ContactAction action =
createAction(
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1,
- testRegistrarPoc2);
+ adminPoc,
+ techPoc);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
assertThat(
@@ -168,14 +183,14 @@ class ContactActionTest {
@Test
void testSuccess_postUpdateContactInfo() throws IOException {
- insertInDb(testRegistrarPoc1.asBuilder().setEmailAddress("incorrect@email.com").build());
+ insertInDb(techPoc.asBuilder().setEmailAddress("incorrect@email.com").build());
ContactAction action =
createAction(
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1,
- testRegistrarPoc2);
+ adminPoc,
+ techPoc);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
HashMap testResult = new HashMap<>();
@@ -197,8 +212,8 @@ class ContactActionTest {
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1,
- testRegistrarPoc2.asBuilder().setEmailAddress("test.registrar1@example.com").build());
+ adminPoc,
+ techPoc.asBuilder().setEmailAddress("test.registrar1@example.com").build());
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
@@ -213,13 +228,13 @@ class ContactActionTest {
@Test
void testFailure_postUpdateContactInfo_requiredContactRemoved() throws IOException {
- insertInDb(testRegistrarPoc1);
+ insertInDb(adminPoc);
ContactAction action =
createAction(
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1.asBuilder().setTypes(ImmutableSet.of(ABUSE)).build());
+ adminPoc.asBuilder().setTypes(ImmutableSet.of(ABUSE)).build());
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
@@ -228,20 +243,19 @@ class ContactActionTest {
loadAllOf(RegistrarPoc.class).stream()
.filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId()))
.collect(toImmutableList()))
- .containsExactly(testRegistrarPoc1);
+ .containsExactly(adminPoc);
}
@Test
void testFailure_postUpdateContactInfo_phoneNumberRemoved() throws IOException {
- testRegistrarPoc1 =
- testRegistrarPoc1.asBuilder().setTypes(ImmutableSet.of(ADMIN, TECH)).build();
- insertInDb(testRegistrarPoc1);
+ adminPoc = adminPoc.asBuilder().setTypes(ImmutableSet.of(ADMIN, TECH)).build();
+ insertInDb(adminPoc);
ContactAction action =
createAction(
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1
+ adminPoc
.asBuilder()
.setPhoneNumber(null)
.setTypes(ImmutableSet.of(ADMIN, TECH))
@@ -254,7 +268,7 @@ class ContactActionTest {
loadAllOf(RegistrarPoc.class).stream()
.filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId()))
.collect(toImmutableList()))
- .containsExactly(testRegistrarPoc1);
+ .containsExactly(adminPoc);
}
@Test
@@ -264,11 +278,7 @@ class ContactActionTest {
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1
- .asBuilder()
- .setPhoneNumber(null)
- .setVisibleInDomainWhoisAsAbuse(true)
- .build());
+ adminPoc.asBuilder().setPhoneNumber(null).setVisibleInDomainWhoisAsAbuse(true).build());
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
@@ -282,14 +292,14 @@ class ContactActionTest {
@Test
void testFailure_postUpdateContactInfo_whoisContactPhoneNumberRemoved() throws IOException {
- testRegistrarPoc1 = testRegistrarPoc1.asBuilder().setVisibleInDomainWhoisAsAbuse(true).build();
- insertInDb(testRegistrarPoc1);
+ adminPoc = adminPoc.asBuilder().setVisibleInDomainWhoisAsAbuse(true).build();
+ insertInDb(adminPoc);
ContactAction action =
createAction(
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1.asBuilder().setVisibleInDomainWhoisAsAbuse(false).build());
+ adminPoc.asBuilder().setVisibleInDomainWhoisAsAbuse(false).build());
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
@@ -298,7 +308,7 @@ class ContactActionTest {
loadAllOf(RegistrarPoc.class).stream()
.filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId()))
.collect(toImmutableList()))
- .containsExactly(testRegistrarPoc1);
+ .containsExactly(adminPoc);
}
@Test
@@ -309,7 +319,7 @@ class ContactActionTest {
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1
+ adminPoc
.asBuilder()
.setAllowedToSetRegistryLockPassword(true)
.setRegistryLockEmailAddress("lock@example.com")
@@ -327,22 +337,19 @@ class ContactActionTest {
@Test
void testFailure_postUpdateContactInfo_cannotModifyRegistryLockEmail() throws IOException {
- testRegistrarPoc1 =
- testRegistrarPoc1
+ adminPoc =
+ adminPoc
.asBuilder()
.setRegistryLockEmailAddress("lock@example.com")
.setAllowedToSetRegistryLockPassword(true)
.build();
- insertInDb(testRegistrarPoc1);
+ insertInDb(adminPoc);
ContactAction action =
createAction(
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1
- .asBuilder()
- .setRegistryLockEmailAddress("unlock@example.com")
- .build());
+ adminPoc.asBuilder().setRegistryLockEmailAddress("unlock@example.com").build());
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
@@ -351,25 +358,25 @@ class ContactActionTest {
loadAllOf(RegistrarPoc.class).stream()
.filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId()))
.collect(toImmutableList()))
- .containsExactly(testRegistrarPoc1);
+ .containsExactly(adminPoc);
}
@Test
void testFailure_postUpdateContactInfo_cannotSetIsAllowedToSetRegistryLockPassword()
throws IOException {
- testRegistrarPoc1 =
- testRegistrarPoc1
+ adminPoc =
+ adminPoc
.asBuilder()
.setRegistryLockEmailAddress("lock@example.com")
.setAllowedToSetRegistryLockPassword(false)
.build();
- insertInDb(testRegistrarPoc1);
+ insertInDb(adminPoc);
ContactAction action =
createAction(
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1.asBuilder().setAllowedToSetRegistryLockPassword(true).build());
+ adminPoc.asBuilder().setAllowedToSetRegistryLockPassword(true).build());
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
@@ -378,18 +385,18 @@ class ContactActionTest {
loadAllOf(RegistrarPoc.class).stream()
.filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId()))
.collect(toImmutableList()))
- .containsExactly(testRegistrarPoc1);
+ .containsExactly(adminPoc);
}
@Test
void testSuccess_sendsEmail() throws IOException, AddressException {
- insertInDb(testRegistrarPoc1.asBuilder().setEmailAddress("incorrect@email.com").build());
+ insertInDb(techPoc.asBuilder().setEmailAddress("incorrect@email.com").build());
ContactAction action =
createAction(
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc1);
+ techPoc);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
verify(consoleApiParams.sendEmailUtils().gmailClient, times(1))
@@ -404,44 +411,42 @@ class ContactActionTest {
+ "\n"
+ "contacts:\n"
+ " ADDED:\n"
- + " {name=Test Registrar 1,"
- + " emailAddress=test.registrar1@example.com, registrarId=registrarId,"
- + " registryLockEmailAddress=null, phoneNumber=+1.9999999999,"
- + " faxNumber=+1.9999999991, types=[ADMIN],"
- + " visibleInWhoisAsAdmin=true, visibleInWhoisAsTech=false,"
+ + " {name=Test Registrar 2,"
+ + " emailAddress=test.registrar2@example.com, registrarId=registrarId,"
+ + " registryLockEmailAddress=null, phoneNumber=+1.1234567890,"
+ + " faxNumber=+1.1234567891, types=[TECH],"
+ + " visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=true,"
+ " visibleInDomainWhoisAsAbuse=false,"
+ " allowedToSetRegistryLockPassword=false}\n"
+ " REMOVED:\n"
- + " {name=Test Registrar 1, emailAddress=incorrect@email.com,"
+ + " {name=Test Registrar 2, emailAddress=incorrect@email.com,"
+ " registrarId=registrarId, registryLockEmailAddress=null,"
- + " phoneNumber=+1.9999999999, faxNumber=+1.9999999991, types=[ADMIN],"
- + " visibleInWhoisAsAdmin=true,"
- + " visibleInWhoisAsTech=false, visibleInDomainWhoisAsAbuse=false,"
+ + " phoneNumber=+1.1234567890, faxNumber=+1.1234567891, types=[TECH],"
+ + " visibleInWhoisAsAdmin=false,"
+ + " visibleInWhoisAsTech=true, visibleInDomainWhoisAsAbuse=false,"
+ " allowedToSetRegistryLockPassword=false}\n"
+ " FINAL CONTENTS:\n"
- + " {name=Test Registrar 1,"
- + " emailAddress=test.registrar1@example.com, registrarId=registrarId,"
- + " registryLockEmailAddress=null, phoneNumber=+1.9999999999,"
- + " faxNumber=+1.9999999991, types=[ADMIN],"
- + " visibleInWhoisAsAdmin=true, visibleInWhoisAsTech=false,"
+ + " {name=Test Registrar 2,"
+ + " emailAddress=test.registrar2@example.com, registrarId=registrarId,"
+ + " registryLockEmailAddress=null, phoneNumber=+1.1234567890,"
+ + " faxNumber=+1.1234567891, types=[TECH],"
+ + " visibleInWhoisAsAdmin=false, visibleInWhoisAsTech=true,"
+ " visibleInDomainWhoisAsAbuse=false,"
+ " allowedToSetRegistryLockPassword=false}\n")
- .setRecipients(
- ImmutableList.of(
- new InternetAddress("notification@test.example"),
- new InternetAddress("incorrect@email.com")))
+ .setRecipients(ImmutableList.of(new InternetAddress("notification@test.example")))
.build());
}
@Test
void testSuccess_postDeleteContactInfo() throws IOException {
- insertInDb(testRegistrarPoc1);
+ insertInDb(adminPoc, techPoc, marketingPoc);
ContactAction action =
createAction(
Action.Method.POST,
AuthResult.createUser(createAdminUser("email@email.com")),
testRegistrar.getRegistrarId(),
- testRegistrarPoc2);
+ adminPoc,
+ techPoc);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_OK);
assertThat(
@@ -449,12 +454,12 @@ class ContactActionTest {
.filter(r -> r.registrarId.equals(testRegistrar.getRegistrarId()))
.map(r -> r.getName())
.collect(toImmutableList()))
- .containsExactly("Test Registrar 2");
+ .containsExactly("Test Registrar 1", "Test Registrar 2");
}
@Test
void testFailure_postDeleteContactInfo_missingPermission() throws IOException {
- insertInDb(testRegistrarPoc1);
+ insertInDb(adminPoc);
ContactAction action =
createAction(
Action.Method.POST,
@@ -469,11 +474,27 @@ class ContactActionTest {
.build())
.build()),
testRegistrar.getRegistrarId(),
- testRegistrarPoc2);
+ techPoc);
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus()).isEqualTo(SC_FORBIDDEN);
}
+ @Test
+ void testFailure_changesAdminEmail() throws Exception {
+ insertInDb(adminPoc.asBuilder().setEmailAddress("oldemail@example.com").build());
+ ContactAction action =
+ createAction(
+ Action.Method.POST,
+ AuthResult.createUser(createAdminUser("email@email.com")),
+ testRegistrar.getRegistrarId(),
+ adminPoc);
+ action.run();
+ FakeResponse fakeResponse = (FakeResponse) consoleApiParams.response();
+ assertThat(fakeResponse.getStatus()).isEqualTo(400);
+ assertThat(fakeResponse.getPayload())
+ .isEqualTo("Cannot remove or change the email address of primary contacts");
+ }
+
private ContactAction createAction(
Action.Method method, AuthResult authResult, String registrarId, RegistrarPoc... contacts)
throws IOException {
diff --git a/core/src/test/java/google/registry/webdriver/ConsoleScreenshotTest.java b/core/src/test/java/google/registry/webdriver/ConsoleScreenshotTest.java
index 220c8cbcf..679eeb038 100644
--- a/core/src/test/java/google/registry/webdriver/ConsoleScreenshotTest.java
+++ b/core/src/test/java/google/registry/webdriver/ConsoleScreenshotTest.java
@@ -23,6 +23,7 @@ import google.registry.model.console.RegistrarRole;
import google.registry.server.RegistryTestServer;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Timeout;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junitpioneer.jupiter.RetryingTest;
@@ -50,7 +51,15 @@ import org.openqa.selenium.WebElement;
*/
// The Selenium image only supports amd64 architecture.
@EnabledIfSystemProperty(named = "os.arch", matches = "amd64")
-public class ConsoleScreenshotTest extends WebDriverTestCase {
+@Timeout(120)
+public class ConsoleScreenshotTest {
+
+ @RegisterExtension
+ static final DockerWebDriverExtension webDriverProvider = new DockerWebDriverExtension();
+
+ @RegisterExtension
+ final WebDriverPlusScreenDifferExtension driver =
+ new WebDriverPlusScreenDifferExtension(webDriverProvider::getWebDriver);
@RegisterExtension
final TestServerExtension server =
diff --git a/core/src/test/java/google/registry/webdriver/WebDriverTestCase.java b/core/src/test/java/google/registry/webdriver/WebDriverTestCase.java
deleted file mode 100644
index 6b5a688c2..000000000
--- a/core/src/test/java/google/registry/webdriver/WebDriverTestCase.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2019 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.webdriver;
-
-import org.junit.jupiter.api.Timeout;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-/** Base class for tests that needs a {@link WebDriverPlusScreenDifferExtension}. */
-@Timeout(120)
-class WebDriverTestCase {
-
- @RegisterExtension
- static final DockerWebDriverExtension webDriverProvider = new DockerWebDriverExtension();
-
- @RegisterExtension
- final WebDriverPlusScreenDifferExtension driver =
- new WebDriverPlusScreenDifferExtension(webDriverProvider::getWebDriver);
-}