Clean up RegistryLockPostAction (#470)

* Clean up RegistryLockPostAction

* pocId -> userEmail when appropriate

* Merge remote-tracking branch 'origin/master' into lockPostImprovements

* Remove pocId
This commit is contained in:
gbrodman 2020-02-11 08:43:44 -07:00 committed by GitHub
parent 79b46001b6
commit a076b746a3
2 changed files with 48 additions and 61 deletions

View file

@ -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<InternetAddress> 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;
}
}

View file

@ -132,6 +132,7 @@ public final class RegistryLockPostActionTest {
createAction(
AuthResult.create(AuthLevel.USER, UserAuthInfo.create(userWithoutPermission, true)));
Map<String, ?> 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<String, ?> response =
action.handleJsonRequest(
ImmutableMap.of(
"clientId", "TheRegistrar",
"fullyQualifiedDomainName", "example.tld",
"isLock", true));
assertSuccess(response, "lock", "johndoe@theregistrar.com");
}
@Test
public void testFailure_noInput() {
Map<String, ?> 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<String, ?> 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<String, ?> 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<String, ?> 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");
}