diff --git a/core/src/main/java/google/registry/ui/server/registrar/RegistryLockPostAction.java b/core/src/main/java/google/registry/ui/server/registrar/RegistryLockPostAction.java index 237d4a2c9..1abe04a2f 100644 --- a/core/src/main/java/google/registry/ui/server/registrar/RegistryLockPostAction.java +++ b/core/src/main/java/google/registry/ui/server/registrar/RegistryLockPostAction.java @@ -21,7 +21,6 @@ import static google.registry.security.JsonResponseHelper.Status.ERROR; import static google.registry.security.JsonResponseHelper.Status.SUCCESS; import static google.registry.ui.server.registrar.RegistrarConsoleModule.PARAM_CLIENT_ID; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; -import static google.registry.util.PreconditionsUtils.checkArgumentPresent; import com.google.common.base.Strings; import com.google.common.base.Throwables; @@ -34,6 +33,7 @@ import google.registry.model.registrar.Registrar; import google.registry.model.registrar.RegistrarContact; import google.registry.request.Action; import google.registry.request.Action.Method; +import google.registry.request.HttpException.ForbiddenException; import google.registry.request.JsonActionRunner; import google.registry.request.auth.Auth; import google.registry.request.auth.AuthResult; @@ -123,10 +123,16 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc !Strings.isNullOrEmpty(postInput.fullyQualifiedDomainName), "Missing key for fullyQualifiedDomainName"); checkNotNull(postInput.isLock, "Missing key for isLock"); - checkArgumentPresent(authResult.userAuthInfo(), "User is not logged in"); + UserAuthInfo userAuthInfo = + authResult + .userAuthInfo() + .orElseThrow(() -> new ForbiddenException("User is not logged in")); - boolean isAdmin = authResult.userAuthInfo().get().isUserAdmin(); - verifyRegistryLockPassword(postInput); + boolean isAdmin = userAuthInfo.isUserAdmin(); + String userEmail = userAuthInfo.user().getEmail(); + if (!isAdmin) { + verifyRegistryLockPassword(postInput, userEmail); + } jpaTm() .transact( () -> { @@ -135,12 +141,12 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc ? domainLockUtils.createRegistryLockRequest( postInput.fullyQualifiedDomainName, postInput.clientId, - postInput.pocId, + userEmail, isAdmin, clock) : domainLockUtils.createRegistryUnlockRequest( postInput.fullyQualifiedDomainName, postInput.clientId, isAdmin, clock); - sendVerificationEmail(registryLock, postInput.isLock); + sendVerificationEmail(registryLock, userEmail, postInput.isLock); }); String action = postInput.isLock ? "lock" : "unlock"; return JsonResponseHelper.create(SUCCESS, String.format("Successful %s", action)); @@ -152,7 +158,7 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc } } - private void sendVerificationEmail(RegistryLock lock, boolean isLock) { + private void sendVerificationEmail(RegistryLock lock, String userEmail, boolean isLock) { try { String url = new URIBuilder() @@ -165,8 +171,7 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc .toString(); String body = String.format(VERIFICATION_EMAIL_TEMPLATE, lock.getDomainName(), url); ImmutableList recipients = - ImmutableList.of( - new InternetAddress(authResult.userAuthInfo().get().user().getEmail(), true)); + ImmutableList.of(new InternetAddress(userEmail, true)); String action = isLock ? "lock" : "unlock"; sendEmailService.sendEmail( EmailMessage.newBuilder() @@ -180,30 +185,25 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc } } - private void verifyRegistryLockPassword(RegistryLockPostInput postInput) + private void verifyRegistryLockPassword(RegistryLockPostInput postInput, String userEmail) throws RegistrarAccessDeniedException { - // Verify that the user can access the registrar and that the user is either an admin or has + // Verify that the user can access the registrar and that the user has // registry lock enabled and provided a correct password - checkArgument(authResult.userAuthInfo().isPresent(), "Auth result not present"); Registrar registrar = registrarAccessor.getRegistrar(postInput.clientId); checkArgument( registrar.isRegistryLockAllowed(), "Registry lock not allowed for this registrar"); - UserAuthInfo userAuthInfo = authResult.userAuthInfo().get(); - if (!userAuthInfo.isUserAdmin()) { - checkArgument(!Strings.isNullOrEmpty(postInput.pocId), "Missing key for pocId"); - checkArgument(!Strings.isNullOrEmpty(postInput.password), "Missing key for password"); - RegistrarContact registrarContact = - registrar.getContacts().stream() - .filter(contact -> contact.getEmailAddress().equals(postInput.pocId)) - .findFirst() - .orElseThrow( - () -> - new IllegalArgumentException( - String.format("Unknown registrar POC ID %s", postInput.pocId))); - checkArgument( - registrarContact.verifyRegistryLockPassword(postInput.password), - "Incorrect registry lock password for contact"); - } + checkArgument(!Strings.isNullOrEmpty(postInput.password), "Missing key for password"); + RegistrarContact registrarContact = + registrar.getContacts().stream() + .filter(contact -> contact.getEmailAddress().equals(userEmail)) + .findFirst() + .orElseThrow( + () -> + new IllegalArgumentException( + String.format("Unknown user email %s", userEmail))); + checkArgument( + registrarContact.verifyRegistryLockPassword(postInput.password), + "Incorrect registry lock password for contact"); } /** Value class that represents the expected input body from the UI request. */ @@ -211,7 +211,6 @@ public class RegistryLockPostAction implements Runnable, JsonActionRunner.JsonAc private String clientId; private String fullyQualifiedDomainName; private Boolean isLock; - private String pocId; private String password; } } diff --git a/core/src/test/java/google/registry/ui/server/registrar/RegistryLockPostActionTest.java b/core/src/test/java/google/registry/ui/server/registrar/RegistryLockPostActionTest.java index 3bfc9514c..c0db4a95b 100644 --- a/core/src/test/java/google/registry/ui/server/registrar/RegistryLockPostActionTest.java +++ b/core/src/test/java/google/registry/ui/server/registrar/RegistryLockPostActionTest.java @@ -132,6 +132,7 @@ public final class RegistryLockPostActionTest { createAction( AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, true))); Map response = action.handleJsonRequest(unlockRequest()); + // we should still email the admin user's email address assertSuccess(response, "unlock", "johndoe@theregistrar.com"); } @@ -171,7 +172,7 @@ public final class RegistryLockPostActionTest { @Test public void testSuccess_adminUser() throws Exception { - // Admin user should be able to lock/unlock regardless + // Admin user should be able to lock/unlock regardless -- and we use the admin user's email action = createAction( AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, true))); @@ -179,6 +180,20 @@ public final class RegistryLockPostActionTest { assertSuccess(response, "lock", "johndoe@theregistrar.com"); } + @Test + public void testSuccess_adminUser_doesNotRequirePassword() throws Exception { + action = + createAction( + AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, true))); + Map response = + action.handleJsonRequest( + ImmutableMap.of( + "clientId", "TheRegistrar", + "fullyQualifiedDomainName", "example.tld", + "isLock", true)); + assertSuccess(response, "lock", "johndoe@theregistrar.com"); + } + @Test public void testFailure_noInput() { Map response = action.handleJsonRequest(null); @@ -231,20 +246,21 @@ public final class RegistryLockPostActionTest { ImmutableMap.of( "clientId", "TheRegistrar", "fullyQualifiedDomainName", "example.tld", - "isLock", true, - "pocId", "Marla.Singer@crr.com")); + "isLock", true)); assertFailureWithMessage(response, "Missing key for password"); } @Test public void testFailure_notEnabledForRegistrarContact() { + action = + createAction( + AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, false))); Map response = action.handleJsonRequest( ImmutableMap.of( "clientId", "TheRegistrar", "fullyQualifiedDomainName", "example.tld", "isLock", true, - "pocId", "johndoe@theregistrar.com", "password", "hi")); assertFailureWithMessage(response, "Incorrect registry lock password for contact"); } @@ -257,7 +273,6 @@ public final class RegistryLockPostActionTest { "clientId", "TheRegistrar", "fullyQualifiedDomainName", "example.tld", "isLock", true, - "pocId", "Marla.Singer@crr.com", "password", "badPassword")); assertFailureWithMessage(response, "Incorrect registry lock password for contact"); } @@ -270,36 +285,10 @@ public final class RegistryLockPostActionTest { "clientId", "TheRegistrar", "fullyQualifiedDomainName", "bad.tld", "isLock", true, - "pocId", "Marla.Singer@crr.com", "password", "hi")); assertFailureWithMessage(response, "Unknown domain bad.tld"); } - @Test - public void testFailure_noPocId() { - Map response = - action.handleJsonRequest( - ImmutableMap.of( - "clientId", "TheRegistrar", - "fullyQualifiedDomainName", "bad.tld", - "isLock", true, - "password", "hi")); - assertFailureWithMessage(response, "Missing key for pocId"); - } - - @Test - public void testFailure_invalidPocId() { - Map response = - action.handleJsonRequest( - ImmutableMap.of( - "clientId", "TheRegistrar", - "fullyQualifiedDomainName", "bad.tld", - "isLock", true, - "pocId", "someotherpoc@crr.com", - "password", "hi")); - assertFailureWithMessage(response, "Unknown registrar POC ID someotherpoc@crr.com"); - } - @Test public void testSuccess_previousLockUnlocked() throws Exception { RegistryLockDao.save( @@ -357,7 +346,6 @@ public final class RegistryLockPostActionTest { "isLock", lock, "clientId", "TheRegistrar", "fullyQualifiedDomainName", "example.tld", - "pocId", "Marla.Singer@crr.com", "password", "hi"); }