Pay off technical debt with ConsoleUiServlet

1. Turn ConsoleUiServlet into an action
2. Remove AbstractUiServlet, which fixes its threading bug
3. Use type-safe soy template parameters when rendering console

A follow-up change will add a new template parameter that renders the
payment page link on the navigation bar.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=117969638
This commit is contained in:
jart 2016-03-23 14:31:45 -07:00 committed by Justine Tunney
parent 79b2d5a990
commit b6b13333dd
22 changed files with 265 additions and 365 deletions

View file

@ -395,6 +395,12 @@ public final class ConfigModule {
} }
} }
@Provides
@Config("registrarConsoleEnabled")
public static boolean provideRegistrarConsoleEnabled() {
return true;
}
/** Maximum amount of time for syncing a spreadsheet, before killing. */ /** Maximum amount of time for syncing a spreadsheet, before killing. */
@Provides @Provides
@Config("sheetLockTimeout") @Config("sheetLockTimeout")

View file

@ -201,11 +201,6 @@ public interface RegistryConfig {
*/ */
public URL getRegistrarDefaultReferralUrl(); public URL getRegistrarDefaultReferralUrl();
/**
* Returns whether the registrar console is enabled.
*/
public boolean isRegistrarConsoleEnabled();
/** /**
* Returns the title of the project used in generating documentation. * Returns the title of the project used in generating documentation.
*/ */

View file

@ -149,11 +149,6 @@ public class TestRegistryConfig implements RegistryConfig {
return makeUrl("http://www.referral.example/path"); return makeUrl("http://www.referral.example/path");
} }
@Override
public boolean isRegistrarConsoleEnabled() {
return true;
}
@Override @Override
public String getDocumentationProjectTitle() { public String getDocumentationProjectTitle() {
return "Domain Registry"; return "Domain Registry";

View file

@ -19,21 +19,6 @@
<url-pattern>/_dr/epp</url-pattern> <url-pattern>/_dr/epp</url-pattern>
</servlet-mapping> </servlet-mapping>
<!-- Registrar Console -->
<servlet>
<description>
Registrar Console UI servlet.
</description>
<display-name>Registrar Console UI</display-name>
<servlet-name>registrar-ui</servlet-name>
<servlet-class>com.google.domain.registry.ui.server.registrar.ConsoleUiServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>registrar-ui</servlet-name>
<url-pattern>/registrar</url-pattern>
</servlet-mapping>
<servlet> <servlet>
<description> <description>
Registrar Console XHR servlet. Accepts EPP XHRs from GAE GAIA-authenticated frontend sessions. Registrar Console XHR servlet. Accepts EPP XHRs from GAE GAIA-authenticated frontend sessions.
@ -67,6 +52,12 @@
<load-on-startup>1</load-on-startup> <load-on-startup>1</load-on-startup>
</servlet> </servlet>
<!-- Registrar Console. -->
<servlet-mapping>
<servlet-name>frontend-servlet</servlet-name>
<url-pattern>/registrar</url-pattern>
</servlet-mapping>
<!-- Registrar Braintree payment form setup. --> <!-- Registrar Braintree payment form setup. -->
<servlet-mapping> <servlet-mapping>
<servlet-name>frontend-servlet</servlet-name> <servlet-name>frontend-servlet</servlet-name>

View file

@ -38,6 +38,6 @@ java_binary(
":frontend", ":frontend",
"//java/com/google/domain/registry/monitoring/whitebox", # MetricsTaskServlet "//java/com/google/domain/registry/monitoring/whitebox", # MetricsTaskServlet
"//java/com/google/domain/registry/ui/server/api", # CheckApiServlet "//java/com/google/domain/registry/ui/server/api", # CheckApiServlet
"//java/com/google/domain/registry/ui/server/registrar", # ConsoleUiServlet, etc. "//java/com/google/domain/registry/ui/server/registrar", # ResourceServlet
], ],
) )

View file

@ -26,6 +26,7 @@ import com.google.domain.registry.rdap.RdapNameserverAction;
import com.google.domain.registry.rdap.RdapNameserverSearchAction; import com.google.domain.registry.rdap.RdapNameserverSearchAction;
import com.google.domain.registry.request.RequestModule; import com.google.domain.registry.request.RequestModule;
import com.google.domain.registry.request.RequestScope; import com.google.domain.registry.request.RequestScope;
import com.google.domain.registry.ui.server.registrar.ConsoleUiAction;
import com.google.domain.registry.ui.server.registrar.RegistrarPaymentAction; import com.google.domain.registry.ui.server.registrar.RegistrarPaymentAction;
import com.google.domain.registry.ui.server.registrar.RegistrarPaymentSetupAction; import com.google.domain.registry.ui.server.registrar.RegistrarPaymentSetupAction;
import com.google.domain.registry.ui.server.registrar.RegistrarUserModule; import com.google.domain.registry.ui.server.registrar.RegistrarUserModule;
@ -45,6 +46,7 @@ import dagger.Subcomponent;
WhoisModule.class, WhoisModule.class,
}) })
interface FrontendRequestComponent { interface FrontendRequestComponent {
ConsoleUiAction consoleUiAction();
RdapAutnumAction rdapAutnumAction(); RdapAutnumAction rdapAutnumAction();
RegistrarPaymentAction registrarPaymentAction(); RegistrarPaymentAction registrarPaymentAction();
RegistrarPaymentSetupAction registrarPaymentSetupAction(); RegistrarPaymentSetupAction registrarPaymentSetupAction();

View file

@ -1,105 +0,0 @@
// Copyright 2016 Google Inc. 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 com.google.domain.registry.ui.server;
import static com.google.domain.registry.security.XsrfTokenManager.generateToken;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.common.net.MediaType;
import com.google.template.soy.data.SoyMapData;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** Abstract servlet for serving HTML pages. */
public abstract class AbstractUiServlet extends HttpServlet {
protected String userId;
protected String userName;
protected String userActionName;
protected String userActionHref;
protected boolean userIsAdmin;
@Override
public void service(HttpServletRequest req, HttpServletResponse rsp)
throws ServletException, IOException {
UserService userService = UserServiceFactory.getUserService();
if (userService.isUserLoggedIn()) {
User u = userService.getCurrentUser();
userId = u.getUserId();
userName = u.getNickname();
userActionName = "Sign out";
userActionHref = userService.createLogoutURL(req.getRequestURI());
userIsAdmin = userService.isUserAdmin();
} else {
userId = null;
userName = null;
userActionName = "Sign in";
userActionHref = userService.createLoginURL(req.getRequestURI());
userIsAdmin = false;
}
super.service(req, rsp);
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse rsp)
throws ServletException, IOException {
rsp.addHeader("X-Frame-Options", "SAMEORIGIN"); // Disallow iframing.
rsp.setHeader("X-Ui-Compatible", "IE=edge"); // Ask IE not to be silly.
rsp.setContentType(MediaType.HTML_UTF_8.toString());
UserService userService = UserServiceFactory.getUserService();
if (!userService.isUserLoggedIn()) {
rsp.sendRedirect(userService.createLoginURL(req.getRequestURI()));
return;
}
rsp.getWriter().write(get(req));
}
/**
* Subclasses may override this method to access request params, or
* get() to simply return content.
*/
protected String get(@SuppressWarnings("unused") HttpServletRequest req) {
return get();
}
/** Override this to just return content. */
protected String get() {
throw new UnsupportedOperationException();
}
/**
* Returns a map with {@code (user: (id,name,actionName,actionHref), gaeUserId:, xsrfToken:)}
*/
protected SoyMapData getTemplateArgs(String xsrfToken) {
SoyMapData user = new SoyMapData();
user.put("id", userId);
user.put("name", userName);
user.put("actionName", userActionName);
user.put("actionHref", userActionHref);
user.put("isAdmin", userIsAdmin);
SoyMapData result = new SoyMapData();
result.put("user", user);
result.put("gaeUserId", userId);
result.put("xsrfToken", generateToken(xsrfToken));
return result;
}
}

View file

@ -0,0 +1,106 @@
// Copyright 2016 Google Inc. 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.net.HttpHeaders.X_FRAME_OPTIONS;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
import com.google.appengine.api.users.UserService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.io.Resources;
import com.google.common.net.MediaType;
import com.google.domain.registry.config.ConfigModule.Config;
import com.google.domain.registry.flows.EppConsoleServlet;
import com.google.domain.registry.model.registrar.Registrar;
import com.google.domain.registry.request.Action;
import com.google.domain.registry.request.Response;
import com.google.domain.registry.security.XsrfTokenManager;
import com.google.domain.registry.ui.server.SoyTemplateUtils;
import com.google.domain.registry.ui.soy.registrar.ConsoleSoyInfo;
import com.google.template.soy.data.SoyMapData;
import com.google.template.soy.shared.SoyCssRenamingMap;
import com.google.template.soy.tofu.SoyTofu;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
/** Action that serves Registrar Console single HTML page (SPA). */
@Action(path = ConsoleUiAction.PATH, requireLogin = true, xsrfProtection = false)
public final class ConsoleUiAction implements Runnable {
public static final String PATH = "/registrar";
private static final Supplier<SoyTofu> TOFU_SUPPLIER =
SoyTemplateUtils.createTofuSupplier(
com.google.domain.registry.ui.soy.ConsoleSoyInfo.getInstance(),
com.google.domain.registry.ui.soy.registrar.ConsoleSoyInfo.getInstance());
@VisibleForTesting // webdriver and screenshot tests need this
public static final Supplier<SoyCssRenamingMap> CSS_RENAMING_MAP_SUPPLIER =
SoyTemplateUtils.createCssRenamingMapSupplier(
Resources.getResource("com/google/domain/registry/ui/css/registrar_bin.css.js"),
Resources.getResource("com/google/domain/registry/ui/css/registrar_dbg.css.js"));
@Inject HttpServletRequest req;
@Inject Response response;
@Inject SessionUtils sessionUtils;
@Inject UserService userService;
@Inject @Config("registrarConsoleEnabled") boolean enabled;
@Inject ConsoleUiAction() {}
@Override
public void run() {
response.setContentType(MediaType.HTML_UTF_8);
response.setHeader(X_FRAME_OPTIONS, "SAMEORIGIN"); // Disallow iframing.
response.setHeader("X-Ui-Compatible", "IE=edge"); // Ask IE not to be silly.
if (!enabled) {
response.setStatus(SC_SERVICE_UNAVAILABLE);
response.setPayload(
TOFU_SUPPLIER.get()
.newRenderer(ConsoleSoyInfo.DISABLED)
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
.render());
return;
}
if (!sessionUtils.checkRegistrarConsoleLogin(req)) {
SoyMapData data = new SoyMapData();
data.put("username", userService.getCurrentUser().getNickname());
data.put("logoutUrl", userService.createLogoutURL(PATH));
response.setStatus(SC_FORBIDDEN);
response.setPayload(
TOFU_SUPPLIER.get()
.newRenderer(ConsoleSoyInfo.WHOAREYOU)
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
.setData(data)
.render());
return;
}
Registrar registrar = Registrar.loadByClientId(sessionUtils.getRegistrarClientId(req));
SoyMapData data = new SoyMapData();
data.put("xsrfToken", XsrfTokenManager.generateToken(EppConsoleServlet.XSRF_SCOPE));
data.put("clientId", registrar.getClientIdentifier());
data.put("username", userService.getCurrentUser().getNickname());
data.put("isAdmin", userService.isUserAdmin());
data.put("logoutUrl", userService.createLogoutURL(PATH));
response.setPayload(
TOFU_SUPPLIER.get()
.newRenderer(ConsoleSoyInfo.MAIN)
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
.setData(data)
.render());
}
}

View file

@ -1,76 +0,0 @@
// Copyright 2016 Google Inc. 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 com.google.domain.registry.ui.server.registrar;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.io.Resources;
import com.google.domain.registry.config.RegistryEnvironment;
import com.google.domain.registry.flows.EppConsoleServlet;
import com.google.domain.registry.ui.server.AbstractUiServlet;
import com.google.domain.registry.ui.server.SoyTemplateUtils;
import com.google.domain.registry.ui.soy.registrar.ConsoleSoyInfo;
import com.google.domain.registry.util.NonFinalForTesting;
import com.google.template.soy.data.SoyMapData;
import com.google.template.soy.shared.SoyCssRenamingMap;
import com.google.template.soy.tofu.SoyTofu;
import javax.servlet.http.HttpServletRequest;
/** Main registrar console servlet that serves the client code. */
public final class ConsoleUiServlet extends AbstractUiServlet {
@VisibleForTesting
static final Supplier<SoyTofu> TOFU_SUPPLIER =
SoyTemplateUtils.createTofuSupplier(
com.google.domain.registry.ui.soy.ConsoleSoyInfo.getInstance(),
com.google.domain.registry.ui.soy.registrar.ConsoleSoyInfo.getInstance());
@VisibleForTesting
public static final Supplier<SoyCssRenamingMap> CSS_RENAMING_MAP_SUPPLIER =
SoyTemplateUtils.createCssRenamingMapSupplier(
Resources.getResource("com/google/domain/registry/ui/css/registrar_bin.css.js"),
Resources.getResource("com/google/domain/registry/ui/css/registrar_dbg.css.js"));
@NonFinalForTesting
private static SessionUtils sessionUtils = new SessionUtils(UserServiceFactory.getUserService());
@Override
protected String get(HttpServletRequest req) {
if (!RegistryEnvironment.get().config().isRegistrarConsoleEnabled()) {
return TOFU_SUPPLIER.get()
.newRenderer(ConsoleSoyInfo.DISABLED)
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
.render();
}
SoyMapData data = getTemplateArgs(EppConsoleServlet.XSRF_SCOPE);
if (!sessionUtils.checkRegistrarConsoleLogin(req)) {
data.getMapData("user").put("actionName", "Logout and switch to another account");
return TOFU_SUPPLIER.get()
.newRenderer(ConsoleSoyInfo.WHOAREYOU)
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
.setData(data)
.render();
}
data.put("clientId", req.getSession().getAttribute(SessionUtils.CLIENT_ID_ATTRIBUTE));
return TOFU_SUPPLIER.get()
.newRenderer(ConsoleSoyInfo.MAIN)
.setCssRenamingMap(CSS_RENAMING_MAP_SUPPLIER.get())
.setData(data)
.render();
}
}

View file

@ -54,7 +54,8 @@
* Happy little googley bar. * Happy little googley bar.
*/ */
{template .googlebar} {template .googlebar}
{@param user: map<string, ?>} {@param username: string}
{@param logoutUrl: string}
<div id="kd-googlebar" role="banner"> <div id="kd-googlebar" role="banner">
<a class="{css logo}" href="/registrar"> <a class="{css logo}" href="/registrar">
<img src="/assets/images/glogo_black.png" alt="Google">Registry <img src="/assets/images/glogo_black.png" alt="Google">Registry
@ -79,16 +80,10 @@
</p> </p>
</div> </div>
<div id="kd-social" class="{css kd-buttonbar} {css right}"> <div id="kd-social" class="{css kd-buttonbar} {css right}">
{if isNonnull($user['id'])} <span class="{css kd-name} {css mobile-hide} {css x-crush-hide}">
<span class="{css kd-name} {css mobile-hide} {css x-crush-hide}"> {$username}{sp}
{$user['name']}{sp} <a href="{$logoutUrl}" tabindex="-1">Sign out</a>
<a href="{$user['actionHref']}" tabindex="-1">{$user['actionName']}</a> </span>
</span>
{else}
<a href="{$user['actionHref']}"
class="{css kd-button} {css kd-button-submit}"
tabindex="-1">{$user['actionName']}</a>
{/if}
</div> </div>
</div> </div>
{/template} {/template}

View file

@ -7,9 +7,11 @@
* and other templates within it. * and other templates within it.
*/ */
{template .main} {template .main}
{@param user: map<string, ?>} /** Passed to googlebar. */
{@param xsrfToken: string} /** Security token. */ {@param xsrfToken: string} /** Security token. */
{@param clientId: string} /** App Engine user ID. */ {@param clientId: string} /** Registrar client identifier. */
{@param username: string} /** Arbitrary username to display. */
{@param isAdmin: bool} /** Is this user an App Engine account admin? */
{@param logoutUrl: string} /** Generated URL for logging out of Google. */
{call registry.soy.console.header} {call registry.soy.console.header}
{param app: 'registrar' /} {param app: 'registrar' /}
{param subtitle: 'Registrar Console' /} {param subtitle: 'Registrar Console' /}
@ -27,7 +29,7 @@
</div> </div>
{switch DEBUG} {switch DEBUG}
{case com.google.domain.registry.ui.ConsoleDebug.PRODUCTION} {case com.google.domain.registry.ui.ConsoleDebug.PRODUCTION}
{if $user['isAdmin']} {if $isAdmin}
<script src="/assets/js/registrar_bin_map.js"></script> <script src="/assets/js/registrar_bin_map.js"></script>
{else} {else}
<script src="/assets/js/registrar_bin.js"></script> <script src="/assets/js/registrar_bin.js"></script>
@ -92,11 +94,13 @@
</div> </div>
{/template} {/template}
/** /**
* Who goes thar?! * Who goes thar?!
*/ */
{template .whoareyou} {template .whoareyou}
{@param user: map<string, string>} {@param username: string} /** Arbitrary username to display. */
{@param logoutUrl: string} /** Generated URL for logging out of Google. */
{call registry.soy.console.header} {call registry.soy.console.header}
{param app: 'registrar' /} {param app: 'registrar' /}
{param subtitle: 'Please Login' /} {param subtitle: 'Please Login' /}
@ -110,13 +114,12 @@
The account you are logged in as is not associated with Google The account you are logged in as is not associated with Google
Registry. Please contact your customer service representative or Registry. Please contact your customer service representative or
switch to an account associated with Google Registry. switch to an account associated with Google Registry.
{if isNonnull($user['name'])} <p>
<p>You are signed in as <strong>{$user['name']}</strong>. You are signed in as <strong>{$username}</strong>.
{/if}
<div> <div>
<a href="{$user['actionHref']}" <a href="{$logoutUrl}"
class="{css kd-button} {css kd-button-submit}" class="{css kd-button} {css kd-button-submit}"
tabindex="-1">{$user['actionName']}</a> tabindex="-1">Logout and switch to another account</a>
</div> </div>
</div> </div>
{/template} {/template}

View file

@ -69,8 +69,7 @@ public final class RegistryTestServer {
com.google.domain.registry.module.backend.BackendServlet.class), com.google.domain.registry.module.backend.BackendServlet.class),
// Registrar Console // Registrar Console
route("/registrar", route("/registrar", com.google.domain.registry.module.frontend.FrontendServlet.class),
com.google.domain.registry.ui.server.registrar.ConsoleUiServlet.class),
route("/registrar-settings", route("/registrar-settings",
com.google.domain.registry.ui.server.registrar.RegistrarServlet.class), com.google.domain.registry.ui.server.registrar.RegistrarServlet.class),
route("/registrar-payment", route("/registrar-payment",

View file

@ -46,11 +46,10 @@ function setUp() {
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo); stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
var testElt = goog.dom.getElement('test'); var testElt = goog.dom.getElement('test');
goog.soy.renderElement(testElt, registry.soy.registrar.console.main, { goog.soy.renderElement(testElt, registry.soy.registrar.console.main, {
user: {
id: 'pmy@google.com',
actionHref: 'blah'
},
xsrfToken: test.testXsrfToken, xsrfToken: test.testXsrfToken,
username: 'blah',
logoutUrl: 'omg',
isAdmin: true,
clientId: test.testClientId clientId: test.testClientId
}); });
registry.registrar.ConsoleTestUtil.setup(test); registry.registrar.ConsoleTestUtil.setup(test);

View file

@ -45,12 +45,10 @@ function setUp() {
registry.testing.addToDocument('<div class="kd-butterbar"/>'); registry.testing.addToDocument('<div class="kd-butterbar"/>');
testContact = createTestContact(); testContact = createTestContact();
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, { goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
user: {
id: 'test@acme.com',
actionHref: 'blah',
actionName: 'omg'
},
xsrfToken: test.testXsrfToken, xsrfToken: test.testXsrfToken,
username: 'blah',
logoutUrl: 'omg',
isAdmin: true,
clientId: test.testClientId clientId: test.testClientId
}); });
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo); stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);

