mirror of
https://github.com/google/nomulus.git
synced 2025-07-23 19:20:44 +02:00
Add handler for Console API requests and XSRF token creation and verification (#2211)
This commit is contained in:
parent
779d0c9d37
commit
69ea87be31
11 changed files with 266 additions and 37 deletions
|
@ -15,6 +15,7 @@
|
||||||
package google.registry.request;
|
package google.registry.request;
|
||||||
|
|
||||||
import com.google.common.net.MediaType;
|
import com.google.common.net.MediaType;
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
|
@ -51,4 +52,11 @@ public interface Response {
|
||||||
* @see HttpServletResponse#setDateHeader(String, long)
|
* @see HttpServletResponse#setDateHeader(String, long)
|
||||||
*/
|
*/
|
||||||
void setDateHeader(String header, DateTime timestamp);
|
void setDateHeader(String header, DateTime timestamp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a cookie to the response
|
||||||
|
*
|
||||||
|
* @see HttpServletResponse#addCookie(Cookie)
|
||||||
|
*/
|
||||||
|
void addCookie(Cookie cookie);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ package google.registry.request;
|
||||||
import com.google.common.net.MediaType;
|
import com.google.common.net.MediaType;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
|
@ -58,4 +59,9 @@ public final class ResponseImpl implements Response {
|
||||||
public void setDateHeader(String header, DateTime timestamp) {
|
public void setDateHeader(String header, DateTime timestamp) {
|
||||||
rsp.setDateHeader(header, timestamp.getMillis());
|
rsp.setDateHeader(header, timestamp.getMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addCookie(Cookie cookie) {
|
||||||
|
rsp.addCookie(cookie);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ import org.joda.time.Duration;
|
||||||
/** Helper class for generating and validate XSRF tokens. */
|
/** Helper class for generating and validate XSRF tokens. */
|
||||||
public final class XsrfTokenManager {
|
public final class XsrfTokenManager {
|
||||||
|
|
||||||
/** HTTP header used for transmitting XSRF tokens. */
|
/** HTTP header or cookie name used for transmitting XSRF tokens. */
|
||||||
public static final String X_CSRF_TOKEN = "X-CSRF-Token";
|
public static final String X_CSRF_TOKEN = "X-CSRF-Token";
|
||||||
|
|
||||||
/** POST parameter used for transmitting XSRF tokens. */
|
/** POST parameter used for transmitting XSRF tokens. */
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
// 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.ui.server.console;
|
||||||
|
|
||||||
|
import static google.registry.request.Action.Method.GET;
|
||||||
|
|
||||||
|
import com.google.api.client.http.HttpStatusCodes;
|
||||||
|
import google.registry.model.console.User;
|
||||||
|
import google.registry.security.XsrfTokenManager;
|
||||||
|
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Optional;
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
|
|
||||||
|
/** Base class for handling Console API requests */
|
||||||
|
public abstract class ConsoleApiAction implements Runnable {
|
||||||
|
protected ConsoleApiParams consoleApiParams;
|
||||||
|
|
||||||
|
public ConsoleApiAction(ConsoleApiParams consoleApiParams) {
|
||||||
|
this.consoleApiParams = consoleApiParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void run() {
|
||||||
|
// Shouldn't be even possible because of Auth annotations on the various implementing classes
|
||||||
|
if (!consoleApiParams.authResult().userAuthInfo().get().consoleUser().isPresent()) {
|
||||||
|
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
User user = consoleApiParams.authResult().userAuthInfo().get().consoleUser().get();
|
||||||
|
if (consoleApiParams.request().getMethod().equals(GET.toString())) {
|
||||||
|
getHandler(user);
|
||||||
|
} else {
|
||||||
|
if (verifyXSRF()) {
|
||||||
|
postHandler(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void postHandler(User user) {
|
||||||
|
throw new UnsupportedOperationException("Console API POST handler not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void getHandler(User user) {
|
||||||
|
throw new UnsupportedOperationException("Console API GET handler not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean verifyXSRF() {
|
||||||
|
Optional<Cookie> maybeCookie =
|
||||||
|
Arrays.stream(consoleApiParams.request().getCookies())
|
||||||
|
.filter(c -> XsrfTokenManager.X_CSRF_TOKEN.equals(c.getName()))
|
||||||
|
.findFirst();
|
||||||
|
if (!maybeCookie.isPresent()
|
||||||
|
|| !consoleApiParams.xsrfTokenManager().validateToken(maybeCookie.get().getValue())) {
|
||||||
|
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,12 +21,10 @@ import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.config.RegistryConfig.Config;
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.model.console.User;
|
import google.registry.model.console.User;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.Response;
|
|
||||||
import google.registry.request.auth.Auth;
|
import google.registry.request.auth.Auth;
|
||||||
import google.registry.request.auth.AuthResult;
|
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||||
import google.registry.request.auth.UserAuthInfo;
|
|
||||||
import google.registry.ui.server.registrar.JsonGetAction;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
@Action(
|
@Action(
|
||||||
|
@ -34,12 +32,10 @@ import org.json.JSONObject;
|
||||||
path = ConsoleUserDataAction.PATH,
|
path = ConsoleUserDataAction.PATH,
|
||||||
method = {GET},
|
method = {GET},
|
||||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
||||||
public class ConsoleUserDataAction implements JsonGetAction {
|
public class ConsoleUserDataAction extends ConsoleApiAction {
|
||||||
|
|
||||||
public static final String PATH = "/console-api/userdata";
|
public static final String PATH = "/console-api/userdata";
|
||||||
|
|
||||||
private final AuthResult authResult;
|
|
||||||
private final Response response;
|
|
||||||
private final String productName;
|
private final String productName;
|
||||||
private final String supportPhoneNumber;
|
private final String supportPhoneNumber;
|
||||||
private final String supportEmail;
|
private final String supportEmail;
|
||||||
|
@ -47,14 +43,12 @@ public class ConsoleUserDataAction implements JsonGetAction {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ConsoleUserDataAction(
|
public ConsoleUserDataAction(
|
||||||
AuthResult authResult,
|
ConsoleApiParams consoleApiParams,
|
||||||
Response response,
|
|
||||||
@Config("productName") String productName,
|
@Config("productName") String productName,
|
||||||
@Config("supportEmail") String supportEmail,
|
@Config("supportEmail") String supportEmail,
|
||||||
@Config("supportPhoneNumber") String supportPhoneNumber,
|
@Config("supportPhoneNumber") String supportPhoneNumber,
|
||||||
@Config("technicalDocsUrl") String technicalDocsUrl) {
|
@Config("technicalDocsUrl") String technicalDocsUrl) {
|
||||||
this.response = response;
|
super(consoleApiParams);
|
||||||
this.authResult = authResult;
|
|
||||||
this.productName = productName;
|
this.productName = productName;
|
||||||
this.supportEmail = supportEmail;
|
this.supportEmail = supportEmail;
|
||||||
this.supportPhoneNumber = supportPhoneNumber;
|
this.supportPhoneNumber = supportPhoneNumber;
|
||||||
|
@ -62,13 +56,15 @@ public class ConsoleUserDataAction implements JsonGetAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
protected void getHandler(User user) {
|
||||||
UserAuthInfo authInfo = authResult.userAuthInfo().get();
|
// As this is a first GET request we use it as an opportunity to set a XSRF cookie
|
||||||
if (!authInfo.consoleUser().isPresent()) {
|
// for angular to read - https://angular.io/guide/http-security-xsrf-protection
|
||||||
response.setStatus(HttpStatusCodes.STATUS_CODE_UNAUTHORIZED);
|
Cookie xsrfCookie =
|
||||||
return;
|
new Cookie(
|
||||||
}
|
consoleApiParams.xsrfTokenManager().X_CSRF_TOKEN,
|
||||||
User user = authInfo.consoleUser().get();
|
consoleApiParams.xsrfTokenManager().generateToken(user.getEmailAddress()));
|
||||||
|
xsrfCookie.setSecure(true);
|
||||||
|
consoleApiParams.response().addCookie(xsrfCookie);
|
||||||
|
|
||||||
JSONObject json =
|
JSONObject json =
|
||||||
new JSONObject(
|
new JSONObject(
|
||||||
|
@ -90,7 +86,7 @@ public class ConsoleUserDataAction implements JsonGetAction {
|
||||||
// Is used by UI to construct a link to registry resources
|
// Is used by UI to construct a link to registry resources
|
||||||
"technicalDocsUrl", technicalDocsUrl));
|
"technicalDocsUrl", technicalDocsUrl));
|
||||||
|
|
||||||
response.setPayload(json.toString());
|
consoleApiParams.response().setPayload(json.toString());
|
||||||
response.setStatus(HttpStatusCodes.STATUS_CODE_OK);
|
consoleApiParams.response().setStatus(HttpStatusCodes.STATUS_CODE_OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
// 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.ui.server.registrar;
|
||||||
|
|
||||||
|
import com.google.auto.value.AutoValue;
|
||||||
|
import google.registry.request.Response;
|
||||||
|
import google.registry.request.auth.AuthResult;
|
||||||
|
import google.registry.security.XsrfTokenManager;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
/** Groups necessary dependencies for Console API actions * */
|
||||||
|
@AutoValue
|
||||||
|
public abstract class ConsoleApiParams {
|
||||||
|
public static ConsoleApiParams create(
|
||||||
|
HttpServletRequest request,
|
||||||
|
Response response,
|
||||||
|
AuthResult authResult,
|
||||||
|
XsrfTokenManager xsrfTokenManager) {
|
||||||
|
return new AutoValue_ConsoleApiParams(request, response, authResult, xsrfTokenManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract HttpServletRequest request();
|
||||||
|
|
||||||
|
public abstract Response response();
|
||||||
|
|
||||||
|
public abstract AuthResult authResult();
|
||||||
|
|
||||||
|
public abstract XsrfTokenManager xsrfTokenManager();
|
||||||
|
}
|
|
@ -28,6 +28,10 @@ import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.model.registrar.RegistrarPoc;
|
import google.registry.model.registrar.RegistrarPoc;
|
||||||
import google.registry.request.OptionalJsonPayload;
|
import google.registry.request.OptionalJsonPayload;
|
||||||
import google.registry.request.Parameter;
|
import google.registry.request.Parameter;
|
||||||
|
import google.registry.request.RequestScope;
|
||||||
|
import google.registry.request.Response;
|
||||||
|
import google.registry.request.auth.AuthResult;
|
||||||
|
import google.registry.security.XsrfTokenManager;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -35,9 +39,18 @@ import org.joda.time.DateTime;
|
||||||
/** Dagger module for the Registrar Console parameters. */
|
/** Dagger module for the Registrar Console parameters. */
|
||||||
@Module
|
@Module
|
||||||
public final class RegistrarConsoleModule {
|
public final class RegistrarConsoleModule {
|
||||||
|
|
||||||
static final String PARAM_CLIENT_ID = "clientId";
|
static final String PARAM_CLIENT_ID = "clientId";
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@RequestScope
|
||||||
|
ConsoleApiParams provideConsoleApiParams(
|
||||||
|
HttpServletRequest request,
|
||||||
|
Response response,
|
||||||
|
AuthResult authResult,
|
||||||
|
XsrfTokenManager xsrfTokenManager) {
|
||||||
|
return ConsoleApiParams.create(request, response, authResult, xsrfTokenManager);
|
||||||
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Parameter(PARAM_CLIENT_ID)
|
@Parameter(PARAM_CLIENT_ID)
|
||||||
static Optional<String> provideOptionalClientId(HttpServletRequest req) {
|
static Optional<String> provideOptionalClientId(HttpServletRequest req) {
|
||||||
|
|
|
@ -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.base.Throwables;
|
||||||
import com.google.common.net.MediaType;
|
import com.google.common.net.MediaType;
|
||||||
import google.registry.request.Response;
|
import google.registry.request.Response;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/** Fake implementation of {@link Response} for testing. */
|
/** Fake implementation of {@link Response} for testing. */
|
||||||
|
@ -36,6 +38,8 @@ public final class FakeResponse implements Response {
|
||||||
private boolean wasMutuallyExclusiveResponseSet;
|
private boolean wasMutuallyExclusiveResponseSet;
|
||||||
private String lastResponseStackTrace;
|
private String lastResponseStackTrace;
|
||||||
|
|
||||||
|
private ArrayList<Cookie> cookies = new ArrayList<>();
|
||||||
|
|
||||||
public int getStatus() {
|
public int getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +87,15 @@ public final class FakeResponse implements Response {
|
||||||
headers.put(checkNotNull(header), checkNotNull(timestamp));
|
headers.put(checkNotNull(header), checkNotNull(timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addCookie(Cookie cookie) {
|
||||||
|
cookies.add(cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Cookie> getCookies() {
|
||||||
|
return cookies;
|
||||||
|
}
|
||||||
|
|
||||||
private void checkResponsePerformedOnce() {
|
private void checkResponsePerformedOnce() {
|
||||||
checkState(
|
checkState(
|
||||||
!wasMutuallyExclusiveResponseSet,
|
!wasMutuallyExclusiveResponseSet,
|
||||||
|
|
|
@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assertWithMessage;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import google.registry.request.Action;
|
import google.registry.request.Action;
|
||||||
import google.registry.request.JsonActionRunner;
|
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.HtmlAction;
|
||||||
import google.registry.ui.server.registrar.JsonGetAction;
|
import google.registry.ui.server.registrar.JsonGetAction;
|
||||||
import io.github.classgraph.ClassGraph;
|
import io.github.classgraph.ClassGraph;
|
||||||
|
@ -34,6 +35,7 @@ final class ActionMembershipTest {
|
||||||
// 1. Extending HtmlAction to signal that we are serving an HTML page
|
// 1. Extending HtmlAction to signal that we are serving an HTML page
|
||||||
// 2. Extending JsonAction to show that we are serving JSON POST requests
|
// 2. Extending JsonAction to show that we are serving JSON POST requests
|
||||||
// 3. Extending JsonGetAction to serve JSON GET requests
|
// 3. Extending JsonGetAction to serve JSON GET requests
|
||||||
|
// 4. Extending ConsoleApiAction to serve JSON requests
|
||||||
ImmutableSet.Builder<String> failingClasses = new ImmutableSet.Builder<>();
|
ImmutableSet.Builder<String> failingClasses = new ImmutableSet.Builder<>();
|
||||||
try (ScanResult scanResult =
|
try (ScanResult scanResult =
|
||||||
new ClassGraph().enableAnnotationInfo().whitelistPackages("google.registry.ui").scan()) {
|
new ClassGraph().enableAnnotationInfo().whitelistPackages("google.registry.ui").scan()) {
|
||||||
|
@ -41,7 +43,8 @@ final class ActionMembershipTest {
|
||||||
.getClassesWithAnnotation(Action.class.getName())
|
.getClassesWithAnnotation(Action.class.getName())
|
||||||
.forEach(
|
.forEach(
|
||||||
classInfo -> {
|
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(JsonActionRunner.JsonAction.class.getName())
|
||||||
&& !classInfo.implementsInterface(JsonGetAction.class.getName())) {
|
&& !classInfo.implementsInterface(JsonGetAction.class.getName())) {
|
||||||
failingClasses.add(classInfo.getName());
|
failingClasses.add(classInfo.getName());
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
|
|
||||||
package google.registry.ui.server.console;
|
package google.registry.ui.server.console;
|
||||||
|
|
||||||
|
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import com.google.api.client.http.HttpStatusCodes;
|
import com.google.api.client.http.HttpStatusCodes;
|
||||||
import com.google.gson.Gson;
|
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.User;
|
||||||
import google.registry.model.console.UserRoles;
|
import google.registry.model.console.UserRoles;
|
||||||
import google.registry.persistence.transaction.JpaTestExtensions;
|
import google.registry.persistence.transaction.JpaTestExtensions;
|
||||||
|
import google.registry.request.Action;
|
||||||
import google.registry.request.RequestModule;
|
import google.registry.request.RequestModule;
|
||||||
import google.registry.request.auth.AuthResult;
|
import google.registry.request.auth.AuthResult;
|
||||||
import google.registry.request.auth.UserAuthInfo;
|
import google.registry.request.auth.UserAuthInfo;
|
||||||
|
import google.registry.testing.FakeConsoleApiParams;
|
||||||
import google.registry.testing.FakeResponse;
|
import google.registry.testing.FakeResponse;
|
||||||
|
import google.registry.ui.server.registrar.ConsoleApiParams;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import javax.servlet.http.Cookie;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.RegisterExtension;
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
@ -35,12 +43,31 @@ import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
class ConsoleUserDataActionTest {
|
class ConsoleUserDataActionTest {
|
||||||
|
|
||||||
private static final Gson GSON = RequestModule.provideGson();
|
private static final Gson GSON = RequestModule.provideGson();
|
||||||
private FakeResponse response = new FakeResponse();
|
|
||||||
|
private ConsoleApiParams consoleApiParams;
|
||||||
|
|
||||||
@RegisterExtension
|
@RegisterExtension
|
||||||
final JpaTestExtensions.JpaIntegrationTestExtension jpa =
|
final JpaTestExtensions.JpaIntegrationTestExtension jpa =
|
||||||
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
|
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
|
@Test
|
||||||
void testSuccess_getContactInfo() throws IOException {
|
void testSuccess_getContactInfo() throws IOException {
|
||||||
User user =
|
User user =
|
||||||
|
@ -49,10 +76,15 @@ class ConsoleUserDataActionTest {
|
||||||
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build())
|
.setUserRoles(new UserRoles.Builder().setGlobalRole(GlobalRole.FTE).build())
|
||||||
.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();
|
action.run();
|
||||||
assertThat(response.getStatus()).isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
|
assertThat(((FakeResponse) consoleApiParams.response()).getStatus())
|
||||||
Map jsonObject = GSON.fromJson(response.getPayload(), Map.class);
|
.isEqualTo(HttpStatusCodes.STATUS_CODE_OK);
|
||||||
|
Map jsonObject =
|
||||||
|
GSON.fromJson(((FakeResponse) consoleApiParams.response()).getPayload(), Map.class);
|
||||||
assertThat(jsonObject)
|
assertThat(jsonObject)
|
||||||
.containsExactly(
|
.containsExactly(
|
||||||
"isAdmin",
|
"isAdmin",
|
||||||
|
@ -71,19 +103,18 @@ class ConsoleUserDataActionTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testFailure_notAConsoleUser() throws IOException {
|
void testFailure_notAConsoleUser() throws IOException {
|
||||||
ConsoleUserDataAction action =
|
ConsoleUserDataAction action = createAction(Optional.empty(), Action.Method.GET);
|
||||||
createAction(
|
|
||||||
AuthResult.createUser(
|
|
||||||
UserAuthInfo.create(
|
|
||||||
new com.google.appengine.api.users.User(
|
|
||||||
"JohnDoe@theregistrar.com", "theregistrar.com"),
|
|
||||||
false)));
|
|
||||||
action.run();
|
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(
|
return new ConsoleUserDataAction(
|
||||||
authResult, response, "Nomulus", "support@example.com", "+1 (212) 867 5309", "test");
|
consoleApiParams, "Nomulus", "support@example.com", "+1 (212) 867 5309", "test");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue