From 5f87c3bff38fb3feb738121a99c171fe4fe28546 Mon Sep 17 00:00:00 2001 From: gbrodman Date: Fri, 18 Jan 2019 12:14:17 -0800 Subject: [PATCH] Add a button in the admin panel to check OT&E status of a registrar For now, it only displays a status of "Passed: true|false" or an error message in simple text. In further work we will make the UI nicer. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=229971564 --- .../env/common/default/WEB-INF/web.xml | 14 ++- java/google/registry/ui/externs/json.js | 19 +++- java/google/registry/ui/js/component.js | 2 +- java/google/registry/ui/js/edit_item.js | 12 +++ .../ui/js/registrar/admin_settings.js | 97 ++++++++++++++----- .../ui/soy/registrar/AdminSettings.soy | 19 +++- .../google/registry/model/OteStatsTest.java | 2 +- .../registry/model/OteStatsTestHelper.java | 35 ++++--- javatests/google/registry/server/BUILD | 1 + javatests/google/registry/server/Fixture.java | 10 ++ .../registry/server/RegistryTestServer.java | 60 ++++++------ .../tools/server/VerifyOteActionTest.java | 2 +- .../server/registrar/OteStatusActionTest.java | 4 +- 13 files changed, 195 insertions(+), 82 deletions(-) diff --git a/java/google/registry/env/common/default/WEB-INF/web.xml b/java/google/registry/env/common/default/WEB-INF/web.xml index 5861ad0c1..639a1204d 100644 --- a/java/google/registry/env/common/default/WEB-INF/web.xml +++ b/java/google/registry/env/common/default/WEB-INF/web.xml @@ -31,10 +31,10 @@ /registrar - + frontend-servlet - /registrar-settings + /registrar-create @@ -43,10 +43,16 @@ /registrar-ote-setup - + frontend-servlet - /registrar-create + /registrar-ote-status + + + + + frontend-servlet + /registrar-settings diff --git a/java/google/registry/ui/externs/json.js b/java/google/registry/ui/externs/json.js index 3c64e8c25..a1203d781 100644 --- a/java/google/registry/ui/externs/json.js +++ b/java/google/registry/ui/externs/json.js @@ -19,7 +19,6 @@ * @externs */ - /** * @suppress {duplicate} */ @@ -31,6 +30,24 @@ var registry = {}; */ registry.json = {}; +registry.json.ote = {}; + +/** + * @typedef {{ + * clientId: string, + * completed: boolean + * }} + */ +registry.json.ote.OteStatusResult; + +/** + * @typedef {{ + * status: string, + * message: string, + * results: !Array. + * }} + */ +registry.json.ote.OteStatusResponse; /** diff --git a/java/google/registry/ui/js/component.js b/java/google/registry/ui/js/component.js index 793068b88..e0f899d06 100644 --- a/java/google/registry/ui/js/component.js +++ b/java/google/registry/ui/js/component.js @@ -85,7 +85,7 @@ goog.inherits(registry.Component, goog.events.EventHandler); /** - * Subclasses shold override this to implement panel display. + * Subclasses should override this to implement panel display. * @param {string} id The target resource id. */ registry.Component.prototype.bindToDom = function(id) { diff --git a/java/google/registry/ui/js/edit_item.js b/java/google/registry/ui/js/edit_item.js index 131f88eb7..4ee507f1b 100644 --- a/java/google/registry/ui/js/edit_item.js +++ b/java/google/registry/ui/js/edit_item.js @@ -128,6 +128,7 @@ registry.EditItem.prototype.renderItem = function(objArgs) { goog.soy.renderElement(goog.dom.getRequiredElement('reg-content'), this.itemTmpl, objArgs); + this.runAfterRender(objArgs); }; @@ -263,10 +264,21 @@ registry.EditItem.prototype.cancel = function() { /** * Called after this.renderItem(), to allow for further setup of * editing. + * + * TODO(b/122661518): merge this with runAfterRender so we don't have two + * similar methods * @param {!Object} objArgs */ registry.EditItem.prototype.setupEditor = function(objArgs) {}; +/** + * Called at the end of this.renderItem() to allow for registration + * of listeners and other tasks that depend on the existence of the items in the + * DOM + * @param {!Object} objArgs + */ +registry.EditItem.prototype.runAfterRender = function(objArgs) {}; + // XXX: These should really take @param {object} which is the form. Alas the // only override which doesn't work this way, ResourceComponent.sendCreate diff --git a/java/google/registry/ui/js/registrar/admin_settings.js b/java/google/registry/ui/js/registrar/admin_settings.js index 24a4c0272..4955a3788 100644 --- a/java/google/registry/ui/js/registrar/admin_settings.js +++ b/java/google/registry/ui/js/registrar/admin_settings.js @@ -19,6 +19,8 @@ goog.require('goog.dom'); goog.require('goog.dom.classlist'); goog.require('goog.events'); goog.require('goog.events.EventType'); +goog.require('goog.json'); +goog.require('goog.net.XhrIo'); goog.require('goog.soy'); goog.require('registry.Resource'); goog.require('registry.ResourceComponent'); @@ -50,30 +52,75 @@ registry.registrar.AdminSettings.prototype.bindToDom = function(id) { goog.dom.removeNode(goog.dom.getRequiredElement('reg-app-btn-back')); }; - /** @override */ -registry.registrar.AdminSettings.prototype.setupEditor = - function(objArgs) { - goog.dom.classlist.add(goog.dom.getRequiredElement('tlds'), - goog.getCssName('editing')); - var tlds = goog.dom.getElementsByClass(goog.getCssName('tld'), - goog.dom.getRequiredElement('tlds')); - goog.array.forEach(tlds, function(tld) { - var remBtn = goog.dom.getChildren(tld)[0]; - goog.events.listen(remBtn, - goog.events.EventType.CLICK, - goog.bind(this.onTldRemove_, this, remBtn)); - }, this); - this.typeCounts['reg-tlds'] = objArgs.allowedTlds ? - objArgs.allowedTlds.length : 0; - - goog.events.listen(goog.dom.getRequiredElement('btn-add-tld'), - goog.events.EventType.CLICK, - this.onTldAdd_, - false, - this); +registry.registrar.AdminSettings.prototype.runAfterRender = function(objArgs) { + goog.events.listen( + goog.dom.getRequiredElement('btn-ote-status'), + goog.events.EventType.CLICK, + goog.bind( + this.oteStatusCheck_, this, objArgs.xsrfToken, objArgs.clientId), + false, this); }; +/** @override */ +registry.registrar.AdminSettings.prototype.setupEditor = function(objArgs) { + goog.dom.classlist.add( + goog.dom.getRequiredElement('tlds'), goog.getCssName('editing')); + var tlds = goog.dom.getElementsByClass( + goog.getCssName('tld'), goog.dom.getRequiredElement('tlds')); + goog.array.forEach(tlds, function(tld) { + var remBtn = goog.dom.getChildren(tld)[0]; + goog.events.listen( + remBtn, goog.events.EventType.CLICK, + goog.bind(this.onTldRemove_, this, remBtn)); + }, this); + this.typeCounts['reg-tlds'] = + objArgs.allowedTlds ? objArgs.allowedTlds.length : 0; + + goog.events.listen( + goog.dom.getRequiredElement('btn-add-tld'), goog.events.EventType.CLICK, + this.onTldAdd_, false, this); +}; + +/** + * JSON response prefix which prevents evaluation. + * @private {string} + * @const + */ +registry.registrar.AdminSettings.PARSER_BREAKER_ = ')]}\'\n'; + +/** + * Click handler for OT&E status checking button. + * @param {string} xsrfToken + * @param {string} clientId + * @private + */ +registry.registrar.AdminSettings.prototype.oteStatusCheck_ = function( + xsrfToken, clientId) { + goog.net.XhrIo.send('/registrar-ote-status', function(e) { + var response = + /** @type {!registry.json.ote.OteStatusResponse} */ + (e.target.getResponseJson( + registry.registrar.AdminSettings.PARSER_BREAKER_)); + var message; + if (response.status === 'SUCCESS') { + var results = response.results[0]; + message = 'Passed: '.concat(results.completed); + } else { + message = 'Error: '.concat(response.message); + } + var textParent = goog.dom.getRequiredElement('ote-status-area-parent'); + if (!textParent.hasChildNodes()) { + var textElement = document.createElement('p'); + textElement.id = 'ote-status-area'; + textParent.appendChild(textElement); + } + textParent.firstElementChild.textContent = message; + }, 'POST', goog.json.serialize({'clientId': clientId}), { + 'X-CSRF-Token': xsrfToken, + 'Content-Type': 'application/json; charset=UTF-8' + }); +}; /** * Click handler for TLD add button. @@ -88,8 +135,9 @@ registry.registrar.AdminSettings.prototype.onTldAdd_ = function() { goog.dom.appendChild(goog.dom.getRequiredElement('tlds'), tldElt); var remBtn = goog.dom.getFirstElementChild(tldElt); goog.dom.classlist.remove(remBtn, goog.getCssName('hidden')); - goog.events.listen(remBtn, goog.events.EventType.CLICK, - goog.bind(this.onTldRemove_, this, remBtn)); + goog.events.listen( + remBtn, goog.events.EventType.CLICK, + goog.bind(this.onTldRemove_, this, remBtn)); this.typeCounts['reg-tlds']++; tldInputElt.value = ''; }; @@ -100,7 +148,6 @@ registry.registrar.AdminSettings.prototype.onTldAdd_ = function() { * @param {!Element} remBtn The remove button. * @private */ -registry.registrar.AdminSettings.prototype.onTldRemove_ = - function(remBtn) { +registry.registrar.AdminSettings.prototype.onTldRemove_ = function(remBtn) { goog.dom.removeNode(goog.dom.getParentElement(remBtn)); }; diff --git a/java/google/registry/ui/soy/registrar/AdminSettings.soy b/java/google/registry/ui/soy/registrar/AdminSettings.soy index d9e18993e..b9643b079 100644 --- a/java/google/registry/ui/soy/registrar/AdminSettings.soy +++ b/java/google/registry/ui/soy/registrar/AdminSettings.soy @@ -14,8 +14,6 @@ {namespace registry.soy.registrar.admin} - - /** Registrar admin settings page for view and edit. */ {template .settings} {@param allowedTlds: list} @@ -48,6 +46,9 @@

Generate new OT&E accounts here +

+ + {call .oteStatus /} {/template} @@ -64,3 +65,17 @@ {/template} + +{template .oteStatus} + + + + + + +{/template} diff --git a/javatests/google/registry/model/OteStatsTest.java b/javatests/google/registry/model/OteStatsTest.java index 502701277..f8e84df71 100644 --- a/javatests/google/registry/model/OteStatsTest.java +++ b/javatests/google/registry/model/OteStatsTest.java @@ -31,7 +31,7 @@ public final class OteStatsTest { @Before public void init() throws Exception { - OteStatsTestHelper.setupHistoryEntries(); + OteStatsTestHelper.setupHistoryEntries("blobio"); } @Test diff --git a/javatests/google/registry/model/OteStatsTestHelper.java b/javatests/google/registry/model/OteStatsTestHelper.java index 1c8eaab94..e5f4972e5 100644 --- a/javatests/google/registry/model/OteStatsTestHelper.java +++ b/javatests/google/registry/model/OteStatsTestHelper.java @@ -31,92 +31,95 @@ public final class OteStatsTestHelper { private static HistoryEntry domainCreateHistoryEntry; private static HistoryEntry domainRestoreHistoryEntry; - public static void setupHistoryEntries() throws IOException { + // TODO(b/122830156): Have this replicate the exact OT&E workflow with the correct client IDs + public static void setupHistoryEntries(String baseClientId) throws IOException { persistPremiumList("default_sandbox_list", "sandbox,USD 1000"); + OteAccountBuilder.forClientId(baseClientId).addContact("email@example.com").buildAndPersist(); + String oteAccount1 = String.format("%s-1", baseClientId); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_CREATE) .setXmlBytes(getBytes("domain_create_sunrise.xml")) .build()); domainCreateHistoryEntry = persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_CREATE) .setXmlBytes(getBytes("domain_create_idn.xml")) .build()); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_CREATE) .setXmlBytes(getBytes("domain_create_claim_notice.xml")) .build()); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_CREATE) .setXmlBytes(getBytes("domain_create_anchor_tenant_fee_standard.xml")) .build()); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_CREATE) .setXmlBytes(getBytes("domain_create_dsdata.xml")) .build()); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_DELETE) .setXmlBytes(getBytes("domain_delete.xml")) .build()); domainRestoreHistoryEntry = persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_RESTORE) .setXmlBytes(getBytes("domain_restore.xml")) .build()); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_TRANSFER_APPROVE) .setXmlBytes(getBytes("domain_transfer_approve.xml")) .build()); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_TRANSFER_CANCEL) .setXmlBytes(getBytes("domain_transfer_cancel.xml")) .build()); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_TRANSFER_REJECT) .setXmlBytes(getBytes("domain_transfer_reject.xml")) .build()); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_TRANSFER_REQUEST) .setXmlBytes(getBytes("domain_transfer_request.xml")) .build()); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.DOMAIN_UPDATE) .setXmlBytes(getBytes("domain_update_with_secdns.xml")) .build()); persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.HOST_CREATE) .setXmlBytes(getBytes("host_create_complete.xml")) .build()); hostDeleteHistoryEntry = persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.HOST_DELETE) .setXmlBytes(getBytes("host_delete.xml")) .build()); @@ -126,7 +129,7 @@ public final class OteStatsTestHelper { for (int i = 0; i < 10; i++) { persistResource( new HistoryEntry.Builder() - .setClientId("blobio-1") + .setClientId(oteAccount1) .setType(Type.HOST_UPDATE) .setXmlBytes(getBytes("host_update.xml")) .setTrid(Trid.create(null, String.format("blahtrid-%d", i))) diff --git a/javatests/google/registry/server/BUILD b/javatests/google/registry/server/BUILD index 402e147bc..30a630d1a 100644 --- a/javatests/google/registry/server/BUILD +++ b/javatests/google/registry/server/BUILD @@ -34,6 +34,7 @@ java_library( srcs = ["Fixture.java"], deps = [ "//java/google/registry/model", + "//javatests/google/registry/model", "//javatests/google/registry/testing", "//third_party/objectify:objectify-v4_1", "@com_google_appengine_api_1_0_sdk", diff --git a/javatests/google/registry/server/Fixture.java b/javatests/google/registry/server/Fixture.java index afe875d8e..938ea1347 100644 --- a/javatests/google/registry/server/Fixture.java +++ b/javatests/google/registry/server/Fixture.java @@ -28,6 +28,8 @@ import static google.registry.testing.DatastoreHelper.persistResource; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.googlecode.objectify.Key; +import google.registry.model.OteAccountBuilder; +import google.registry.model.OteStatsTestHelper; import google.registry.model.contact.ContactAddress; import google.registry.model.contact.ContactResource; import google.registry.model.contact.PostalInfo; @@ -35,6 +37,7 @@ import google.registry.model.domain.DesignatedContact; import google.registry.model.ofy.Ofy; import google.registry.testing.FakeClock; import google.registry.testing.InjectRule; +import java.io.IOException; import org.joda.time.DateTime; /** @@ -62,6 +65,13 @@ public enum Fixture { // Used for OT&E TLDs persistPremiumList("default_sandbox_list"); + OteAccountBuilder.forClientId("oteunfinished").addContact("email@example.com").buildAndPersist(); + try { + OteStatsTestHelper.setupHistoryEntries("otefinished"); + } catch (IOException e) { + throw new RuntimeException(e); + } + ContactResource google = persistResource(newContactResource("google") .asBuilder() .setLocalizedPostalInfo(new PostalInfo.Builder() diff --git a/javatests/google/registry/server/RegistryTestServer.java b/javatests/google/registry/server/RegistryTestServer.java index a24aa9507..b7ebe7c27 100644 --- a/javatests/google/registry/server/RegistryTestServer.java +++ b/javatests/google/registry/server/RegistryTestServer.java @@ -53,41 +53,43 @@ public final class RegistryTestServer { Paths.get("../domain_registry/java/google/registry/ui/assets")) .build(); - private static final ImmutableList ROUTES = ImmutableList.of( - // Frontend Services - route("/whois/*", FrontendServlet.class), - route("/rdap/*", FrontendServlet.class), - route("/registrar-xhr", FrontendServlet.class), - route("/check", FrontendServlet.class), + private static final ImmutableList ROUTES = + ImmutableList.of( + // Frontend Services + route("/whois/*", FrontendServlet.class), + route("/rdap/*", FrontendServlet.class), + route("/registrar-xhr", FrontendServlet.class), + route("/check", FrontendServlet.class), - // Proxy Services - route("/_dr/epp", FrontendServlet.class), - route("/_dr/whois", FrontendServlet.class), + // Proxy Services + route("/_dr/epp", FrontendServlet.class), + route("/_dr/whois", FrontendServlet.class), - // Registry Data Escrow (RDE) - route("/_dr/cron/rdeCreate", BackendServlet.class), - route("/_dr/task/rdeStaging", BackendServlet.class), - route("/_dr/task/rdeUpload", BackendServlet.class), - route("/_dr/task/rdeReport", BackendServlet.class), - route("/_dr/task/brdaCopy", BackendServlet.class), + // Registry Data Escrow (RDE) + route("/_dr/cron/rdeCreate", BackendServlet.class), + route("/_dr/task/rdeStaging", BackendServlet.class), + route("/_dr/task/rdeUpload", BackendServlet.class), + route("/_dr/task/rdeReport", BackendServlet.class), + route("/_dr/task/brdaCopy", BackendServlet.class), - // Trademark Clearinghouse (TMCH) - route("/_dr/cron/tmchDnl", BackendServlet.class), - route("/_dr/task/tmchSmdrl", BackendServlet.class), - route("/_dr/task/tmchCrl", BackendServlet.class), + // Trademark Clearinghouse (TMCH) + route("/_dr/cron/tmchDnl", BackendServlet.class), + route("/_dr/task/tmchSmdrl", BackendServlet.class), + route("/_dr/task/tmchCrl", BackendServlet.class), - // Notification of Registered Domain Names (NORDN) - route("/_dr/task/nordnUpload", BackendServlet.class), - route("/_dr/task/nordnVerify", BackendServlet.class), + // Notification of Registered Domain Names (NORDN) + route("/_dr/task/nordnUpload", BackendServlet.class), + route("/_dr/task/nordnVerify", BackendServlet.class), - // Process DNS pull queue - route("/_dr/cron/readDnsQueue", BackendServlet.class), + // Process DNS pull queue + route("/_dr/cron/readDnsQueue", BackendServlet.class), - // Registrar Console - route("/registrar", FrontendServlet.class), - route("/registrar-settings", FrontendServlet.class), - route("/registrar-ote-setup", FrontendServlet.class), - route("/registrar-create", FrontendServlet.class)); + // Registrar Console + route("/registrar", FrontendServlet.class), + route("/registrar-create", FrontendServlet.class), + route("/registrar-ote-setup", FrontendServlet.class), + route("/registrar-ote-status", FrontendServlet.class), + route("/registrar-settings", FrontendServlet.class)); private static final ImmutableList> FILTERS = ImmutableList.of( ObjectifyFilter.class, diff --git a/javatests/google/registry/tools/server/VerifyOteActionTest.java b/javatests/google/registry/tools/server/VerifyOteActionTest.java index 881a4b8d7..5df96ebae 100644 --- a/javatests/google/registry/tools/server/VerifyOteActionTest.java +++ b/javatests/google/registry/tools/server/VerifyOteActionTest.java @@ -38,7 +38,7 @@ public class VerifyOteActionTest { @Before public void init() throws Exception { - OteStatsTestHelper.setupHistoryEntries(); + OteStatsTestHelper.setupHistoryEntries("blobio"); } @Test diff --git a/javatests/google/registry/ui/server/registrar/OteStatusActionTest.java b/javatests/google/registry/ui/server/registrar/OteStatusActionTest.java index 29c6ce6fb..89c223509 100644 --- a/javatests/google/registry/ui/server/registrar/OteStatusActionTest.java +++ b/javatests/google/registry/ui/server/registrar/OteStatusActionTest.java @@ -52,11 +52,11 @@ public final class OteStatusActionTest { @Before public void init() throws Exception { - OteStatsTestHelper.setupHistoryEntries(); + OteStatsTestHelper.setupHistoryEntries(BASE_CLIENT_ID); persistNewRegistrar(CLIENT_ID, "SomeRegistrar", Type.OTE, null); ImmutableSetMultimap authValues = - OteAccountBuilder.createClientIdToTldMap("blobio").keySet().stream() + OteAccountBuilder.createClientIdToTldMap(BASE_CLIENT_ID).keySet().stream() .collect(toImmutableSetMultimap(Function.identity(), ignored -> Role.OWNER)); action.registrarAccessor = AuthenticatedRegistrarAccessor.createForTesting(authValues); }