View file

@ -36,11 +36,10 @@ function setUp() {
registry.testing.addToDocument('<div id="test"/>'); registry.testing.addToDocument('<div id="test"/>');
registry.testing.addToDocument('<div class="kd-butterbar"/>'); registry.testing.addToDocument('<div class="kd-butterbar"/>');
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, { goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
user: {
id: 'test1.ui@example.com',
actionHref: 'blah'
},
xsrfToken: 'test', xsrfToken: 'test',
username: 'blah',
logoutUrl: 'omg',
isAdmin: true,
clientId: 'daddy' clientId: 'daddy'
}); });
registry.registrar.ConsoleTestUtil.setup(test); registry.registrar.ConsoleTestUtil.setup(test);

View file

@ -43,12 +43,10 @@ function setUp() {
registry.testing.addToDocument('<div class="kd-butterbar"/>'); registry.testing.addToDocument('<div class="kd-butterbar"/>');
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, { goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
xsrfToken: 'ignore', xsrfToken: 'ignore',
clientId: 'ignore', username: 'jart',
user: { logoutUrl: 'https://justinetunney.com',
id: 'jart@google.com', isAdmin: true,
actionHref: 'https://justinetunney.com', clientId: 'ignore'
actionName: 'gtfo'
}
}); });
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo); stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);

View file

@ -43,12 +43,10 @@ function setUp() {
registry.testing.addToDocument('<div class="kd-butterbar"/>'); registry.testing.addToDocument('<div class="kd-butterbar"/>');
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, { goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
xsrfToken: 'ignore', xsrfToken: 'ignore',
clientId: 'ignore', username: 'jart',
user: { logoutUrl: 'https://example.com',
id: 'test2.ui@example.com', isAdmin: true,
actionHref: 'https://example.com', clientId: 'ignore'
actionName: 'gtfo'
}
}); });
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo); stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);

View file

@ -50,11 +50,9 @@ function setUp() {
registry.testing.addToDocument('<div id="test"/>'); registry.testing.addToDocument('<div id="test"/>');
registry.testing.addToDocument('<div class="kd-butterbar"/>'); registry.testing.addToDocument('<div class="kd-butterbar"/>');
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, { goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
user: { username: 'jart',
id: 'test@acme.com', logoutUrl: 'https://example.com',
actionHref: 'blah', isAdmin: true,
actionName: 'omg'
},
xsrfToken: test.testXsrfToken, xsrfToken: test.testXsrfToken,
clientId: test.testClientId clientId: test.testClientId
}); });

View file

@ -44,12 +44,10 @@ function setUp() {
registry.testing.addToDocument('<div id="test"/>'); registry.testing.addToDocument('<div id="test"/>');
registry.testing.addToDocument('<div class="kd-butterbar"/>'); registry.testing.addToDocument('<div class="kd-butterbar"/>');
goog.soy.renderElement($('test'), registry.soy.registrar.console.main, { goog.soy.renderElement($('test'), registry.soy.registrar.console.main, {
user: {
id: 'test1.ui@example.com',
actionHref: 'blah',
actionName: 'omg'
},
xsrfToken: test.testXsrfToken, xsrfToken: test.testXsrfToken,
username: 'blah',
logoutUrl: 'omg',
isAdmin: true,
clientId: test.testClientId clientId: test.testClientId
}); });
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo); stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);

