mirror of
https://github.com/google/nomulus.git
synced 2025-07-14 06:55:20 +02:00
Convert RegistrarServlet to RegistrarAction
Convert to an action and remove ResourceServlet, JsonTransportServlet and JsonTransportServlet, all of which exist only to support it. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=137519385
This commit is contained in:
parent
2e4273c4f4
commit
bbd20ec71d
24 changed files with 330 additions and 858 deletions
|
@ -17,6 +17,7 @@ package google.registry.config;
|
|||
import static google.registry.config.ConfigUtils.makeUrl;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
@ -325,6 +326,13 @@ public final class ConfigModule {
|
|||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Config("registrarChangesNotificationEmailAddresses")
|
||||
public static ImmutableList<String> provideRegistrarChangesNotificationEmailAddresses(
|
||||
RegistryConfig config) {
|
||||
return config.getRegistrarChangesNotificationEmailAddresses();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the publicly accessible domain name for the running Google Apps instance.
|
||||
*
|
||||
|
|
|
@ -163,7 +163,7 @@ public interface RegistryConfig {
|
|||
* Returns the email address(es) that notifications of registrar and/or registrar contact updates
|
||||
* should be sent to, or the empty list if updates should not be sent.
|
||||
*
|
||||
* @see google.registry.ui.server.registrar.RegistrarServlet
|
||||
* @see google.registry.ui.server.registrar.RegistrarAction
|
||||
*/
|
||||
public ImmutableList<String> getRegistrarChangesNotificationEmailAddresses();
|
||||
|
||||
|
|
|
@ -25,17 +25,6 @@
|
|||
<url-pattern>/registrar-xhr</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<display-name>Registrar Self-serve Settings</display-name>
|
||||
<servlet-name>registrar-settings</servlet-name>
|
||||
<servlet-class>google.registry.ui.server.registrar.RegistrarServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>registrar-settings</servlet-name>
|
||||
<url-pattern>/registrar-settings</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Registrar Console. -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>frontend-servlet</servlet-name>
|
||||
|
@ -54,6 +43,12 @@
|
|||
<url-pattern>/registrar-payment</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- Registrar Self-serve Settings. -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>frontend-servlet</servlet-name>
|
||||
<url-pattern>/registrar-settings</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<!-- HTTP WHOIS. -->
|
||||
<servlet-mapping>
|
||||
<servlet-name>frontend-servlet</servlet-name>
|
||||
|
|
|
@ -36,6 +36,7 @@ import google.registry.rdap.RdapNameserverSearchAction;
|
|||
import google.registry.request.RequestModule;
|
||||
import google.registry.request.RequestScope;
|
||||
import google.registry.ui.server.registrar.ConsoleUiAction;
|
||||
import google.registry.ui.server.registrar.RegistrarAction;
|
||||
import google.registry.ui.server.registrar.RegistrarPaymentAction;
|
||||
import google.registry.ui.server.registrar.RegistrarPaymentSetupAction;
|
||||
import google.registry.ui.server.registrar.RegistrarUserModule;
|
||||
|
@ -65,6 +66,7 @@ interface FrontendRequestComponent {
|
|||
RdapAutnumAction rdapAutnumAction();
|
||||
RegistrarPaymentAction registrarPaymentAction();
|
||||
RegistrarPaymentSetupAction registrarPaymentSetupAction();
|
||||
RegistrarAction registrarAction();
|
||||
RdapDomainAction rdapDomainAction();
|
||||
RdapDomainSearchAction rdapDomainSearchAction();
|
||||
RdapEntityAction rdapEntityAction();
|
||||
|
|
|
@ -35,9 +35,13 @@ public final class JsonActionRunner {
|
|||
Map<String, ?> handleJsonRequest(Map<String, ?> json);
|
||||
}
|
||||
|
||||
@Inject @JsonPayload Map<String, Object> payload;
|
||||
@Inject JsonResponse response;
|
||||
@Inject JsonActionRunner() {}
|
||||
@JsonPayload Map<String, Object> payload;
|
||||
JsonResponse response;
|
||||
|
||||
@Inject public JsonActionRunner(@JsonPayload Map<String, Object> payload, JsonResponse response) {
|
||||
this.payload = payload;
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
/** Delegates request to {@code action}. */
|
||||
public void run(JsonAction action) {
|
||||
|
|
|
@ -28,16 +28,3 @@ java_library(
|
|||
"//java/google/registry/util",
|
||||
],
|
||||
)
|
||||
|
||||
java_library(
|
||||
name = "servlets",
|
||||
srcs = glob(["*Servlet.java"]),
|
||||
deps = [
|
||||
":security",
|
||||
"//java/com/google/common/base",
|
||||
"//third_party/java/appengine:appengine-api",
|
||||
"//third_party/java/joda_time",
|
||||
"//third_party/java/servlet/servlet_api",
|
||||
"//java/google/registry/request",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
// Copyright 2016 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.security;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||
|
||||
import google.registry.request.HttpException;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Secure servlet that speaks JSON for both input and output.
|
||||
*
|
||||
* <p>This servlet accepts only JSON inputs (using the payload) and returns only JSON
|
||||
* responses, using and various security best practices such as a parser breaker,
|
||||
* {@code Content-Disposition: attachment}, etc.
|
||||
*
|
||||
* @see JsonHttp
|
||||
*/
|
||||
public abstract class JsonTransportServlet extends XsrfProtectedServlet {
|
||||
|
||||
protected JsonTransportServlet(String xsrfScope, boolean requireAdmin) {
|
||||
super(xsrfScope, requireAdmin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that this is a well-formed request and then execute it. A well-formed request will have
|
||||
* either a JSON string in the "json" param that evaluates to a map, or nothing in "json".
|
||||
*/
|
||||
@Override
|
||||
protected final void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException {
|
||||
Map<String, ?> input = JsonHttp.read(req);
|
||||
if (input == null) {
|
||||
rsp.sendError(SC_BAD_REQUEST, "Malformed JSON");
|
||||
return;
|
||||
}
|
||||
Map<String, ?> output;
|
||||
try {
|
||||
output = doJsonPost(req, input);
|
||||
} catch (HttpException e) {
|
||||
e.send(rsp);
|
||||
return;
|
||||
}
|
||||
checkNotNull(output, "doJsonPost() returned null");
|
||||
rsp.setStatus(SC_OK);
|
||||
JsonHttp.write(rsp, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for HTTP POST requests.
|
||||
*
|
||||
* @param req Servlet request object.
|
||||
* @param input JSON request object or empty if none was provided.
|
||||
* @return an arbitrary JSON object. Must not be {@code null}.
|
||||
* @throws HttpException in order to send a non-200 status code / message to the client.
|
||||
*/
|
||||
public abstract Map<String, Object> doJsonPost(HttpServletRequest req, Map<String, ?> input);
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
// Copyright 2016 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.security;
|
||||
|
||||
import static com.google.appengine.api.users.UserServiceFactory.getUserService;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Strings.nullToEmpty;
|
||||
import static google.registry.security.XsrfTokenManager.X_CSRF_TOKEN;
|
||||
import static google.registry.security.XsrfTokenManager.validateToken;
|
||||
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||
|
||||
import com.google.appengine.api.users.UserService;
|
||||
import java.io.IOException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.joda.time.Duration;
|
||||
|
||||
/**
|
||||
* Servlet with Cross-Site Request Forgery (XSRF) protection.
|
||||
*
|
||||
* <p>This servlet enforces XSRF protection on all requests by checking the value provided in the
|
||||
* "X-CSRF-Token" header. It can also optionally enforce that only admin users can call it.
|
||||
*
|
||||
* <p>All servlets that handle client requests should use XSRF protection.
|
||||
*/
|
||||
public abstract class XsrfProtectedServlet extends HttpServlet {
|
||||
|
||||
private static final Duration XSRF_VALIDITY = Duration.standardDays(1);
|
||||
|
||||
/** Used to validate XSRF tokens. */
|
||||
private String xsrfScope;
|
||||
|
||||
/** Whether to do a security check for admin status. */
|
||||
private boolean requireAdmin;
|
||||
|
||||
/** Gets the XSRF scope for this servlet. */
|
||||
public String getScope() {
|
||||
return xsrfScope;
|
||||
}
|
||||
|
||||
protected XsrfProtectedServlet(String xsrfScope, boolean requireAdmin) {
|
||||
this.xsrfScope = checkNotNull(xsrfScope);
|
||||
this.requireAdmin = requireAdmin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void service(HttpServletRequest req, HttpServletResponse rsp)
|
||||
throws IOException, ServletException {
|
||||
if (!validateToken(nullToEmpty(req.getHeader(X_CSRF_TOKEN)), xsrfScope, XSRF_VALIDITY)) {
|
||||
rsp.sendError(SC_FORBIDDEN, "Invalid " + X_CSRF_TOKEN);
|
||||
return;
|
||||
}
|
||||
if (!validateAdmin()) {
|
||||
rsp.sendError(SC_FORBIDDEN, "Administrator access only");
|
||||
return;
|
||||
}
|
||||
doPost(req, rsp);
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is an admin-only servlet, require admin permissions or being in development mode. Such
|
||||
* servlets should primarily be defended by being marked internal-only in web.xml, but it's worth
|
||||
* adding a defense-in-depth.
|
||||
*/
|
||||
private boolean validateAdmin() {
|
||||
UserService userService = getUserService();
|
||||
return requireAdmin ? (userService.isUserLoggedIn() && userService.isUserAdmin()) : true;
|
||||
}
|
||||
}
|
|
@ -26,7 +26,6 @@ java_library(
|
|||
"//java/google/registry/model",
|
||||
"//java/google/registry/request",
|
||||
"//java/google/registry/security",
|
||||
"//java/google/registry/security:servlets",
|
||||
"//java/google/registry/ui/forms",
|
||||
"//java/google/registry/ui/server",
|
||||
"//java/google/registry/ui/soy:soy_java_wrappers",
|
||||
|
|
|
@ -18,23 +18,29 @@ import static com.google.common.collect.Iterables.any;
|
|||
import static com.google.common.collect.Iterables.concat;
|
||||
import static com.google.common.collect.Sets.difference;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.security.JsonResponseHelper.Status.ERROR;
|
||||
import static google.registry.security.JsonResponseHelper.Status.SUCCESS;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.FluentIterable;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.googlecode.objectify.Work;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.config.ConfigModule.Config;
|
||||
import google.registry.export.sheet.SyncRegistrarsSheetAction;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.request.Action;
|
||||
import google.registry.request.HttpException.BadRequestException;
|
||||
import google.registry.request.JsonActionRunner;
|
||||
import google.registry.security.JsonResponseHelper;
|
||||
import google.registry.ui.forms.FormException;
|
||||
import google.registry.ui.forms.FormFieldException;
|
||||
import google.registry.ui.server.RegistrarFormFields;
|
||||
import google.registry.util.CidrAddressBlock;
|
||||
import google.registry.util.CollectionUtils;
|
||||
|
@ -44,15 +50,33 @@ import java.util.HashSet;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Admin servlet that allows creating or updating a registrar. Deletes are not allowed so as to
|
||||
* preserve history.
|
||||
*/
|
||||
public class RegistrarServlet extends ResourceServlet {
|
||||
@Action(
|
||||
path = RegistrarAction.PATH,
|
||||
requireLogin = true,
|
||||
xsrfProtection = true,
|
||||
xsrfScope = "console",
|
||||
method = Action.Method.POST)
|
||||
public class RegistrarAction implements Runnable, JsonActionRunner.JsonAction {
|
||||
|
||||
private static final RegistryConfig CONFIG = RegistryEnvironment.get().config();
|
||||
public static final String PATH = "/registrar-settings";
|
||||
|
||||
private static final String OP_PARAM = "op";
|
||||
private static final String ARGS_PARAM = "args";
|
||||
|
||||
@Inject HttpServletRequest request;
|
||||
@Inject SessionUtils sessionUtils;
|
||||
@Inject JsonActionRunner jsonActionRunner;
|
||||
@Inject Registrar initialRegistrar;
|
||||
@Inject @Config("registrarChangesNotificationEmailAddresses") ImmutableList<String>
|
||||
registrarChangesNotificationEmailAddresses;
|
||||
@Inject RegistrarAction() {}
|
||||
|
||||
private static final Predicate<RegistrarContact> HAS_PHONE = new Predicate<RegistrarContact>() {
|
||||
@Override
|
||||
|
@ -71,25 +95,20 @@ public class RegistrarServlet extends ResourceServlet {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> read(HttpServletRequest req, Map<String, ?> args) {
|
||||
String clientId = sessionUtils.getRegistrarClientId(req);
|
||||
Registrar registrar = getCheckedRegistrar(clientId);
|
||||
public Map<String, Object> read(Map<String, ?> args, Registrar registrar) {
|
||||
return JsonResponseHelper.create(SUCCESS, "Success", registrar.toJsonMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
Map<String, Object> update(HttpServletRequest req, final Map<String, ?> args) {
|
||||
final String clientId = sessionUtils.getRegistrarClientId(req);
|
||||
Map<String, Object> update(final Map<String, ?> args, final Registrar registrar) {
|
||||
final String clientId = sessionUtils.getRegistrarClientId(request);
|
||||
return ofy().transact(new Work<Map<String, Object>>() {
|
||||
@Override
|
||||
public Map<String, Object> run() {
|
||||
Registrar existingRegistrar = getCheckedRegistrar(clientId);
|
||||
ImmutableSet<RegistrarContact> oldContacts = existingRegistrar.getContacts();
|
||||
ImmutableSet<RegistrarContact> oldContacts = registrar.getContacts();
|
||||
Map<String, Object> existingRegistrarMap =
|
||||
expandRegistrarWithContacts(existingRegistrar, oldContacts);
|
||||
Registrar.Builder builder = existingRegistrar.asBuilder();
|
||||
ImmutableSet<RegistrarContact> updatedContacts = update(existingRegistrar, builder, args);
|
||||
expandRegistrarWithContacts(oldContacts, registrar);
|
||||
Registrar.Builder builder = registrar.asBuilder();
|
||||
ImmutableSet<RegistrarContact> updatedContacts = update(registrar, builder, args);
|
||||
if (!updatedContacts.isEmpty()) {
|
||||
builder.setContactsRequireSyncing(true);
|
||||
}
|
||||
|
@ -102,7 +121,7 @@ public class RegistrarServlet extends ResourceServlet {
|
|||
// Update the registrar map with updated contacts to bypass Objectify caching issues that
|
||||
// come into play with calling getContacts().
|
||||
Map<String, Object> updatedRegistrarMap =
|
||||
expandRegistrarWithContacts(updatedRegistrar, updatedContacts);
|
||||
expandRegistrarWithContacts(updatedContacts, updatedRegistrar);
|
||||
sendExternalUpdatesIfNecessary(
|
||||
updatedRegistrar.getRegistrarName(),
|
||||
existingRegistrarMap,
|
||||
|
@ -114,8 +133,8 @@ public class RegistrarServlet extends ResourceServlet {
|
|||
}});
|
||||
}
|
||||
|
||||
private Map<String, Object> expandRegistrarWithContacts(
|
||||
Registrar registrar, Iterable<RegistrarContact> contacts) {
|
||||
private Map<String, Object> expandRegistrarWithContacts(Iterable<RegistrarContact> contacts,
|
||||
Registrar registrar) {
|
||||
ImmutableSet<Map<String, Object>> expandedContacts = FluentIterable.from(contacts)
|
||||
.transform(new Function<RegistrarContact, Map<String, Object>>() {
|
||||
@Override
|
||||
|
@ -146,21 +165,15 @@ public class RegistrarServlet extends ResourceServlet {
|
|||
return;
|
||||
}
|
||||
SyncRegistrarsSheetAction.enqueueBackendTask();
|
||||
ImmutableList<String> toEmailAddress = CONFIG.getRegistrarChangesNotificationEmailAddresses();
|
||||
if (!toEmailAddress.isEmpty()) {
|
||||
if (!registrarChangesNotificationEmailAddresses.isEmpty()) {
|
||||
SendEmailUtils.sendEmail(
|
||||
toEmailAddress,
|
||||
registrarChangesNotificationEmailAddresses,
|
||||
String.format("Registrar %s updated", registrarName),
|
||||
"The following changes were made to the registrar:\n"
|
||||
+ DiffUtils.prettyPrintDiffedMap(diffs, null));
|
||||
}
|
||||
}
|
||||
|
||||
private Registrar getCheckedRegistrar(String clientId) {
|
||||
return checkExists(Registrar.loadByClientId(clientId),
|
||||
"No registrar exists with the given client id: " + clientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces business logic checks on registrar contacts.
|
||||
*
|
||||
|
@ -255,4 +268,42 @@ public class RegistrarServlet extends ResourceServlet {
|
|||
|
||||
return contacts.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> handleJsonRequest(Map<String, ?> input) {
|
||||
if (input == null) {
|
||||
throw new BadRequestException("Malformed JSON");
|
||||
}
|
||||
|
||||
if (!sessionUtils.checkRegistrarConsoleLogin(request)) {
|
||||
return JsonResponseHelper.create(ERROR, "Not authorized to access Registrar Console");
|
||||
}
|
||||
|
||||
// Process the operation. Though originally derived from a CRUD
|
||||
// handlder, registrar-settings really only supports read and update.
|
||||
String op = Optional.fromNullable((String) input.get(OP_PARAM)).or("read");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, ?> args = (Map<String, Object>)
|
||||
Optional.<Object>fromNullable(input.get(ARGS_PARAM)).or(ImmutableMap.of());
|
||||
try {
|
||||
switch (op) {
|
||||
case "update":
|
||||
return update(args, initialRegistrar);
|
||||
case "read":
|
||||
return read(args, initialRegistrar);
|
||||
default:
|
||||
return JsonResponseHelper.create(ERROR, "Unknown or unsupported operation: " + op);
|
||||
}
|
||||
} catch (FormFieldException e) {
|
||||
return JsonResponseHelper.createFormFieldError(e.getMessage(), e.getFieldName());
|
||||
} catch (FormException ee) {
|
||||
return JsonResponseHelper.create(ERROR, ee.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
jsonActionRunner.run(this);
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
// Copyright 2016 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 static com.google.appengine.api.users.UserServiceFactory.getUserService;
|
||||
import static google.registry.flows.EppConsoleAction.XSRF_SCOPE;
|
||||
import static google.registry.security.JsonResponseHelper.Status.ERROR;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.request.HttpException.NotFoundException;
|
||||
import google.registry.security.JsonResponseHelper;
|
||||
import google.registry.security.JsonTransportServlet;
|
||||
import google.registry.ui.forms.FormException;
|
||||
import google.registry.ui.forms.FormFieldException;
|
||||
import google.registry.util.NonFinalForTesting;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/** A servlet for callbacks that manipulate resources. */
|
||||
public abstract class ResourceServlet extends JsonTransportServlet {
|
||||
|
||||
private static final String OP_PARAM = "op";
|
||||
private static final String ARGS_PARAM = "args";
|
||||
|
||||
@NonFinalForTesting
|
||||
protected static SessionUtils sessionUtils = new SessionUtils(getUserService());
|
||||
|
||||
public ResourceServlet() {
|
||||
super(XSRF_SCOPE, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> doJsonPost(HttpServletRequest req, Map<String, ?> params) {
|
||||
if (!sessionUtils.isLoggedIn()) {
|
||||
return JsonResponseHelper.create(ERROR, "Not logged in");
|
||||
}
|
||||
if (!sessionUtils.checkRegistrarConsoleLogin(req)) {
|
||||
return JsonResponseHelper.create(ERROR, "Not authorized to access Registrar Console");
|
||||
}
|
||||
String op = Optional.fromNullable((String) params.get(OP_PARAM)).or("read");
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, ?> args = (Map<String, Object>)
|
||||
Optional.<Object>fromNullable(params.get(ARGS_PARAM)).or(ImmutableMap.of());
|
||||
try {
|
||||
switch (op) {
|
||||
case "create":
|
||||
return create(req, args);
|
||||
case "update":
|
||||
return update(req, args);
|
||||
case "delete":
|
||||
return delete(req, args);
|
||||
case "read":
|
||||
return read(req, args);
|
||||
default:
|
||||
return JsonResponseHelper.create(ERROR, "Unknown operation: " + op);
|
||||
}
|
||||
} catch (FormFieldException e) {
|
||||
return JsonResponseHelper.createFormFieldError(e.getMessage(), e.getFieldName());
|
||||
} catch (FormException ee) {
|
||||
return JsonResponseHelper.create(ERROR, ee.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
Map<String, Object> create(HttpServletRequest req, Map<String, ?> args) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
Map<String, Object> read(HttpServletRequest req, Map<String, ?> args) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
Map<String, Object> update(HttpServletRequest req, Map<String, ?> args) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
Map<String, Object> delete(HttpServletRequest req, Map<String, ?> args) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/** Like checkNotNull, but throws NotFoundException if given arg is null. */
|
||||
protected static <T> T checkExists(@Nullable T obj, String msg) {
|
||||
if (obj == null) {
|
||||
throw new NotFoundException(msg);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue