Remove the web console EPP endpoint
This removes the "create Domain/Host/Contact" forms that were supposed to be used instead of regular EPPs for CC-TLD that wanted to support it. We're removing it because we don't use it and want to reduce unneeded code for the registry 3.0 migration. Also, this is a security risk, as it allowed to do "billable actions" (creating a new domain for example) with the only authentication being access to the registrar's G Suite account. This bypassed the certificate, IP whitelist, and EPP password, which is bad. PUBLIC: Remove the web console EPP endpoint This removes the "create Domain/Host/Contact" forms that were supposed to be used instead of regular EPPs for CC-TLD that wanted to support it. We're removing it because we don't use it and want to reduce unneeded code for the registry 3.0 migration. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=236244195
|
@ -945,7 +945,6 @@ An EPP flow for login.
|
||||||
* 2103
|
* 2103
|
||||||
* Specified extension is not implemented.
|
* Specified extension is not implemented.
|
||||||
* 2200
|
* 2200
|
||||||
* GAE User can't access the requested registrar.
|
|
||||||
* Registrar certificate does not match stored certificate.
|
* Registrar certificate does not match stored certificate.
|
||||||
* Registrar IP address is not in stored whitelist.
|
* Registrar IP address is not in stored whitelist.
|
||||||
* Registrar certificate not present.
|
* Registrar certificate not present.
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
// Copyright 2017 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.flows;
|
|
||||||
|
|
||||||
import com.google.appengine.api.users.UserService;
|
|
||||||
import google.registry.model.eppcommon.ProtocolDefinition;
|
|
||||||
import google.registry.request.Action;
|
|
||||||
import google.registry.request.Action.Method;
|
|
||||||
import google.registry.request.Parameter;
|
|
||||||
import google.registry.request.Payload;
|
|
||||||
import google.registry.request.auth.Auth;
|
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.servlet.http.HttpSession;
|
|
||||||
|
|
||||||
/** Runs EPP from the console and requires GAE user authentication. */
|
|
||||||
@Action(
|
|
||||||
service = Action.Service.DEFAULT,
|
|
||||||
path = "/registrar-xhr",
|
|
||||||
method = Method.POST,
|
|
||||||
auth = Auth.AUTH_PUBLIC_LOGGED_IN)
|
|
||||||
public class EppConsoleAction implements Runnable {
|
|
||||||
|
|
||||||
@Inject @Payload byte[] inputXmlBytes;
|
|
||||||
@Inject HttpSession session;
|
|
||||||
@Inject EppRequestHandler eppRequestHandler;
|
|
||||||
@Inject UserService userService;
|
|
||||||
@Inject AuthenticatedRegistrarAccessor registrarAccessor;
|
|
||||||
@Inject @Parameter("clientId") String clientId;
|
|
||||||
@Inject EppConsoleAction() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
eppRequestHandler.executeEpp(
|
|
||||||
new StatelessRequestSessionMetadata(clientId,
|
|
||||||
ProtocolDefinition.getVisibleServiceExtensionUris()),
|
|
||||||
new GaeUserCredentials(registrarAccessor),
|
|
||||||
EppRequestSource.CONSOLE,
|
|
||||||
false, // This endpoint is never a dry run.
|
|
||||||
false, // This endpoint is never a superuser.
|
|
||||||
inputXmlBytes);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
// Copyright 2017 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.flows;
|
|
||||||
|
|
||||||
import static com.google.common.base.MoreObjects.toStringHelper;
|
|
||||||
|
|
||||||
import google.registry.flows.EppException.AuthenticationErrorException;
|
|
||||||
import google.registry.model.registrar.Registrar;
|
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor.RegistrarAccessDeniedException;
|
|
||||||
|
|
||||||
/** Credentials provided by {@link com.google.appengine.api.users.UserService}. */
|
|
||||||
public class GaeUserCredentials implements TransportCredentials {
|
|
||||||
|
|
||||||
private final AuthenticatedRegistrarAccessor registrarAccessor;
|
|
||||||
|
|
||||||
public GaeUserCredentials(AuthenticatedRegistrarAccessor registrarAccessor) {
|
|
||||||
this.registrarAccessor = registrarAccessor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void validate(Registrar registrar, String ignoredPassword)
|
|
||||||
throws AuthenticationErrorException {
|
|
||||||
try {
|
|
||||||
registrarAccessor.verifyAccess(registrar.getClientId());
|
|
||||||
} catch (RegistrarAccessDeniedException e) {
|
|
||||||
throw new UserForbiddenException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return toStringHelper(getClass()).add("user", registrarAccessor.userIdForLogging()).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** GAE User can't access the requested registrar. */
|
|
||||||
public static class UserForbiddenException extends AuthenticationErrorException {
|
|
||||||
public UserForbiddenException(RegistrarAccessDeniedException e) {
|
|
||||||
super(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -51,7 +51,6 @@ import javax.inject.Inject;
|
||||||
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
|
* @error {@link google.registry.flows.EppException.UnimplementedExtensionException}
|
||||||
* @error {@link google.registry.flows.EppException.UnimplementedObjectServiceException}
|
* @error {@link google.registry.flows.EppException.UnimplementedObjectServiceException}
|
||||||
* @error {@link google.registry.flows.EppException.UnimplementedProtocolVersionException}
|
* @error {@link google.registry.flows.EppException.UnimplementedProtocolVersionException}
|
||||||
* @error {@link google.registry.flows.GaeUserCredentials.UserForbiddenException}
|
|
||||||
* @error {@link google.registry.flows.TlsCredentials.BadRegistrarCertificateException}
|
* @error {@link google.registry.flows.TlsCredentials.BadRegistrarCertificateException}
|
||||||
* @error {@link google.registry.flows.TlsCredentials.BadRegistrarIpAddressException}
|
* @error {@link google.registry.flows.TlsCredentials.BadRegistrarIpAddressException}
|
||||||
* @error {@link google.registry.flows.TlsCredentials.MissingRegistrarCertificateException}
|
* @error {@link google.registry.flows.TlsCredentials.MissingRegistrarCertificateException}
|
||||||
|
|
|
@ -17,7 +17,6 @@ package google.registry.module.frontend;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Subcomponent;
|
import dagger.Subcomponent;
|
||||||
import google.registry.dns.DnsModule;
|
import google.registry.dns.DnsModule;
|
||||||
import google.registry.flows.EppConsoleAction;
|
|
||||||
import google.registry.flows.EppTlsAction;
|
import google.registry.flows.EppTlsAction;
|
||||||
import google.registry.flows.FlowComponent;
|
import google.registry.flows.FlowComponent;
|
||||||
import google.registry.flows.TlsCredentials.EppTlsModule;
|
import google.registry.flows.TlsCredentials.EppTlsModule;
|
||||||
|
@ -46,7 +45,6 @@ interface FrontendRequestComponent {
|
||||||
ConsoleOteSetupAction consoleOteSetupAction();
|
ConsoleOteSetupAction consoleOteSetupAction();
|
||||||
ConsoleRegistrarCreatorAction consoleRegistrarCreatorAction();
|
ConsoleRegistrarCreatorAction consoleRegistrarCreatorAction();
|
||||||
ConsoleUiAction consoleUiAction();
|
ConsoleUiAction consoleUiAction();
|
||||||
EppConsoleAction eppConsoleAction();
|
|
||||||
EppTlsAction eppTlsAction();
|
EppTlsAction eppTlsAction();
|
||||||
FlowComponent.Builder flowComponentBuilder();
|
FlowComponent.Builder flowComponentBuilder();
|
||||||
OteStatusAction oteStatusAction();
|
OteStatusAction oteStatusAction();
|
||||||
|
|
|
@ -14,13 +14,7 @@
|
||||||
|
|
||||||
goog.provide('registry.Component');
|
goog.provide('registry.Component');
|
||||||
|
|
||||||
goog.require('goog.dom');
|
|
||||||
goog.require('goog.dom.TagName');
|
|
||||||
goog.require('goog.dom.classlist');
|
|
||||||
goog.require('goog.events');
|
|
||||||
goog.require('goog.events.EventHandler');
|
goog.require('goog.events.EventHandler');
|
||||||
goog.require('goog.events.EventType');
|
|
||||||
goog.require('registry.soy.forms');
|
|
||||||
goog.require('registry.util');
|
goog.require('registry.util');
|
||||||
|
|
||||||
goog.forwardDeclare('registry.Console');
|
goog.forwardDeclare('registry.Console');
|
||||||
|
@ -38,16 +32,9 @@ goog.forwardDeclare('registry.Console');
|
||||||
* ^
|
* ^
|
||||||
* \
|
* \
|
||||||
* |-ui/js/resource_component.js - JSON resources
|
* |-ui/js/resource_component.js - JSON resources
|
||||||
* | ^
|
* ^
|
||||||
* | \
|
* \
|
||||||
* | |- ui/js/registrar/settings.js
|
* |- ui/js/registrar/settings.js
|
||||||
* |
|
|
||||||
* |-ui/js/registrar/xml_resource_component.js - EPP resources
|
|
||||||
* ^
|
|
||||||
* \
|
|
||||||
* |- ui/js/registrar/contact.js
|
|
||||||
* |- ui/js/registrar/domain.js
|
|
||||||
* |- ui/js/registrar/host.js
|
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param {!registry.Console} cons the console singleton.
|
* @param {!registry.Console} cons the console singleton.
|
||||||
|
@ -91,122 +78,3 @@ goog.inherits(registry.Component, goog.events.EventHandler);
|
||||||
registry.Component.prototype.bindToDom = function(id) {
|
registry.Component.prototype.bindToDom = function(id) {
|
||||||
registry.util.unbutter();
|
registry.util.unbutter();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// XXX: Should clean up the many remove button handler setup funcs.
|
|
||||||
/**
|
|
||||||
* Shared functionality for contact and host add button click events
|
|
||||||
* to add form elements for inputing a new item name. Requires the
|
|
||||||
* template to have:
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>an add button with id="domain-[type]-add-button".
|
|
||||||
* <li>a table row with id="domain-[type]s-footer".
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param {string} type e.g. 'contact', 'host'.
|
|
||||||
* @param {function(): string} newFieldNameFn generates new form field's name.
|
|
||||||
* @param {function(string): (?Element)=} opt_onAddFn currying further setup.
|
|
||||||
* @param {function()=} opt_tmpl input element template.
|
|
||||||
* @param {!Object=} opt_tmplArgs input element template parameter object.
|
|
||||||
* @param {boolean=} opt_disable optionally disable the add button.
|
|
||||||
* @protected
|
|
||||||
*/
|
|
||||||
registry.Component.prototype.addRemBtnHandlers = function(
|
|
||||||
type,
|
|
||||||
newFieldNameFn,
|
|
||||||
opt_onAddFn,
|
|
||||||
opt_tmpl,
|
|
||||||
opt_tmplArgs,
|
|
||||||
opt_disable) {
|
|
||||||
var addBtnId = 'domain-' + type + '-add-button';
|
|
||||||
var addBtn = goog.dom.getRequiredElement(addBtnId);
|
|
||||||
if (!opt_disable) {
|
|
||||||
addBtn.removeAttribute('disabled');
|
|
||||||
}
|
|
||||||
var addButtonClickCallback = function() {
|
|
||||||
var fieldElts = [];
|
|
||||||
var newFieldName = newFieldNameFn();
|
|
||||||
var tmpl =
|
|
||||||
opt_tmpl ? opt_tmpl : registry.soy.forms.inputFieldRow;
|
|
||||||
var tmplArgs = opt_tmplArgs ? opt_tmplArgs : {
|
|
||||||
label: 'New ' + type,
|
|
||||||
name: newFieldName + '.value'
|
|
||||||
};
|
|
||||||
var newFieldInputRow = registry.util.renderBeforeRow(
|
|
||||||
'domain-' + type + 's-footer', tmpl, tmplArgs);
|
|
||||||
fieldElts.push(newFieldInputRow);
|
|
||||||
// Save the add/rem op type as a hidden elt for use by
|
|
||||||
// determine EPP add/remove semantics in subclasses.
|
|
||||||
// e.g. domain.js#saveItem()
|
|
||||||
var opElt = goog.dom.createDom(goog.dom.TagName.INPUT, {
|
|
||||||
'type': 'hidden',
|
|
||||||
'name': newFieldName + '.op',
|
|
||||||
'value': 'add'
|
|
||||||
});
|
|
||||||
newFieldInputRow.lastChild.appendChild(opElt);
|
|
||||||
if (opt_onAddFn) {
|
|
||||||
var elt = opt_onAddFn(newFieldName);
|
|
||||||
if (elt) {
|
|
||||||
fieldElts.push(elt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.appendRemoveBtn(
|
|
||||||
goog.dom.getLastElementChild(newFieldInputRow),
|
|
||||||
fieldElts,
|
|
||||||
goog.bind(function() {
|
|
||||||
this.typeCounts[type]--;
|
|
||||||
}, this));
|
|
||||||
this.typeCounts[type]++;
|
|
||||||
};
|
|
||||||
goog.events.listen(goog.dom.getRequiredElement(addBtnId),
|
|
||||||
goog.events.EventType.CLICK,
|
|
||||||
goog.bind(addButtonClickCallback, this));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper for making an element removable.
|
|
||||||
* @param {Element} parent The element to append the remove button to.
|
|
||||||
* @param {(Array.<Element>|function())=} opt_eltsToRemove
|
|
||||||
* Elements to remove when the button is clicked or Function to do
|
|
||||||
* the removing for full customization.
|
|
||||||
* @param {function()=} opt_cb callback will be called if no
|
|
||||||
* customized function is given.
|
|
||||||
*/
|
|
||||||
registry.Component.prototype.appendRemoveBtn =
|
|
||||||
function(parent, opt_eltsToRemove, opt_cb) {
|
|
||||||
var rmBtn = goog.dom.createDom(goog.dom.TagName.BUTTON,
|
|
||||||
goog.getCssName('kd-button'),
|
|
||||||
'Remove');
|
|
||||||
goog.dom.appendChild(parent, rmBtn);
|
|
||||||
var clickCb;
|
|
||||||
if (opt_eltsToRemove instanceof Function) {
|
|
||||||
clickCb = opt_eltsToRemove;
|
|
||||||
} else {
|
|
||||||
var eltsToRemove = opt_eltsToRemove ? opt_eltsToRemove : [parent];
|
|
||||||
clickCb = function() {
|
|
||||||
for (var i = 0; i < eltsToRemove.length; i++) {
|
|
||||||
goog.dom.removeNode(eltsToRemove[i]);
|
|
||||||
}
|
|
||||||
if (opt_cb) {
|
|
||||||
opt_cb();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
goog.events.listen(rmBtn, goog.events.EventType.CLICK, clickCb, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind the remove button action for the given container element.
|
|
||||||
* @param {!Element} containerElt
|
|
||||||
*/
|
|
||||||
registry.Component.prototype.enableRemoveButton = function(containerElt) {
|
|
||||||
var rmBtn = goog.dom.getElementByClass(
|
|
||||||
goog.getCssName('remove'), containerElt);
|
|
||||||
goog.dom.classlist.toggle(rmBtn, goog.getCssName('hidden'));
|
|
||||||
goog.events.listen(rmBtn, goog.events.EventType.CLICK, function() {
|
|
||||||
goog.dom.removeNode(goog.dom.getParentElement(rmBtn));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
|
@ -24,17 +24,15 @@ goog.require('goog.history.EventType');
|
||||||
goog.require('registry.util');
|
goog.require('registry.util');
|
||||||
|
|
||||||
goog.forwardDeclare('goog.events.KeyEvent');
|
goog.forwardDeclare('goog.events.KeyEvent');
|
||||||
goog.forwardDeclare('registry.Session');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract console for both admin and registrar console UIs.
|
* Abstract console for both admin and registrar console UIs.
|
||||||
* @param {?registry.Session} session server request session.
|
|
||||||
* @constructor
|
* @constructor
|
||||||
* @extends {goog.Disposable}
|
* @extends {goog.Disposable}
|
||||||
*/
|
*/
|
||||||
registry.Console = function(session) {
|
registry.Console = function() {
|
||||||
registry.Console.base(this, 'constructor');
|
registry.Console.base(this, 'constructor');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,19 +40,37 @@ registry.Console = function(session) {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
this.history = new goog.History();
|
this.history = new goog.History();
|
||||||
|
};
|
||||||
|
goog.inherits(registry.Console, goog.Disposable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the console's events and sets everything up.
|
||||||
|
*
|
||||||
|
* Should be called after the constructor.
|
||||||
|
*
|
||||||
|
* The reason this isn't done in the constructor is that this is a base class
|
||||||
|
* designed to be extended. We have to wait for the actual implementation to
|
||||||
|
* finish constructing before using it.
|
||||||
|
*/
|
||||||
|
registry.Console.prototype.setUp = function() {
|
||||||
goog.events.listen(
|
goog.events.listen(
|
||||||
this.history,
|
this.history,
|
||||||
goog.history.EventType.NAVIGATE,
|
goog.history.EventType.NAVIGATE,
|
||||||
goog.bind(this.handleHashChange, this));
|
goog.bind(this.handleHashChange, this));
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {?registry.Session} The server session.
|
|
||||||
*/
|
|
||||||
this.session = session;
|
|
||||||
|
|
||||||
this.bindToDom();
|
this.bindToDom();
|
||||||
|
|
||||||
|
// goog.History always starts off as "not enabled", meaning it doesn't trigger
|
||||||
|
// the listeners on change.
|
||||||
|
//
|
||||||
|
// When it's set to be enabled, it will start triggering the listeners on
|
||||||
|
// every change, but it also triggers the listeners immediately with the
|
||||||
|
// current history entry.
|
||||||
|
//
|
||||||
|
// This means the handleHashChange listener registered above will be called
|
||||||
|
// now.
|
||||||
|
this.history.setEnabled(true);
|
||||||
};
|
};
|
||||||
goog.inherits(registry.Console, goog.Disposable);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,6 +102,8 @@ registry.Console.prototype.handleHashChange = goog.abstractMethod;
|
||||||
* @param {string} resourcePath Resource description path.
|
* @param {string} resourcePath Resource description path.
|
||||||
*/
|
*/
|
||||||
registry.Console.prototype.view = function(resourcePath) {
|
registry.Console.prototype.view = function(resourcePath) {
|
||||||
|
// Setting the new history token will also trigger the handleHashChange
|
||||||
|
// listener registered in the setUp() function.
|
||||||
this.history.setToken(resourcePath);
|
this.history.setToken(resourcePath);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -305,9 +305,9 @@ registry.EditItem.prototype.prepareUpdate = goog.abstractMethod;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclasses should provide a function to parse either XML or JSON response
|
* Subclasses should provide a function to parse JSON response from server and
|
||||||
* from server and return a result object as described below.
|
* return a result object as described below.
|
||||||
* @param {!Object} rsp Decoded XML/JSON response from the server.
|
* @param {!Object} rsp Decoded JSON response from the server.
|
||||||
* @return {!Object} a result object describing next steps. On
|
* @return {!Object} a result object describing next steps. On
|
||||||
* success, if next is defined, visit(ret.next) is called, otherwise
|
* success, if next is defined, visit(ret.next) is called, otherwise
|
||||||
* if err is set, the butterbar message is set to it.
|
* if err is set, the butterbar message is set to it.
|
||||||
|
|
|
@ -22,13 +22,9 @@ goog.require('goog.net.XhrIo');
|
||||||
goog.require('registry.Console');
|
goog.require('registry.Console');
|
||||||
goog.require('registry.Resource');
|
goog.require('registry.Resource');
|
||||||
goog.require('registry.registrar.AdminSettings');
|
goog.require('registry.registrar.AdminSettings');
|
||||||
goog.require('registry.registrar.Contact');
|
|
||||||
goog.require('registry.registrar.ContactSettings');
|
goog.require('registry.registrar.ContactSettings');
|
||||||
goog.require('registry.registrar.ContactUs');
|
goog.require('registry.registrar.ContactUs');
|
||||||
goog.require('registry.registrar.Dashboard');
|
goog.require('registry.registrar.Dashboard');
|
||||||
goog.require('registry.registrar.Domain');
|
|
||||||
goog.require('registry.registrar.EppSession');
|
|
||||||
goog.require('registry.registrar.Host');
|
|
||||||
goog.require('registry.registrar.Resources');
|
goog.require('registry.registrar.Resources');
|
||||||
goog.require('registry.registrar.SecuritySettings');
|
goog.require('registry.registrar.SecuritySettings');
|
||||||
goog.require('registry.registrar.WhoisSettings');
|
goog.require('registry.registrar.WhoisSettings');
|
||||||
|
@ -49,16 +45,13 @@ goog.forwardDeclare('registry.Component');
|
||||||
* @final
|
* @final
|
||||||
*/
|
*/
|
||||||
registry.registrar.Console = function(params) {
|
registry.registrar.Console = function(params) {
|
||||||
|
registry.registrar.Console.base(this, 'constructor');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {!Object}
|
* @type {!Object}
|
||||||
*/
|
*/
|
||||||
// We have to define this before creating an EppSession because EppSession's
|
|
||||||
// constructor expects us to have it as an attribute.
|
|
||||||
this.params = params;
|
this.params = params;
|
||||||
|
|
||||||
registry.registrar.Console.base(
|
|
||||||
this, 'constructor', new registry.registrar.EppSession(this));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that's currently embedded in the page.
|
* Component that's currently embedded in the page.
|
||||||
* @type {?registry.Component}
|
* @type {?registry.Component}
|
||||||
|
@ -66,13 +59,9 @@ registry.registrar.Console = function(params) {
|
||||||
*/
|
*/
|
||||||
this.component_ = null;
|
this.component_ = null;
|
||||||
|
|
||||||
// XXX: This was in parent ctor but was triggering event dispatching before
|
|
||||||
// ready here.
|
|
||||||
this.history.setEnabled(true);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Last active nav element.
|
* Last active nav element.
|
||||||
* @type {Element}
|
* @type {?Element}
|
||||||
*/
|
*/
|
||||||
this.lastActiveNavElt;
|
this.lastActiveNavElt;
|
||||||
|
|
||||||
|
@ -107,13 +96,6 @@ registry.registrar.Console = function(params) {
|
||||||
if (this.params.isAdmin) {
|
if (this.params.isAdmin) {
|
||||||
this.pageMap['admin-settings'] = registry.registrar.AdminSettings;
|
this.pageMap['admin-settings'] = registry.registrar.AdminSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sending EPPs through the console. Currently hidden (doesn't have a "tab")
|
|
||||||
// but still accessible if the user manually puts #domain (or other) in the
|
|
||||||
// fragment
|
|
||||||
this.pageMap['contact'] = registry.registrar.Contact;
|
|
||||||
this.pageMap['domain'] = registry.registrar.Domain;
|
|
||||||
this.pageMap['host'] = registry.registrar.Host;
|
|
||||||
};
|
};
|
||||||
goog.inherits(registry.registrar.Console, registry.Console);
|
goog.inherits(registry.registrar.Console, registry.Console);
|
||||||
|
|
||||||
|
@ -134,17 +116,7 @@ goog.inherits(registry.registrar.Console, registry.Console);
|
||||||
*/
|
*/
|
||||||
registry.registrar.Console.prototype.handleHashChange = function() {
|
registry.registrar.Console.prototype.handleHashChange = function() {
|
||||||
var hashToken = this.history.getToken();
|
var hashToken = this.history.getToken();
|
||||||
// On page reloads, opening a new tab, etc. it's possible that the
|
|
||||||
// session cookie for a logged-in session exists, but the
|
|
||||||
// this.session is not yet aware, so come back here after syncing.
|
|
||||||
//
|
|
||||||
// XXX: Method should be refactored to avoid this 2-stage behavior.
|
|
||||||
if (!this.session.isEppLoggedIn()) {
|
|
||||||
this.session.login(goog.bind(this.handleHashChange, this));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, a resource operation.
|
|
||||||
var parts = hashToken.split('/');
|
var parts = hashToken.split('/');
|
||||||
var type = '';
|
var type = '';
|
||||||
var id = '';
|
var id = '';
|
||||||
|
|
|
@ -1,129 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
goog.provide('registry.registrar.Contact');
|
|
||||||
|
|
||||||
goog.require('goog.dom');
|
|
||||||
goog.require('registry.registrar.XmlResourceComponent');
|
|
||||||
goog.require('registry.soy.registrar.contact');
|
|
||||||
goog.require('registry.soy.registrar.contactepp');
|
|
||||||
|
|
||||||
goog.forwardDeclare('registry.registrar.Console');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The `Contact` class respresents a registry contact object and
|
|
||||||
* binds UI CRUD operations to it.
|
|
||||||
* @param {!registry.registrar.Console} console the
|
|
||||||
* console singleton.
|
|
||||||
* @constructor
|
|
||||||
* @extends {registry.registrar.XmlResourceComponent}
|
|
||||||
* @final
|
|
||||||
*/
|
|
||||||
registry.registrar.Contact = function(console) {
|
|
||||||
registry.registrar.Contact.base(
|
|
||||||
this, 'constructor',
|
|
||||||
/** @type {function()} */(registry.soy.registrar.contact.item),
|
|
||||||
registry.soy.registrar.contactepp,
|
|
||||||
console);
|
|
||||||
};
|
|
||||||
goog.inherits(registry.registrar.Contact,
|
|
||||||
registry.registrar.XmlResourceComponent);
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Contact.prototype.processItem = function() {
|
|
||||||
this.model.item = this.model['epp']['response']['resData']['contact:infData'];
|
|
||||||
if (!goog.isArray(this.model.item['contact:postalInfo'])) {
|
|
||||||
this.model.item['contact:postalInfo'] =
|
|
||||||
[this.model.item['contact:postalInfo']];
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: Is this code necessary?
|
|
||||||
var fixPlus = function(val) {
|
|
||||||
var str = (val || '') + '';
|
|
||||||
if (str == '' || str.match(/\+.*/)) {
|
|
||||||
return str;
|
|
||||||
} else {
|
|
||||||
return '+' + str;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Both of these are optional.
|
|
||||||
if (this.model.item['contact:voice']) {
|
|
||||||
this.model.item['contact:voice']['keyValue'] =
|
|
||||||
fixPlus(this.model.item['contact:voice']['keyValue']);
|
|
||||||
}
|
|
||||||
if (this.model.item['contact:voice']) {
|
|
||||||
this.model.item['contact:fax']['keyValue'] =
|
|
||||||
fixPlus(this.model.item['contact:fax']['keyValue']);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Contact.prototype.setupEditor = function(objArgs) {
|
|
||||||
// For now always keep the first contact and make it i18n. Toggle button
|
|
||||||
// disables to enforce state.
|
|
||||||
//
|
|
||||||
// XXX: Should be simplified to make more modular.
|
|
||||||
var postalElt = goog.dom.getRequiredElement('contact-postalInfo');
|
|
||||||
var addPostalInfoBtn = goog.dom.getRequiredElement(
|
|
||||||
'domain-contact-postalInfo-add-button');
|
|
||||||
this.typeCounts['contact-postalInfo'] = postalElt.childNodes.length;
|
|
||||||
// 4 child nodes means both addresses are present:
|
|
||||||
// 2 data tables, the footer id elt and a hidden input.
|
|
||||||
var setupRemoveBtns = this.typeCounts['contact-postalInfo'] == 4;
|
|
||||||
if (setupRemoveBtns) {
|
|
||||||
this.appendRemoveBtn(/** @type {!Element} */ (postalElt.childNodes[0]));
|
|
||||||
this.appendRemoveBtn(/** @type {!Element} */ (postalElt.childNodes[1]));
|
|
||||||
} else {
|
|
||||||
addPostalInfoBtn.removeAttribute('disabled');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.addRemBtnHandlers(
|
|
||||||
'contact-postalInfo',
|
|
||||||
function() {
|
|
||||||
return 'contact:postalInfo[1].contact:';
|
|
||||||
},
|
|
||||||
function() {
|
|
||||||
addPostalInfoBtn.setAttribute('disabled', true);
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
/** @type {function()} */ (registry.soy.registrar.contact.postalInfo),
|
|
||||||
{
|
|
||||||
item: {},
|
|
||||||
localized: true,
|
|
||||||
itemPrefix: 'contact:',
|
|
||||||
namePrefix: 'contact:postalInfo[1].contact:'
|
|
||||||
},
|
|
||||||
setupRemoveBtns);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Contact.prototype.prepareCreate = function(params) {
|
|
||||||
params.nextId = params.item['contact:id'];
|
|
||||||
return registry.soy.registrar.contactepp.create(
|
|
||||||
/** @type {{clTrid: ?, item: ?}} */ (params)).toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Contact.prototype.prepareUpdate = function(params) {
|
|
||||||
params.nextId = params.item['contact:id'];
|
|
||||||
return registry.soy.registrar.contactepp.update(
|
|
||||||
/** @type {{clTrid: ?, item: ?}} */(params)).toString();
|
|
||||||
};
|
|
|
@ -221,7 +221,7 @@ registry.registrar.ContactSettings.prototype.prepareUpdate =
|
||||||
* Handler for contact save that navigates to that item on success.
|
* Handler for contact save that navigates to that item on success.
|
||||||
* Does nothing on failure as UI will be left with error messages for
|
* Does nothing on failure as UI will be left with error messages for
|
||||||
* the user to resolve.
|
* the user to resolve.
|
||||||
* @param {!Object} rsp Decoded XML/JSON response from the server.
|
* @param {!Object} rsp Decoded JSON response from the server.
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
registry.registrar.ContactSettings.prototype.handleCreateResponse =
|
registry.registrar.ContactSettings.prototype.handleCreateResponse =
|
||||||
|
@ -238,7 +238,7 @@ registry.registrar.ContactSettings.prototype.handleCreateResponse =
|
||||||
* Handler for contact delete that navigates back to the collection on success.
|
* Handler for contact delete that navigates back to the collection on success.
|
||||||
* Does nothing on failure as UI will be left with error messages for
|
* Does nothing on failure as UI will be left with error messages for
|
||||||
* the user to resolve.
|
* the user to resolve.
|
||||||
* @param {!Object} rsp Decoded XML/JSON response from the server.
|
* @param {!Object} rsp Decoded JSON response from the server.
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
registry.registrar.ContactSettings.prototype.handleDeleteResponse =
|
registry.registrar.ContactSettings.prototype.handleDeleteResponse =
|
||||||
|
|
|
@ -40,10 +40,10 @@ registry.registrar.Dashboard = function(console) {
|
||||||
/** @private {number} */
|
/** @private {number} */
|
||||||
this.x_ = 0;
|
this.x_ = 0;
|
||||||
|
|
||||||
/** @private {Element} */
|
/** @private {?Element} */
|
||||||
this.gear_ = null;
|
this.gear_ = null;
|
||||||
|
|
||||||
/** @private {goog.Timer} */
|
/** @private {?goog.Timer} */
|
||||||
this.timer_ = null;
|
this.timer_ = null;
|
||||||
};
|
};
|
||||||
goog.inherits(registry.registrar.Dashboard, registry.Component);
|
goog.inherits(registry.registrar.Dashboard, registry.Component);
|
||||||
|
@ -63,14 +63,6 @@ registry.registrar.Dashboard.prototype.bindToDom = function(id) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do EPP logout.
|
|
||||||
*/
|
|
||||||
registry.registrar.Dashboard.prototype.doEppLogout = function() {
|
|
||||||
this.console.session.logout();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Let's do the twist.
|
* Let's do the twist.
|
||||||
* @private
|
* @private
|
||||||
|
|
|
@ -1,167 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
goog.provide('registry.registrar.Domain');
|
|
||||||
|
|
||||||
goog.require('goog.json');
|
|
||||||
goog.require('registry.registrar.XmlResourceComponent');
|
|
||||||
goog.require('registry.soy.forms');
|
|
||||||
goog.require('registry.soy.registrar.domain');
|
|
||||||
goog.require('registry.soy.registrar.domainepp');
|
|
||||||
goog.require('registry.util');
|
|
||||||
|
|
||||||
goog.forwardDeclare('registry.registrar.Console');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CRUD for EPP domain objects.
|
|
||||||
* @param {!registry.registrar.Console} console
|
|
||||||
* @constructor
|
|
||||||
* @extends {registry.registrar.XmlResourceComponent}
|
|
||||||
* @final
|
|
||||||
*/
|
|
||||||
registry.registrar.Domain = function(console) {
|
|
||||||
registry.registrar.Domain.base(
|
|
||||||
this, 'constructor',
|
|
||||||
/** @type {function()} */ (registry.soy.registrar.domain.item),
|
|
||||||
registry.soy.registrar.domainepp,
|
|
||||||
console);
|
|
||||||
};
|
|
||||||
goog.inherits(registry.registrar.Domain,
|
|
||||||
registry.registrar.XmlResourceComponent);
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Domain.prototype.newModel = function() {
|
|
||||||
var newModel = {item: {'domain:period': ''}};
|
|
||||||
return newModel;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepare a fetch query for the domain by its id.
|
|
||||||
* @param {!Object} params should have a name field with a
|
|
||||||
* possibly extended domain name id of the form "example.tld:1234"
|
|
||||||
* where the 1234 is the domain application id assigned by the
|
|
||||||
* backend flows.
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
registry.registrar.Domain.prototype.prepareFetch = function(params) {
|
|
||||||
return registry.soy.registrar.domainepp.info(
|
|
||||||
/** @type {{clTrid: ?, id: ?}} */ (params)).toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Domain.prototype.processItem = function() {
|
|
||||||
this.model.item = this.model['epp']['response']['resData']['domain:infData'];
|
|
||||||
// Hoist extensions for easy soy access.
|
|
||||||
var extension = this.model['epp']['response']['extension'];
|
|
||||||
if (extension && extension['launch:infData']) {
|
|
||||||
var extendedInfData = extension['launch:infData'];
|
|
||||||
|
|
||||||
var mark = extendedInfData['mark:mark'];
|
|
||||||
if (mark) {
|
|
||||||
this.model.item['mark:mark'] = {'keyValue': goog.json.serialize(mark)};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap single item into an array.
|
|
||||||
if (this.model.item['domain:ns'] &&
|
|
||||||
this.model.item['domain:ns']['domain:hostObj']) {
|
|
||||||
var hostObj = this.model.item['domain:ns']['domain:hostObj'];
|
|
||||||
if (!goog.isArray(hostObj)) {
|
|
||||||
this.model.item['domain:ns']['domain:hostObj'] = [hostObj];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Domain.prototype.setupEditor = function(objArgs) {
|
|
||||||
this.typeCounts['contact'] = objArgs.item['domain:contact'] ?
|
|
||||||
objArgs.item['domain:contact'].length : 0;
|
|
||||||
|
|
||||||
var ji = objArgs.item['domain:ns'];
|
|
||||||
this.typeCounts['host'] =
|
|
||||||
ji && ji['domain:hostObj'] ? ji['domain:hostObj'].length : 0;
|
|
||||||
|
|
||||||
this.formInputRowRemovable(
|
|
||||||
document.querySelectorAll('input.domain-hostObj[readonly]'));
|
|
||||||
|
|
||||||
this.formInputRowRemovable(
|
|
||||||
document.querySelectorAll('input.domain-contact[readonly]'));
|
|
||||||
|
|
||||||
this.addRemBtnHandlers(
|
|
||||||
'contact',
|
|
||||||
goog.bind(function() {
|
|
||||||
return 'domain:contact[' + this.typeCounts['contact'] + ']';
|
|
||||||
}, this),
|
|
||||||
goog.bind(function(newFieldName) {
|
|
||||||
return registry.util.renderBeforeRow(
|
|
||||||
'domain-contacts-footer',
|
|
||||||
/** @type {function()} */(registry.soy.forms.selectRow), {
|
|
||||||
label: 'Type',
|
|
||||||
name: newFieldName + '.@type',
|
|
||||||
options: ['admin', 'tech', 'billing']
|
|
||||||
});
|
|
||||||
}, this));
|
|
||||||
|
|
||||||
this.addRemBtnHandlers('host', goog.bind(function() {
|
|
||||||
return 'domain:ns.domain:hostObj[' + this.typeCounts['host'] + ']';
|
|
||||||
}, this));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Domain.prototype.prepareCreate = function(params) {
|
|
||||||
var form = params.item;
|
|
||||||
params.nextId = form['domain:name'];
|
|
||||||
|
|
||||||
// The presence of this field is used to signal extended template, so remove
|
|
||||||
// if not used.
|
|
||||||
if (form['smd:encodedSignedMark'] == '') {
|
|
||||||
delete form['smd:encodedSignedMark'];
|
|
||||||
}
|
|
||||||
var xml = registry.soy.registrar.domainepp.create(
|
|
||||||
/** @type {{clTrid: ?, item: ?}} */(params));
|
|
||||||
return xml.toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Domain.prototype.prepareUpdate =
|
|
||||||
function(params) {
|
|
||||||
var form = params.item;
|
|
||||||
var nextId = form['domain:name'];
|
|
||||||
params.nextId = nextId;
|
|
||||||
|
|
||||||
if (form['domain:contact']) {
|
|
||||||
this.addRem(form['domain:contact'], 'Contacts', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (form['domain:ns'] && form['domain:ns']['domain:hostObj']) {
|
|
||||||
this.addRem(form['domain:ns']['domain:hostObj'], 'Hosts', params);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (form['domain:ns'] && form['domain:ns']['domain:hostObj']) {
|
|
||||||
this.addRem(form['domain:ns']['domain:hostObj'], 'Hosts', params);
|
|
||||||
}
|
|
||||||
this.addRem(form['domain:contact'], 'Contacts', params);
|
|
||||||
var xml = registry.soy.registrar.domainepp.update(
|
|
||||||
/** @type {{clTrid: ?, item: ?}} */(params));
|
|
||||||
|
|
||||||
return xml.toString();
|
|
||||||
};
|
|
|
@ -1,128 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
goog.provide('registry.registrar.EppSession');
|
|
||||||
|
|
||||||
goog.require('goog.Uri');
|
|
||||||
goog.require('registry.Session');
|
|
||||||
goog.require('registry.soy.registrar.epp');
|
|
||||||
goog.require('registry.util');
|
|
||||||
goog.require('registry.xml');
|
|
||||||
|
|
||||||
goog.forwardDeclare('registry.registrar.Console');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Session state for console.
|
|
||||||
* @param {!registry.registrar.Console} console
|
|
||||||
* @constructor
|
|
||||||
* @extends {registry.Session}
|
|
||||||
* @final
|
|
||||||
*/
|
|
||||||
registry.registrar.EppSession = function(console) {
|
|
||||||
registry.registrar.EppSession.base(
|
|
||||||
this, 'constructor',
|
|
||||||
new goog.Uri('/registrar-xhr')
|
|
||||||
.setParameterValue('clientId', console.params.clientId),
|
|
||||||
console.params.xsrfToken,
|
|
||||||
registry.Session.ContentType.EPP);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {!registry.registrar.Console}
|
|
||||||
*/
|
|
||||||
this.console = console;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type {!boolean}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
this.isEppLoggedIn_ = false;
|
|
||||||
};
|
|
||||||
goog.inherits(registry.registrar.EppSession, registry.Session);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the session has received an EPP success response to an EPP
|
|
||||||
* login attempt.
|
|
||||||
* @return {boolean} Whether the user is logged into an EPP session.
|
|
||||||
*/
|
|
||||||
registry.registrar.EppSession.prototype.isEppLoggedIn = function() {
|
|
||||||
return this.isEppLoggedIn_;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the clientId if the user is logged in, or throw Error.
|
|
||||||
* @throws Error if the user is not logged in.
|
|
||||||
* @return {string} the clientId.
|
|
||||||
*/
|
|
||||||
registry.registrar.EppSession.prototype.getClientId = function() {
|
|
||||||
return this.console.params.clientId;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Login or display butterbar info about error.
|
|
||||||
* @param {function()} successCb to be called on success.
|
|
||||||
*/
|
|
||||||
registry.registrar.EppSession.prototype.login = function(successCb) {
|
|
||||||
var eppArgs = {clId: this.console.params.clientId, clTrid: 'asdf-1235'};
|
|
||||||
this.send(
|
|
||||||
registry.soy.registrar.epp.login(eppArgs).getContent(),
|
|
||||||
goog.bind(function(xml) {
|
|
||||||
var result = xml['epp']['response']['result'];
|
|
||||||
var eppCode = result['@code'];
|
|
||||||
if (eppCode == '1000' || eppCode == '2002') {
|
|
||||||
// Success || Already logged in.
|
|
||||||
this.isEppLoggedIn_ = true;
|
|
||||||
successCb();
|
|
||||||
} else {
|
|
||||||
// Failure.
|
|
||||||
this.isEppLoggedIn_ = false;
|
|
||||||
registry.util.butter('login error: ' + eppCode);
|
|
||||||
}
|
|
||||||
}, this));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logout or display butterbar info about error.
|
|
||||||
*/
|
|
||||||
registry.registrar.EppSession.prototype.logout = function() {
|
|
||||||
this.send(
|
|
||||||
registry.soy.registrar.epp.logout(
|
|
||||||
{clTrid: 'asdf-1235'}).getContent(),
|
|
||||||
goog.bind(function(xml) {
|
|
||||||
var result = xml['epp']['response']['result'];
|
|
||||||
var eppCode = result['@code'];
|
|
||||||
registry.util.butter(
|
|
||||||
'logout ' + eppCode + ': ' + result['msg']['keyValue']);
|
|
||||||
// Going to be safe here and force a login either way.
|
|
||||||
this.isEppLoggedIn_ = false;
|
|
||||||
}, this));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send xml to the server.
|
|
||||||
* @param {string} xml Request document.
|
|
||||||
* @param {function(!Object)} callback For XhrIo result throws.
|
|
||||||
*/
|
|
||||||
registry.registrar.EppSession.prototype.send = function(xml, callback) {
|
|
||||||
var toXmlJsonCb = function(rspXml) {
|
|
||||||
callback(registry.xml.convertToJson(rspXml));
|
|
||||||
};
|
|
||||||
this.sendXhrIo(xml, toXmlJsonCb);
|
|
||||||
};
|
|
|
@ -1,107 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
goog.provide('registry.registrar.Host');
|
|
||||||
|
|
||||||
goog.require('registry.registrar.XmlResourceComponent');
|
|
||||||
goog.require('registry.soy.registrar.host');
|
|
||||||
goog.require('registry.soy.registrar.hostepp');
|
|
||||||
|
|
||||||
goog.forwardDeclare('registry.registrar.Console');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CRUD for EPP host objects.
|
|
||||||
* @param {!registry.registrar.Console} console
|
|
||||||
* @constructor
|
|
||||||
* @extends {registry.registrar.XmlResourceComponent}
|
|
||||||
* @final
|
|
||||||
*/
|
|
||||||
registry.registrar.Host = function(console) {
|
|
||||||
registry.registrar.Host.base(
|
|
||||||
this, 'constructor',
|
|
||||||
registry.soy.registrar.host.item,
|
|
||||||
registry.soy.registrar.hostepp,
|
|
||||||
console);
|
|
||||||
};
|
|
||||||
goog.inherits(registry.registrar.Host,
|
|
||||||
registry.registrar.XmlResourceComponent);
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Host.prototype.processItem = function() {
|
|
||||||
this.model.item = this.model['epp']['response']['resData']['host:infData'];
|
|
||||||
if (this.model.item['host:addr']) {
|
|
||||||
if (!goog.isArray(this.model.item['host:addr'])) {
|
|
||||||
this.model.item['host:addr'] = [this.model.item['host:addr']];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.model.item['host:addr'] = [];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Host.prototype.setupEditor = function(objArgs) {
|
|
||||||
this.typeCounts['host-addr'] =
|
|
||||||
objArgs.item['host:addr'] ? objArgs.item['host:addr'].length : 0;
|
|
||||||
this.addRemBtnHandlers('host-addr', goog.bind(function() {
|
|
||||||
return 'host:addr[' + this.typeCounts['host-addr'] + ']';
|
|
||||||
}, this));
|
|
||||||
|
|
||||||
this.formInputRowRemovable(document.querySelectorAll('input[readonly]'));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Host.prototype.prepareCreate = function(params) {
|
|
||||||
params.nextId = params.item['host:name'];
|
|
||||||
return registry.soy.registrar.hostepp.create(
|
|
||||||
/** @type {{clTrid: ?, item: ?}} */(params)).toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.Host.prototype.prepareUpdate = function(params) {
|
|
||||||
var form = params.item;
|
|
||||||
var addAddrs = [];
|
|
||||||
var remAddrs = [];
|
|
||||||
if (form['host:addr']) {
|
|
||||||
var oldAddrs = form['host:oldAddr'] || [];
|
|
||||||
var newAddrs = form['host:addr'];
|
|
||||||
var length = Math.max(oldAddrs.length, newAddrs.length);
|
|
||||||
for (var i = 0; i < length; i++) {
|
|
||||||
if (i >= oldAddrs.length) {
|
|
||||||
addAddrs.push(newAddrs[i]['value']);
|
|
||||||
} else if (i >= newAddrs.length) {
|
|
||||||
remAddrs.push(oldAddrs[i]['value']);
|
|
||||||
} else {
|
|
||||||
if (newAddrs[i]['value'] == oldAddrs[i]['value']) {
|
|
||||||
// Do nothing.
|
|
||||||
} else if (newAddrs[i]['value'] == '') {
|
|
||||||
remAddrs.push(oldAddrs[i]['value']);
|
|
||||||
} else {
|
|
||||||
remAddrs.push(oldAddrs[i]['value']);
|
|
||||||
addAddrs.push(newAddrs[i]['value']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
params.addAddrs = addAddrs;
|
|
||||||
params.remAddrs = remAddrs;
|
|
||||||
params.nextId = form['host:chgName'];
|
|
||||||
return registry.soy.registrar.hostepp.update(
|
|
||||||
/** @type {{clTrid: ?, item: ?}} */(params)).toString();
|
|
||||||
};
|
|
|
@ -38,11 +38,10 @@ goog.require('registry.registrar.Console');
|
||||||
* @param {string} technicalDocsUrl
|
* @param {string} technicalDocsUrl
|
||||||
* @export
|
* @export
|
||||||
*/
|
*/
|
||||||
registry.registrar.main = function(xsrfToken, clientId, isAdmin, isOwner,
|
registry.registrar.main = function(
|
||||||
productName, integrationEmail, supportEmail,
|
xsrfToken, clientId, isAdmin, isOwner, productName, integrationEmail,
|
||||||
announcementsEmail, supportPhoneNumber,
|
supportEmail, announcementsEmail, supportPhoneNumber, technicalDocsUrl) {
|
||||||
technicalDocsUrl) {
|
const console = new registry.registrar.Console({
|
||||||
new registry.registrar.Console({
|
|
||||||
xsrfToken: xsrfToken,
|
xsrfToken: xsrfToken,
|
||||||
clientId: clientId,
|
clientId: clientId,
|
||||||
isAdmin: isAdmin,
|
isAdmin: isAdmin,
|
||||||
|
@ -54,4 +53,6 @@ registry.registrar.main = function(xsrfToken, clientId, isAdmin, isOwner,
|
||||||
supportPhoneNumber: supportPhoneNumber,
|
supportPhoneNumber: supportPhoneNumber,
|
||||||
technicalDocsUrl: technicalDocsUrl
|
technicalDocsUrl: technicalDocsUrl
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.setUp();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,219 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
goog.provide('registry.registrar.XmlResourceComponent');
|
|
||||||
|
|
||||||
goog.require('goog.dom');
|
|
||||||
goog.require('goog.dom.TagName');
|
|
||||||
goog.require('goog.dom.classlist');
|
|
||||||
goog.require('registry.EditItem');
|
|
||||||
goog.require('registry.util');
|
|
||||||
|
|
||||||
goog.forwardDeclare('registry.registrar.Console');
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The ResourceComponent class respresents server state for a named
|
|
||||||
* resource and binds UI CRUD operations on it, or its constituent
|
|
||||||
* collection.
|
|
||||||
* @param {function()} itemTmpl
|
|
||||||
* @param {!Object} eppTmpls Epp xml templates for info requests.
|
|
||||||
* @param {!registry.registrar.Console} console
|
|
||||||
* @constructor
|
|
||||||
* @extends {registry.EditItem}
|
|
||||||
*/
|
|
||||||
registry.registrar.XmlResourceComponent = function(
|
|
||||||
itemTmpl, eppTmpls, console) {
|
|
||||||
registry.registrar.XmlResourceComponent.base(
|
|
||||||
this, 'constructor', console, itemTmpl, console.params.isOwner);
|
|
||||||
|
|
||||||
/** @type {!Object} */
|
|
||||||
this.eppTmpls = eppTmpls;
|
|
||||||
};
|
|
||||||
goog.inherits(registry.registrar.XmlResourceComponent, registry.EditItem);
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.XmlResourceComponent.prototype.bindToDom =
|
|
||||||
function(id) {
|
|
||||||
// XXX: EPP resources still use null state.
|
|
||||||
registry.registrar.XmlResourceComponent.base(
|
|
||||||
this, 'bindToDom', (id || ''));
|
|
||||||
if (id) {
|
|
||||||
this.fetchItem(id);
|
|
||||||
} else {
|
|
||||||
// Start edit of empty object.
|
|
||||||
this.edit();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.XmlResourceComponent.prototype.fetchItem = function(id) {
|
|
||||||
var queryParams = {id: id, clTrid: 'abc-1234'};
|
|
||||||
var xml = this.prepareFetch(queryParams);
|
|
||||||
this.console.session.send(xml, goog.bind(this.handleFetchItem, this, id));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.XmlResourceComponent.prototype.handleFetchItem =
|
|
||||||
function(id, rsp) {
|
|
||||||
this.model = rsp;
|
|
||||||
var result = rsp['epp']['response']['result'];
|
|
||||||
var resCode = result['@code'];
|
|
||||||
// XXX: Should use enum.
|
|
||||||
if (resCode == 1000) { // OK
|
|
||||||
this.model.readonly = true;
|
|
||||||
this.processItem();
|
|
||||||
this.renderItem(this.model);
|
|
||||||
} else if (resCode == 2303) { // Missing
|
|
||||||
registry.util.butter(
|
|
||||||
'Could not find: "' + id + '". Please enter as "type/id"');
|
|
||||||
} else {
|
|
||||||
// includes general failure.
|
|
||||||
registry.util.butter(resCode + ':' + result['msg']['keyValue']);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sublcasses should override to populate create queryParams with form
|
|
||||||
* fields as needed. `queryParams.nextId` MUST be set to the
|
|
||||||
* new object's ID.
|
|
||||||
* @param {!Object} queryParams
|
|
||||||
*/
|
|
||||||
registry.registrar.XmlResourceComponent.prototype.prepareCreate =
|
|
||||||
goog.abstractMethod;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls prepareCreate with template params and then send the returned
|
|
||||||
* XML to the server
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
registry.registrar.XmlResourceComponent.prototype.sendCreate = function() {
|
|
||||||
var form = registry.util.parseForm('item');
|
|
||||||
var queryParams = {item: form, clTrid: 'abc-1234'};
|
|
||||||
var xml = this.prepareCreate(queryParams);
|
|
||||||
this.nextId = queryParams.nextId;
|
|
||||||
this.console.session.send(xml, goog.bind(this.handleUpdateResponse, this));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calls prepareUpdate with template params and then send the returned
|
|
||||||
* XML to the server.
|
|
||||||
* @override
|
|
||||||
*/
|
|
||||||
registry.registrar.XmlResourceComponent.prototype.sendUpdate = function() {
|
|
||||||
var form = registry.util.parseForm('item');
|
|
||||||
var queryParams = {item: form, clTrid: 'abc-1234'};
|
|
||||||
var xml = this.prepareUpdate(queryParams);
|
|
||||||
this.nextId = queryParams.nextId;
|
|
||||||
this.console.session.send(xml, goog.bind(this.handleUpdateResponse, this));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sublcasses should override to populate fetch queryParams with form
|
|
||||||
* fields as needed.
|
|
||||||
* @param {!Object} queryParams
|
|
||||||
* @return {string} EPP xml string
|
|
||||||
*/
|
|
||||||
registry.registrar.XmlResourceComponent.prototype.prepareFetch =
|
|
||||||
function(queryParams) {
|
|
||||||
return this.eppTmpls.info(queryParams).toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
registry.registrar.XmlResourceComponent.prototype.handleUpdateResponse =
|
|
||||||
function(rsp) {
|
|
||||||
var result = rsp['epp']['response']['result'];
|
|
||||||
if (result['@code'] == 1000) {
|
|
||||||
// XXX: Consider timer, probably just as a seconds arg with impl in butter.
|
|
||||||
registry.util.butter('Saved.');
|
|
||||||
this.fetchItem(this.nextId || '');
|
|
||||||
this.nextId = null;
|
|
||||||
this.toggleEdit();
|
|
||||||
} else {
|
|
||||||
registry.util.butter(result['msg']['keyValue']);
|
|
||||||
}
|
|
||||||
return rsp;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper to add add/remove hosts/contacts on queryParams:
|
|
||||||
*
|
|
||||||
* queryParams[op + fieldType] = formFields.
|
|
||||||
*
|
|
||||||
* @param {Array.<Object>} formFields named form item representations
|
|
||||||
* that have an associated {op: (add|rem)} attribute.
|
|
||||||
* @param {string} fieldType capitalized pluralized type name, e.g. "Contacts".
|
|
||||||
* @param {!Object} queryParams
|
|
||||||
*/
|
|
||||||
registry.registrar.XmlResourceComponent.prototype.addRem =
|
|
||||||
function(formFields, fieldType, queryParams) {
|
|
||||||
var add = [];
|
|
||||||
var rem = [];
|
|
||||||
for (var i = 0; i < formFields.length; i++) {
|
|
||||||
var formField = formFields[i];
|
|
||||||
var op = formField['op'];
|
|
||||||
switch (op) {
|
|
||||||
case 'add':
|
|
||||||
add.push(formField);
|
|
||||||
break;
|
|
||||||
case 'rem':
|
|
||||||
rem.push(formField);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
registry.util.log(
|
|
||||||
'Unknown op attribute ' + op + ' on form field:',
|
|
||||||
formField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (add.length > 0) {
|
|
||||||
queryParams['add' + fieldType] = add;
|
|
||||||
}
|
|
||||||
if (rem.length > 0) {
|
|
||||||
queryParams['rem' + fieldType] = rem;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make the given form input rows removable.
|
|
||||||
* @param {NodeList} elts array of input elements.
|
|
||||||
* @param {function()=} opt_onclickCb called when remove button is clicked.
|
|
||||||
*/
|
|
||||||
registry.registrar.XmlResourceComponent.prototype.formInputRowRemovable =
|
|
||||||
function(elts, opt_onclickCb) {
|
|
||||||
for (var i = 0; i < elts.length; i++) {
|
|
||||||
var parent = goog.dom.getParentElement(elts[i]);
|
|
||||||
this.appendRemoveBtn(parent, goog.partial(function(elt) {
|
|
||||||
var eppRemInput = goog.dom.createDom(goog.dom.TagName.INPUT, {
|
|
||||||
'name': elt.name.replace(/\.value/, '.op'),
|
|
||||||
'value': 'rem',
|
|
||||||
'type': 'hidden'
|
|
||||||
});
|
|
||||||
goog.dom.appendChild(goog.dom.getParentElement(elt), eppRemInput);
|
|
||||||
goog.dom.classlist.add(
|
|
||||||
goog.dom.getParentElement(
|
|
||||||
goog.dom.getParentElement(elt)), goog.getCssName('hidden'));
|
|
||||||
}, elts[i]));
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -31,8 +31,7 @@ goog.forwardDeclare('goog.Uri');
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
registry.Resource = function(baseUri, id, xsrfToken) {
|
registry.Resource = function(baseUri, id, xsrfToken) {
|
||||||
registry.Resource.base(this, 'constructor', baseUri, xsrfToken,
|
registry.Resource.base(this, 'constructor', baseUri, xsrfToken);
|
||||||
registry.Session.ContentType.JSON);
|
|
||||||
/** @const @private {string} the ID of the target resource. */
|
/** @const @private {string} the ID of the target resource. */
|
||||||
this.id_ = id;
|
this.id_ = id;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,14 +23,13 @@ goog.forwardDeclare('goog.Uri');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XHR launcher for both JSON and XML requests.
|
* XHR launcher for JSON requests.
|
||||||
* @param {!goog.Uri} defaultUri URI to which requests are POSTed.
|
* @param {!goog.Uri} defaultUri URI to which requests are POSTed.
|
||||||
* @param {string} xsrfToken Cross-site request forgery protection token.
|
* @param {string} xsrfToken Cross-site request forgery protection token.
|
||||||
* @param {!registry.Session.ContentType} contentType Payload mode.
|
|
||||||
* @constructor
|
* @constructor
|
||||||
* @template REQUEST, RESPONSE
|
* @template REQUEST, RESPONSE
|
||||||
*/
|
*/
|
||||||
registry.Session = function(defaultUri, xsrfToken, contentType) {
|
registry.Session = function(defaultUri, xsrfToken) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URI to which requests are posted.
|
* URI to which requests are posted.
|
||||||
|
@ -39,36 +38,19 @@ registry.Session = function(defaultUri, xsrfToken, contentType) {
|
||||||
*/
|
*/
|
||||||
this.uri = defaultUri;
|
this.uri = defaultUri;
|
||||||
|
|
||||||
/**
|
|
||||||
* Content type set in request body.
|
|
||||||
* @private {!registry.Session.ContentType}
|
|
||||||
* @const
|
|
||||||
*/
|
|
||||||
this.contentType_ = contentType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XHR request headers.
|
* XHR request headers.
|
||||||
* @private {!Object<string, string>}
|
* @private {!Object<string, string>}
|
||||||
* @const
|
* @const
|
||||||
*/
|
*/
|
||||||
this.headers_ = {
|
this.headers_ = {
|
||||||
'Content-Type': contentType,
|
'Content-Type': 'application/json; charset=utf-8',
|
||||||
'X-CSRF-Token': xsrfToken,
|
'X-CSRF-Token': xsrfToken,
|
||||||
'X-Requested-With': 'XMLHttpRequest'
|
'X-Requested-With': 'XMLHttpRequest'
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Payload modes supported by this class.
|
|
||||||
* @enum {string}
|
|
||||||
*/
|
|
||||||
registry.Session.ContentType = {
|
|
||||||
JSON: 'application/json; charset=utf-8',
|
|
||||||
EPP: 'application/epp+xml'
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract method to send a request to the server.
|
* Abstract method to send a request to the server.
|
||||||
* @param {REQUEST} body HTTP request body as a string or JSON object.
|
* @param {REQUEST} body HTTP request body as a string or JSON object.
|
||||||
|
@ -99,9 +81,7 @@ registry.Session.prototype.sendXhrIo =
|
||||||
registry.Session.prototype.onXhrComplete_ = function(onSuccess, onError, e) {
|
registry.Session.prototype.onXhrComplete_ = function(onSuccess, onError, e) {
|
||||||
if (e.target.isSuccess()) {
|
if (e.target.isSuccess()) {
|
||||||
onSuccess(/** @type {!RESPONSE} */ (
|
onSuccess(/** @type {!RESPONSE} */ (
|
||||||
this.contentType_ == registry.Session.ContentType.JSON ?
|
e.target.getResponseJson(registry.Session.PARSER_BREAKER_)));
|
||||||
e.target.getResponseJson(registry.Session.PARSER_BREAKER_) :
|
|
||||||
e.target.getResponseXml()));
|
|
||||||
} else {
|
} else {
|
||||||
onError(e.target.getLastError());
|
onError(e.target.getLastError());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
goog.provide('registry.xml');
|
|
||||||
goog.provide('registry.xml.XmlJson');
|
|
||||||
|
|
||||||
goog.require('goog.dom.NodeType');
|
|
||||||
goog.require('goog.object');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turns XML document into a JSON data structure. This function is similar to
|
|
||||||
* <a href="https://developer.mozilla.org/en-US/docs/JXON">Mozilla JXON</a>
|
|
||||||
* except it handles text differently. This routine will not coalesce text
|
|
||||||
* interspersed with elements. This routine does not coerce string types to
|
|
||||||
* number, boolean, or null.
|
|
||||||
* @param {!Node} node
|
|
||||||
* @return {!Object<string, registry.xml.XmlJson>}
|
|
||||||
* @throws {Error} upon encountering interspersed text.
|
|
||||||
*/
|
|
||||||
registry.xml.convertToJson = function(node) {
|
|
||||||
var result = goog.object.create();
|
|
||||||
if (goog.isDefAndNotNull(node.attributes)) {
|
|
||||||
for (var i = 0; i < node.attributes.length; i++) {
|
|
||||||
var attr = node.attributes.item(i);
|
|
||||||
goog.object.set(result, '@' + attr.name, attr.value || '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (var j = 0; j < node.childNodes.length; j++) {
|
|
||||||
var child = node.childNodes.item(j);
|
|
||||||
switch (child.nodeType) {
|
|
||||||
case goog.dom.NodeType.TEXT:
|
|
||||||
case goog.dom.NodeType.CDATA_SECTION:
|
|
||||||
var text = String(child.nodeValue).trim();
|
|
||||||
if (text != '') {
|
|
||||||
var curr = goog.object.get(result, registry.xml.jsonValueFieldName_);
|
|
||||||
if (goog.isDef(curr)) {
|
|
||||||
throw new Error(
|
|
||||||
'XML text "' + curr + '" interspersed with "' + text + '"');
|
|
||||||
}
|
|
||||||
goog.object.set(result, registry.xml.jsonValueFieldName_, text);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case goog.dom.NodeType.ELEMENT:
|
|
||||||
var json = registry.xml.convertToJson(child);
|
|
||||||
var name = child.nodeName;
|
|
||||||
if (goog.object.containsKey(result, name)) {
|
|
||||||
var field = goog.object.get(result, name);
|
|
||||||
if (goog.isArray(field)) {
|
|
||||||
field.push(json);
|
|
||||||
} else {
|
|
||||||
goog.object.set(result, name, [field, json]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
goog.object.set(result, name, json);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* XML JSON object recursive type definition.
|
|
||||||
* @typedef {(string|
|
|
||||||
* !Array<registry.xml.XmlJson>|
|
|
||||||
* !Object<string, registry.xml.XmlJson>)}
|
|
||||||
*/
|
|
||||||
registry.xml.XmlJson;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* XML JSON value field name, inherited from JXON.
|
|
||||||
* @private {string}
|
|
||||||
* @const
|
|
||||||
*/
|
|
||||||
registry.xml.jsonValueFieldName_ = 'keyValue';
|
|
|
@ -1,177 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
{namespace registry.soy.registrar.contact}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set view for contacts.
|
|
||||||
*/
|
|
||||||
{template .set}
|
|
||||||
<div class="{css('set')} {css('contact')}">
|
|
||||||
<p>Please enter a query for a single contact in the form "contact/[contact id]".
|
|
||||||
</div>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Item view for contact.
|
|
||||||
*/
|
|
||||||
{template .item}
|
|
||||||
{@param? item: ?}
|
|
||||||
{@param? readonly: ?} /** passed through to field rendering. */
|
|
||||||
<form name="item" class="{css('item')} {css('contact')}">
|
|
||||||
<h1>
|
|
||||||
{if isNonnull($item['contact:id'])}
|
|
||||||
{$item['contact:id']['keyValue']}
|
|
||||||
{else}
|
|
||||||
New Contact
|
|
||||||
{/if}
|
|
||||||
</h1>
|
|
||||||
<table>
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2"><h2>Authentication</h2></th>
|
|
||||||
</tr>
|
|
||||||
{if not isNonnull($item['contact:id'])}
|
|
||||||
{call registry.soy.forms.inputFieldRow data="all"}
|
|
||||||
{param label: 'Contact ID *' /}
|
|
||||||
{param name: 'contact:id' /}
|
|
||||||
{/call}
|
|
||||||
{/if}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Password *' /}
|
|
||||||
{param name: 'contact:authInfo.contact:pw' /}
|
|
||||||
{param value: isNonnull($item['contact:authInfo']) ?
|
|
||||||
$item['contact:authInfo']['contact:pw'] : '' /}
|
|
||||||
{/call}
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2"><h2>Contacts</h2></th>
|
|
||||||
</tr>
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Email *' /}
|
|
||||||
{param name: 'contact:email' /}
|
|
||||||
{param value: $item['contact:email'] /}
|
|
||||||
{/call}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Phone' /}
|
|
||||||
{param name: 'contact:voice' /}
|
|
||||||
{param value: $item['contact:voice'] /}
|
|
||||||
{param placeholder: 'e.g. +1.6508675309' /}
|
|
||||||
{/call}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Fax' /}
|
|
||||||
{param name: 'contact:fax' /}
|
|
||||||
{param value: $item['contact:fax'] /}
|
|
||||||
{param placeholder: 'e.g. +1.2125552638' /}
|
|
||||||
{/call}
|
|
||||||
<tr class="{css('section-lead')} {css('subsection')}">
|
|
||||||
<th id="contact-postalInfoHeader" colspan="2">
|
|
||||||
<h3>Postal address(es)</h3>
|
|
||||||
<button id="domain-contact-postalInfo-add-button" type="button"
|
|
||||||
class="{css('kd-button')} {css('reg-add')}"
|
|
||||||
{if $readonly}disabled{/if}>
|
|
||||||
Add Localized Address
|
|
||||||
</button>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td colspan="2">
|
|
||||||
<div id="contact-postalInfo">
|
|
||||||
{if isNonnull($item['contact:postalInfo'])}
|
|
||||||
{for $pi in $item['contact:postalInfo']}
|
|
||||||
{call .postalInfo data="all"}
|
|
||||||
{param localized: index($pi) == 1 /}
|
|
||||||
{param item: $pi/}
|
|
||||||
{param namePrefix: 'contact:postalInfo[' + index($pi) + '].contact:' /}
|
|
||||||
{/call}
|
|
||||||
{/for}
|
|
||||||
{else}
|
|
||||||
{call .postalInfo data="all"}
|
|
||||||
{param namePrefix: 'contact:postalInfo[0].contact:' /}
|
|
||||||
{/call}
|
|
||||||
{/if}
|
|
||||||
<table id="domain-contact-postalInfos-footer"></table>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
{if isNonnull($item['contact:id'])}
|
|
||||||
<input type="hidden" name="contact:id" value="{$item['contact:id']['keyValue']}"/>
|
|
||||||
{/if}
|
|
||||||
</form>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Postal info.
|
|
||||||
*/
|
|
||||||
{template .postalInfo}
|
|
||||||
{@param item: ?}
|
|
||||||
{@param namePrefix: ?}
|
|
||||||
{@param? localized: ?} /** if true, this is the second, localized postalInfo. */
|
|
||||||
<table>
|
|
||||||
<tr><th colspan=2>
|
|
||||||
{if $localized}
|
|
||||||
<strong>Localized address</strong><br>
|
|
||||||
<span class="{css('info')}">Full UTF-8 charsets allowed</span>
|
|
||||||
{else}
|
|
||||||
<strong>Internationalized address</strong><br>
|
|
||||||
<span class="{css('info')}">Only 7-bit ASCII allowed</span>
|
|
||||||
{/if}
|
|
||||||
</th></tr>
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Name *' /}
|
|
||||||
{param name: 'name' /}
|
|
||||||
{param value: $item['contact:name']/}
|
|
||||||
{/call}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Organization' /}
|
|
||||||
{param name: 'org' /}
|
|
||||||
{param value: $item['contact:org'] /}
|
|
||||||
{/call}
|
|
||||||
{call registry.soy.forms.textareaFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Street' /}
|
|
||||||
{param name: 'street' /}
|
|
||||||
{param namePrefix: $namePrefix + 'addr.contact:' /}
|
|
||||||
{param value: isNonnull($item['contact:addr']) ? $item['contact:addr']['contact:street'] : '' /}
|
|
||||||
{/call}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'City *' /}
|
|
||||||
{param name: 'city' /}
|
|
||||||
{param namePrefix: $namePrefix + 'addr.contact:' /}
|
|
||||||
{param value: isNonnull($item['contact:addr']) ? $item['contact:addr']['contact:city'] : '' /}
|
|
||||||
{/call}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'State / Region' /}
|
|
||||||
{param name: 'sp' /}
|
|
||||||
{param namePrefix: $namePrefix + 'addr.contact:' /}
|
|
||||||
{param value: isNonnull($item['contact:addr']) ? $item['contact:addr']['contact:sp'] : '' /}
|
|
||||||
{param placeholder: 'e.g. CA' /}
|
|
||||||
{/call}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Zip / Postal code' /}
|
|
||||||
{param name: 'pc' /}
|
|
||||||
{param namePrefix: $namePrefix + 'addr.contact:' /}
|
|
||||||
{param value: isNonnull($item['contact:addr']) ? $item['contact:addr']['contact:pc'] : '' /}
|
|
||||||
{param placeholder: 'e.g. 10282' /}
|
|
||||||
{/call}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Country code *' /}
|
|
||||||
{param name: 'cc' /}
|
|
||||||
{param namePrefix: $namePrefix + 'addr.contact:' /}
|
|
||||||
{param value: isNonnull($item['contact:addr']) ? $item['contact:addr']['contact:cc'] : '' /}
|
|
||||||
{param placeholder: 'e.g. US' /}
|
|
||||||
{/call}
|
|
||||||
</table>
|
|
||||||
{/template}
|
|
|
@ -1,118 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
{namespace registry.soy.registrar.contactepp}
|
|
||||||
|
|
||||||
|
|
||||||
/* XXX: Forces first postalInfo type to be "int" and second "loc" if it is
|
|
||||||
* present, for compatibility with the server. */
|
|
||||||
/**
|
|
||||||
* Contact create request.
|
|
||||||
*/
|
|
||||||
{template .create stricthtml="false"}
|
|
||||||
{@param item: ?}
|
|
||||||
{@param clTrid: ?}
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<create>
|
|
||||||
<contact:create xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
|
|
||||||
<contact:id>{$item['contact:id']}</contact:id>
|
|
||||||
{for $pi in $item['contact:postalInfo']}
|
|
||||||
<contact:postalInfo type="{if index($pi) == 0}int{else}loc{/if}">
|
|
||||||
<contact:name>{$pi['contact:name']}</contact:name>
|
|
||||||
<contact:org>{$pi['contact:org']}</contact:org>
|
|
||||||
<contact:addr>
|
|
||||||
{let $addr: $pi['contact:addr'] /}
|
|
||||||
<contact:street>{$addr['contact:street']}</contact:street>
|
|
||||||
<contact:city>{$addr['contact:city']}</contact:city>
|
|
||||||
<contact:sp>{$addr['contact:sp']}</contact:sp>
|
|
||||||
<contact:pc>{$addr['contact:pc']}</contact:pc>
|
|
||||||
<contact:cc>{$addr['contact:cc']}</contact:cc>
|
|
||||||
</contact:addr>
|
|
||||||
</contact:postalInfo>
|
|
||||||
{/for}
|
|
||||||
<contact:voice>{$item['contact:voice']}</contact:voice>
|
|
||||||
<contact:fax>{$item['contact:fax']}</contact:fax>
|
|
||||||
<contact:email>{$item['contact:email']}</contact:email>
|
|
||||||
<contact:authInfo>
|
|
||||||
<contact:pw>{$item['contact:authInfo']['contact:pw']}</contact:pw>
|
|
||||||
</contact:authInfo>
|
|
||||||
</contact:create>
|
|
||||||
</create>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/* XXX: Forces first postalInfo type to be "int" and second "loc" if it is
|
|
||||||
* present, for compatibility with the server. */
|
|
||||||
/**
|
|
||||||
* Contact update request.
|
|
||||||
*/
|
|
||||||
{template .update stricthtml="false"}
|
|
||||||
{@param item: ?}
|
|
||||||
{@param clTrid: ?}
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<update>
|
|
||||||
<contact:update xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
|
|
||||||
<contact:id>{$item['contact:id']}</contact:id>
|
|
||||||
<contact:chg>
|
|
||||||
{for $pi in $item['contact:postalInfo']}
|
|
||||||
<contact:postalInfo type="{if index($pi) == 0}int{else}loc{/if}">
|
|
||||||
<contact:name>{$pi['contact:name']}</contact:name>
|
|
||||||
<contact:org>{$pi['contact:org']}</contact:org>
|
|
||||||
{let $addr: $pi['contact:addr'] /}
|
|
||||||
<contact:addr>
|
|
||||||
<contact:street>{$addr['contact:street']}</contact:street>
|
|
||||||
<contact:city>{$addr['contact:city']}</contact:city>
|
|
||||||
<contact:sp>{$addr['contact:sp']}</contact:sp>
|
|
||||||
<contact:pc>{$addr['contact:pc']}</contact:pc>
|
|
||||||
<contact:cc>{$addr['contact:cc']}</contact:cc>
|
|
||||||
</contact:addr>
|
|
||||||
</contact:postalInfo>
|
|
||||||
{/for}
|
|
||||||
<contact:voice>{$item['contact:voice']}</contact:voice>
|
|
||||||
<contact:fax>{$item['contact:fax']}</contact:fax>
|
|
||||||
<contact:email>{$item['contact:email']}</contact:email>
|
|
||||||
<contact:authInfo>
|
|
||||||
<contact:pw>{$item['contact:authInfo']['contact:pw']}</contact:pw>
|
|
||||||
</contact:authInfo>
|
|
||||||
</contact:chg>
|
|
||||||
</contact:update>
|
|
||||||
</update>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contact info request.
|
|
||||||
*/
|
|
||||||
{template .info stricthtml="false"}
|
|
||||||
{@param id: ?}
|
|
||||||
{@param clTrid: ?}
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<info>
|
|
||||||
<contact:info xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
|
|
||||||
<contact:id>{$id}</contact:id>
|
|
||||||
</contact:info>
|
|
||||||
</info>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
|
@ -1,200 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
{namespace registry.soy.registrar.domain}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set view for domains.
|
|
||||||
*/
|
|
||||||
{template .set}
|
|
||||||
<div class="{css('set')} {css('domain')}">
|
|
||||||
<p>Please enter a query for a single contact in the form "domain/[domain id]".
|
|
||||||
</div>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Item view for domain.
|
|
||||||
*/
|
|
||||||
{template .item}
|
|
||||||
{@param item: ?}
|
|
||||||
{@param? readonly: ?} /** passed through to field rendering. */
|
|
||||||
{let $isEdit: isNonnull($item['domain:name']) /}
|
|
||||||
<form name="item" class="{css('item')} {css('domain')}">
|
|
||||||
<h1>
|
|
||||||
{if $isEdit}
|
|
||||||
{$item['domain:name']['keyValue']}
|
|
||||||
{else}
|
|
||||||
New Domain
|
|
||||||
{/if}
|
|
||||||
</h1>
|
|
||||||
<table>
|
|
||||||
{if not $isEdit}
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2"><h2>Domain</h2></th>
|
|
||||||
</tr>
|
|
||||||
{call registry.soy.forms.inputFieldRow data="all"}
|
|
||||||
{param label: 'Domain name *' /}
|
|
||||||
{param name: 'domain:name' /}
|
|
||||||
{/call}
|
|
||||||
{call registry.soy.forms.inputFieldRow data="all"}
|
|
||||||
{param label: 'Period (in years) *' /}
|
|
||||||
{param name: 'domain:period' /}
|
|
||||||
{/call}
|
|
||||||
{/if}
|
|
||||||
{if isNonnull($item['domain:exDate'])}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Expiration date' /}
|
|
||||||
{param name: 'domain:exDate' /}
|
|
||||||
{param value: $item['domain:exDate'] /}
|
|
||||||
{/call}
|
|
||||||
{/if}
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2"><h2>Authentication</h2></th>
|
|
||||||
</tr>
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Password *' /}
|
|
||||||
{param name: 'domain:authInfo.domain:pw' /}
|
|
||||||
{param value: isNonnull($item['domain:authInfo']) ?
|
|
||||||
$item['domain:authInfo']['domain:pw'] : '' /}
|
|
||||||
{/call}
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2">
|
|
||||||
<h3>Contact information</h3>
|
|
||||||
<button id="domain-contact-add-button" type="button"
|
|
||||||
class="{css('kd-button')} {css('reg-add')}"
|
|
||||||
{if $readonly}disabled{/if}>
|
|
||||||
Add Contact
|
|
||||||
</button>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Registrant *' /}
|
|
||||||
{param name: 'domain:registrant' /}
|
|
||||||
{param value: $item['domain:registrant'] /}
|
|
||||||
{/call}
|
|
||||||
{if isNonnull($item['domain:contact'])}
|
|
||||||
// Render contact list with stable ordering for the screenshot tests.
|
|
||||||
{call .showContact_ data="all"}
|
|
||||||
{param contacts: $item['domain:contact'] /}
|
|
||||||
{param type: 'admin' /}
|
|
||||||
{/call}
|
|
||||||
{call .showContact_ data="all"}
|
|
||||||
{param contacts: $item['domain:contact'] /}
|
|
||||||
{param type: 'billing' /}
|
|
||||||
{/call}
|
|
||||||
{call .showContact_ data="all"}
|
|
||||||
{param contacts: $item['domain:contact'] /}
|
|
||||||
{param type: 'tech' /}
|
|
||||||
{/call}
|
|
||||||
{/if}
|
|
||||||
<tr id="domain-contacts-footer"></tr>
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2">
|
|
||||||
<h3>Nameservers</h3>
|
|
||||||
<button id="domain-host-add-button" type="button"
|
|
||||||
class="{css('kd-button')} {css('reg-add')}"
|
|
||||||
{if $readonly}disabled{/if}>
|
|
||||||
Add Host
|
|
||||||
</button>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
{if isNonnull($item['domain:ns']) and isNonnull($item['domain:ns']['domain:hostObj'])}
|
|
||||||
{for $hostObj in $item['domain:ns']['domain:hostObj']}
|
|
||||||
{let $hostIdx: index($hostObj) /}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Host ' + $hostIdx /}
|
|
||||||
{param name: 'domain:ns.domain:hostObj[' + $hostIdx + '].value' /}
|
|
||||||
{param value: $hostObj /}
|
|
||||||
{param clazz kind="text"}{css('domain-hostObj')}{/param}
|
|
||||||
{/call}
|
|
||||||
{/for}
|
|
||||||
{/if}
|
|
||||||
<tr id="domain-hosts-footer"></tr>
|
|
||||||
|
|
||||||
{if isNonnull($item['mark:mark'])}
|
|
||||||
<tr>
|
|
||||||
<td>Mark Data
|
|
||||||
<td>
|
|
||||||
<textarea
|
|
||||||
class="{css('reg-domain-mark')}"
|
|
||||||
spellcheck="false"
|
|
||||||
{if $readonly}readonly{/if}>
|
|
||||||
{$item['mark:mark']['keyValue']}</textarea>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
</table>
|
|
||||||
{if $isEdit}
|
|
||||||
<input type="hidden"
|
|
||||||
name="domain:name"
|
|
||||||
value="{$item['domain:name']['keyValue']}">
|
|
||||||
{/if}
|
|
||||||
</form>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/** Renders an input form row for a specific type of contact. */
|
|
||||||
{template .showContact_ visibility="private"}
|
|
||||||
{@param contacts: list<legacy_object_map<string, ?>>} /** List of EPP domain:contacts. */
|
|
||||||
{@param type: string} /** Type of contact (e.g. admin, tech) */
|
|
||||||
{for $contact in $contacts}
|
|
||||||
{if $type == $contact['@type']}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: $contact['@type'] + ' contact' /}
|
|
||||||
{param name: 'domain:contact[' + index($contact) + '].value' /}
|
|
||||||
{param value: $contact /}
|
|
||||||
{param clazz: 'domain-contact' /}
|
|
||||||
{/call}
|
|
||||||
<input name="domain:contact[{index($contact)}].@type"
|
|
||||||
type="hidden"
|
|
||||||
value="{$contact['@type']}">
|
|
||||||
{/if}
|
|
||||||
{/for}
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/* XXX: Should change support for admin/tech. */
|
|
||||||
/**
|
|
||||||
* Update domain.
|
|
||||||
*/
|
|
||||||
{template .update}
|
|
||||||
{@param? item: ?}
|
|
||||||
<form name="item" class="{css('item')} {css('domain')}">
|
|
||||||
<h1>{$item['domain:name']['keyValue']}</h1>
|
|
||||||
<table>
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2"><h2>Contact</h2></th>
|
|
||||||
</tr>
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Registrant' /}
|
|
||||||
{param name: 'domain:registrant' /}
|
|
||||||
{param value: $item['domain:registrant'] /}
|
|
||||||
{/call}
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2"><h2>Authentication</h2></th>
|
|
||||||
</tr>
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Password' /}
|
|
||||||
{param name: 'domain:authInfo.domain:pw' /}
|
|
||||||
{param value: isNonnull($item['domain:authInfo']) ?
|
|
||||||
$item['domain:authInfo']['domain:pw'] : '' /}
|
|
||||||
{/call}
|
|
||||||
<input type="hidden"
|
|
||||||
name="domain:name"
|
|
||||||
value="{$item['domain:name']['keyValue']}">
|
|
||||||
</table>
|
|
||||||
</form>
|
|
||||||
{/template}
|
|
|
@ -1,140 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
{namespace registry.soy.registrar.domainepp}
|
|
||||||
|
|
||||||
|
|
||||||
/* General Availability. */
|
|
||||||
/**
|
|
||||||
* Domain create request.
|
|
||||||
*/
|
|
||||||
{template .create stricthtml="false"}
|
|
||||||
{@param item: ?}
|
|
||||||
{@param clTrid: ?}
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<create>
|
|
||||||
<domain:create xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
|
||||||
<domain:name>{$item['domain:name']}</domain:name>
|
|
||||||
{if isNonnull($item['domain:period'])}
|
|
||||||
<domain:period unit="y">{$item['domain:period']}</domain:period>
|
|
||||||
{/if}
|
|
||||||
{if isNonnull($item['domain:ns'])}
|
|
||||||
<domain:ns>
|
|
||||||
{for $hostObj in $item['domain:ns']['domain:hostObj']}
|
|
||||||
<domain:hostObj>{$hostObj.value}</domain:hostObj>
|
|
||||||
{/for}
|
|
||||||
</domain:ns>
|
|
||||||
{/if}
|
|
||||||
{if isNonnull($item['domain:registrant'])}
|
|
||||||
<domain:registrant>{$item['domain:registrant']}</domain:registrant>
|
|
||||||
{/if}
|
|
||||||
{if isNonnull($item['domain:contact'])}
|
|
||||||
{for $contact in $item['domain:contact']}
|
|
||||||
<domain:contact type="{$contact['@type']}">{$contact.value}</domain:contact>
|
|
||||||
{/for}
|
|
||||||
{/if}
|
|
||||||
<domain:authInfo>
|
|
||||||
<domain:pw>{$item['domain:authInfo']['domain:pw']}</domain:pw>
|
|
||||||
</domain:authInfo>
|
|
||||||
</domain:create>
|
|
||||||
</create>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Domain info request.
|
|
||||||
*/
|
|
||||||
{template .info stricthtml="false"}
|
|
||||||
{@param id: ?}
|
|
||||||
{@param clTrid: ?}
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<info>
|
|
||||||
<domain:info xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
|
||||||
<domain:name hosts="all">{$id}</domain:name>
|
|
||||||
</domain:info>
|
|
||||||
</info>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Domain update request.
|
|
||||||
*/
|
|
||||||
{template .update stricthtml="false"}
|
|
||||||
{@param item: ?}
|
|
||||||
{@param clTrid: ?}
|
|
||||||
{@param? addHosts: ?} /** list of hostObj to add. */
|
|
||||||
{@param? remHosts: ?} /** list of hostObj to remove. */
|
|
||||||
{@param? addContacts: ?} /** list of contact to add. */
|
|
||||||
{@param? remContacts: ?} /** list of contact to remove. */
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<update>
|
|
||||||
<domain:update xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
|
|
||||||
<domain:name>{$item['domain:name']}</domain:name>
|
|
||||||
{if isNonnull($addHosts) or isNonnull($addContacts)}
|
|
||||||
{call .addRem}
|
|
||||||
{param isAdd: true /}
|
|
||||||
{param hosts: $addHosts /}
|
|
||||||
{param contacts: $addContacts /}
|
|
||||||
{/call}
|
|
||||||
{/if}
|
|
||||||
{if isNonnull($remHosts) or isNonnull($remContacts)}
|
|
||||||
{call .addRem}
|
|
||||||
{param isAdd: false /}
|
|
||||||
{param hosts: $remHosts /}
|
|
||||||
{param contacts: $remContacts /}
|
|
||||||
{/call}
|
|
||||||
{/if}
|
|
||||||
<domain:chg>
|
|
||||||
<domain:registrant>{$item['domain:registrant']}</domain:registrant>
|
|
||||||
<domain:authInfo>
|
|
||||||
<domain:pw>{$item['domain:authInfo']['domain:pw']}</domain:pw>
|
|
||||||
</domain:authInfo>
|
|
||||||
</domain:chg>
|
|
||||||
</domain:update>
|
|
||||||
</update>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
{template .addRem}
|
|
||||||
{@param isAdd: ?}
|
|
||||||
{@param? hosts: ?}
|
|
||||||
{@param? contacts: ?}
|
|
||||||
{let $tagName: $isAdd ? 'domain:add' : 'domain:rem' /}
|
|
||||||
<{$tagName}>
|
|
||||||
{if isNonnull($hosts)}
|
|
||||||
<domain:ns>
|
|
||||||
{for $host in $hosts}
|
|
||||||
<domain:hostObj>{$host.value}</domain:hostObj>
|
|
||||||
{/for}
|
|
||||||
</domain:ns>
|
|
||||||
{/if}
|
|
||||||
{if isNonnull($contacts)}
|
|
||||||
{for $contact in $contacts}
|
|
||||||
<domain:contact type="{$contact['@type']}">{$contact.value}</domain:contact>
|
|
||||||
{/for}
|
|
||||||
{/if}
|
|
||||||
</{$tagName}>
|
|
||||||
{/template}
|
|
|
@ -1,57 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
{namespace registry.soy.registrar.epp}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Login request.
|
|
||||||
* @param clId
|
|
||||||
* @param pw
|
|
||||||
* @param clTrid
|
|
||||||
*/
|
|
||||||
{template .login stricthtml="false"}
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<login>
|
|
||||||
<clID>{$clId}</clID>
|
|
||||||
<pw>{$pw}</pw>
|
|
||||||
<options>
|
|
||||||
<version>1.0</version>
|
|
||||||
<lang>en</lang>
|
|
||||||
</options>
|
|
||||||
<svcs>
|
|
||||||
<objURI>urn:ietf:params:xml:ns:host-1.0</objURI>
|
|
||||||
<objURI>urn:ietf:params:xml:ns:domain-1.0</objURI>
|
|
||||||
<objURI>urn:ietf:params:xml:ns:contact-1.0</objURI>
|
|
||||||
</svcs>
|
|
||||||
</login>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logout request.
|
|
||||||
* @param clTrid
|
|
||||||
*/
|
|
||||||
{template .logout stricthtml="false"}
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<logout/>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
|
@ -1,108 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
{namespace registry.soy.registrar.host}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set view for hosts.
|
|
||||||
*/
|
|
||||||
{template .set}
|
|
||||||
<div class="{css('set')} {css('host')}">
|
|
||||||
<p>Please enter a query for a single host in the form "host/[hostname]".
|
|
||||||
</div>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Item view for host.
|
|
||||||
* @param? item
|
|
||||||
* @param? readonly passed through to field rendering.
|
|
||||||
*/
|
|
||||||
{template .item}
|
|
||||||
<form name="item" class="{css('item')} {css('host')}">
|
|
||||||
<h1>
|
|
||||||
{if isNonnull($item['host:name'])}
|
|
||||||
{$item['host:name']['keyValue']}
|
|
||||||
{else}
|
|
||||||
New Host
|
|
||||||
{/if}
|
|
||||||
</h1>
|
|
||||||
<table>
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2"><h2>Host</h2></th>
|
|
||||||
</tr>
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Name *' /}
|
|
||||||
{param name: isNonnull($item['host:name']) ? 'host:chgName' : 'host:name' /}
|
|
||||||
{param value: $item['host:name'] /}
|
|
||||||
{/call}
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2">
|
|
||||||
<h3>Addresses</h3>
|
|
||||||
<button id="domain-host-addr-add-button" type="button"
|
|
||||||
class="{css('kd-button')} {css('reg-add')}"
|
|
||||||
{if $readonly}disabled{/if}>
|
|
||||||
Add Address
|
|
||||||
</button>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
{if isNonnull($item['host:addr'])}
|
|
||||||
{for $addr in $item['host:addr']}
|
|
||||||
{if not $readonly}
|
|
||||||
<input type="hidden"
|
|
||||||
name="host:oldAddr[{index($addr)}].value"
|
|
||||||
value="{$item['host:addr'][index($addr)]['keyValue']}">
|
|
||||||
{/if}
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Address No. ' + (index($addr) + 1) /}
|
|
||||||
{param name: 'host:addr[' + index($addr) + '].value' /}
|
|
||||||
{param value: $item['host:addr'][index($addr)] /}
|
|
||||||
{/call}
|
|
||||||
{/for}
|
|
||||||
{/if}
|
|
||||||
<tr id="domain-host-addrs-footer"></tr>
|
|
||||||
</table>
|
|
||||||
{if isNonnull($item['host:name'])}
|
|
||||||
<input type="hidden"
|
|
||||||
name="host:name"
|
|
||||||
value="{$item['host:name']['keyValue']}">
|
|
||||||
{/if}
|
|
||||||
</form>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Item view for host.
|
|
||||||
* @param? item
|
|
||||||
* @param? readonly passed through to field rendering.
|
|
||||||
*/
|
|
||||||
{template .update}
|
|
||||||
<form name="item" class="{css('item')} {css('host')}">
|
|
||||||
<h1>{$item['host:name']['keyValue']}</h1>
|
|
||||||
<table>
|
|
||||||
<tr class="{css('section-lead')}">
|
|
||||||
<th colspan="2"><h2>Host</h2></th>
|
|
||||||
</tr>
|
|
||||||
{call registry.soy.forms.inputFieldRowWithValue data="all"}
|
|
||||||
{param label: 'Name' /}
|
|
||||||
{param name: 'host:chgName' /}
|
|
||||||
{param value: $item['host:name'] /}
|
|
||||||
{/call}
|
|
||||||
</table>
|
|
||||||
{if isNonnull($item['host:name'])}
|
|
||||||
<input type="hidden" name="host:name" value="{$item['host:name']['keyValue']}">
|
|
||||||
{/if}
|
|
||||||
</form>
|
|
||||||
{/template}
|
|
|
@ -1,108 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
{namespace registry.soy.registrar.hostepp}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Host create request.
|
|
||||||
*/
|
|
||||||
{template .create stricthtml="false"}
|
|
||||||
{@param item: ?}
|
|
||||||
{@param clTrid: ?}
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<create>
|
|
||||||
<host:create xmlns:host="urn:ietf:params:xml:ns:host-1.0">
|
|
||||||
<host:name>{$item['host:name']}</host:name>
|
|
||||||
{if isNonnull($item['host:addr'])}
|
|
||||||
{for $addr in $item['host:addr']}
|
|
||||||
{let $type: strContains($addr['value'], ':') ? 'v6' : 'v4' /}
|
|
||||||
<host:addr ip="{$type}">{$addr['value']}</host:addr>
|
|
||||||
{/for}
|
|
||||||
{/if}
|
|
||||||
</host:create>
|
|
||||||
</create>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Host update request.
|
|
||||||
*/
|
|
||||||
{template .update stricthtml="false"}
|
|
||||||
{@param item: ?}
|
|
||||||
{@param clTrid: ?}
|
|
||||||
{@param? addAddrs: ?} /** list of addrs to add. */
|
|
||||||
{@param? remAddrs: ?} /** list of addrs to remove. */
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<update>
|
|
||||||
<host:update xmlns:host="urn:ietf:params:xml:ns:host-1.0">
|
|
||||||
<host:name>{$item['host:name']}</host:name>
|
|
||||||
{call .addRem}
|
|
||||||
{param isAdd: true /}
|
|
||||||
{param addrs: $addAddrs /}
|
|
||||||
{/call}
|
|
||||||
{call .addRem}
|
|
||||||
{param isAdd: false /}
|
|
||||||
{param addrs: $remAddrs /}
|
|
||||||
{/call}
|
|
||||||
{if $item['host:name'] != $item['host:chgName']}
|
|
||||||
<host:chg>
|
|
||||||
<host:name>{$item['host:chgName']}</host:name>
|
|
||||||
</host:chg>
|
|
||||||
{/if}
|
|
||||||
</host:update>
|
|
||||||
</update>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Host info request.
|
|
||||||
*/
|
|
||||||
{template .info stricthtml="false"}
|
|
||||||
{@param clTrid: ?}
|
|
||||||
{@param id: ?} /** The hostname (named "id" to preserve component API). */
|
|
||||||
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
|
|
||||||
<command>
|
|
||||||
<info>
|
|
||||||
<host:info xmlns:host="urn:ietf:params:xml:ns:host-1.0">
|
|
||||||
<host:name>{$id}</host:name>
|
|
||||||
</host:info>
|
|
||||||
</info>
|
|
||||||
<clTRID>{$clTrid}</clTRID>
|
|
||||||
</command>
|
|
||||||
</epp>
|
|
||||||
{/template}
|
|
||||||
|
|
||||||
|
|
||||||
{template .addRem}
|
|
||||||
{@param isAdd: ?}
|
|
||||||
{@param? addrs: ?}
|
|
||||||
{let $tagName: $isAdd ? 'host:add' : 'host:rem' /}
|
|
||||||
{if length($addrs) > 0}
|
|
||||||
<{$tagName}>
|
|
||||||
{for $addr in $addrs}
|
|
||||||
{let $type: strContains($addr, ':') ? 'v6' : 'v4' /}
|
|
||||||
<host:addr ip="{$type}">{$addr}</host:addr>
|
|
||||||
{/for}
|
|
||||||
</{$tagName}>
|
|
||||||
{/if}
|
|
||||||
{/template}
|
|
|
@ -1,73 +0,0 @@
|
||||||
// Copyright 2017 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.flows;
|
|
||||||
|
|
||||||
import static com.google.appengine.api.users.UserServiceFactory.getUserService;
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
|
||||||
import static org.mockito.Matchers.eq;
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSetMultimap;
|
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
|
||||||
import google.registry.testing.AppEngineRule;
|
|
||||||
import google.registry.testing.FakeHttpSession;
|
|
||||||
import google.registry.testing.ShardableTestCase;
|
|
||||||
import google.registry.testing.UserInfo;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.JUnit4;
|
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
|
|
||||||
/** Tests for {@link EppConsoleAction}. */
|
|
||||||
@RunWith(JUnit4.class)
|
|
||||||
public class EppConsoleActionTest extends ShardableTestCase {
|
|
||||||
|
|
||||||
private static final byte[] INPUT_XML_BYTES = "<xml>".getBytes(UTF_8);
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public final AppEngineRule appEngine = AppEngineRule.builder()
|
|
||||||
.withUserService(UserInfo.create("person@example.com", "12345"))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAction() {
|
|
||||||
EppConsoleAction action = new EppConsoleAction();
|
|
||||||
action.inputXmlBytes = INPUT_XML_BYTES;
|
|
||||||
action.session = new FakeHttpSession();
|
|
||||||
action.clientId = "ClientIdentifier";
|
|
||||||
action.eppRequestHandler = mock(EppRequestHandler.class);
|
|
||||||
action.userService = getUserService();
|
|
||||||
action.registrarAccessor =
|
|
||||||
AuthenticatedRegistrarAccessor.createForTesting(ImmutableSetMultimap.of());
|
|
||||||
action.run();
|
|
||||||
ArgumentCaptor<TransportCredentials> credentialsCaptor =
|
|
||||||
ArgumentCaptor.forClass(TransportCredentials.class);
|
|
||||||
ArgumentCaptor<SessionMetadata> metadataCaptor = ArgumentCaptor.forClass(SessionMetadata.class);
|
|
||||||
verify(action.eppRequestHandler)
|
|
||||||
.executeEpp(
|
|
||||||
metadataCaptor.capture(),
|
|
||||||
credentialsCaptor.capture(),
|
|
||||||
eq(EppRequestSource.CONSOLE),
|
|
||||||
eq(false),
|
|
||||||
eq(false),
|
|
||||||
eq(INPUT_XML_BYTES));
|
|
||||||
assertThat(credentialsCaptor.getValue().toString()).contains("user=TestUserId");
|
|
||||||
assertThat(metadataCaptor.getValue().getClientId()).isEqualTo("ClientIdentifier");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
// Copyright 2017 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.flows;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSetMultimap;
|
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
|
||||||
import google.registry.testing.AppEngineRule;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.JUnit4;
|
|
||||||
|
|
||||||
/** Test logging in with appengine admin user credentials. */
|
|
||||||
@RunWith(JUnit4.class)
|
|
||||||
public class EppLoginAdminUserTest extends EppTestCase {
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public final AppEngineRule appEngine = AppEngineRule.builder()
|
|
||||||
.withDatastore()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void initTransportCredentials() {
|
|
||||||
setTransportCredentials(
|
|
||||||
new GaeUserCredentials(
|
|
||||||
AuthenticatedRegistrarAccessor.createForTesting(
|
|
||||||
ImmutableSetMultimap.of(
|
|
||||||
"TheRegistrar", AuthenticatedRegistrarAccessor.Role.ADMIN,
|
|
||||||
"NewRegistrar", AuthenticatedRegistrarAccessor.Role.ADMIN))));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoginLogout_wrongPasswordStillWorks() throws Exception {
|
|
||||||
// For user-based logins the password in the epp xml is ignored.
|
|
||||||
assertThatLoginSucceeds("NewRegistrar", "incorrect");
|
|
||||||
assertThatLogoutSucceeds();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNonAuthedMultiLogin_succeedsAsAdmin() throws Exception {
|
|
||||||
// The admin can log in as different registrars.
|
|
||||||
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
|
|
||||||
assertThatLogoutSucceeds();
|
|
||||||
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
|
|
||||||
assertThatLogoutSucceeds();
|
|
||||||
assertThatLoginSucceeds("TheRegistrar", "password2");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
// Copyright 2017 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.flows;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableSetMultimap;
|
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
|
||||||
import google.registry.testing.AppEngineRule;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.JUnit4;
|
|
||||||
|
|
||||||
/** Test logging in with appengine user credentials, such as via the console. */
|
|
||||||
@RunWith(JUnit4.class)
|
|
||||||
public class EppLoginUserTest extends EppTestCase {
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public final AppEngineRule appEngine = AppEngineRule.builder()
|
|
||||||
.withDatastore()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void initTest() {
|
|
||||||
setTransportCredentials(
|
|
||||||
new GaeUserCredentials(
|
|
||||||
AuthenticatedRegistrarAccessor.createForTesting(
|
|
||||||
ImmutableSetMultimap.of(
|
|
||||||
"NewRegistrar", AuthenticatedRegistrarAccessor.Role.OWNER))));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoginLogout() throws Exception {
|
|
||||||
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
|
|
||||||
assertThatLogoutSucceeds();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testNonAuthedLogin_fails() throws Exception {
|
|
||||||
assertThatLogin("TheRegistrar", "password2")
|
|
||||||
.hasResponse(
|
|
||||||
"response_error.xml",
|
|
||||||
ImmutableMap.of(
|
|
||||||
"CODE", "2200",
|
|
||||||
"MSG", "TestUserId doesn't have access to registrar TheRegistrar"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMultiLogin() throws Exception {
|
|
||||||
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
|
|
||||||
assertThatLogoutSucceeds();
|
|
||||||
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
|
|
||||||
assertThatLogoutSucceeds();
|
|
||||||
assertThatLogin("TheRegistrar", "password2")
|
|
||||||
.hasResponse(
|
|
||||||
"response_error.xml",
|
|
||||||
ImmutableMap.of(
|
|
||||||
"CODE", "2200",
|
|
||||||
"MSG", "TestUserId doesn't have access to registrar TheRegistrar"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testLoginLogout_wrongPasswordStillWorks() throws Exception {
|
|
||||||
// For user-based logins the password in the epp xml is ignored.
|
|
||||||
assertThatLoginSucceeds("NewRegistrar", "incorrect");
|
|
||||||
assertThatLogoutSucceeds();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,14 +26,12 @@ import static org.mockito.Mockito.verify;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ImmutableSetMultimap;
|
|
||||||
import com.google.common.flogger.LoggerConfig;
|
import com.google.common.flogger.LoggerConfig;
|
||||||
import com.google.common.testing.TestLogHandler;
|
import com.google.common.testing.TestLogHandler;
|
||||||
import google.registry.model.eppcommon.Trid;
|
import google.registry.model.eppcommon.Trid;
|
||||||
import google.registry.model.eppoutput.EppOutput.ResponseOrGreeting;
|
import google.registry.model.eppoutput.EppOutput.ResponseOrGreeting;
|
||||||
import google.registry.model.eppoutput.EppResponse;
|
import google.registry.model.eppoutput.EppResponse;
|
||||||
import google.registry.monitoring.whitebox.EppMetric;
|
import google.registry.monitoring.whitebox.EppMetric;
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
import google.registry.testing.FakeClock;
|
import google.registry.testing.FakeClock;
|
||||||
import google.registry.testing.FakeHttpSession;
|
import google.registry.testing.FakeHttpSession;
|
||||||
|
@ -140,16 +138,6 @@ public class FlowRunnerTest extends ShardableTestCase {
|
||||||
+ "{clientId=TheRegistrar, failedLoginAttempts=0, serviceExtensionUris=}");
|
+ "{clientId=TheRegistrar, failedLoginAttempts=0, serviceExtensionUris=}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRun_loggingStatement_gaeUserCredentials() throws Exception {
|
|
||||||
flowRunner.credentials =
|
|
||||||
new GaeUserCredentials(AuthenticatedRegistrarAccessor.createForTesting(
|
|
||||||
ImmutableSetMultimap.of()));
|
|
||||||
flowRunner.run(eppMetricBuilder);
|
|
||||||
assertThat(findFirstLogMessageByPrefix(handler, "EPP Command\n\t"))
|
|
||||||
.contains("user=TestUserId");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRun_loggingStatement_tlsCredentials() throws Exception {
|
public void testRun_loggingStatement_tlsCredentials() throws Exception {
|
||||||
flowRunner.credentials = new TlsCredentials(true, "abc123def", Optional.of("127.0.0.1"));
|
flowRunner.credentials = new TlsCredentials(true, "abc123def", Optional.of("127.0.0.1"));
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
// Copyright 2017 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.flows.session;
|
|
||||||
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSetMultimap;
|
|
||||||
import google.registry.flows.GaeUserCredentials;
|
|
||||||
import google.registry.flows.GaeUserCredentials.UserForbiddenException;
|
|
||||||
import google.registry.request.auth.AuthenticatedRegistrarAccessor;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit tests for {@link LoginFlow} when accessed via a web frontend
|
|
||||||
* transport, i.e. with GAIA ids.
|
|
||||||
*/
|
|
||||||
public class LoginFlowViaConsoleTest extends LoginFlowTestCase {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSuccess_withAccess() throws Exception {
|
|
||||||
credentials =
|
|
||||||
new GaeUserCredentials(
|
|
||||||
AuthenticatedRegistrarAccessor.createForTesting(
|
|
||||||
ImmutableSetMultimap.of(
|
|
||||||
"NewRegistrar", AuthenticatedRegistrarAccessor.Role.OWNER)));
|
|
||||||
doSuccessfulTest("login_valid.xml");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFailure_withoutAccess() {
|
|
||||||
credentials =
|
|
||||||
new GaeUserCredentials(
|
|
||||||
AuthenticatedRegistrarAccessor.createForTesting(
|
|
||||||
ImmutableSetMultimap.of()));
|
|
||||||
doFailingTest("login_valid.xml", UserForbiddenException.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFailure_withAccessToDifferentRegistrar() {
|
|
||||||
credentials =
|
|
||||||
new GaeUserCredentials(
|
|
||||||
AuthenticatedRegistrarAccessor.createForTesting(
|
|
||||||
ImmutableSetMultimap.of(
|
|
||||||
"TheRegistrar", AuthenticatedRegistrarAccessor.Role.OWNER)));
|
|
||||||
doFailingTest("login_valid.xml", UserForbiddenException.class);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,4 +5,3 @@ PATH CLASS METHODS OK AUTH_METHODS
|
||||||
/registrar-ote-setup ConsoleOteSetupAction POST,GET n INTERNAL,API,LEGACY NONE PUBLIC
|
/registrar-ote-setup ConsoleOteSetupAction POST,GET n INTERNAL,API,LEGACY NONE PUBLIC
|
||||||
/registrar-ote-status OteStatusAction POST n API,LEGACY USER PUBLIC
|
/registrar-ote-status OteStatusAction POST n API,LEGACY USER PUBLIC
|
||||||
/registrar-settings RegistrarSettingsAction POST n API,LEGACY USER PUBLIC
|
/registrar-settings RegistrarSettingsAction POST n API,LEGACY USER PUBLIC
|
||||||
/registrar-xhr EppConsoleAction POST n API,LEGACY USER PUBLIC
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ import google.registry.module.frontend.FrontendServlet;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import javax.servlet.Filter;
|
import javax.servlet.Filter;
|
||||||
|
|
||||||
|
@ -54,7 +53,6 @@ public final class RegistryTestServer {
|
||||||
// Frontend Services
|
// Frontend Services
|
||||||
route("/whois/*", FrontendServlet.class),
|
route("/whois/*", FrontendServlet.class),
|
||||||
route("/rdap/*", FrontendServlet.class),
|
route("/rdap/*", FrontendServlet.class),
|
||||||
route("/registrar-xhr", FrontendServlet.class),
|
|
||||||
route("/check", FrontendServlet.class),
|
route("/check", FrontendServlet.class),
|
||||||
|
|
||||||
// Proxy Services
|
// Proxy Services
|
||||||
|
|
|
@ -21,7 +21,6 @@ goog.require('goog.testing.MockControl');
|
||||||
goog.require('goog.testing.PropertyReplacer');
|
goog.require('goog.testing.PropertyReplacer');
|
||||||
goog.require('goog.testing.asserts');
|
goog.require('goog.testing.asserts');
|
||||||
goog.require('goog.testing.jsunit');
|
goog.require('goog.testing.jsunit');
|
||||||
goog.require('goog.testing.mockmatchers');
|
|
||||||
goog.require('goog.testing.net.XhrIo');
|
goog.require('goog.testing.net.XhrIo');
|
||||||
goog.require('registry.registrar.ConsoleTestUtil');
|
goog.require('registry.registrar.ConsoleTestUtil');
|
||||||
goog.require('registry.testing');
|
goog.require('registry.testing');
|
||||||
|
@ -71,36 +70,6 @@ function testButter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The EPP login should be triggered if the user `isGaeLoggedIn`
|
|
||||||
* but not yet `isEppLoggedIn`.
|
|
||||||
*/
|
|
||||||
function testEppLogin() {
|
|
||||||
// This is a little complex, as handleHashChange triggers an async
|
|
||||||
// event to do the EPP login with a callback to come back to
|
|
||||||
// handleHashChange after completion.
|
|
||||||
registry.registrar.ConsoleTestUtil.visit(
|
|
||||||
test, {
|
|
||||||
isEppLoggedIn: true,
|
|
||||||
clientId: test.testClientId,
|
|
||||||
xsrfToken: test.testXsrfToken,
|
|
||||||
productName: 'Foo Registry'
|
|
||||||
}, function() {
|
|
||||||
test.sessionMock.login(
|
|
||||||
goog.testing.mockmatchers.isFunction).$does(function() {
|
|
||||||
test.sessionMock.$reset();
|
|
||||||
test.sessionMock.isEppLoggedIn().$returns(true).$anyTimes();
|
|
||||||
test.sessionMock.getClientId().$returns(
|
|
||||||
test.testClientId).$anyTimes();
|
|
||||||
test.sessionMock.$replay();
|
|
||||||
test.console.handleHashChange(test.testClientId);
|
|
||||||
}).$anyTimes();
|
|
||||||
});
|
|
||||||
assertTrue(test.console.session.isEppLoggedIn());
|
|
||||||
assertNotNull(goog.dom.getElement('domain-registrar-dashboard'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Authed user with no path op specified should nav to welcome page. */
|
/** Authed user with no path op specified should nav to welcome page. */
|
||||||
function testShowLoginOrDash() {
|
function testShowLoginOrDash() {
|
||||||
registry.registrar.ConsoleTestUtil.visit(test, {
|
registry.registrar.ConsoleTestUtil.visit(test, {
|
||||||
|
|
|
@ -16,14 +16,9 @@ goog.provide('registry.registrar.ConsoleTestUtil');
|
||||||
goog.setTestOnly('registry.registrar.ConsoleTestUtil');
|
goog.setTestOnly('registry.registrar.ConsoleTestUtil');
|
||||||
|
|
||||||
goog.require('goog.History');
|
goog.require('goog.History');
|
||||||
goog.require('goog.asserts');
|
|
||||||
goog.require('goog.dom.xml');
|
|
||||||
goog.require('goog.soy');
|
goog.require('goog.soy');
|
||||||
goog.require('goog.testing.mockmatchers');
|
|
||||||
goog.require('registry.registrar.Console');
|
goog.require('registry.registrar.Console');
|
||||||
goog.require('registry.registrar.EppSession');
|
|
||||||
goog.require('registry.soy.registrar.console');
|
goog.require('registry.soy.registrar.console');
|
||||||
goog.require('registry.xml');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,14 +29,8 @@ goog.require('registry.xml');
|
||||||
*/
|
*/
|
||||||
registry.registrar.ConsoleTestUtil.setup = function(test) {
|
registry.registrar.ConsoleTestUtil.setup = function(test) {
|
||||||
test.historyMock = test.mockControl.createLooseMock(goog.History, true);
|
test.historyMock = test.mockControl.createLooseMock(goog.History, true);
|
||||||
test.sessionMock = test.mockControl.createLooseMock(
|
|
||||||
registry.registrar.EppSession, true);
|
|
||||||
test.mockControl.createConstructorMock(goog, 'History')()
|
test.mockControl.createConstructorMock(goog, 'History')()
|
||||||
.$returns(test.historyMock);
|
.$returns(test.historyMock);
|
||||||
test.mockControl
|
|
||||||
.createConstructorMock(registry.registrar, 'EppSession')(
|
|
||||||
goog.testing.mockmatchers.isObject)
|
|
||||||
.$returns(test.sessionMock);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,10 +65,10 @@ registry.registrar.ConsoleTestUtil.renderConsoleMain = function(
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulates visiting a page on the console. Sets path, then mocks
|
* Simulates visiting a page on the console. Sets path, then calls
|
||||||
* session and calls `handleHashChange_`.
|
* `handleHashChange_`.
|
||||||
* @param {!Object} test the test case to configure.
|
* @param {!Object} test the test case to configure.
|
||||||
* @param {?Object=} opt_args may include path, isEppLoggedIn.
|
* @param {?Object=} opt_args may include path.
|
||||||
* @param {?Function=} opt_moar extra setup after called just before
|
* @param {?Function=} opt_moar extra setup after called just before
|
||||||
* `$replayAll`. See memegen/3437690.
|
* `$replayAll`. See memegen/3437690.
|
||||||
*/
|
*/
|
||||||
|
@ -99,33 +88,17 @@ registry.registrar.ConsoleTestUtil.visit = function(
|
||||||
if (opt_args.isOwner === undefined) {
|
if (opt_args.isOwner === undefined) {
|
||||||
opt_args.isOwner = !opt_args.isAdmin;
|
opt_args.isOwner = !opt_args.isAdmin;
|
||||||
}
|
}
|
||||||
if (opt_args.isEppLoggedIn === undefined) {
|
|
||||||
opt_args.isEppLoggedIn = true;
|
|
||||||
}
|
|
||||||
test.historyMock.$reset();
|
test.historyMock.$reset();
|
||||||
test.sessionMock.$reset();
|
|
||||||
test.historyMock.getToken().$returns(opt_args.path).$anyTimes();
|
test.historyMock.getToken().$returns(opt_args.path).$anyTimes();
|
||||||
test.sessionMock.isEppLoggedIn().$returns(opt_args.isEppLoggedIn).$anyTimes();
|
|
||||||
test.sessionMock.getClientId().$returns(opt_args.isEppLoggedIn ?
|
|
||||||
opt_args.clientId : null).$anyTimes();
|
|
||||||
if (opt_args.rspXml) {
|
|
||||||
test.sessionMock
|
|
||||||
.send(goog.testing.mockmatchers.isString,
|
|
||||||
goog.testing.mockmatchers.isFunction)
|
|
||||||
.$does(function(args, cb) {
|
|
||||||
// XXX: Args should be checked.
|
|
||||||
const xml = goog.dom.xml.loadXml(opt_args.rspXml);
|
|
||||||
goog.asserts.assert(xml != null);
|
|
||||||
cb(registry.xml.convertToJson(xml));
|
|
||||||
}).$anyTimes();
|
|
||||||
}
|
|
||||||
if (opt_moar) {
|
if (opt_moar) {
|
||||||
opt_moar();
|
opt_moar();
|
||||||
}
|
}
|
||||||
test.mockControl.$replayAll();
|
test.mockControl.$replayAll();
|
||||||
/** @type {!registry.registrar.Console} */
|
/** @type {!registry.registrar.Console} */
|
||||||
test.console = new registry.registrar.Console(opt_args);
|
test.console = new registry.registrar.Console(opt_args);
|
||||||
// XXX: Should be triggered via event passing.
|
test.console.setUp();
|
||||||
|
// Should be triggered via the History object in test.console.setUp(), but
|
||||||
|
// since we're using a mock that isn't happening. So we call it manually.
|
||||||
test.console.handleHashChange();
|
test.console.handleHashChange();
|
||||||
test.mockControl.$verifyAll();
|
test.mockControl.$verifyAll();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
goog.setTestOnly();
|
|
||||||
|
|
||||||
goog.require('goog.dispose');
|
|
||||||
goog.require('goog.dom');
|
|
||||||
goog.require('goog.testing.MockControl');
|
|
||||||
goog.require('goog.testing.asserts');
|
|
||||||
goog.require('goog.testing.jsunit');
|
|
||||||
goog.require('registry.registrar.ConsoleTestUtil');
|
|
||||||
goog.require('registry.testing');
|
|
||||||
|
|
||||||
|
|
||||||
const $ = goog.dom.getRequiredElement;
|
|
||||||
|
|
||||||
const test = {
|
|
||||||
mockControl: new goog.testing.MockControl()
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function setUp() {
|
|
||||||
registry.testing.addToDocument('<div id="test"/>');
|
|
||||||
registry.testing.addToDocument('<div class="kd-butterbar"/>');
|
|
||||||
registry.registrar.ConsoleTestUtil.renderConsoleMain($('test'), {});
|
|
||||||
registry.registrar.ConsoleTestUtil.setup(test);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function tearDown() {
|
|
||||||
goog.dispose(test.console);
|
|
||||||
test.mockControl.$tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Contact hash path should nav to contact page. */
|
|
||||||
function testVisitContact() {
|
|
||||||
registry.registrar.ConsoleTestUtil.visit(test, {
|
|
||||||
path: 'contact/pabloistrad',
|
|
||||||
rspXml: '<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns:domain="urn:ietf:params:xml:ns:domain-1.0"' +
|
|
||||||
' xmlns:contact="urn:ietf:params:xml:ns:contact-1.0"' +
|
|
||||||
' xmlns:host="urn:ietf:params:xml:ns:host-1.0"' +
|
|
||||||
' xmlns:launch="urn:ietf:params:xml:ns:launch-1.0"' +
|
|
||||||
' xmlns:rgp="urn:ietf:params:xml:ns:rgp-1.0"' +
|
|
||||||
' xmlns="urn:ietf:params:xml:ns:epp-1.0"' +
|
|
||||||
' xmlns:secDNS="urn:ietf:params:xml:ns:secDNS-1.1"' +
|
|
||||||
' xmlns:mark="urn:ietf:params:xml:ns:mark-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>Command completed successfully</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <resData>' +
|
|
||||||
' <contact:infData>' +
|
|
||||||
' <contact:id>pabloistrad</contact:id>' +
|
|
||||||
' <contact:roid>1-roid</contact:roid>' +
|
|
||||||
' <contact:status s="ok"/>' +
|
|
||||||
' <contact:postalInfo type="int">' +
|
|
||||||
' <contact:name>name2</contact:name>' +
|
|
||||||
' <contact:addr>' +
|
|
||||||
' <contact:street></contact:street>' +
|
|
||||||
' <contact:city>city2</contact:city>' +
|
|
||||||
' <contact:cc>US</contact:cc>' +
|
|
||||||
' </contact:addr>' +
|
|
||||||
' </contact:postalInfo>' +
|
|
||||||
' <contact:voice/>' +
|
|
||||||
' <contact:fax/>' +
|
|
||||||
' <contact:email>test2.ui@example.com</contact:email>' +
|
|
||||||
' <contact:clID>daddy</contact:clID>' +
|
|
||||||
' <contact:crID>daddy</contact:crID>' +
|
|
||||||
' <contact:crDate>2014-05-06T22:16:36Z</contact:crDate>' +
|
|
||||||
' <contact:upID>daddy</contact:upID>' +
|
|
||||||
' <contact:upDate>2014-05-07T16:20:07Z</contact:upDate>' +
|
|
||||||
' <contact:authInfo>' +
|
|
||||||
' <contact:pw>asdfasdf</contact:pw>' +
|
|
||||||
' </contact:authInfo>' +
|
|
||||||
' </contact:infData>' +
|
|
||||||
' </resData>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>c4O3B0pRRKKSrrXsJvxP5w==-2</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>'
|
|
||||||
});
|
|
||||||
assertEquals(2, $('contact-postalInfo').childNodes.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Contact hash path should nav to contact page. */
|
|
||||||
function testEdit() {
|
|
||||||
testVisitContact();
|
|
||||||
registry.testing.assertVisible($('reg-app-btns-edit'));
|
|
||||||
registry.testing.click($('reg-app-btn-edit'));
|
|
||||||
registry.testing.assertHidden($('reg-app-btns-edit'));
|
|
||||||
registry.testing.assertVisible($('reg-app-btns-save'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Contact hash path should nav to contact page. */
|
|
||||||
function testAddPostalInfo() {
|
|
||||||
testEdit();
|
|
||||||
const addPiBtn = $('domain-contact-postalInfo-add-button');
|
|
||||||
assertNull(addPiBtn.getAttribute('disabled'));
|
|
||||||
registry.testing.click(addPiBtn);
|
|
||||||
assertTrue(addPiBtn.hasAttribute('disabled'));
|
|
||||||
assertEquals(3, $('contact-postalInfo').childNodes.length);
|
|
||||||
}
|
|
|
@ -1,475 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
goog.setTestOnly();
|
|
||||||
|
|
||||||
goog.require('goog.History');
|
|
||||||
goog.require('goog.dispose');
|
|
||||||
goog.require('goog.dom');
|
|
||||||
goog.require('goog.testing.MockControl');
|
|
||||||
goog.require('goog.testing.PropertyReplacer');
|
|
||||||
goog.require('goog.testing.asserts');
|
|
||||||
goog.require('goog.testing.jsunit');
|
|
||||||
goog.require('goog.testing.mockmatchers');
|
|
||||||
goog.require('goog.testing.net.XhrIo');
|
|
||||||
goog.require('registry.registrar.Console');
|
|
||||||
goog.require('registry.registrar.ConsoleTestUtil');
|
|
||||||
goog.require('registry.testing');
|
|
||||||
|
|
||||||
|
|
||||||
const $ = goog.dom.getRequiredElement;
|
|
||||||
const _ = goog.testing.mockmatchers.ignoreArgument;
|
|
||||||
const stubs = new goog.testing.PropertyReplacer();
|
|
||||||
const mocks = new goog.testing.MockControl();
|
|
||||||
|
|
||||||
let historyMock;
|
|
||||||
let registrarConsole;
|
|
||||||
|
|
||||||
|
|
||||||
function setUp() {
|
|
||||||
registry.testing.addToDocument('<div id="test"/>');
|
|
||||||
registry.testing.addToDocument('<div class="kd-butterbar"/>');
|
|
||||||
registry.registrar.ConsoleTestUtil.renderConsoleMain($('test'), {});
|
|
||||||
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
|
|
||||||
|
|
||||||
historyMock = mocks.createStrictMock(goog.History);
|
|
||||||
mocks.createConstructorMock(goog, 'History')().$returns(historyMock);
|
|
||||||
historyMock.addEventListener(_, _, _);
|
|
||||||
historyMock.setEnabled(true);
|
|
||||||
|
|
||||||
mocks.$replayAll();
|
|
||||||
registrarConsole = new registry.registrar.Console({
|
|
||||||
xsrfToken: '☢',
|
|
||||||
clientId: 'jartine'
|
|
||||||
});
|
|
||||||
mocks.$verifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function tearDown() {
|
|
||||||
goog.dispose(registrarConsole);
|
|
||||||
stubs.reset();
|
|
||||||
mocks.$tearDown();
|
|
||||||
goog.testing.net.XhrIo.cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Handles EPP login. */
|
|
||||||
function handleLogin() {
|
|
||||||
const request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <login>' +
|
|
||||||
' <clID>jartine</clID>' +
|
|
||||||
' <pw>undefined</pw>' +
|
|
||||||
' <options>' +
|
|
||||||
' <version>1.0</version>' +
|
|
||||||
' <lang>en</lang>' +
|
|
||||||
' </options>' +
|
|
||||||
' <svcs>' +
|
|
||||||
' <objURI>urn:ietf:params:xml:ns:host-1.0</objURI>' +
|
|
||||||
' <objURI>urn:ietf:params:xml:ns:domain-1.0</objURI>' +
|
|
||||||
' <objURI>urn:ietf:params:xml:ns:contact-1.0</objURI>' +
|
|
||||||
' </svcs>' +
|
|
||||||
' </login>' +
|
|
||||||
' <clTRID>asdf-1235</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
const response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="2002">' +
|
|
||||||
' <msg>Registrar is already logged in</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>asdf-1235</clTRID>' +
|
|
||||||
' <svTRID>ytk1RO+8SmaDQxrTIdulnw==-3</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
const xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue(xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testView() {
|
|
||||||
historyMock.$reset();
|
|
||||||
historyMock.getToken().$returns('domain/justine.lol').$anyTimes();
|
|
||||||
|
|
||||||
mocks.$replayAll();
|
|
||||||
|
|
||||||
registrarConsole.handleHashChange();
|
|
||||||
handleLogin();
|
|
||||||
|
|
||||||
const request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <info>' +
|
|
||||||
' <domain:info xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
|
|
||||||
' <domain:name hosts="all">justine.lol</domain:name>' +
|
|
||||||
' </domain:info>' +
|
|
||||||
' </info>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
const response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>Command completed successfully</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <resData>' +
|
|
||||||
' <domain:infData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
|
|
||||||
' <domain:name>justine.lol</domain:name>' +
|
|
||||||
' <domain:roid>6-roid</domain:roid>' +
|
|
||||||
' <domain:status s="inactive"/>' +
|
|
||||||
' <domain:registrant>GK Chesterton</domain:registrant>' +
|
|
||||||
' <domain:contact type="admin"><justine></domain:contact>' +
|
|
||||||
' <domain:contact type="billing">candycrush</domain:contact>' +
|
|
||||||
' <domain:contact type="tech">krieger</domain:contact>' +
|
|
||||||
' <domain:ns>' +
|
|
||||||
' <domain:hostObj>ns1.justine.lol</domain:hostObj>' +
|
|
||||||
' <domain:hostObj>ns2.justine.lol</domain:hostObj>' +
|
|
||||||
' </domain:ns>' +
|
|
||||||
' <domain:host>ns1.justine.lol</domain:host>' +
|
|
||||||
' <domain:clID>justine</domain:clID>' +
|
|
||||||
' <domain:crID>justine</domain:crID>' +
|
|
||||||
' <domain:crDate>2014-07-10T02:17:02Z</domain:crDate>' +
|
|
||||||
' <domain:exDate>2015-07-10T02:17:02Z</domain:exDate>' +
|
|
||||||
' <domain:authInfo>' +
|
|
||||||
' <domain:pw>lolcat</domain:pw>' +
|
|
||||||
' </domain:authInfo>' +
|
|
||||||
' </domain:infData>' +
|
|
||||||
' </resData>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>ytk1RO+8SmaDQxrTIdulnw==-4</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
const xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue('XHR is inactive.', xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
assertEquals('We require more vespene gas.',
|
|
||||||
0, goog.testing.net.XhrIo.getSendInstances().length);
|
|
||||||
|
|
||||||
mocks.$verifyAll();
|
|
||||||
|
|
||||||
assertTrue('Form should be read-only.', $('domain:exDate').readOnly);
|
|
||||||
assertContains('justine.lol', $('reg-content').innerHTML);
|
|
||||||
assertEquals('2015-07-10T02:17:02Z', $('domain:exDate').value);
|
|
||||||
assertEquals('GK Chesterton', $('domain:registrant').value);
|
|
||||||
assertEquals('<justine>', $('domain:contact[0].value').value);
|
|
||||||
assertEquals('candycrush', $('domain:contact[1].value').value);
|
|
||||||
assertEquals('krieger', $('domain:contact[2].value').value);
|
|
||||||
assertEquals('lolcat', $('domain:authInfo.domain:pw').value);
|
|
||||||
assertEquals('ns1.justine.lol', $('domain:ns.domain:hostObj[0].value').value);
|
|
||||||
assertEquals('ns2.justine.lol', $('domain:ns.domain:hostObj[1].value').value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testEdit() {
|
|
||||||
testView();
|
|
||||||
|
|
||||||
historyMock.$reset();
|
|
||||||
|
|
||||||
mocks.$replayAll();
|
|
||||||
|
|
||||||
registry.testing.click($('reg-app-btn-edit'));
|
|
||||||
assertFalse('Form should be edible.', $('domain:exDate').readOnly);
|
|
||||||
$('domain:registrant').value = 'Jonathan Swift';
|
|
||||||
$('domain:authInfo.domain:pw').value = '(✿◕‿◕)ノ';
|
|
||||||
|
|
||||||
registry.testing.click($('reg-app-btn-save'));
|
|
||||||
|
|
||||||
let request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <update>' +
|
|
||||||
' <domain:update xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
|
|
||||||
' <domain:name>justine.lol</domain:name>' +
|
|
||||||
' <domain:chg>' +
|
|
||||||
' <domain:registrant>Jonathan Swift</domain:registrant>' +
|
|
||||||
' <domain:authInfo>' +
|
|
||||||
' <domain:pw>(✿◕‿◕)ノ</domain:pw>' +
|
|
||||||
' </domain:authInfo>' +
|
|
||||||
' </domain:chg>' +
|
|
||||||
' </domain:update>' +
|
|
||||||
' </update>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
let response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>This world is built from a million lies.</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>214CjbYuTsijoP8sgyFUNg==-e</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
let xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue('XHR is inactive.', xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
|
|
||||||
request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <info>' +
|
|
||||||
' <domain:info xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
|
|
||||||
' <domain:name hosts="all">justine.lol</domain:name>' +
|
|
||||||
' </domain:info>' +
|
|
||||||
' </info>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>How can we live in the land of the dead?</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <resData>' +
|
|
||||||
' <domain:infData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
|
|
||||||
' <domain:name>justine.lol</domain:name>' +
|
|
||||||
' <domain:roid>6-roid</domain:roid>' +
|
|
||||||
' <domain:status s="inactive"/>' +
|
|
||||||
' <domain:registrant>Jonathan Swift</domain:registrant>' +
|
|
||||||
' <domain:contact type="admin"><justine></domain:contact>' +
|
|
||||||
' <domain:contact type="billing">candycrush</domain:contact>' +
|
|
||||||
' <domain:contact type="tech">krieger</domain:contact>' +
|
|
||||||
' <domain:ns>' +
|
|
||||||
' <domain:hostObj>ns1.justine.lol</domain:hostObj>' +
|
|
||||||
' <domain:hostObj>ns2.justine.lol</domain:hostObj>' +
|
|
||||||
' </domain:ns>' +
|
|
||||||
' <domain:host>ns1.justine.lol</domain:host>' +
|
|
||||||
' <domain:clID>justine</domain:clID>' +
|
|
||||||
' <domain:crID>justine</domain:crID>' +
|
|
||||||
' <domain:crDate>2014-07-10T02:17:02Z</domain:crDate>' +
|
|
||||||
' <domain:exDate>2015-07-10T02:17:02Z</domain:exDate>' +
|
|
||||||
' <domain:authInfo>' +
|
|
||||||
' <domain:pw>(✿◕‿◕)ノ</domain:pw>' +
|
|
||||||
' </domain:authInfo>' +
|
|
||||||
' </domain:infData>' +
|
|
||||||
' </resData>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>ytk1RO+8SmaDQxrTIdulnw==-4</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue('XHR is inactive.', xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
assertEquals('We require more vespene gas.',
|
|
||||||
0, goog.testing.net.XhrIo.getSendInstances().length);
|
|
||||||
|
|
||||||
mocks.$verifyAll();
|
|
||||||
|
|
||||||
assertTrue($('domain:exDate').readOnly);
|
|
||||||
assertContains('justine.lol', $('reg-content').innerHTML);
|
|
||||||
assertEquals('2015-07-10T02:17:02Z', $('domain:exDate').value);
|
|
||||||
assertEquals('Jonathan Swift', $('domain:registrant').value);
|
|
||||||
assertEquals('<justine>', $('domain:contact[0].value').value);
|
|
||||||
assertEquals('candycrush', $('domain:contact[1].value').value);
|
|
||||||
assertEquals('krieger', $('domain:contact[2].value').value);
|
|
||||||
assertEquals('(✿◕‿◕)ノ', $('domain:authInfo.domain:pw').value);
|
|
||||||
assertEquals('ns1.justine.lol', $('domain:ns.domain:hostObj[0].value').value);
|
|
||||||
assertEquals('ns2.justine.lol', $('domain:ns.domain:hostObj[1].value').value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testEdit_cancel_restoresOriginalValues() {
|
|
||||||
testView();
|
|
||||||
|
|
||||||
registry.testing.click($('reg-app-btn-edit'));
|
|
||||||
assertFalse('Form should be edible.', $('domain:exDate').readOnly);
|
|
||||||
$('domain:registrant').value = 'Jonathan Swift';
|
|
||||||
$('domain:authInfo.domain:pw').value = '(✿◕‿◕)ノ';
|
|
||||||
|
|
||||||
registry.testing.click($('reg-app-btn-cancel'));
|
|
||||||
assertTrue('Form should be read-only.', $('domain:exDate').readOnly);
|
|
||||||
assertEquals('GK Chesterton', $('domain:registrant').value);
|
|
||||||
assertEquals('lolcat', $('domain:authInfo.domain:pw').value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testCreate() {
|
|
||||||
historyMock.$reset();
|
|
||||||
historyMock.getToken().$returns('domain').$anyTimes();
|
|
||||||
mocks.$replayAll();
|
|
||||||
registrarConsole.handleHashChange();
|
|
||||||
handleLogin();
|
|
||||||
mocks.$verifyAll();
|
|
||||||
|
|
||||||
assertFalse('Form should be edible.', $('domain:name').readOnly);
|
|
||||||
$('domain:name').value = 'bog.lol';
|
|
||||||
$('domain:period').value = '1';
|
|
||||||
$('domain:authInfo.domain:pw').value = 'attorney at lawl';
|
|
||||||
$('domain:registrant').value = 'Chris Pohl';
|
|
||||||
registry.testing.click($('domain-contact-add-button'));
|
|
||||||
$('domain:contact[0].value').value = 'BlutEngel';
|
|
||||||
$('domain:contact[0].@type').value = 'admin';
|
|
||||||
registry.testing.click($('domain-contact-add-button'));
|
|
||||||
$('domain:contact[1].value').value = 'Ravenous';
|
|
||||||
$('domain:contact[1].@type').value = 'tech';
|
|
||||||
registry.testing.click($('domain-contact-add-button'));
|
|
||||||
$('domain:contact[2].value').value = 'Dark Angels';
|
|
||||||
$('domain:contact[2].@type').value = 'billing';
|
|
||||||
|
|
||||||
historyMock.$reset();
|
|
||||||
mocks.$replayAll();
|
|
||||||
|
|
||||||
registry.testing.click($('reg-app-btn-save'));
|
|
||||||
|
|
||||||
let request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <create>' +
|
|
||||||
' <domain:create xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
|
|
||||||
' <domain:name>bog.lol</domain:name>' +
|
|
||||||
' <domain:period unit="y">1</domain:period>' +
|
|
||||||
' <domain:registrant>Chris Pohl</domain:registrant>' +
|
|
||||||
' <domain:contact type="admin">BlutEngel</domain:contact>' +
|
|
||||||
' <domain:contact type="tech">Ravenous</domain:contact>' +
|
|
||||||
' <domain:contact type="billing">Dark Angels</domain:contact>' +
|
|
||||||
' <domain:authInfo>' +
|
|
||||||
' <domain:pw>attorney at lawl</domain:pw>' +
|
|
||||||
' </domain:authInfo>' +
|
|
||||||
' </domain:create>' +
|
|
||||||
' </create>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
let response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>Command completed successfully</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <resData>' +
|
|
||||||
' <domain:creData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
|
|
||||||
' <domain:name>bog.lol</domain:name>' +
|
|
||||||
' <domain:crDate>2014-07-17T08:19:24Z</domain:crDate>' +
|
|
||||||
' <domain:exDate>2015-07-17T08:19:24Z</domain:exDate>' +
|
|
||||||
' </domain:creData>' +
|
|
||||||
' </resData>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>OBPI6JvEQfOUaO8qGf+IKA==-7</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
let xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue('XHR is inactive.', xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
|
|
||||||
request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <info>' +
|
|
||||||
' <domain:info xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
|
|
||||||
' <domain:name hosts="all">bog.lol</domain:name>' +
|
|
||||||
' </domain:info>' +
|
|
||||||
' </info>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>Command completed successfully</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <resData>' +
|
|
||||||
' <domain:infData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
|
|
||||||
' <domain:name>bog.lol</domain:name>' +
|
|
||||||
' <domain:roid>1f-roid</domain:roid>' +
|
|
||||||
' <domain:status s="inactive"/>' +
|
|
||||||
' <domain:registrant>Chris Pohl</domain:registrant>' +
|
|
||||||
' <domain:contact type="admin">BlutEngel</domain:contact>' +
|
|
||||||
' <domain:contact type="tech">Ravenous</domain:contact>' +
|
|
||||||
' <domain:contact type="billing">Dark Angels</domain:contact>' +
|
|
||||||
' <domain:clID>justine</domain:clID>' +
|
|
||||||
' <domain:crID>justine</domain:crID>' +
|
|
||||||
' <domain:crDate>2014-07-17T08:19:24Z</domain:crDate>' +
|
|
||||||
' <domain:exDate>2015-07-17T08:19:24Z</domain:exDate>' +
|
|
||||||
' <domain:authInfo>' +
|
|
||||||
' <domain:pw>attorney at lawl</domain:pw>' +
|
|
||||||
' </domain:authInfo>' +
|
|
||||||
' </domain:infData>' +
|
|
||||||
' </resData>' +
|
|
||||||
' <extension>' +
|
|
||||||
' <rgp:infData xmlns:rgp="urn:ietf:params:xml:ns:rgp-1.0">' +
|
|
||||||
' <rgp:rgpStatus s="addPeriod"/>' +
|
|
||||||
' </rgp:infData>' +
|
|
||||||
' </extension>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>OBPI6JvEQfOUaO8qGf+IKA==-8</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue('XHR is inactive.', xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
assertEquals('We require more vespene gas.',
|
|
||||||
0, goog.testing.net.XhrIo.getSendInstances().length);
|
|
||||||
|
|
||||||
mocks.$verifyAll();
|
|
||||||
|
|
||||||
assertTrue('Form should be read-only.', $('domain:exDate').readOnly);
|
|
||||||
assertContains('bog.lol', $('reg-content').innerHTML);
|
|
||||||
assertEquals('2015-07-17T08:19:24Z', $('domain:exDate').value);
|
|
||||||
assertEquals('Chris Pohl', $('domain:registrant').value);
|
|
||||||
assertEquals('BlutEngel', $('domain:contact[0].value').value);
|
|
||||||
assertEquals('Ravenous', $('domain:contact[1].value').value);
|
|
||||||
assertEquals('Dark Angels', $('domain:contact[2].value').value);
|
|
||||||
assertEquals('attorney at lawl', $('domain:authInfo.domain:pw').value);
|
|
||||||
assertNull(goog.dom.getElement('domain:ns.domain:hostObj[0].value'));
|
|
||||||
}
|
|
|
@ -1,415 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
goog.setTestOnly();
|
|
||||||
|
|
||||||
goog.require('goog.History');
|
|
||||||
goog.require('goog.dispose');
|
|
||||||
goog.require('goog.dom');
|
|
||||||
goog.require('goog.testing.MockControl');
|
|
||||||
goog.require('goog.testing.PropertyReplacer');
|
|
||||||
goog.require('goog.testing.asserts');
|
|
||||||
goog.require('goog.testing.jsunit');
|
|
||||||
goog.require('goog.testing.mockmatchers');
|
|
||||||
goog.require('goog.testing.net.XhrIo');
|
|
||||||
goog.require('registry.registrar.Console');
|
|
||||||
goog.require('registry.registrar.ConsoleTestUtil');
|
|
||||||
goog.require('registry.testing');
|
|
||||||
|
|
||||||
|
|
||||||
const $ = goog.dom.getRequiredElement;
|
|
||||||
const _ = goog.testing.mockmatchers.ignoreArgument;
|
|
||||||
const stubs = new goog.testing.PropertyReplacer();
|
|
||||||
const mocks = new goog.testing.MockControl();
|
|
||||||
|
|
||||||
let historyMock;
|
|
||||||
let registrarConsole;
|
|
||||||
|
|
||||||
|
|
||||||
function setUp() {
|
|
||||||
registry.testing.addToDocument('<div id="test"/>');
|
|
||||||
registry.testing.addToDocument('<div class="kd-butterbar"/>');
|
|
||||||
registry.registrar.ConsoleTestUtil.renderConsoleMain($('test'), {});
|
|
||||||
stubs.setPath('goog.net.XhrIo', goog.testing.net.XhrIo);
|
|
||||||
|
|
||||||
historyMock = mocks.createStrictMock(goog.History);
|
|
||||||
mocks.createConstructorMock(goog, 'History')().$returns(historyMock);
|
|
||||||
historyMock.addEventListener(_, _, _);
|
|
||||||
historyMock.setEnabled(true);
|
|
||||||
|
|
||||||
mocks.$replayAll();
|
|
||||||
registrarConsole = new registry.registrar.Console({
|
|
||||||
xsrfToken: '☢',
|
|
||||||
clientId: 'jartine'
|
|
||||||
});
|
|
||||||
mocks.$verifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function tearDown() {
|
|
||||||
goog.dispose(registrarConsole);
|
|
||||||
stubs.reset();
|
|
||||||
mocks.$tearDown();
|
|
||||||
goog.testing.net.XhrIo.cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Handles EPP login. */
|
|
||||||
function handleLogin() {
|
|
||||||
const request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <login>' +
|
|
||||||
' <clID>jartine</clID>' +
|
|
||||||
' <pw>undefined</pw>' +
|
|
||||||
' <options>' +
|
|
||||||
' <version>1.0</version>' +
|
|
||||||
' <lang>en</lang>' +
|
|
||||||
' </options>' +
|
|
||||||
' <svcs>' +
|
|
||||||
' <objURI>urn:ietf:params:xml:ns:host-1.0</objURI>' +
|
|
||||||
' <objURI>urn:ietf:params:xml:ns:domain-1.0</objURI>' +
|
|
||||||
' <objURI>urn:ietf:params:xml:ns:contact-1.0</objURI>' +
|
|
||||||
' </svcs>' +
|
|
||||||
' </login>' +
|
|
||||||
' <clTRID>asdf-1235</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
const response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="2002">' +
|
|
||||||
' <msg>Registrar is already logged in</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>asdf-1235</clTRID>' +
|
|
||||||
' <svTRID>ytk1RO+8SmaDQxrTIdulnw==-3</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
const xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue(xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testView() {
|
|
||||||
historyMock.$reset();
|
|
||||||
historyMock.getToken().$returns('host/ns1.justine.lol').$anyTimes();
|
|
||||||
|
|
||||||
mocks.$replayAll();
|
|
||||||
|
|
||||||
registrarConsole.handleHashChange();
|
|
||||||
handleLogin();
|
|
||||||
|
|
||||||
const request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <info>' +
|
|
||||||
' <host:info xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
|
|
||||||
' <host:name>ns1.justine.lol</host:name>' +
|
|
||||||
' </host:info>' +
|
|
||||||
' </info>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
const response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"' +
|
|
||||||
' xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>Command completed successfully</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <resData>' +
|
|
||||||
' <host:infData>' +
|
|
||||||
' <host:name>ns1.justine.lol</host:name>' +
|
|
||||||
' <host:roid>8-roid</host:roid>' +
|
|
||||||
' <host:status s="ok"/>' +
|
|
||||||
' <host:addr ip="v4">8.8.8.8</host:addr>' +
|
|
||||||
' <host:addr ip="v6">feed:a:bee::1</host:addr>' +
|
|
||||||
' <host:clID>justine</host:clID>' +
|
|
||||||
' <host:crID>justine</host:crID>' +
|
|
||||||
' <host:crDate>2014-07-10T02:18:34Z</host:crDate>' +
|
|
||||||
' </host:infData>' +
|
|
||||||
' </resData>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>EweBEzCZTJirOqRmrtYrAA==-b</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
const xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue('XHR is inactive.', xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('application/epp+xml',
|
|
||||||
xhr.getLastRequestHeaders()['Content-Type']);
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
assertEquals('We require more vespene gas.',
|
|
||||||
0, goog.testing.net.XhrIo.getSendInstances().length);
|
|
||||||
|
|
||||||
mocks.$verifyAll();
|
|
||||||
|
|
||||||
assertTrue('Form should be read-only.', $('host:chgName').readOnly);
|
|
||||||
assertContains('ns1.justine.lol', $('reg-content').innerHTML);
|
|
||||||
assertEquals('ns1.justine.lol', $('host:chgName').value);
|
|
||||||
assertEquals('8.8.8.8', $('host:addr[0].value').value);
|
|
||||||
assertEquals('feed:a:bee::1', $('host:addr[1].value').value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testEditFirstAddr_ignoreSecond_addThird() {
|
|
||||||
testView();
|
|
||||||
|
|
||||||
historyMock.$reset();
|
|
||||||
|
|
||||||
mocks.$replayAll();
|
|
||||||
|
|
||||||
registry.testing.click($('reg-app-btn-edit'));
|
|
||||||
|
|
||||||
assertFalse('Form should be edible.', $('host:addr[0].value').readOnly);
|
|
||||||
$('host:addr[0].value').value = '1.2.3.4';
|
|
||||||
registry.testing.click($('domain-host-addr-add-button'));
|
|
||||||
$('host:addr[2].value').value = 'feed:a:fed::1';
|
|
||||||
|
|
||||||
registry.testing.click($('reg-app-btn-save'));
|
|
||||||
|
|
||||||
let request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <update>' +
|
|
||||||
' <host:update xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
|
|
||||||
' <host:name>ns1.justine.lol</host:name>' +
|
|
||||||
' <host:add>' +
|
|
||||||
' <host:addr ip="v4">1.2.3.4</host:addr>' +
|
|
||||||
' <host:addr ip="v6">feed:a:fed::1</host:addr>' +
|
|
||||||
' </host:add>' +
|
|
||||||
' <host:rem>' +
|
|
||||||
' <host:addr ip="v4">8.8.8.8</host:addr>' +
|
|
||||||
' </host:rem>' +
|
|
||||||
' </host:update>' +
|
|
||||||
' </update>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
let response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>This world is built from a million lies.</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>214CjbYuTsijoP8sgyFUNg==-e</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
let xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue('XHR is inactive.', xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
|
|
||||||
request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <info>' +
|
|
||||||
' <host:info xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
|
|
||||||
' <host:name>ns1.justine.lol</host:name>' +
|
|
||||||
' </host:info>' +
|
|
||||||
' </info>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0"' +
|
|
||||||
' xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>Command completed successfully</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <resData>' +
|
|
||||||
' <host:infData>' +
|
|
||||||
' <host:name>ns1.justine.lol</host:name>' +
|
|
||||||
' <host:roid>8-roid</host:roid>' +
|
|
||||||
' <host:status s="ok"/>' +
|
|
||||||
' <host:addr ip="v6">feed:a:bee::1</host:addr>' +
|
|
||||||
' <host:addr ip="v4">1.2.3.4</host:addr>' +
|
|
||||||
' <host:addr ip="v6">feed:a:fed::1</host:addr>' +
|
|
||||||
' <host:clID>justine</host:clID>' +
|
|
||||||
' <host:crID>justine</host:crID>' +
|
|
||||||
' <host:crDate>2014-07-10T02:18:34Z</host:crDate>' +
|
|
||||||
' </host:infData>' +
|
|
||||||
' </resData>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>EweBEzCZTJirOqRmrtYrAA==-b</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue('XHR is inactive.', xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
assertEquals('We require more vespene gas.',
|
|
||||||
0, goog.testing.net.XhrIo.getSendInstances().length);
|
|
||||||
|
|
||||||
mocks.$verifyAll();
|
|
||||||
|
|
||||||
assertTrue('Form should be read-only.', $('host:chgName').readOnly);
|
|
||||||
assertContains('ns1.justine.lol', $('reg-content').innerHTML);
|
|
||||||
assertEquals('ns1.justine.lol', $('host:chgName').value);
|
|
||||||
assertEquals('feed:a:bee::1', $('host:addr[0].value').value);
|
|
||||||
assertEquals('1.2.3.4', $('host:addr[1].value').value);
|
|
||||||
assertEquals('feed:a:fed::1', $('host:addr[2].value').value);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testCreate() {
|
|
||||||
historyMock.$reset();
|
|
||||||
historyMock.getToken().$returns('host').$anyTimes();
|
|
||||||
mocks.$replayAll();
|
|
||||||
registrarConsole.handleHashChange();
|
|
||||||
handleLogin();
|
|
||||||
mocks.$verifyAll();
|
|
||||||
|
|
||||||
assertFalse('Form should be edible.', $('host:name').readOnly);
|
|
||||||
$('host:name').value = 'ns1.example.tld';
|
|
||||||
registry.testing.click($('domain-host-addr-add-button'));
|
|
||||||
$('host:addr[0].value').value = '192.0.2.2';
|
|
||||||
registry.testing.click($('domain-host-addr-add-button'));
|
|
||||||
$('host:addr[1].value').value = '192.0.2.29';
|
|
||||||
registry.testing.click($('domain-host-addr-add-button'));
|
|
||||||
$('host:addr[2].value').value = '1080:0:0:0:8:800:200C:417A';
|
|
||||||
|
|
||||||
historyMock.$reset();
|
|
||||||
mocks.$replayAll();
|
|
||||||
|
|
||||||
registry.testing.click($('reg-app-btn-save'));
|
|
||||||
|
|
||||||
let request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <create>' +
|
|
||||||
' <host:create xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
|
|
||||||
' <host:name>ns1.example.tld</host:name>' +
|
|
||||||
' <host:addr ip="v4">192.0.2.2</host:addr>' +
|
|
||||||
' <host:addr ip="v4">192.0.2.29</host:addr>' +
|
|
||||||
' <host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr>' +
|
|
||||||
' </host:create>' +
|
|
||||||
' </create>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
let response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>Command completed successfully</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <resData>' +
|
|
||||||
' <host:creData xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
|
|
||||||
' <host:name>ns1.example.tld</host:name>' +
|
|
||||||
' <host:crDate>1999-04-03T22:00:00.0Z</host:crDate>' +
|
|
||||||
' </host:creData>' +
|
|
||||||
' </resData>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>EweBEzCZTJirOqRmrtYrAA==-b</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
let xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue('XHR is inactive.', xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
|
|
||||||
request = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <command>' +
|
|
||||||
' <info>' +
|
|
||||||
' <host:info xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
|
|
||||||
' <host:name>ns1.example.tld</host:name>' +
|
|
||||||
' </host:info>' +
|
|
||||||
' </info>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' </command>' +
|
|
||||||
'</epp>');
|
|
||||||
response = registry.testing.loadXml(
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>Command completed successfully</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <resData>' +
|
|
||||||
' <host:infData xmlns:host="urn:ietf:params:xml:ns:host-1.0">' +
|
|
||||||
' <host:name>ns1.example.tld</host:name>' +
|
|
||||||
' <host:roid>NS1_EXAMPLE1-REP</host:roid>' +
|
|
||||||
' <host:status s="linked"/>' +
|
|
||||||
' <host:status s="clientUpdateProhibited"/>' +
|
|
||||||
' <host:addr ip="v4">192.0.2.2</host:addr>' +
|
|
||||||
' <host:addr ip="v4">192.0.2.29</host:addr>' +
|
|
||||||
' <host:addr ip="v6">1080:0:0:0:8:800:200C:417A</host:addr>' +
|
|
||||||
' <host:clID>TheRegistrar</host:clID>' +
|
|
||||||
' <host:crID>NewRegistrar</host:crID>' +
|
|
||||||
' <host:crDate>1999-04-03T22:00:00.0Z</host:crDate>' +
|
|
||||||
' <host:upID>NewRegistrar</host:upID>' +
|
|
||||||
' <host:upDate>1999-12-03T09:00:00.0Z</host:upDate>' +
|
|
||||||
' <host:trDate>2000-04-08T09:00:00.0Z</host:trDate>' +
|
|
||||||
' </host:infData>' +
|
|
||||||
' </resData>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>EweBEzCZTJirOqRmrtYrAA==-b</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
xhr = goog.testing.net.XhrIo.getSendInstances().pop();
|
|
||||||
assertTrue('XHR is inactive.', xhr.isActive());
|
|
||||||
assertEquals('/registrar-xhr?clientId=jartine', xhr.getLastUri());
|
|
||||||
assertEquals('☢', xhr.getLastRequestHeaders()['X-CSRF-Token']);
|
|
||||||
registry.testing.assertXmlEquals(request, xhr.getLastContent());
|
|
||||||
xhr.simulateResponse(200, response);
|
|
||||||
assertEquals('We require more vespene gas.',
|
|
||||||
0, goog.testing.net.XhrIo.getSendInstances().length);
|
|
||||||
|
|
||||||
mocks.$verifyAll();
|
|
||||||
|
|
||||||
assertTrue('Form should be read-only.', $('host:chgName').readOnly);
|
|
||||||
assertEquals('ns1.example.tld', $('host:chgName').value);
|
|
||||||
assertEquals('192.0.2.2', $('host:addr[0].value').value);
|
|
||||||
assertEquals('192.0.2.29', $('host:addr[1].value').value);
|
|
||||||
assertEquals('1080:0:0:0:8:800:200C:417A', $('host:addr[2].value').value);
|
|
||||||
}
|
|
|
@ -15,15 +15,12 @@
|
||||||
goog.provide('registry.testing');
|
goog.provide('registry.testing');
|
||||||
goog.setTestOnly('registry.testing');
|
goog.setTestOnly('registry.testing');
|
||||||
|
|
||||||
goog.require('goog.asserts');
|
|
||||||
goog.require('goog.dom');
|
goog.require('goog.dom');
|
||||||
goog.require('goog.dom.classlist');
|
goog.require('goog.dom.classlist');
|
||||||
goog.require('goog.dom.xml');
|
|
||||||
goog.require('goog.events.EventType');
|
goog.require('goog.events.EventType');
|
||||||
goog.require('goog.format.JsonPrettyPrinter');
|
goog.require('goog.format.JsonPrettyPrinter');
|
||||||
goog.require('goog.html.testing');
|
goog.require('goog.html.testing');
|
||||||
goog.require('goog.json');
|
goog.require('goog.json');
|
||||||
goog.require('goog.testing.asserts');
|
|
||||||
goog.require('goog.testing.events');
|
goog.require('goog.testing.events');
|
||||||
goog.require('goog.testing.events.Event');
|
goog.require('goog.testing.events.Event');
|
||||||
goog.require('goog.testing.net.XhrIo');
|
goog.require('goog.testing.net.XhrIo');
|
||||||
|
@ -40,32 +37,6 @@ registry.testing.addToDocument = function(html) {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts XML document from inside an `<iframe>`.
|
|
||||||
* @param {string} xmlText
|
|
||||||
* @return {!Document}
|
|
||||||
*/
|
|
||||||
registry.testing.loadXml = function(xmlText) {
|
|
||||||
var xml = goog.dom.xml.loadXml(xmlText);
|
|
||||||
goog.asserts.assert(xml != null);
|
|
||||||
if ('parsererror' in xml) {
|
|
||||||
fail(xml['parsererror']['keyValue']);
|
|
||||||
}
|
|
||||||
return xml;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts plain text string from inside an `<iframe>`.
|
|
||||||
* @param {string|!Document|!Element} want
|
|
||||||
* @param {string|!Document|!Element} got
|
|
||||||
*/
|
|
||||||
registry.testing.assertXmlEquals = function(want, got) {
|
|
||||||
assertHTMLEquals(registry.testing.sanitizeXml_(want),
|
|
||||||
registry.testing.sanitizeXml_(got));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulates a mouse click on a browser element.
|
* Simulates a mouse click on a browser element.
|
||||||
* @param {!Element} element
|
* @param {!Element} element
|
||||||
|
@ -135,22 +106,6 @@ registry.testing.assertReqMockRsp =
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes stuff from XML text that we don't want to compare.
|
|
||||||
* @param {string|!Document|!Element} xml
|
|
||||||
* @return {string}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
registry.testing.sanitizeXml_ = function(xml) {
|
|
||||||
var xmlString = goog.isString(xml) ? xml : goog.dom.xml.serialize(xml);
|
|
||||||
return xmlString
|
|
||||||
.replace(/^\s*<\?.*?\?>\s*/, '') // Remove declaration thing.
|
|
||||||
.replace(/xmlns(:\w+)?="[^"]+"/g, '') // Remove namespace things.
|
|
||||||
.replace(/>\s+</g, '><') // Remove spaces between XML tags.
|
|
||||||
.replace(/<!--.*?-->/, ''); // Remove comments.
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON pretty printer.
|
* JSON pretty printer.
|
||||||
* @type {!goog.format.JsonPrettyPrinter}
|
* @type {!goog.format.JsonPrettyPrinter}
|
||||||
|
|
|
@ -1,183 +0,0 @@
|
||||||
// Copyright 2017 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.
|
|
||||||
|
|
||||||
goog.setTestOnly();
|
|
||||||
|
|
||||||
goog.require('goog.dom.xml');
|
|
||||||
goog.require('goog.testing.asserts');
|
|
||||||
goog.require('goog.testing.jsunit');
|
|
||||||
goog.require('registry.testing');
|
|
||||||
goog.require('registry.xml');
|
|
||||||
|
|
||||||
|
|
||||||
function testEmptyElement_hasNoKeyValue() {
|
|
||||||
assertXmlTurnsIntoJson(
|
|
||||||
{'epp': {}},
|
|
||||||
'<epp></epp>');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testSelfClosingRootElement_hasNoKeyValue() {
|
|
||||||
assertXmlTurnsIntoJson(
|
|
||||||
{'epp': {}},
|
|
||||||
'<epp/>');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testElementWithWhitespaceTextContent_getsIgnored() {
|
|
||||||
assertXmlTurnsIntoJson(
|
|
||||||
{'epp': {}},
|
|
||||||
'<epp> \r\n </epp>');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testElementWithTextContent_getsSetToKeyValueField() {
|
|
||||||
assertXmlTurnsIntoJson(
|
|
||||||
{'epp': {'keyValue': 'hello'}},
|
|
||||||
'<epp>hello</epp>');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testTextWithSpacesOnSides_getsTrimmed() {
|
|
||||||
assertXmlTurnsIntoJson(
|
|
||||||
{'epp': {'keyValue': 'hello'}},
|
|
||||||
'<epp> hello </epp>');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testAttribute_getsSetToFieldPrefixedByAtSymbol() {
|
|
||||||
assertXmlTurnsIntoJson(
|
|
||||||
{'epp': {'@ohmy': 'goth'}},
|
|
||||||
'<epp ohmy="goth"/>');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testSingleNestedElement_keyIsNameAndValueIsNode() {
|
|
||||||
assertXmlTurnsIntoJson(
|
|
||||||
{'epp': {'ohmy': {'keyValue': 'goth'}}},
|
|
||||||
'<epp><ohmy>goth</ohmy></epp>');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testMultipleNestedElements_valueBecomesArray() {
|
|
||||||
assertXmlTurnsIntoJson(
|
|
||||||
{'epp': {'ohmy': [{'keyValue': 'goth1'}, {'keyValue': 'goth2'}]}},
|
|
||||||
'<epp><ohmy>goth1</ohmy><ohmy>goth2</ohmy></epp>');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testInterspersedText_throwsError() {
|
|
||||||
assertEquals(
|
|
||||||
'XML text "hello" interspersed with "there"',
|
|
||||||
assertThrows(function() {
|
|
||||||
registry.xml.convertToJson(
|
|
||||||
goog.dom.xml.loadXml(
|
|
||||||
'<epp> hello <omg/> there </epp>'));
|
|
||||||
}).message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function testEppMessage() {
|
|
||||||
assertXmlTurnsIntoJson(
|
|
||||||
{
|
|
||||||
'epp': {
|
|
||||||
'@xmlns': 'urn:ietf:params:xml:ns:epp-1.0',
|
|
||||||
'response': {
|
|
||||||
'result': {
|
|
||||||
'@code': '1000',
|
|
||||||
'msg': {'keyValue': 'Command completed successfully'}
|
|
||||||
},
|
|
||||||
'resData': {
|
|
||||||
'domain:infData': {
|
|
||||||
'@xmlns:domain': 'urn:ietf:params:xml:ns:domain-1.0',
|
|
||||||
'domain:name': {'keyValue': 'justine.lol'},
|
|
||||||
'domain:roid': {'keyValue': '6-roid'},
|
|
||||||
'domain:status': {'@s': 'inactive'},
|
|
||||||
'domain:registrant': {'keyValue': 'GK Chesterton'},
|
|
||||||
'domain:contact': [
|
|
||||||
{'@type': 'admin', 'keyValue': '<justine>'},
|
|
||||||
{'@type': 'billing', 'keyValue': 'candycrush'},
|
|
||||||
{'@type': 'tech', 'keyValue': 'krieger'}
|
|
||||||
],
|
|
||||||
'domain:ns': {
|
|
||||||
'domain:hostObj': [
|
|
||||||
{'keyValue': 'ns1.justine.lol'},
|
|
||||||
{'keyValue': 'ns2.justine.lol'}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
'domain:host': {'keyValue': 'ns1.justine.lol'},
|
|
||||||
'domain:clID': {'keyValue': 'justine'},
|
|
||||||
'domain:crID': {'keyValue': 'justine'},
|
|
||||||
'domain:crDate': {'keyValue': '2014-07-10T02:17:02Z'},
|
|
||||||
'domain:exDate': {'keyValue': '2015-07-10T02:17:02Z'},
|
|
||||||
'domain:authInfo': {
|
|
||||||
'domain:pw': {'keyValue': 'lolcat'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'trID': {
|
|
||||||
'clTRID': {'keyValue': 'abc-1234'},
|
|
||||||
'svTRID': {'keyValue': 'ytk1RO+8SmaDQxrTIdulnw==-4'}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'<?xml version="1.0"?>' +
|
|
||||||
'<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">' +
|
|
||||||
' <response>' +
|
|
||||||
' <result code="1000">' +
|
|
||||||
' <msg>Command completed successfully</msg>' +
|
|
||||||
' </result>' +
|
|
||||||
' <resData>' +
|
|
||||||
' <domain:infData' +
|
|
||||||
' xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">' +
|
|
||||||
' <domain:name>justine.lol</domain:name>' +
|
|
||||||
' <domain:roid>6-roid</domain:roid>' +
|
|
||||||
' <domain:status s="inactive"/>' +
|
|
||||||
' <domain:registrant>GK Chesterton</domain:registrant>' +
|
|
||||||
' <domain:contact type="admin"><justine></domain:contact>' +
|
|
||||||
' <domain:contact type="billing">candycrush</domain:contact>' +
|
|
||||||
' <domain:contact type="tech">krieger</domain:contact>' +
|
|
||||||
' <domain:ns>' +
|
|
||||||
' <domain:hostObj>ns1.justine.lol</domain:hostObj>' +
|
|
||||||
' <domain:hostObj>ns2.justine.lol</domain:hostObj>' +
|
|
||||||
' </domain:ns>' +
|
|
||||||
' <domain:host>ns1.justine.lol</domain:host>' +
|
|
||||||
' <domain:clID>justine</domain:clID>' +
|
|
||||||
' <domain:crID>justine</domain:crID>' +
|
|
||||||
' <domain:crDate>2014-07-10T02:17:02Z</domain:crDate>' +
|
|
||||||
' <domain:exDate>2015-07-10T02:17:02Z</domain:exDate>' +
|
|
||||||
' <domain:authInfo>' +
|
|
||||||
' <domain:pw>lolcat</domain:pw>' +
|
|
||||||
' </domain:authInfo>' +
|
|
||||||
' </domain:infData>' +
|
|
||||||
' </resData>' +
|
|
||||||
' <trID>' +
|
|
||||||
' <clTRID>abc-1234</clTRID>' +
|
|
||||||
' <svTRID>ytk1RO+8SmaDQxrTIdulnw==-4</svTRID>' +
|
|
||||||
' </trID>' +
|
|
||||||
' </response>' +
|
|
||||||
'</epp>');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asserts `xml` turns into `json`.
|
|
||||||
* @param {!Object} json
|
|
||||||
* @param {string} xml
|
|
||||||
*/
|
|
||||||
function assertXmlTurnsIntoJson(json, xml) {
|
|
||||||
registry.testing.assertObjectEqualsPretty(
|
|
||||||
json, registry.xml.convertToJson(goog.dom.xml.loadXml(xml)));
|
|
||||||
}
|
|
|
@ -26,7 +26,6 @@ import google.registry.model.ofy.OfyFilter;
|
||||||
import google.registry.module.frontend.FrontendServlet;
|
import google.registry.module.frontend.FrontendServlet;
|
||||||
import google.registry.server.RegistryTestServer;
|
import google.registry.server.RegistryTestServer;
|
||||||
import google.registry.testing.CertificateSamples;
|
import google.registry.testing.CertificateSamples;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
@ -44,8 +43,7 @@ public class RegistrarConsoleScreenshotTest {
|
||||||
.setRoutes(
|
.setRoutes(
|
||||||
route("/registrar", FrontendServlet.class),
|
route("/registrar", FrontendServlet.class),
|
||||||
route("/registrar-ote-status", FrontendServlet.class),
|
route("/registrar-ote-status", FrontendServlet.class),
|
||||||
route("/registrar-settings", FrontendServlet.class),
|
route("/registrar-settings", FrontendServlet.class))
|
||||||
route("/registrar-xhr", FrontendServlet.class))
|
|
||||||
.setFilters(ObjectifyFilter.class, OfyFilter.class)
|
.setFilters(ObjectifyFilter.class, OfyFilter.class)
|
||||||
.setFixtures(BASIC)
|
.setFixtures(BASIC)
|
||||||
.setEmail("Marla.Singer@google.com")
|
.setEmail("Marla.Singer@google.com")
|
||||||
|
@ -286,77 +284,6 @@ public class RegistrarConsoleScreenshotTest {
|
||||||
driver.diffPage("page");
|
driver.diffPage("page");
|
||||||
}
|
}
|
||||||
|
|
||||||
// EPP pages aren't being included in launch, so temporarily disable the following tests.
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void domainCreate() throws Throwable {
|
|
||||||
// TODO(b/17675279): Change labels to unicode.
|
|
||||||
driver.get(server.getUrl("/registrar#domain"));
|
|
||||||
driver.waitForElement(By.tagName("h1"));
|
|
||||||
driver.diffPage("page");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore("TODO(b/26984251): Unflake nameserver ordering.")
|
|
||||||
public void domainView() throws Throwable {
|
|
||||||
driver.get(server.getUrl("/registrar#domain/love.xn--q9jyb4c"));
|
|
||||||
driver.waitForElement(By.tagName("h1"));
|
|
||||||
driver.diffPage("page");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore("TODO(b/26984251): Unflake nameserver ordering.")
|
|
||||||
public void domainEdit() throws Throwable {
|
|
||||||
driver.get(server.getUrl("/registrar#domain/love.xn--q9jyb4c"));
|
|
||||||
driver.waitForElement(By.id("reg-app-btn-edit")).click();
|
|
||||||
Thread.sleep(1000);
|
|
||||||
driver.diffPage("page");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void contactCreate() throws Throwable {
|
|
||||||
driver.get(server.getUrl("/registrar#contact"));
|
|
||||||
driver.waitForElement(By.tagName("h1"));
|
|
||||||
driver.diffPage("page");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void contactView() throws Throwable {
|
|
||||||
driver.get(server.getUrl("/registrar#contact/google"));
|
|
||||||
driver.waitForElement(By.tagName("h1"));
|
|
||||||
driver.diffPage("page");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void contactEdit() throws Throwable {
|
|
||||||
driver.get(server.getUrl("/registrar#contact/google"));
|
|
||||||
driver.waitForElement(By.id("reg-app-btn-edit")).click();
|
|
||||||
Thread.sleep(1000);
|
|
||||||
driver.diffPage("page");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void hostCreate() throws Throwable {
|
|
||||||
driver.get(server.getUrl("/registrar#host"));
|
|
||||||
driver.waitForElement(By.tagName("h1"));
|
|
||||||
driver.diffPage("page");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void hostView() throws Throwable {
|
|
||||||
driver.get(server.getUrl("/registrar#host/ns1.love.xn--q9jyb4c"));
|
|
||||||
driver.waitForElement(By.tagName("h1"));
|
|
||||||
driver.diffPage("page");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void hostEdit() throws Throwable {
|
|
||||||
driver.get(server.getUrl("/registrar#host/ns1.love.xn--q9jyb4c"));
|
|
||||||
driver.waitForElement(By.id("reg-app-btn-edit")).click();
|
|
||||||
Thread.sleep(1000);
|
|
||||||
driver.diffPage("page");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void indexPage_smallScrolledDown() throws Throwable {
|
public void indexPage_smallScrolledDown() throws Throwable {
|
||||||
driver.manage().window().setSize(new Dimension(400, 300));
|
driver.manage().window().setSize(new Dimension(400, 300));
|
||||||
|
|
|
@ -17,9 +17,7 @@ package google.registry.webdriver;
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static google.registry.server.Fixture.BASIC;
|
import static google.registry.server.Fixture.BASIC;
|
||||||
import static google.registry.server.Route.route;
|
import static google.registry.server.Route.route;
|
||||||
import static google.registry.testing.DatastoreHelper.createTld;
|
|
||||||
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
import static google.registry.testing.DatastoreHelper.loadRegistrar;
|
||||||
import static google.registry.testing.DatastoreHelper.persistActiveDomain;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
@ -31,7 +29,6 @@ import google.registry.model.registrar.RegistrarContact;
|
||||||
import google.registry.module.frontend.FrontendServlet;
|
import google.registry.module.frontend.FrontendServlet;
|
||||||
import google.registry.server.RegistryTestServer;
|
import google.registry.server.RegistryTestServer;
|
||||||
import google.registry.testing.AppEngineRule;
|
import google.registry.testing.AppEngineRule;
|
||||||
import google.registry.ui.server.registrar.ConsoleUiAction;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.Timeout;
|
import org.junit.rules.Timeout;
|
||||||
|
@ -55,7 +52,6 @@ public class RegistrarConsoleWebTest {
|
||||||
new TestServerRule.Builder()
|
new TestServerRule.Builder()
|
||||||
.setRunfiles(RegistryTestServer.RUNFILES)
|
.setRunfiles(RegistryTestServer.RUNFILES)
|
||||||
.setRoutes(
|
.setRoutes(
|
||||||
route("/registrar-xhr", FrontendServlet.class),
|
|
||||||
route("/registrar", FrontendServlet.class),
|
route("/registrar", FrontendServlet.class),
|
||||||
route("/registrar-settings", FrontendServlet.class))
|
route("/registrar-settings", FrontendServlet.class))
|
||||||
.setFilters(ObjectifyFilter.class, OfyFilter.class)
|
.setFilters(ObjectifyFilter.class, OfyFilter.class)
|
||||||
|
@ -209,44 +205,4 @@ public class RegistrarConsoleWebTest {
|
||||||
.getAttribute("value"))
|
.getAttribute("value"))
|
||||||
.isEqualTo(registrar.getPhonePasscode());
|
.isEqualTo(registrar.getPhonePasscode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHostCreate_hostIsAnSld_eppErrorShowsInButterBar() throws Throwable {
|
|
||||||
driver.get(server.getUrl("/registrar#host"));
|
|
||||||
driver.waitForElement(By.id("domain-host-addr-add-button")).click();
|
|
||||||
driver.setFormFieldsById(ImmutableMap.of(
|
|
||||||
"host:name", "empire.vampyre",
|
|
||||||
"host:addr[0].value", "1.2.3.4"));
|
|
||||||
driver.findElement(By.id("reg-app-btn-save")).click();
|
|
||||||
Thread.sleep(1000); // TODO(b/26129174): Change butterbar code to add/remove dynamically.
|
|
||||||
assertThat(getButterBarText())
|
|
||||||
.isEqualTo("Host names must be at least two levels below the registry suffix");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHostCreate() throws Throwable {
|
|
||||||
server.runInAppEngineEnvironment(
|
|
||||||
() -> {
|
|
||||||
createTld("vampyre");
|
|
||||||
persistActiveDomain("empire.vampyre");
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
driver.get(server.getUrl("/registrar#host"));
|
|
||||||
driver.waitForElement(By.id("domain-host-addr-add-button")).click();
|
|
||||||
driver.setFormFieldsById(ImmutableMap.of(
|
|
||||||
"host:name", "the.empire.vampyre",
|
|
||||||
"host:addr[0].value", "1.2.3.4"));
|
|
||||||
driver.findElement(By.id("reg-app-btn-save")).click();
|
|
||||||
Thread.sleep(1000); // TODO(b/26129174): Change butterbar code to add/remove dynamically.
|
|
||||||
assertThat(getButterBarText()).isEqualTo("Saved.");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getButterBarText() {
|
|
||||||
return (String) driver.executeScript(
|
|
||||||
String.format("return document.querySelector('.%s').innerText", css("kd-butterbar-text")));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String css(String name) {
|
|
||||||
return ConsoleUiAction.CSS_RENAMING_MAP_SUPPLIER.get().get(name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Before Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 38 KiB |