mirror of
https://github.com/google/nomulus
synced 2026-04-22 01:00:44 +00:00
Add handler for Console API requests and XSRF token creation and verification (#2211)
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.testing;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import google.registry.request.auth.AuthResult;
|
||||
import google.registry.request.auth.UserAuthInfo;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||
import java.util.Optional;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
public final class FakeConsoleApiParams {
|
||||
|
||||
public static ConsoleApiParams get(Optional<AuthResult> maybeAuthResult) {
|
||||
AuthResult authResult =
|
||||
maybeAuthResult.orElseGet(
|
||||
() ->
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
new com.google.appengine.api.users.User(
|
||||
"JohnDoe@theregistrar.com", "theregistrar.com"),
|
||||
false)));
|
||||
return ConsoleApiParams.create(
|
||||
mock(HttpServletRequest.class),
|
||||
new FakeResponse(),
|
||||
authResult,
|
||||
new XsrfTokenManager(
|
||||
new FakeClock(DateTime.parse("2020-02-02T01:23:45Z")), mock(UserService.class)));
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,10 @@ import static java.util.Collections.unmodifiableMap;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.request.Response;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.Cookie;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Fake implementation of {@link Response} for testing. */
|
||||
@@ -36,6 +38,8 @@ public final class FakeResponse implements Response {
|
||||
private boolean wasMutuallyExclusiveResponseSet;
|
||||
private String lastResponseStackTrace;
|
||||
|
||||
private ArrayList<Cookie> cookies = new ArrayList<>();
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
@@ -83,6 +87,15 @@ public final class FakeResponse implements Response {
|
||||
headers.put(checkNotNull(header), checkNotNull(timestamp));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCookie(Cookie cookie) {
|
||||
cookies.add(cookie);
|
||||
}
|
||||
|
||||
public ArrayList<Cookie> getCookies() {
|
||||
return cookies;
|
||||
}
|
||||
|
||||
private void checkResponsePerformedOnce() {
|
||||
checkState(
|
||||
!wasMutuallyExclusiveResponseSet,
|
||||
|
||||
@@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.JsonActionRunner;
|
||||
import google.registry.ui.server.console.ConsoleApiAction;
|
||||
import google.registry.ui.server.registrar.HtmlAction;
|
||||
import google.registry.ui.server.registrar.JsonGetAction;
|
||||
import io.github.classgraph.ClassGraph;
|
||||
@@ -34,6 +35,7 @@ final class ActionMembershipTest {
|
||||
// 1. Extending HtmlAction to signal that we are serving an HTML page
|
||||
// 2. Extending JsonAction to show that we are serving JSON POST requests
|
||||
// 3. Extending JsonGetAction to serve JSON GET requests
|
||||
// 4. Extending ConsoleApiAction to serve JSON requests
|
||||
ImmutableSet.Builder<String> failingClasses = new ImmutableSet.Builder<>();
|
||||
try (ScanResult scanResult =
|
||||
new ClassGraph().enableAnnotationInfo().whitelistPackages("google.registry.ui").scan()) {
|
||||
@@ -41,7 +43,8 @@ final class ActionMembershipTest {
|
||||
.getClassesWithAnnotation(Action.class.getName())
|
||||
.forEach(
|
||||
classInfo -> {
|
||||
if (!classInfo.extendsSuperclass(HtmlAction.class.getName())
|
||||
if (!classInfo.extendsSuperclass(ConsoleApiAction.class.getName())
|
||||
&& !classInfo.extendsSuperclass(HtmlAction.class.getName())
|
||||
&& !classInfo.implementsInterface(JsonActionRunner.JsonAction.class.getName())
|
||||
&& !classInfo.implementsInterface(JsonGetAction.class.getName())) {
|
||||
failingClasses.add(classInfo.getName());
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
package google.registry.ui.server.console;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.google.api.client.http.HttpStatusCodes;
|
||||
import com.google.gson.Gson;
|
||||
@@ -22,12 +24,18 @@ import google.registry.model.console.GlobalRole;
|
||||
import google.registry.model.console.User;
|
||||
import google.registry.model.console.UserRoles;
|
||||
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.UserAuthInfo;
|
||||
import google.registry.testing.FakeConsoleApiParams;
|
||||
import google.registry.testing.FakeResponse;
|
||||
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import javax.servlet.http.Cookie;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
|
||||
@@ -35,12 +43,31 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||
class ConsoleUserDataActionTest {
|
||||
|
||||
private static final Gson GSON = RequestModule.provideGson();
|
||||
private FakeResponse response = new FakeResponse();
|
||||
|
||||
private ConsoleApiParams consoleApiParams;
|
||||
|
||||
@RegisterExtension
|
||||
final JpaTestExtensions.JpaIntegrationTestExtension jpa =
|
||||
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
|
||||
|
||||
@Test
|
||||
void testSuccess_hasXSRFCookie() throws IOException {
|
||||
User user =
|
||||
new User.Builder()
|
||||
.setEmailAddress("email@email.com")
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build())
|
||||
.build();
|
||||
|
||||
AuthResult authResult = AuthResult.createUser(UserAuthInfo.create(user));
|
||||
ConsoleUserDataAction action =
|
||||
createAction(
|
||||
Optional.of(FakeConsoleApiParams.get(Optional.of(authResult))), Action.Method.GET);
|
||||
action.run();
|
||||
ArrayList<Cookie> cookies = ((FakeResponse) consoleApiParams.response()).getCookies();
|
||||
assertThat(cookies.stream().map(cookie -> cookie.getName()).collect(toImmutableList()))
|
||||
.containsExactly("X-CSRF-Token");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccess_getContactInfo() throws IOException {
|
||||
User user =
|
||||
@@ -49,10 +76,15 @@ class ConsoleUserDataActionTest {
|
||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build())
|
||||
.build();
|
||||
|
||||
ConsoleUserDataAction action = createAction(AuthResult.createUser(UserAuthInfo.create(user)));
|
||||
AuthResult authResult = AuthResult.createUser(UserAuthInfo.create(user));
|
||||
ConsoleUserDataAction action =
|
||||
createAction(
|
||||
Optional.of(FakeConsoleApiParams.get(Optional.of(authResult))), Action.Method.GET);
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
|
||||
Map jsonObject = GSON.fromJson(response.getPayload(), Map.class);
|
||||
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
|
||||
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
|
||||
Map jsonObject =
|
||||
GSON.fromJson(((FakeResponse) consoleApiParams.response()).getPayload(), Map.class);
|
||||
assertThat(jsonObject)
|
||||
.containsExactly(
|
||||
"isAdmin",
|
||||
@@ -71,19 +103,18 @@ class ConsoleUserDataActionTest {
|
||||
|
||||
@Test
|
||||
void testFailure_notAConsoleUser() throws IOException {
|
||||
ConsoleUserDataAction action =
|
||||
createAction(
|
||||
AuthResult.createUser(
|
||||
UserAuthInfo.create(
|
||||
new com.google.appengine.api.users.User(
|
||||
"JohnDoe@theregistrar.com", "theregistrar.com"),
|
||||
false)));
|
||||
ConsoleUserDataAction action = createAction(Optional.empty(), Action.Method.GET);
|
||||
action.run();
|
||||
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
|
||||
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
|
||||
.isEqualTo(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
private ConsoleUserDataAction createAction(AuthResult authResult) throws IOException {
|
||||
private ConsoleUserDataAction createAction(
|
||||
Optional<ConsoleApiParams> maybeConsoleApiParams, Action.Method method) throws IOException {
|
||||
consoleApiParams =
|
||||
maybeConsoleApiParams.orElseGet(() -> FakeConsoleApiParams.get(Optional.empty()));
|
||||
when(consoleApiParams.request().getMethod()).thenReturn(method.toString());
|
||||
return new ConsoleUserDataAction(
|
||||
authResult, response, "Nomulus", "support@example.com", "+1 (212) 867 5309", "test");
|
||||
consoleApiParams, "Nomulus", "support@example.com", "+1 (212) 867 5309", "test");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user