View file

@ -11,6 +11,7 @@ java_library(
"//java/com/google/common/base", "//java/com/google/common/base",
"//java/com/google/common/collect", "//java/com/google/common/collect",
"//java/com/google/common/io", "//java/com/google/common/io",
"//java/com/google/common/net",
"//java/com/google/common/testing", "//java/com/google/common/testing",
"//java/com/google/domain/registry/config", "//java/com/google/domain/registry/config",
"//java/com/google/domain/registry/export/sheet", "//java/com/google/domain/registry/export/sheet",
@ -31,8 +32,6 @@ java_library(
"//third_party/java/objectify:objectify-v4_1", "//third_party/java/objectify:objectify-v4_1",
"//third_party/java/servlet/servlet_api", "//third_party/java/servlet/servlet_api",
"//third_party/java/truth", "//third_party/java/truth",
"//third_party/closure/templates",
], ],
) )

View file

@ -0,0 +1,101 @@
// Copyright 2016 Google Inc. 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.common.net.MediaType;
import com.google.domain.registry.testing.AppEngineRule;
import com.google.domain.registry.testing.FakeResponse;
import com.google.domain.registry.testing.UserInfo;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import javax.servlet.http.HttpServletRequest;
/** Unit tests for {@link ConsoleUiAction}. */
@RunWith(MockitoJUnitRunner.class)
public class ConsoleUiActionTest {
@Rule
public final AppEngineRule appEngineRule = AppEngineRule.builder()
.withDatastore()
.withUserService(UserInfo.create("marla.singer@example.com", "12345"))
.build();
@Mock
private SessionUtils sessionUtils;
private final FakeResponse response = new FakeResponse();
private final ConsoleUiAction action = new ConsoleUiAction();
@Before
public void setUp() throws Exception {
action.enabled = true;
action.response = response;
action.sessionUtils = sessionUtils;
action.userService = UserServiceFactory.getUserService();
when(sessionUtils.checkRegistrarConsoleLogin(any(HttpServletRequest.class))).thenReturn(true);
when(sessionUtils.getRegistrarClientId(any(HttpServletRequest.class)))
.thenReturn("TheRegistrar");
}
@Test
public void webPage_disallowsIframe() throws Exception {
action.run();
assertThat(response.getHeaders()).containsEntry("X-Frame-Options", "SAMEORIGIN");
}
@Test
public void webPage_setsHtmlUtf8ContentType() throws Exception {
action.run();
assertThat(response.getContentType()).isEqualTo(MediaType.HTML_UTF_8);
}
@Test
public void webPage_containsUserNickname() throws Exception {
action.run();
assertThat(response.getPayload()).contains("marla.singer");
}
@Test
public void userHasAccessAsTheRegistrar_showsRegistrarConsole() throws Exception {
action.run();
assertThat(response.getPayload()).contains("Registrar Console");
assertThat(response.getPayload()).contains("reg-content-and-footer");
}
@Test
public void consoleDisabled_showsDisabledPage() throws Exception {
action.enabled = false;
action.run();
assertThat(response.getPayload()).contains("<h1>Console is disabled</h1>");
}
@Test
public void userDoesntHaveAccessToAnyRegistrar_showsWhoAreYouPage() throws Exception {
when(sessionUtils.checkRegistrarConsoleLogin(any(HttpServletRequest.class))).thenReturn(false);
action.run();
assertThat(response.getPayload()).contains("<h1>You need permission</h1>");
}
}

