diff --git a/core/src/main/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java b/core/src/main/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java index 59b4cc522..87b453e2b 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/RegistrarSettingsAction.java @@ -454,7 +454,13 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA .orElseThrow( () -> new FormException( - "Not allowed to set registry lock password directly on new contact")); + "Cannot set registry lock password directly on new contact")); + // Can't modify registry lock email address + if (!Objects.equals( + updatedContact.getRegistryLockEmailAddress(), + existingContact.getRegistryLockEmailAddress())) { + throw new FormException("Cannot modify registryLockEmailAddress through the UI"); + } if (updatedContact.isRegistryLockAllowed()) { // the password must have been set before or the user was allowed to set it now if (!existingContact.isAllowedToSetRegistryLockPassword() @@ -464,7 +470,8 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA } if (updatedContact.isAllowedToSetRegistryLockPassword()) { if (!existingContact.isAllowedToSetRegistryLockPassword()) { - throw new FormException("Cannot set isAllowedToSetRegistryLockPassword through UI"); + throw new FormException( + "Cannot modify isAllowedToSetRegistryLockPassword through the UI"); } } } diff --git a/core/src/main/javascript/google/registry/ui/externs/json.js b/core/src/main/javascript/google/registry/ui/externs/json.js index e808201bf..d398baa7a 100644 --- a/core/src/main/javascript/google/registry/ui/externs/json.js +++ b/core/src/main/javascript/google/registry/ui/externs/json.js @@ -180,7 +180,8 @@ registry.json.RegistrarAddress; * faxNumber: (string?|undefined), * types: (string?|undefined), * allowedToSetRegistryLockPassword: boolean, - * registryLockAllowed: boolean + * registryLockAllowed: boolean, + * registryLockEmailAddress: (string?|undefined) * }} */ registry.json.RegistrarContact; diff --git a/core/src/main/resources/google/registry/ui/soy/registrar/ContactSettings.soy b/core/src/main/resources/google/registry/ui/soy/registrar/ContactSettings.soy index ac0f6412c..15ea07132 100644 --- a/core/src/main/resources/google/registry/ui/soy/registrar/ContactSettings.soy +++ b/core/src/main/resources/google/registry/ui/soy/registrar/ContactSettings.soy @@ -176,6 +176,10 @@ {if isNonnull($item['gaeUserId'])} {/if} + {if isNonnull($item['registryLockEmailAddress'])} + + {/if} {/template} diff --git a/core/src/test/java/google/registry/ui/server/registrar/ContactSettingsTest.java b/core/src/test/java/google/registry/ui/server/registrar/ContactSettingsTest.java index 9a43b05b2..beb39a73d 100644 --- a/core/src/test/java/google/registry/ui/server/registrar/ContactSettingsTest.java +++ b/core/src/test/java/google/registry/ui/server/registrar/ContactSettingsTest.java @@ -67,26 +67,28 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase { @Test public void testPost_updateContacts_success() throws Exception { // Remove all the contacts but one by updating with a list of just it - ImmutableMap adminContact1 = - ImmutableMap.of( - "name", "Marla Singer", - "emailAddress", "Marla.Singer@crr.com", - "phoneNumber", "+1.2128675309", - // Have to keep ADMIN or else expect FormException for at-least-one. - "types", "ADMIN,TECH"); + Map adminContact = + loadRegistrar(CLIENT_ID).getContacts().stream() + .filter(rc -> rc.getEmailAddress().equals("Marla.Singer@crr.com")) + .findFirst() + .get() + .toJsonMap(); + + // Keep an admin to avoid superfluous issues + adminContact.put("types", "ADMIN,TECH"); Registrar registrar = loadRegistrar(CLIENT_ID); Map regMap = registrar.toJsonMap(); - regMap.put("contacts", ImmutableList.of(adminContact1)); + regMap.put("contacts", ImmutableList.of(adminContact)); Map response = action.handleJsonRequest(ImmutableMap.of("op", "update", "id", CLIENT_ID, "args", regMap)); assertThat(response).containsEntry("status", "SUCCESS"); RegistrarContact foundContact = Iterables.getOnlyElement(loadRegistrar(CLIENT_ID).getContacts()); - assertThat(foundContact.getName()).isEqualTo(adminContact1.get("name")); - assertThat(foundContact.getEmailAddress()).isEqualTo(adminContact1.get("emailAddress")); - assertThat(foundContact.getPhoneNumber()).isEqualTo(adminContact1.get("phoneNumber")); + assertThat(foundContact.getName()).isEqualTo(adminContact.get("name")); + assertThat(foundContact.getEmailAddress()).isEqualTo(adminContact.get("emailAddress")); + assertThat(foundContact.getPhoneNumber()).isEqualTo(adminContact.get("phoneNumber")); assertThat(foundContact.getTypes()).containsExactly(Type.ADMIN, Type.TECH); assertMetric(CLIENT_ID, "update", "[OWNER]", "SUCCESS"); verifyNotificationEmailsSent(); @@ -272,7 +274,7 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase { "results", ImmutableList.of(), "message", - "Not allowed to set registry lock password directly on new contact"); + "Cannot set registry lock password directly on new contact"); assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormException"); } @@ -323,7 +325,39 @@ public class ContactSettingsTest extends RegistrarSettingsActionTestCase { "results", ImmutableList.of(), "message", - "Cannot set isAllowedToSetRegistryLockPassword through UI"); + "Cannot modify isAllowedToSetRegistryLockPassword through the UI"); + assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormException"); + } + + @Test + public void testPost_failure_setRegistryLockEmail() { + addPasswordToContactTwo(); + Map reqJson = loadRegistrar(CLIENT_ID).toJsonMap(); + String emailAddress = AppEngineRule.makeRegistrarContact2().getEmailAddress(); + RegistrarContact newContactWithPassword = + loadRegistrar(CLIENT_ID).getContacts().stream() + .filter(rc -> rc.getEmailAddress().equals(emailAddress)) + .findFirst() + .get(); + Map contactJson = newContactWithPassword.toJsonMap(); + contactJson.put("registryLockEmailAddress", "bogus.email@bogus.tld"); + reqJson.put( + "contacts", + ImmutableList.of( + AppEngineRule.makeRegistrarContact1().toJsonMap(), + contactJson, + AppEngineRule.makeRegistrarContact3().toJsonMap())); + + Map response = + action.handleJsonRequest(ImmutableMap.of("op", "update", "id", CLIENT_ID, "args", reqJson)); + assertThat(response) + .containsExactly( + "status", + "ERROR", + "results", + ImmutableList.of(), + "message", + "Cannot modify registryLockEmailAddress through the UI"); assertMetric(CLIENT_ID, "update", "[OWNER]", "ERROR: FormException"); } diff --git a/core/src/test/java/google/registry/webdriver/RegistrarConsoleScreenshotTest.java b/core/src/test/java/google/registry/webdriver/RegistrarConsoleScreenshotTest.java index f176c64cf..f8aebe099 100644 --- a/core/src/test/java/google/registry/webdriver/RegistrarConsoleScreenshotTest.java +++ b/core/src/test/java/google/registry/webdriver/RegistrarConsoleScreenshotTest.java @@ -14,6 +14,7 @@ package google.registry.webdriver; +import static com.google.common.truth.Truth.assertThat; import static google.registry.server.Fixture.BASIC; import static google.registry.server.Route.route; import static google.registry.testing.AppEngineRule.makeRegistrar2; @@ -32,11 +33,13 @@ import com.googlecode.objectify.ObjectifyFilter; import google.registry.model.domain.DomainBase; import google.registry.model.ofy.OfyFilter; import google.registry.model.registrar.Registrar.State; +import google.registry.model.registrar.RegistrarContact; import google.registry.module.frontend.FrontendServlet; import google.registry.schema.domain.RegistryLock; import google.registry.server.RegistryTestServer; import google.registry.testing.AppEngineRule; import google.registry.testing.CertificateSamples; +import java.util.Optional; import java.util.UUID; import org.junit.Rule; import org.junit.Test; @@ -150,13 +153,13 @@ public class RegistrarConsoleScreenshotTest extends WebDriverTestCase { public void settingsContactEdit_setRegistryLockPassword() throws Throwable { server.runInAppEngineEnvironment( () -> { + persistResource(makeRegistrar2().asBuilder().setRegistryLockAllowed(true).build()); persistResource( makeRegistrarContact2() .asBuilder() .setRegistryLockEmailAddress("johndoe.registrylock@example.com") .setAllowedToSetRegistryLockPassword(true) .build()); - persistResource(makeRegistrar2().asBuilder().setRegistryLockAllowed(true).build()); return null; }); driver.manage().window().setSize(new Dimension(1050, 2000)); @@ -165,6 +168,25 @@ public class RegistrarConsoleScreenshotTest extends WebDriverTestCase { driver.waitForElement(By.tagName("h1")); driver.waitForElement(By.id("reg-app-btn-edit")).click(); driver.diffPage("page"); + + // now actually set the password + driver.findElement(By.id("contacts[1].registryLockPassword")).sendKeys("password"); + driver.waitForElement(By.id("reg-app-btn-save")).click(); + Thread.sleep(500); + driver.diffPage("contactview"); + + server.runInAppEngineEnvironment( + () -> { + RegistrarContact contact = + loadRegistrar("TheRegistrar").getContacts().stream() + .filter(c -> c.getEmailAddress().equals("johndoe@theregistrar.com")) + .findFirst() + .get(); + assertThat(contact.verifyRegistryLockPassword("password")).isTrue(); + assertThat(contact.getRegistryLockEmailAddress()) + .isEqualTo(Optional.of("johndoe.registrylock@example.com")); + return null; + }); } @Test diff --git a/core/src/test/resources/google/registry/webdriver/goldens/chrome-linux/RegistrarConsoleScreenshotTest_settingsContactEdit_setRegistryLockPassword_contactview.png b/core/src/test/resources/google/registry/webdriver/goldens/chrome-linux/RegistrarConsoleScreenshotTest_settingsContactEdit_setRegistryLockPassword_contactview.png new file mode 100644 index 000000000..47f1f7e73 Binary files /dev/null and b/core/src/test/resources/google/registry/webdriver/goldens/chrome-linux/RegistrarConsoleScreenshotTest_settingsContactEdit_setRegistryLockPassword_contactview.png differ