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:
@@ -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) {}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user