1
0
mirror of https://github.com/google/nomulus synced 2026-01-07 05:56:49 +00:00

Fix console EPP password form, minor adjustments (#2445)

This commit is contained in:
Pavlo Tkach
2024-05-17 14:44:44 -04:00
committed by GitHub
parent 43000a5f80
commit 05b43965d1
9 changed files with 179 additions and 97 deletions

View File

@@ -17,20 +17,23 @@ package google.registry.ui.server.console;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.request.Action.Method.POST;
import static google.registry.request.RequestParameters.extractRequiredParameter;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.base.Strings;
import com.google.gson.annotations.Expose;
import google.registry.flows.EppException.AuthenticationErrorException;
import google.registry.flows.PasswordOnlyTransportCredentials;
import google.registry.groups.GmailClient;
import google.registry.model.console.User;
import google.registry.model.registrar.Registrar;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
import google.registry.ui.server.registrar.ConsoleApiParams;
import google.registry.util.EmailMessage;
import java.util.Optional;
import javax.inject.Inject;
import javax.mail.internet.InternetAddress;
@@ -40,7 +43,6 @@ import javax.mail.internet.InternetAddress;
method = {POST},
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
public class ConsoleEppPasswordAction extends ConsoleApiAction {
protected static final String EMAIL_SUBJ = "EPP password update confirmation";
protected static final String EMAIL_BODY =
"Dear %s,\n" + "This is to confirm that your account password has been changed.";
@@ -52,35 +54,50 @@ public class ConsoleEppPasswordAction extends ConsoleApiAction {
private final AuthenticatedRegistrarAccessor registrarAccessor;
private final GmailClient gmailClient;
private final Optional<EppPasswordData> eppPasswordChangeRequest;
@Inject
public ConsoleEppPasswordAction(
ConsoleApiParams consoleApiParams,
AuthenticatedRegistrarAccessor registrarAccessor,
GmailClient gmailClient) {
GmailClient gmailClient,
@Parameter("eppPasswordChangeRequest") Optional<EppPasswordData> eppPasswordChangeRequest) {
super(consoleApiParams);
this.registrarAccessor = registrarAccessor;
this.gmailClient = gmailClient;
this.eppPasswordChangeRequest = eppPasswordChangeRequest;
}
private void confirmParamsAvailable() {
checkArgument(this.eppPasswordChangeRequest.isPresent(), "Epp Password update body is invalid");
var eppRequestBody = this.eppPasswordChangeRequest.get();
var errorMsg = "Missing param(s): %s";
checkArgument(!Strings.isNullOrEmpty(eppRequestBody.registrarId()), errorMsg, "registrarId");
checkArgument(!Strings.isNullOrEmpty(eppRequestBody.oldPassword()), errorMsg, "oldPassword");
checkArgument(!Strings.isNullOrEmpty(eppRequestBody.newPassword()), errorMsg, "newPassword");
checkArgument(
!Strings.isNullOrEmpty(eppRequestBody.newPasswordRepeat()), errorMsg, "newPasswordRepeat");
}
@Override
protected void postHandler(User user) {
String registrarId = extractRequiredParameter(consoleApiParams.request(), "registrarId");
String oldPassword = extractRequiredParameter(consoleApiParams.request(), "oldPassword");
String newPassword = extractRequiredParameter(consoleApiParams.request(), "newPassword");
String newPasswordRepeat =
extractRequiredParameter(consoleApiParams.request(), "newPasswordRepeat");
checkArgument(newPassword.equals(newPasswordRepeat), "New password fields don't match");
this.confirmParamsAvailable();
var eppRequestBody = this.eppPasswordChangeRequest.get();
checkArgument(
eppRequestBody.newPassword().equals(eppRequestBody.newPasswordRepeat()),
"New password fields don't match");
Registrar registrar;
try {
registrar = registrarAccessor.getRegistrar(registrarId);
registrar = registrarAccessor.getRegistrar(eppRequestBody.registrarId());
} catch (RegistrarAccessDeniedException e) {
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_NOT_FOUND);
return;
}
try {
credentials.validate(registrar, oldPassword);
credentials.validate(registrar, eppRequestBody.oldPassword());
} catch (AuthenticationErrorException e) {
setFailedResponse(e.getMessage(), HttpStatusCodes.STATUS_CODE_FORBIDDEN);
return;
@@ -88,7 +105,7 @@ public class ConsoleEppPasswordAction extends ConsoleApiAction {
tm().transact(
() -> {
tm().put(registrar.asBuilder().setPassword(newPassword).build());
tm().put(registrar.asBuilder().setPassword(eppRequestBody.newPassword()).build());
this.gmailClient.sendEmail(
EmailMessage.create(
EMAIL_SUBJ,
@@ -98,4 +115,10 @@ public class ConsoleEppPasswordAction extends ConsoleApiAction {
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
}
public record EppPasswordData(
@Expose String registrarId,
@Expose String oldPassword,
@Expose String newPassword,
@Expose String newPasswordRepeat) {}
}

View File

@@ -32,6 +32,7 @@ import google.registry.request.RequestScope;
import google.registry.request.Response;
import google.registry.request.auth.AuthResult;
import google.registry.security.XsrfTokenManager;
import google.registry.ui.server.console.ConsoleEppPasswordAction.EppPasswordData;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Optional;
import org.joda.time.DateTime;
@@ -232,4 +233,11 @@ public final class RegistrarConsoleModule {
public static Optional<String> provideSearchTerm(HttpServletRequest req) {
return extractOptionalParameter(req, "searchTerm");
}
@Provides
@Parameter("eppPasswordChangeRequest")
public static Optional<EppPasswordData> provideEppPasswordChangeRequest(
Gson gson, @OptionalJsonPayload Optional<JsonElement> payload) {
return payload.map(s -> gson.fromJson(s, EppPasswordData.class));
}
}

View File

@@ -20,13 +20,13 @@ import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.persistNewRegistrar;
import static google.registry.testing.DatabaseHelper.persistResource;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.api.client.http.HttpStatusCodes;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSetMultimap;
import com.google.gson.Gson;
import google.registry.flows.PasswordOnlyTransportCredentials;
@@ -37,14 +37,20 @@ import google.registry.model.console.UserRoles;
import google.registry.model.registrar.Registrar;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.request.Action;
import google.registry.request.RequestModule;
import google.registry.request.auth.AuthResult;
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
import google.registry.request.auth.UserAuthInfo;
import google.registry.testing.FakeConsoleApiParams;
import google.registry.testing.FakeResponse;
import google.registry.tools.GsonUtils;
import google.registry.ui.server.console.ConsoleEppPasswordAction.EppPasswordData;
import google.registry.ui.server.registrar.ConsoleApiParams;
import google.registry.ui.server.registrar.RegistrarConsoleModule;
import google.registry.util.EmailMessage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Optional;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
@@ -54,6 +60,9 @@ import org.junit.jupiter.api.extension.RegisterExtension;
class ConsoleEppPasswordActionTest {
private static final Gson GSON = GsonUtils.provideGson();
private static String eppPostData =
"{\"registrarId\":\"%s\",\"oldPassword\":\"%s\",\"newPassword\":\"%s\",\"newPasswordRepeat\":\"%s\"}";
private ConsoleApiParams consoleApiParams;
protected PasswordOnlyTransportCredentials credentials = new PasswordOnlyTransportCredentials();
private FakeResponse response;
@@ -78,28 +87,19 @@ class ConsoleEppPasswordActionTest {
}
@Test
void testFailure_emptyParams() {
ConsoleEppPasswordAction action = createAction();
void testFailure_emptyParams() throws IOException {
ConsoleEppPasswordAction action = createAction("", "", "", "");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
assertThat(((FakeResponse) consoleApiParams.response()).getPayload())
.isEqualTo("Missing parameter: registrarId");
.isEqualTo("Missing param(s): registrarId");
}
@Test
void testFailure_passwordsDontMatch() {
ConsoleEppPasswordAction action = createAction();
setParams(
ImmutableMap.of(
"registrarId",
"registrarId",
"oldPassword",
"oldPassword",
"newPassword",
"newPassword",
"newPasswordRepeat",
"newPasswordRepeat"));
void testFailure_passwordsDontMatch() throws IOException {
ConsoleEppPasswordAction action =
createAction("registrarId", "oldPassword", "newPassword", "newPasswordRepeat");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_BAD_REQUEST);
@@ -108,18 +108,9 @@ class ConsoleEppPasswordActionTest {
}
@Test
void testFailure_existingPasswordIncorrect() {
ConsoleEppPasswordAction action = createAction();
setParams(
ImmutableMap.of(
"registrarId",
"registrarId",
"oldPassword",
"oldPassword",
"newPassword",
"randomPasword",
"newPasswordRepeat",
"randomPasword"));
void testFailure_existingPasswordIncorrect() throws IOException {
ConsoleEppPasswordAction action =
createAction("registrarId", "oldPassword", "randomPasword", "randomPasword");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_FORBIDDEN);
@@ -128,18 +119,9 @@ class ConsoleEppPasswordActionTest {
}
@Test
void testSuccess_sendsConfirmationEmail() throws AddressException {
ConsoleEppPasswordAction action = createAction();
setParams(
ImmutableMap.of(
"registrarId",
"registrarId",
"oldPassword",
"foobar",
"newPassword",
"randomPassword",
"newPasswordRepeat",
"randomPassword"));
void testSuccess_sendsConfirmationEmail() throws IOException, AddressException {
ConsoleEppPasswordAction action =
createAction("registrarId", "foobar", "randomPassword", "randomPassword");
action.run();
verify(gmailClient, times(1))
.sendEmail(
@@ -153,18 +135,9 @@ class ConsoleEppPasswordActionTest {
}
@Test
void testSuccess_passwordUpdated() {
ConsoleEppPasswordAction action = createAction();
setParams(
ImmutableMap.of(
"registrarId",
"registrarId",
"oldPassword",
"foobar",
"newPassword",
"randomPassword",
"newPasswordRepeat",
"randomPassword"));
void testSuccess_passwordUpdated() throws IOException {
ConsoleEppPasswordAction action =
createAction("registrarId", "foobar", "randomPassword", "randomPassword");
action.run();
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
@@ -174,16 +147,9 @@ class ConsoleEppPasswordActionTest {
});
}
private void setParams(ImmutableMap<String, String> params) {
params.entrySet().stream()
.forEach(
entry -> {
when(consoleApiParams.request().getParameter(entry.getKey()))
.thenReturn(entry.getValue());
});
}
private ConsoleEppPasswordAction createAction() {
private ConsoleEppPasswordAction createAction(
String registrarId, String oldPassword, String newPassword, String newPasswordRepeat)
throws IOException {
response = new FakeResponse();
User user =
new User.Builder()
@@ -197,8 +163,18 @@ class ConsoleEppPasswordActionTest {
AuthenticatedRegistrarAccessor.createForTesting(
ImmutableSetMultimap.of("registrarId", OWNER));
when(consoleApiParams.request().getMethod()).thenReturn(Action.Method.POST.toString());
doReturn(
new BufferedReader(
new StringReader(
String.format(
eppPostData, registrarId, oldPassword, newPassword, newPasswordRepeat))))
.when(consoleApiParams.request())
.getReader();
Optional<EppPasswordData> maybePasswordChangeRequest =
RegistrarConsoleModule.provideEppPasswordChangeRequest(
GSON, RequestModule.provideJsonBody(consoleApiParams.request(), GSON));
return new ConsoleEppPasswordAction(
consoleApiParams, authenticatedRegistrarAccessor, gmailClient);
consoleApiParams, authenticatedRegistrarAccessor, gmailClient, maybePasswordChangeRequest);
}
}