View file

@ -1,99 +0,0 @@
// Copyright 2016 Google Inc. 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 com.google.domain.registry.ui.server.registrar;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import com.google.domain.registry.config.TestRegistryConfig;
import com.google.domain.registry.testing.AppEngineRule;
import com.google.domain.registry.testing.RegistryConfigRule;
import com.google.domain.registry.testing.UserInfo;
import com.google.domain.registry.ui.soy.registrar.ConsoleSoyInfo;
import com.google.template.soy.data.SoyMapData;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** Unit tests for {@link ConsoleUiServlet}. */
@RunWith(MockitoJUnitRunner.class)
public class ConsoleUiServletTest {
@Rule
public AppEngineRule appEngineRule = AppEngineRule.builder()
.withUserService(UserInfo.create("foo@bar.com", "12345"))
.build();
@Rule
public final RegistryConfigRule configRule = new RegistryConfigRule();
@Mock
HttpServletRequest req;
@Mock
HttpServletResponse rsp;
final ConsoleUiServlet servlet = new ConsoleUiServlet();
final StringWriter stringWriter = new StringWriter();
@Before
public void setUp() throws Exception {
when(req.getMethod()).thenReturn("GET");
when(rsp.getWriter()).thenReturn(new PrintWriter(stringWriter));
when(req.getRequestURI()).thenReturn("/registrar");
}
@Test
public void testTofuCompilation() throws Exception {
ConsoleUiServlet.TOFU_SUPPLIER.get();
}
@Test
public void testTofuRender() throws Exception {
SoyMapData data = new SoyMapData();
SoyMapData user = new SoyMapData();
user.put("name", "lol");
user.put("actionName", "lol");
user.put("actionHref", "lol");
data.put("user", user);
ConsoleUiServlet.TOFU_SUPPLIER.get()
.newRenderer(ConsoleSoyInfo.WHOAREYOU)
.setCssRenamingMap(ConsoleUiServlet.CSS_RENAMING_MAP_SUPPLIER.get())
.setData(data)
.render();
}
@Test
public void testGet_consoleDisabled() throws Exception {
configRule.override(new TestRegistryConfig() {
@Override
public boolean isRegistrarConsoleEnabled() {
return false;
}});
servlet.service(req, rsp);
assertThat(stringWriter.toString()).contains("Console is disabled");
}
}