UNPKG

matrix-react-sdk

Version:
589 lines (580 loc) 110 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _matrix = require("matrix-js-sdk/src/matrix"); var _react = _interopRequireWildcard(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _logger = require("matrix-js-sdk/src/logger"); var _languageHandler = require("../../../languageHandler"); var _ErrorUtils = require("../../../utils/ErrorUtils"); var _AutoDiscoveryUtils = _interopRequireDefault(require("../../../utils/AutoDiscoveryUtils")); var Lifecycle = _interopRequireWildcard(require("../../../Lifecycle")); var _MatrixClientPeg = require("../../../MatrixClientPeg"); var _AuthPage = _interopRequireDefault(require("../../views/auth/AuthPage")); var _Login = _interopRequireDefault(require("../../../Login")); var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher")); var _SSOButtons = _interopRequireDefault(require("../../views/elements/SSOButtons")); var _ServerPicker = _interopRequireDefault(require("../../views/elements/ServerPicker")); var _RegistrationForm = _interopRequireDefault(require("../../views/auth/RegistrationForm")); var _AccessibleButton = _interopRequireDefault(require("../../views/elements/AccessibleButton")); var _AuthBody = _interopRequireDefault(require("../../views/auth/AuthBody")); var _AuthHeader = _interopRequireDefault(require("../../views/auth/AuthHeader")); var _InteractiveAuth = _interopRequireDefault(require("../InteractiveAuth")); var _Spinner = _interopRequireDefault(require("../../views/elements/Spinner")); var _AuthHeaderDisplay = require("./header/AuthHeaderDisplay"); var _AuthHeaderProvider = require("./header/AuthHeaderProvider"); var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore")); var _Settings = require("../../../settings/Settings"); var _authorize = require("../../../utils/oidc/authorize"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /* Copyright 2024 New Vector Ltd. Copyright 2015-2021 The Matrix.org Foundation C.I.C. SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ const debuglog = (...args) => { if (_SettingsStore.default.getValue("debug_registration")) { _logger.logger.log.call(console, "Registration debuglog:", ...args); } }; class Registration extends _react.default.Component { constructor(props) { super(props); (0, _defineProperty2.default)(this, "loginLogic", void 0); // `replaceClient` tracks latest serverConfig to spot when it changes under the async method which fetches flows (0, _defineProperty2.default)(this, "latestServerConfig", void 0); // cache value from settings store (0, _defineProperty2.default)(this, "oidcNativeFlowEnabled", false); (0, _defineProperty2.default)(this, "unloadCallback", event => { if (this.state.doingUIAuth) { event.preventDefault(); event.returnValue = ""; return ""; } }); (0, _defineProperty2.default)(this, "onFormSubmit", async formVals => { this.setState({ errorText: "", busy: true, formVals, doingUIAuth: true }); }); (0, _defineProperty2.default)(this, "requestEmailToken", (emailAddress, clientSecret, sendAttempt, sessionId) => { if (!this.state.matrixClient) throw new Error("Matrix client has not yet been loaded"); return this.state.matrixClient.requestRegisterEmailToken(emailAddress, clientSecret, sendAttempt); }); (0, _defineProperty2.default)(this, "onUIAuthFinished", async (success, response) => { if (!this.state.matrixClient) throw new Error("Matrix client has not yet been loaded"); debuglog("Registration: ui authentication finished: ", { success, response }); if (!success) { let errorText = response.message || response.toString(); // can we give a better error message? if (response instanceof _matrix.MatrixError && response.errcode === "M_RESOURCE_LIMIT_EXCEEDED") { const errorTop = (0, _ErrorUtils.messageForResourceLimitError)(response.data.limit_type, response.data.admin_contact, _ErrorUtils.resourceLimitStrings); const errorDetail = (0, _ErrorUtils.messageForResourceLimitError)(response.data.limit_type, response.data.admin_contact, _ErrorUtils.adminContactStrings); errorText = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, errorTop), /*#__PURE__*/_react.default.createElement("p", null, errorDetail)); } else if (response.flows?.some(flow => flow.stages.includes(_matrix.AuthType.Msisdn))) { const flows = response.flows ?? []; const msisdnAvailable = flows.some(flow => flow.stages.includes(_matrix.AuthType.Msisdn)); if (!msisdnAvailable) { errorText = (0, _languageHandler._t)("auth|unsupported_auth_msisdn"); } } else if (response instanceof _matrix.MatrixError && response.errcode === "M_USER_IN_USE") { errorText = (0, _languageHandler._t)("auth|username_in_use"); } else if (response instanceof _matrix.MatrixError && response.errcode === "M_THREEPID_IN_USE") { errorText = (0, _languageHandler._t)("auth|3pid_in_use"); } this.setState({ busy: false, doingUIAuth: false, errorText }); return; } const userId = response.user_id; const accessToken = response.access_token; if (!userId || !accessToken) throw new Error("Registration failed"); _MatrixClientPeg.MatrixClientPeg.setJustRegisteredUserId(userId); const newState = { doingUIAuth: false, registeredUsername: userId, differentLoggedInUserId: undefined, completedNoSignin: false, // we're still busy until we get unmounted: don't show the registration form again busy: true }; // The user came in through an email validation link. To avoid overwriting // their session, check to make sure the session isn't someone else, and // isn't a guest user since we'll usually have set a guest user session before // starting the registration process. This isn't perfect since it's possible // the user had a separate guest session they didn't actually mean to replace. const [sessionOwner, sessionIsGuest] = await Lifecycle.getStoredSessionOwner(); if (sessionOwner && !sessionIsGuest && sessionOwner !== userId) { _logger.logger.log(`Found a session for ${sessionOwner} but ${userId} has just registered.`); newState.differentLoggedInUserId = sessionOwner; } // if we don't have an email at all, only one client can be involved in this flow, and we can directly log in. // // if we've got an email, it needs to be verified. in that case, two clients can be involved in this flow, the // original client starting the process and the client that submitted the verification token. After the token // has been submitted, it can not be used again. // // we can distinguish them based on whether the client has form values saved (if so, it's the one that started // the registration), or whether it doesn't have any form values saved (in which case it's the client that // verified the email address) // // as the client that started registration may be gone by the time we've verified the email, and only the client // that verified the email is guaranteed to exist, we'll always do the login in that client. const hasEmail = Boolean(this.state.formVals.email); const hasAccessToken = Boolean(accessToken); debuglog("Registration: ui auth finished:", { hasEmail, hasAccessToken }); // don’t log in if we found a session for a different user if (hasAccessToken && !newState.differentLoggedInUserId) { if (this.props.mobileRegister) { const mobileResponse = { user_id: userId, home_server: this.state.matrixClient.getHomeserverUrl(), access_token: accessToken, device_id: response.device_id }; const event = new CustomEvent("mobileregistrationresponse", { detail: mobileResponse }); window.dispatchEvent(event); newState.busy = false; newState.completedNoSignin = true; } else { await this.props.onLoggedIn({ userId, deviceId: response.device_id, homeserverUrl: this.state.matrixClient.getHomeserverUrl(), identityServerUrl: this.state.matrixClient.getIdentityServerUrl(), accessToken }, this.state.formVals.password); this.setupPushers(); } } else { newState.busy = false; newState.completedNoSignin = true; } this.setState(newState); }); (0, _defineProperty2.default)(this, "onLoginClick", ev => { ev.preventDefault(); ev.stopPropagation(); this.props.onLoginClick(); }); (0, _defineProperty2.default)(this, "onGoToFormClicked", ev => { ev.preventDefault(); ev.stopPropagation(); this.replaceClient(this.props.serverConfig); this.setState({ busy: false, doingUIAuth: false }); }); (0, _defineProperty2.default)(this, "makeRegisterRequest", auth => { if (!this.state.matrixClient) throw new Error("Matrix client has not yet been loaded"); const registerParams = { username: this.state.formVals.username, password: this.state.formVals.password, initial_device_display_name: this.props.defaultDeviceDisplayName, auth: undefined, // we still want to avoid the race conditions involved with multiple clients handling registration, but // we'll handle these after we've received the access_token in onUIAuthFinished inhibit_login: undefined }; if (auth) registerParams.auth = auth; debuglog("Registration: sending registration request:", auth); return this.state.matrixClient.registerRequest(registerParams); }); // Links to the login page shown after registration is completed are routed through this // which checks the user hasn't already logged in somewhere else (perhaps we should do // this more generally?) (0, _defineProperty2.default)(this, "onLoginClickWithCheck", async ev => { ev.preventDefault(); const sessionLoaded = await Lifecycle.loadSession({ ignoreGuest: true }); if (!sessionLoaded) { // ok fine, there's still no session: really go to the login page this.props.onLoginClick(); } return sessionLoaded; }); this.state = { busy: false, errorText: null, formVals: { email: this.props.email }, doingUIAuth: Boolean(this.props.sessionId), flows: null, completedNoSignin: false, serverIsAlive: true, serverErrorIsFatal: false, serverDeadError: "" }; // only set on a config level, so we don't need to watch this.oidcNativeFlowEnabled = _SettingsStore.default.getValue(_Settings.Features.OidcNativeFlow); const { hsUrl, isUrl, delegatedAuthentication } = this.props.serverConfig; this.loginLogic = new _Login.default(hsUrl, isUrl, null, { defaultDeviceDisplayName: "Element login check", // We shouldn't ever be used // if native OIDC is enabled in the client pass the server's delegated auth settings delegatedAuthentication: this.oidcNativeFlowEnabled ? delegatedAuthentication : undefined }); } componentDidMount() { this.replaceClient(this.props.serverConfig); //triggers a confirmation dialog for data loss before page unloads/refreshes window.addEventListener("beforeunload", this.unloadCallback); } componentWillUnmount() { window.removeEventListener("beforeunload", this.unloadCallback); } componentDidUpdate(prevProps) { if (prevProps.serverConfig.hsUrl !== this.props.serverConfig.hsUrl || prevProps.serverConfig.isUrl !== this.props.serverConfig.isUrl) { this.replaceClient(this.props.serverConfig); } } async replaceClient(serverConfig) { this.latestServerConfig = serverConfig; const { hsUrl, isUrl } = serverConfig; this.setState({ errorText: null, serverDeadError: null, serverErrorIsFatal: false, // busy while we do live-ness check (we need to avoid trying to render // the UI auth component while we don't have a matrix client) busy: true }); // Do a liveliness check on the URLs try { await _AutoDiscoveryUtils.default.validateServerConfigWithStaticUrls(hsUrl, isUrl); if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us this.setState({ serverIsAlive: true, serverErrorIsFatal: false }); } catch (e) { if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us this.setState(_objectSpread({ busy: false }, _AutoDiscoveryUtils.default.authComponentStateForError(e, "register"))); if (this.state.serverErrorIsFatal) { return; // Server is dead - do not continue. } } const cli = (0, _matrix.createClient)({ baseUrl: hsUrl, idBaseUrl: isUrl }); this.loginLogic.setHomeserverUrl(hsUrl); this.loginLogic.setIdentityServerUrl(isUrl); // if native OIDC is enabled in the client pass the server's delegated auth settings const delegatedAuthentication = this.oidcNativeFlowEnabled ? serverConfig.delegatedAuthentication : undefined; this.loginLogic.setDelegatedAuthentication(delegatedAuthentication); let ssoFlow; let oidcNativeFlow; try { const loginFlows = await this.loginLogic.getFlows(true); if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us ssoFlow = loginFlows.find(f => f.type === "m.login.sso" || f.type === "m.login.cas"); oidcNativeFlow = loginFlows.find(f => f.type === "oidcNativeFlow"); } catch (e) { if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us _logger.logger.error("Failed to get login flows to check for SSO support", e); } await new Promise(resolve => { this.setState(({ flows }) => ({ matrixClient: cli, ssoFlow, oidcNativeFlow, // if we are using oidc native we won't continue with flow discovery on HS // so set an empty array to indicate flows are no longer loading flows: oidcNativeFlow ? [] : flows, busy: false }), resolve); }); // don't need to check with homeserver for login flows // since we are going to use OIDC native flow if (oidcNativeFlow) { return; } try { // We do the first registration request ourselves to discover whether we need to // do SSO instead. If we've already started the UI Auth process though, we don't // need to. if (!this.state.doingUIAuth) { await this.makeRegisterRequest(null); if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us // This should never succeed since we specified no auth object. _logger.logger.log("Expecting 401 from register request but got success!"); } } catch (e) { if (serverConfig !== this.latestServerConfig) return; // discard, serverConfig changed from under us if (e instanceof _matrix.MatrixError && e.httpStatus === 401) { this.setState({ flows: e.data.flows }); } else if (e instanceof _matrix.MatrixError && (e.httpStatus === 403 || e.errcode === "M_FORBIDDEN")) { // Check for 403 or M_FORBIDDEN, Synapse used to send 403 M_UNKNOWN but now sends 403 M_FORBIDDEN. // At this point registration is pretty much disabled, but before we do that let's // quickly check to see if the server supports SSO instead. If it does, we'll send // the user off to the login page to figure their account out. if (ssoFlow) { // Redirect to login page - server probably expects SSO only _dispatcher.default.dispatch({ action: "start_login" }); } else { this.setState({ serverErrorIsFatal: true, // fatal because user cannot continue on this server errorText: (0, _languageHandler._t)("auth|registration_disabled"), // add empty flows array to get rid of spinner flows: [] }); } } else { _logger.logger.log("Unable to query for supported registration methods.", e); this.setState({ errorText: (0, _languageHandler._t)("auth|failed_query_registration_methods"), // add empty flows array to get rid of spinner flows: [] }); } } } setupPushers() { if (!this.props.brand) { return Promise.resolve(); } const matrixClient = _MatrixClientPeg.MatrixClientPeg.safeGet(); return matrixClient.getPushers().then(resp => { const pushers = resp.pushers; for (let i = 0; i < pushers.length; ++i) { if (pushers[i].kind === "email") { const emailPusher = pushers[i]; emailPusher.data = { brand: this.props.brand }; matrixClient.setPusher(emailPusher).then(() => { _logger.logger.log("Set email branding to " + this.props.brand); }, error => { _logger.logger.error("Couldn't set email branding: " + error); }); } } }, error => { _logger.logger.error("Couldn't get pushers: " + error); }); } getUIAuthInputs() { return { emailAddress: this.state.formVals.email, phoneCountry: this.state.formVals.phoneCountry, phoneNumber: this.state.formVals.phoneNumber }; } renderRegisterComponent() { if (this.state.matrixClient && this.state.doingUIAuth) { return /*#__PURE__*/_react.default.createElement(_InteractiveAuth.default, { matrixClient: this.state.matrixClient, makeRequest: this.makeRegisterRequest, onAuthFinished: this.onUIAuthFinished, inputs: this.getUIAuthInputs(), requestEmailToken: this.requestEmailToken, sessionId: this.props.sessionId, clientSecret: this.props.clientSecret, emailSid: this.props.idSid, poll: true }); } else if (!this.state.matrixClient && !this.state.busy) { return null; } else if (this.state.busy || !this.state.flows) { return /*#__PURE__*/_react.default.createElement("div", { className: "mx_AuthBody_spinner" }, /*#__PURE__*/_react.default.createElement(_Spinner.default, null)); } else if (this.state.matrixClient && this.state.oidcNativeFlow) { return /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { className: "mx_Login_fullWidthButton", kind: "primary", onClick: async () => { await (0, _authorize.startOidcLogin)(this.props.serverConfig.delegatedAuthentication, this.state.oidcNativeFlow.clientId, this.props.serverConfig.hsUrl, this.props.serverConfig.isUrl, true /* isRegistration */); } }, (0, _languageHandler._t)("action|continue")); } else if (this.state.matrixClient && this.state.flows.length) { let ssoSection; if (!this.props.mobileRegister && this.state.ssoFlow) { let continueWithSection; const providers = this.state.ssoFlow.identity_providers || []; // when there is only a single (or 0) providers we show a wide button with `Continue with X` text if (providers.length > 1) { // i18n: ssoButtons is a placeholder to help translators understand context continueWithSection = /*#__PURE__*/_react.default.createElement("h2", { className: "mx_AuthBody_centered" }, (0, _languageHandler._t)("auth|continue_with_sso", { ssoButtons: "" }).trim()); } // i18n: ssoButtons & usernamePassword are placeholders to help translators understand context ssoSection = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, continueWithSection, /*#__PURE__*/_react.default.createElement(_SSOButtons.default, { matrixClient: this.loginLogic.createTemporaryClient(), flow: this.state.ssoFlow, loginType: this.state.ssoFlow.type === "m.login.sso" ? "sso" : "cas", fragmentAfterLogin: this.props.fragmentAfterLogin, action: _matrix.SSOAction.REGISTER }), /*#__PURE__*/_react.default.createElement("h2", { className: "mx_AuthBody_centered" }, (0, _languageHandler._t)("auth|sso_or_username_password", { ssoButtons: "", usernamePassword: "" }).trim())); } return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, ssoSection, /*#__PURE__*/_react.default.createElement(_RegistrationForm.default, { defaultUsername: this.state.formVals.username, defaultEmail: this.state.formVals.email, defaultPhoneCountry: this.state.formVals.phoneCountry, defaultPhoneNumber: this.state.formVals.phoneNumber, defaultPassword: this.state.formVals.password, onRegisterClick: this.onFormSubmit, flows: this.state.flows, serverConfig: this.props.serverConfig, canSubmit: !this.state.serverErrorIsFatal, matrixClient: this.state.matrixClient, mobileRegister: this.props.mobileRegister })); } return null; } render() { let errorText; const err = this.state.errorText; if (err) { errorText = /*#__PURE__*/_react.default.createElement("div", { className: "mx_Login_error" }, err); } let serverDeadSection; if (!this.state.serverIsAlive) { const classes = (0, _classnames.default)({ mx_Login_error: true, mx_Login_serverError: true, mx_Login_serverErrorNonFatal: !this.state.serverErrorIsFatal }); serverDeadSection = /*#__PURE__*/_react.default.createElement("div", { className: classes }, this.state.serverDeadError); } const signIn = /*#__PURE__*/_react.default.createElement("span", { className: "mx_AuthBody_changeFlow" }, (0, _languageHandler._t)("auth|sign_in_instead_prompt", {}, { a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "link_inline", onClick: this.onLoginClick }, sub) })); // Only show the 'go back' button if you're not looking at the form let goBack; if (this.state.doingUIAuth) { goBack = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "link", className: "mx_AuthBody_changeFlow", onClick: this.onGoToFormClicked }, (0, _languageHandler._t)("action|go_back")); } let body; if (this.state.completedNoSignin) { let regDoneText; if (this.props.mobileRegister) { regDoneText = undefined; } else if (this.state.differentLoggedInUserId) { regDoneText = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("auth|account_clash", { newAccountId: this.state.registeredUsername, loggedInUserId: this.state.differentLoggedInUserId })), /*#__PURE__*/_react.default.createElement("p", null, /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "link_inline", onClick: async event => { const sessionLoaded = await this.onLoginClickWithCheck(event); if (sessionLoaded) { _dispatcher.default.dispatch({ action: "view_welcome_page" }); } } }, (0, _languageHandler._t)("auth|account_clash_previous_account")))); } else { // regardless of whether we're the client that started the registration or not, we should // try our credentials anyway regDoneText = /*#__PURE__*/_react.default.createElement("h2", null, (0, _languageHandler._t)("auth|log_in_new_account", {}, { a: sub => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "link_inline", onClick: async event => { const sessionLoaded = await this.onLoginClickWithCheck(event); if (sessionLoaded) { _dispatcher.default.dispatch({ action: "view_home_page" }); } } }, sub) })); } body = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("h1", null, (0, _languageHandler._t)("auth|registration_successful")), regDoneText); } else if (this.props.mobileRegister) { body = /*#__PURE__*/_react.default.createElement(_react.Fragment, null, /*#__PURE__*/_react.default.createElement("h1", null, (0, _languageHandler._t)("auth|mobile_create_account_title", { hsName: this.props.serverConfig.hsName })), errorText, serverDeadSection, this.renderRegisterComponent()); } else { body = /*#__PURE__*/_react.default.createElement(_react.Fragment, null, /*#__PURE__*/_react.default.createElement("div", { className: "mx_Register_mainContent" }, /*#__PURE__*/_react.default.createElement(_AuthHeaderDisplay.AuthHeaderDisplay, { title: (0, _languageHandler._t)("auth|create_account_title"), serverPicker: /*#__PURE__*/_react.default.createElement(_ServerPicker.default, { title: (0, _languageHandler._t)("auth|server_picker_title_registration"), dialogTitle: (0, _languageHandler._t)("auth|server_picker_dialog_title"), serverConfig: this.props.serverConfig, onServerConfigChange: this.state.doingUIAuth ? undefined : this.props.onServerConfigChange }) }, errorText, serverDeadSection), this.renderRegisterComponent()), /*#__PURE__*/_react.default.createElement("div", { className: "mx_Register_footerActions" }, goBack, signIn)); } if (this.props.mobileRegister) { return /*#__PURE__*/_react.default.createElement("div", { className: "mx_MobileRegister_body", "data-testid": "mobile-register" }, body); } return /*#__PURE__*/_react.default.createElement(_AuthPage.default, null, /*#__PURE__*/_react.default.createElement(_AuthHeader.default, null), /*#__PURE__*/_react.default.createElement(_AuthHeaderProvider.AuthHeaderProvider, null, /*#__PURE__*/_react.default.createElement(_AuthBody.default, { flex: true }, body))); } } exports.default = Registration; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfbWF0cml4IiwicmVxdWlyZSIsIl9yZWFjdCIsIl9pbnRlcm9wUmVxdWlyZVdpbGRjYXJkIiwiX2NsYXNzbmFtZXMiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiX2xvZ2dlciIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfRXJyb3JVdGlscyIsIl9BdXRvRGlzY292ZXJ5VXRpbHMiLCJMaWZlY3ljbGUiLCJfTWF0cml4Q2xpZW50UGVnIiwiX0F1dGhQYWdlIiwiX0xvZ2luIiwiX2Rpc3BhdGNoZXIiLCJfU1NPQnV0dG9ucyIsIl9TZXJ2ZXJQaWNrZXIiLCJfUmVnaXN0cmF0aW9uRm9ybSIsIl9BY2Nlc3NpYmxlQnV0dG9uIiwiX0F1dGhCb2R5IiwiX0F1dGhIZWFkZXIiLCJfSW50ZXJhY3RpdmVBdXRoIiwiX1NwaW5uZXIiLCJfQXV0aEhlYWRlckRpc3BsYXkiLCJfQXV0aEhlYWRlclByb3ZpZGVyIiwiX1NldHRpbmdzU3RvcmUiLCJfU2V0dGluZ3MiLCJfYXV0aG9yaXplIiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0Iiwib3duS2V5cyIsImtleXMiLCJnZXRPd25Qcm9wZXJ0eVN5bWJvbHMiLCJvIiwiZmlsdGVyIiwiZW51bWVyYWJsZSIsInB1c2giLCJhcHBseSIsIl9vYmplY3RTcHJlYWQiLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJmb3JFYWNoIiwiX2RlZmluZVByb3BlcnR5MiIsImdldE93blByb3BlcnR5RGVzY3JpcHRvcnMiLCJkZWZpbmVQcm9wZXJ0aWVzIiwiZGVidWdsb2ciLCJhcmdzIiwiU2V0dGluZ3NTdG9yZSIsImdldFZhbHVlIiwibG9nZ2VyIiwibG9nIiwiY29uc29sZSIsIlJlZ2lzdHJhdGlvbiIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsImV2ZW50Iiwic3RhdGUiLCJkb2luZ1VJQXV0aCIsInByZXZlbnREZWZhdWx0IiwicmV0dXJuVmFsdWUiLCJmb3JtVmFscyIsInNldFN0YXRlIiwiZXJyb3JUZXh0IiwiYnVzeSIsImVtYWlsQWRkcmVzcyIsImNsaWVudFNlY3JldCIsInNlbmRBdHRlbXB0Iiwic2Vzc2lvbklkIiwibWF0cml4Q2xpZW50IiwiRXJyb3IiLCJyZXF1ZXN0UmVnaXN0ZXJFbWFpbFRva2VuIiwic3VjY2VzcyIsInJlc3BvbnNlIiwibWVzc2FnZSIsInRvU3RyaW5nIiwiTWF0cml4RXJyb3IiLCJlcnJjb2RlIiwiZXJyb3JUb3AiLCJtZXNzYWdlRm9yUmVzb3VyY2VMaW1pdEVycm9yIiwiZGF0YSIsImxpbWl0X3R5cGUiLCJhZG1pbl9jb250YWN0IiwicmVzb3VyY2VMaW1pdFN0cmluZ3MiLCJlcnJvckRldGFpbCIsImFkbWluQ29udGFjdFN0cmluZ3MiLCJjcmVhdGVFbGVtZW50IiwiZmxvd3MiLCJzb21lIiwiZmxvdyIsInN0YWdlcyIsImluY2x1ZGVzIiwiQXV0aFR5cGUiLCJNc2lzZG4iLCJtc2lzZG5BdmFpbGFibGUiLCJfdCIsInVzZXJJZCIsInVzZXJfaWQiLCJhY2Nlc3NUb2tlbiIsImFjY2Vzc190b2tlbiIsIk1hdHJpeENsaWVudFBlZyIsInNldEp1c3RSZWdpc3RlcmVkVXNlcklkIiwibmV3U3RhdGUiLCJyZWdpc3RlcmVkVXNlcm5hbWUiLCJkaWZmZXJlbnRMb2dnZWRJblVzZXJJZCIsInVuZGVmaW5lZCIsImNvbXBsZXRlZE5vU2lnbmluIiwic2Vzc2lvbk93bmVyIiwic2Vzc2lvbklzR3Vlc3QiLCJnZXRTdG9yZWRTZXNzaW9uT3duZXIiLCJoYXNFbWFpbCIsIkJvb2xlYW4iLCJlbWFpbCIsImhhc0FjY2Vzc1Rva2VuIiwibW9iaWxlUmVnaXN0ZXIiLCJtb2JpbGVSZXNwb25zZSIsImhvbWVfc2VydmVyIiwiZ2V0SG9tZXNlcnZlclVybCIsImRldmljZV9pZCIsIkN1c3RvbUV2ZW50IiwiZGV0YWlsIiwid2luZG93IiwiZGlzcGF0Y2hFdmVudCIsIm9uTG9nZ2VkSW4iLCJkZXZpY2VJZCIsImhvbWVzZXJ2ZXJVcmwiLCJpZGVudGl0eVNlcnZlclVybCIsImdldElkZW50aXR5U2VydmVyVXJsIiwicGFzc3dvcmQiLCJzZXR1cFB1c2hlcnMiLCJldiIsInN0b3BQcm9wYWdhdGlvbiIsIm9uTG9naW5DbGljayIsInJlcGxhY2VDbGllbnQiLCJzZXJ2ZXJDb25maWciLCJhdXRoIiwicmVnaXN0ZXJQYXJhbXMiLCJ1c2VybmFtZSIsImluaXRpYWxfZGV2aWNlX2Rpc3BsYXlfbmFtZSIsImRlZmF1bHREZXZpY2VEaXNwbGF5TmFtZSIsImluaGliaXRfbG9naW4iLCJyZWdpc3RlclJlcXVlc3QiLCJzZXNzaW9uTG9hZGVkIiwibG9hZFNlc3Npb24iLCJpZ25vcmVHdWVzdCIsInNlcnZlcklzQWxpdmUiLCJzZXJ2ZXJFcnJvcklzRmF0YWwiLCJzZXJ2ZXJEZWFkRXJyb3IiLCJvaWRjTmF0aXZlRmxvd0VuYWJsZWQiLCJGZWF0dXJlcyIsIk9pZGNOYXRpdmVGbG93IiwiaHNVcmwiLCJpc1VybCIsImRlbGVnYXRlZEF1dGhlbnRpY2F0aW9uIiwibG9naW5Mb2dpYyIsIkxvZ2luIiwiY29tcG9uZW50RGlkTW91bnQiLCJhZGRFdmVudExpc3RlbmVyIiwidW5sb2FkQ2FsbGJhY2siLCJjb21wb25lbnRXaWxsVW5tb3VudCIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJjb21wb25lbnREaWRVcGRhdGUiLCJwcmV2UHJvcHMiLCJsYXRlc3RTZXJ2ZXJDb25maWciLCJBdXRvRGlzY292ZXJ5VXRpbHMiLCJ2YWxpZGF0ZVNlcnZlckNvbmZpZ1dpdGhTdGF0aWNVcmxzIiwiYXV0aENvbXBvbmVudFN0YXRlRm9yRXJyb3IiLCJjbGkiLCJjcmVhdGVDbGllbnQiLCJiYXNlVXJsIiwiaWRCYXNlVXJsIiwic2V0SG9tZXNlcnZlclVybCIsInNldElkZW50aXR5U2VydmVyVXJsIiwic2V0RGVsZWdhdGVkQXV0aGVudGljYXRpb24iLCJzc29GbG93Iiwib2lkY05hdGl2ZUZsb3ciLCJsb2dpbkZsb3dzIiwiZ2V0Rmxvd3MiLCJmaW5kIiwiZiIsInR5cGUiLCJlcnJvciIsIlByb21pc2UiLCJyZXNvbHZlIiwibWFrZVJlZ2lzdGVyUmVxdWVzdCIsImh0dHBTdGF0dXMiLCJkaXMiLCJkaXNwYXRjaCIsImFjdGlvbiIsImJyYW5kIiwic2FmZUdldCIsImdldFB1c2hlcnMiLCJ0aGVuIiwicmVzcCIsInB1c2hlcnMiLCJraW5kIiwiZW1haWxQdXNoZXIiLCJzZXRQdXNoZXIiLCJnZXRVSUF1dGhJbnB1dHMiLCJwaG9uZUNvdW50cnkiLCJwaG9uZU51bWJlciIsInJlbmRlclJlZ2lzdGVyQ29tcG9uZW50IiwibWFrZVJlcXVlc3QiLCJvbkF1dGhGaW5pc2hlZCIsIm9uVUlBdXRoRmluaXNoZWQiLCJpbnB1dHMiLCJyZXF1ZXN0RW1haWxUb2tlbiIsImVtYWlsU2lkIiwiaWRTaWQiLCJwb2xsIiwiY2xhc3NOYW1lIiwib25DbGljayIsInN0YXJ0T2lkY0xvZ2luIiwiY2xpZW50SWQiLCJzc29TZWN0aW9uIiwiY29udGludWVXaXRoU2VjdGlvbiIsInByb3ZpZGVycyIsImlkZW50aXR5X3Byb3ZpZGVycyIsInNzb0J1dHRvbnMiLCJ0cmltIiwiRnJhZ21lbnQiLCJjcmVhdGVUZW1wb3JhcnlDbGllbnQiLCJsb2dpblR5cGUiLCJmcmFnbWVudEFmdGVyTG9naW4iLCJTU09BY3Rpb24iLCJSRUdJU1RFUiIsInVzZXJuYW1lUGFzc3dvcmQiLCJkZWZhdWx0VXNlcm5hbWUiLCJkZWZhdWx0RW1haWwiLCJkZWZhdWx0UGhvbmVDb3VudHJ5IiwiZGVmYXVsdFBob25lTnVtYmVyIiwiZGVmYXVsdFBhc3N3b3JkIiwib25SZWdpc3RlckNsaWNrIiwib25Gb3JtU3VibWl0IiwiY2FuU3VibWl0IiwicmVuZGVyIiwiZXJyIiwic2VydmVyRGVhZFNlY3Rpb24iLCJjbGFzc2VzIiwiY2xhc3NOYW1lcyIsIm14X0xvZ2luX2Vycm9yIiwibXhfTG9naW5fc2VydmVyRXJyb3IiLCJteF9Mb2dpbl9zZXJ2ZXJFcnJvck5vbkZhdGFsIiwic2lnbkluIiwic3ViIiwiZ29CYWNrIiwib25Hb1RvRm9ybUNsaWNrZWQiLCJib2R5IiwicmVnRG9uZVRleHQiLCJuZXdBY2NvdW50SWQiLCJsb2dnZWRJblVzZXJJZCIsIm9uTG9naW5DbGlja1dpdGhDaGVjayIsImhzTmFtZSIsIkF1dGhIZWFkZXJEaXNwbGF5IiwidGl0bGUiLCJzZXJ2ZXJQaWNrZXIiLCJkaWFsb2dUaXRsZSIsIm9uU2VydmVyQ29uZmlnQ2hhbmdlIiwiQXV0aEhlYWRlclByb3ZpZGVyIiwiZmxleCIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9zdHJ1Y3R1cmVzL2F1dGgvUmVnaXN0cmF0aW9uLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxNS0yMDIxIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCB7XG4gICAgQXV0aFR5cGUsXG4gICAgY3JlYXRlQ2xpZW50LFxuICAgIElBdXRoRGF0YSxcbiAgICBBdXRoRGljdCxcbiAgICBJSW5wdXRzLFxuICAgIE1hdHJpeEVycm9yLFxuICAgIElSZWdpc3RlclJlcXVlc3RQYXJhbXMsXG4gICAgSVJlcXVlc3RUb2tlblJlc3BvbnNlLFxuICAgIE1hdHJpeENsaWVudCxcbiAgICBTU09GbG93LFxuICAgIFNTT0FjdGlvbixcbiAgICBSZWdpc3RlclJlc3BvbnNlLFxufSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgUmVhY3QsIHsgRnJhZ21lbnQsIFJlYWN0Tm9kZSB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IGNsYXNzTmFtZXMgZnJvbSBcImNsYXNzbmFtZXNcIjtcbmltcG9ydCB7IGxvZ2dlciB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9sb2dnZXJcIjtcblxuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgeyBhZG1pbkNvbnRhY3RTdHJpbmdzLCBtZXNzYWdlRm9yUmVzb3VyY2VMaW1pdEVycm9yLCByZXNvdXJjZUxpbWl0U3RyaW5ncyB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9FcnJvclV0aWxzXCI7XG5pbXBvcnQgQXV0b0Rpc2NvdmVyeVV0aWxzIGZyb20gXCIuLi8uLi8uLi91dGlscy9BdXRvRGlzY292ZXJ5VXRpbHNcIjtcbmltcG9ydCAqIGFzIExpZmVjeWNsZSBmcm9tIFwiLi4vLi4vLi4vTGlmZWN5Y2xlXCI7XG5pbXBvcnQgeyBJTWF0cml4Q2xpZW50Q3JlZHMsIE1hdHJpeENsaWVudFBlZyB9IGZyb20gXCIuLi8uLi8uLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCBBdXRoUGFnZSBmcm9tIFwiLi4vLi4vdmlld3MvYXV0aC9BdXRoUGFnZVwiO1xuaW1wb3J0IExvZ2luLCB7IE9pZGNOYXRpdmVGbG93IH0gZnJvbSBcIi4uLy4uLy4uL0xvZ2luXCI7XG5pbXBvcnQgZGlzIGZyb20gXCIuLi8uLi8uLi9kaXNwYXRjaGVyL2Rpc3BhdGNoZXJcIjtcbmltcG9ydCBTU09CdXR0b25zIGZyb20gXCIuLi8uLi92aWV3cy9lbGVtZW50cy9TU09CdXR0b25zXCI7XG5pbXBvcnQgU2VydmVyUGlja2VyIGZyb20gXCIuLi8uLi92aWV3cy9lbGVtZW50cy9TZXJ2ZXJQaWNrZXJcIjtcbmltcG9ydCBSZWdpc3RyYXRpb25Gb3JtIGZyb20gXCIuLi8uLi92aWV3cy9hdXRoL1JlZ2lzdHJhdGlvbkZvcm1cIjtcbmltcG9ydCBBY2Nlc3NpYmxlQnV0dG9uLCB7IEJ1dHRvbkV2ZW50IH0gZnJvbSBcIi4uLy4uL3ZpZXdzL2VsZW1lbnRzL0FjY2Vzc2libGVCdXR0b25cIjtcbmltcG9ydCBBdXRoQm9keSBmcm9tIFwiLi4vLi4vdmlld3MvYXV0aC9BdXRoQm9keVwiO1xuaW1wb3J0IEF1dGhIZWFkZXIgZnJvbSBcIi4uLy4uL3ZpZXdzL2F1dGgvQXV0aEhlYWRlclwiO1xuaW1wb3J0IEludGVyYWN0aXZlQXV0aCwgeyBJbnRlcmFjdGl2ZUF1dGhDYWxsYmFjayB9IGZyb20gXCIuLi9JbnRlcmFjdGl2ZUF1dGhcIjtcbmltcG9ydCBTcGlubmVyIGZyb20gXCIuLi8uLi92aWV3cy9lbGVtZW50cy9TcGlubmVyXCI7XG5pbXBvcnQgeyBBdXRoSGVhZGVyRGlzcGxheSB9IGZyb20gXCIuL2hlYWRlci9BdXRoSGVhZGVyRGlzcGxheVwiO1xuaW1wb3J0IHsgQXV0aEhlYWRlclByb3ZpZGVyIH0gZnJvbSBcIi4vaGVhZGVyL0F1dGhIZWFkZXJQcm92aWRlclwiO1xuaW1wb3J0IFNldHRpbmdzU3RvcmUgZnJvbSBcIi4uLy4uLy4uL3NldHRpbmdzL1NldHRpbmdzU3RvcmVcIjtcbmltcG9ydCB7IFZhbGlkYXRlZFNlcnZlckNvbmZpZyB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9WYWxpZGF0ZWRTZXJ2ZXJDb25maWdcIjtcbmltcG9ydCB7IEZlYXR1cmVzIH0gZnJvbSBcIi4uLy4uLy4uL3NldHRpbmdzL1NldHRpbmdzXCI7XG5pbXBvcnQgeyBzdGFydE9pZGNMb2dpbiB9IGZyb20gXCIuLi8uLi8uLi91dGlscy9vaWRjL2F1dGhvcml6ZVwiO1xuXG5jb25zdCBkZWJ1Z2xvZyA9ICguLi5hcmdzOiBhbnlbXSk6IHZvaWQgPT4ge1xuICAgIGlmIChTZXR0aW5nc1N0b3JlLmdldFZhbHVlKFwiZGVidWdfcmVnaXN0cmF0aW9uXCIpKSB7XG4gICAgICAgIGxvZ2dlci5sb2cuY2FsbChjb25zb2xlLCBcIlJlZ2lzdHJhdGlvbiBkZWJ1Z2xvZzpcIiwgLi4uYXJncyk7XG4gICAgfVxufTtcblxuZXhwb3J0IGludGVyZmFjZSBNb2JpbGVSZWdpc3RyYXRpb25SZXNwb25zZSB7XG4gICAgdXNlcl9pZDogc3RyaW5nO1xuICAgIGhvbWVfc2VydmVyOiBzdHJpbmc7XG4gICAgYWNjZXNzX3Rva2VuOiBzdHJpbmc7XG4gICAgZGV2aWNlX2lkOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBJUHJvcHMge1xuICAgIHNlcnZlckNvbmZpZzogVmFsaWRhdGVkU2VydmVyQ29uZmlnO1xuICAgIGRlZmF1bHREZXZpY2VEaXNwbGF5TmFtZT86IHN0cmluZztcbiAgICBlbWFpbD86IHN0cmluZztcbiAgICBicmFuZD86IHN0cmluZztcbiAgICBjbGllbnRTZWNyZXQ/OiBzdHJpbmc7XG4gICAgc2Vzc2lvbklkPzogc3RyaW5nO1xuICAgIGlkU2lkPzogc3RyaW5nO1xuICAgIGZyYWdtZW50QWZ0ZXJMb2dpbj86IHN0cmluZztcbiAgICBtb2JpbGVSZWdpc3Rlcj86IGJvb2xlYW47XG4gICAgLy8gQ2FsbGVkIHdoZW4gdGhlIHVzZXIgaGFzIGxvZ2dlZCBpbi4gUGFyYW1zOlxuICAgIC8vIC0gb2JqZWN0IHdpdGggdXNlcklkLCBkZXZpY2VJZCwgaG9tZXNlcnZlclVybCwgaWRlbnRpdHlTZXJ2ZXJVcmwsIGFjY2Vzc1Rva2VuXG4gICAgLy8gLSBUaGUgdXNlcidzIHBhc3N3b3JkLCBpZiBhdmFpbGFibGUgYW5kIGFwcGxpY2FibGUgKG1heSBiZSBjYWNoZWQgaW4gbWVtb3J5XG4gICAgLy8gICBmb3IgYSBzaG9ydCB0aW1lIHNvIHRoZSB1c2VyIGlzIG5vdCByZXF1aXJlZCB0byByZS1lbnRlciB0aGVpciBwYXNzd29yZFxuICAgIC8vICAgZm9yIG9wZXJhdGlvbnMgbGlrZSB1cGxvYWRpbmcgY3Jvc3Mtc2lnbmluZyBrZXlzKS5cbiAgICBvbkxvZ2dlZEluKHBhcmFtczogSU1hdHJpeENsaWVudENyZWRzLCBwYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbiAgICAvLyByZWdpc3RyYXRpb24gc2hvdWxkbid0IGtub3cgb3IgY2FyZSBob3cgbG9naW4gaXMgZG9uZS5cbiAgICBvbkxvZ2luQ2xpY2soKTogdm9pZDtcbiAgICBvblNlcnZlckNvbmZpZ0NoYW5nZShjb25maWc6IFZhbGlkYXRlZFNlcnZlckNvbmZpZyk6IHZvaWQ7XG59XG5cbmludGVyZmFjZSBJU3RhdGUge1xuICAgIC8vIHRydWUgaWYgd2UncmUgd2FpdGluZyBmb3IgdGhlIHVzZXIgdG8gY29tcGxldGVcbiAgICBidXN5OiBib29sZWFuO1xuICAgIGVycm9yVGV4dD86IFJlYWN0Tm9kZTtcbiAgICAvLyBXZSByZW1lbWJlciB0aGUgdmFsdWVzIGVudGVyZWQgYnkgdGhlIHVzZXIgYmVjYXVzZVxuICAgIC8vIHRoZSByZWdpc3RyYXRpb24gZm9ybSB3aWxsIGJlIHVubW91bnRlZCBkdXJpbmcgdGhlXG4gICAgLy8gY291cnNlIG9mIHJlZ2lzdHJhdGlvbiwgYnV0IGlmIHRoZXJlJ3MgYW4gZXJyb3Igd2VcbiAgICAvLyB3YW50IHRvIGJyaW5nIGJhY2sgdGhlIHJlZ2lzdHJhdGlvbiBmb3JtIHdpdGggdGhlXG4gICAgLy8gdmFsdWVzIHRoZSB1c2VyIGVudGVyZWQgc3RpbGwgaW4gaXQuIFdlIGNhbiBrZWVwXG4gICAgLy8gdGhlbSBpbiB0aGlzIGNvbXBvbmVudCdzIHN0YXRlIHNpbmNlIHRoaXMgY29tcG9uZW50XG4gICAgLy8gcGVyc2lzdCBmb3IgdGhlIGR1cmF0aW9uIG9mIHRoZSByZWdpc3RyYXRpb24gcHJvY2Vzcy5cbiAgICBmb3JtVmFsczogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPjtcbiAgICAvLyB1c2VyLWludGVyYWN0aXZlIGF1dGhcbiAgICAvLyBJZiB3ZSd2ZSBiZWVuIGdpdmVuIGEgc2Vzc2lvbiBJRCwgd2UncmUgcmVzdW1pbmdcbiAgICAvLyBzdHJhaWdodCBiYWNrIGludG8gVUkgYXV0aFxuICAgIGRvaW5nVUlBdXRoOiBib29sZWFuO1xuICAgIC8vIElmIHNldCwgd2UndmUgcmVnaXN0ZXJlZCBidXQgYXJlIG5vdCBnb2luZyB0byBsb2dcbiAgICAvLyB0aGUgdXNlciBpbiB0byB0aGVpciBuZXcgYWNjb3VudCBhdXRvbWF0aWNhbGx5LlxuICAgIGNvbXBsZXRlZE5vU2lnbmluOiBib29sZWFuO1xuICAgIGZsb3dzOlxuICAgICAgICB8IHtcbiAgICAgICAgICAgICAgc3RhZ2VzOiBzdHJpbmdbXTtcbiAgICAgICAgICB9W11cbiAgICAgICAgfCBudWxsO1xuICAgIC8vIFdlIHBlcmZvcm0gbGl2ZWxpbmVzcyBjaGVja3MgbGF0ZXIsIGJ1dCBmb3Igbm93IHN1cHByZXNzIHRoZSBlcnJvcnMuXG4gICAgLy8gV2UgYWxzbyB0cmFjayB0aGUgc2VydmVyIGRlYWQgZXJyb3JzIGluZGVwZW5kZW50bHkgb2YgdGhlIHJlZ3VsYXIgZXJyb3JzIHNvXG4gICAgLy8gdGhhdCB3ZSBjYW4gcmVuZGVyIGl0IGRpZmZlcmVudGx5LCBhbmQgb3ZlcnJpZGUgYW55IG90aGVyIGVycm9yIHRoZSB1c2VyIG1heVxuICAgIC8vIGJlIHNlZWluZy5cbiAgICBzZXJ2ZXJJc0FsaXZlOiBib29sZWFuO1xuICAgIHNlcnZlckVycm9ySXNGYXRhbDogYm9vbGVhbjtcbiAgICBzZXJ2ZXJEZWFkRXJyb3I/OiBSZWFjdE5vZGU7XG5cbiAgICAvLyBPdXIgbWF0cml4IGNsaWVudCAtIHBhcnQgb2Ygc3RhdGUgYmVjYXVzZSB3ZSBjYW4ndCByZW5kZXIgdGhlIFVJIGF1dGhcbiAgICAvLyBjb21wb25lbnQgd2l0aG91dCBpdC5cbiAgICBtYXRyaXhDbGllbnQ/OiBNYXRyaXhDbGllbnQ7XG4gICAgLy8gVGhlIHVzZXIgSUQgd2UndmUganVzdCByZWdpc3RlcmVkXG4gICAgcmVnaXN0ZXJlZFVzZXJuYW1lPzogc3RyaW5nO1xuICAgIC8vIGlmIGEgZGlmZmVyZW50IHVzZXIgSUQgdG8gdGhlIG9uZSB3ZSBqdXN0IHJlZ2lzdGVyZWQgaXMgbG9nZ2VkIGluLFxuICAgIC8vIHRoaXMgaXMgdGhlIHVzZXIgSUQgdGhhdCdzIGxvZ2dlZCBpbi5cbiAgICBkaWZmZXJlbnRMb2dnZWRJblVzZXJJZD86IHN0cmluZztcbiAgICAvLyB0aGUgU1NPIGZsb3cgZGVmaW5pdGlvbiwgdGhpcyBpcyBmZXRjaGVkIGZyb20gL2xvZ2luIGFzIHRoYXQncyB0aGUgb25seVxuICAgIC8vIHBsYWNlIGl0IGlzIGV4cG9zZWQuXG4gICAgc3NvRmxvdz86IFNTT0Zsb3c7XG4gICAgLy8gdGhlIE9JREMgbmF0aXZlIGxvZ2luIGZsb3csIHdoZW4gc3VwcG9ydGVkIGFuZCBlbmFibGVkXG4gICAgLy8gaWYgcHJlc2VudCwgbXVzdCBiZSB1c2VkIGZvciByZWdpc3RyYXRpb25cbiAgICBvaWRjTmF0aXZlRmxvdz86IE9pZGNOYXRpdmVGbG93O1xufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBSZWdpc3RyYXRpb24gZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SVByb3BzLCBJU3RhdGU+IHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IGxvZ2luTG9naWM6IExvZ2luO1xuICAgIC8vIGByZXBsYWNlQ2xpZW50YCB0cmFja3MgbGF0ZXN0IHNlcnZlckNvbmZpZyB0byBzcG90IHdoZW4gaXQgY2hhbmdlcyB1bmRlciB0aGUgYXN5bmMgbWV0aG9kIHdoaWNoIGZldGNoZXMgZmxvd3NcbiAgICBwcml2YXRlIGxhdGVzdFNlcnZlckNvbmZpZz86IFZhbGlkYXRlZFNlcnZlckNvbmZpZztcbiAgICAvLyBjYWNoZSB2YWx1ZSBmcm9tIHNldHRpbmdzIHN0b3JlXG4gICAgcHJpdmF0ZSBvaWRjTmF0aXZlRmxvd0VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcm9wczogSVByb3BzKSB7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgYnVzeTogZmFsc2UsXG4gICAgICAgICAgICBlcnJvclRleHQ6IG51bGwsXG4gICAgICAgICAgICBmb3JtVmFsczoge1xuICAgICAgICAgICAgICAgIGVtYWlsOiB0aGlzLnByb3BzLmVtYWlsLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRvaW5nVUlBdXRoOiBCb29sZWFuKHRoaXMucHJvcHMuc2Vzc2lvbklkKSxcbiAgICAgICAgICAgIGZsb3dzOiBudWxsLFxuICAgICAgICAgICAgY29tcGxldGVkTm9TaWduaW46IGZhbHNlLFxuICAgICAgICAgICAgc2VydmVySXNBbGl2ZTogdHJ1ZSxcbiAgICAgICAgICAgIHNlcnZlckVycm9ySXNGYXRhbDogZmFsc2UsXG4gICAgICAgICAgICBzZXJ2ZXJEZWFkRXJyb3I6IFwiXCIsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gb25seSBzZXQgb24gYSBjb25maWcgbGV2ZWwsIHNvIHdlIGRvbid0IG5lZWQgdG8gd2F0Y2hcbiAgICAgICAgdGhpcy5vaWRjTmF0aXZlRmxvd0VuYWJsZWQgPSBTZXR0aW5nc1N0b3JlLmdldFZhbHVlKEZlYXR1cmVzLk9pZGNOYXRpdmVGbG93KTtcblxuICAgICAgICBjb25zdCB7IGhzVXJsLCBpc1VybCwgZGVsZWdhdGVkQXV0aGVudGljYXRpb24gfSA9IHRoaXMucHJvcHMuc2VydmVyQ29uZmlnO1xuICAgICAgICB0aGlzLmxvZ2luTG9naWMgPSBuZXcgTG9naW4oaHNVcmwsIGlzVXJsLCBudWxsLCB7XG4gICAgICAgICAgICBkZWZhdWx0RGV2aWNlRGlzcGxheU5hbWU6IFwiRWxlbWVudCBsb2dpbiBjaGVja1wiLCAvLyBXZSBzaG91bGRuJ3QgZXZlciBiZSB1c2VkXG4gICAgICAgICAgICAvLyBpZiBuYXRpdmUgT0lEQyBpcyBlbmFibGVkIGluIHRoZSBjbGllbnQgcGFzcyB0aGUgc2VydmVyJ3MgZGVsZWdhdGVkIGF1dGggc2V0dGluZ3NcbiAgICAgICAgICAgIGRlbGVnYXRlZEF1dGhlbnRpY2F0aW9uOiB0aGlzLm9pZGNOYXRpdmVGbG93RW5hYmxlZCA/IGRlbGVnYXRlZEF1dGhlbnRpY2F0aW9uIDogdW5kZWZpbmVkLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkTW91bnQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVwbGFjZUNsaWVudCh0aGlzLnByb3BzLnNlcnZlckNvbmZpZyk7XG4gICAgICAgIC8vdHJpZ2dlcnMgYSBjb25maXJtYXRpb24gZGlhbG9nIGZvciBkYXRhIGxvc3MgYmVmb3JlIHBhZ2UgdW5sb2Fkcy9yZWZyZXNoZXNcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoXCJiZWZvcmV1bmxvYWRcIiwgdGhpcy51bmxvYWRDYWxsYmFjayk7XG4gICAgfVxuXG4gICAgcHVibGljIGNvbXBvbmVudFdpbGxVbm1vdW50KCk6IHZvaWQge1xuICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImJlZm9yZXVubG9hZFwiLCB0aGlzLnVubG9hZENhbGxiYWNrKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHVubG9hZENhbGxiYWNrID0gKGV2ZW50OiBCZWZvcmVVbmxvYWRFdmVudCk6IHN0cmluZyB8IHVuZGVmaW5lZCA9PiB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmRvaW5nVUlBdXRoKSB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgZXZlbnQucmV0dXJuVmFsdWUgPSBcIlwiO1xuICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcHVibGljIGNvbXBvbmVudERpZFVwZGF0ZShwcmV2UHJvcHM6IElQcm9wcyk6IHZvaWQge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBwcmV2UHJvcHMuc2VydmVyQ29uZmlnLmhzVXJsICE9PSB0aGlzLnByb3BzLnNlcnZlckNvbmZpZy5oc1VybCB8fFxuICAgICAgICAgICAgcHJldlByb3BzLnNlcnZlckNvbmZpZy5pc1VybCAhPT0gdGhpcy5wcm9wcy5zZXJ2ZXJDb25maWcuaXNVcmxcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLnJlcGxhY2VDbGllbnQodGhpcy5wcm9wcy5zZXJ2ZXJDb25maWcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyByZXBsYWNlQ2xpZW50KHNlcnZlckNvbmZpZzogVmFsaWRhdGVkU2VydmVyQ29uZmlnKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHRoaXMubGF0ZXN0U2VydmVyQ29uZmlnID0gc2VydmVyQ29uZmlnO1xuICAgICAgICBjb25zdCB7IGhzVXJsLCBpc1VybCB9ID0gc2VydmVyQ29uZmlnO1xuXG4gICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgZXJyb3JUZXh0OiBudWxsLFxuICAgICAgICAgICAgc2VydmVyRGVhZEVycm9yOiBudWxsLFxuICAgICAgICAgICAgc2VydmVyRXJyb3JJc0ZhdGFsOiBmYWxzZSxcbiAgICAgICAgICAgIC8vIGJ1c3kgd2hpbGUgd2UgZG8gbGl2ZS1uZXNzIGNoZWNrICh3ZSBuZWVkIHRvIGF2b2lkIHRyeWluZyB0byByZW5kZXJcbiAgICAgICAgICAgIC8vIHRoZSBVSSBhdXRoIGNvbXBvbmVudCB3aGlsZSB3ZSBkb24ndCBoYXZlIGEgbWF0cml4IGNsaWVudClcbiAgICAgICAgICAgIGJ1c3k6IHRydWUsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIERvIGEgbGl2ZWxpbmVzcyBjaGVjayBvbiB0aGUgVVJMc1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgYXdhaXQgQXV0b0Rpc2NvdmVyeVV0aWxzLnZhbGlkYXRlU2VydmVyQ29uZmlnV2l0aFN0YXRpY1VybHMoaHNVcmwsIGlzVXJsKTtcbiAgICAgICAgICAgIGlmIChzZXJ2ZXJDb25maWcgIT09IHRoaXMubGF0ZXN0U2VydmVyQ29uZmlnKSByZXR1cm47IC8vIGRpc2NhcmQsIHNlcnZlckNvbmZpZyBjaGFuZ2VkIGZyb20gdW5kZXIgdXNcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIHNlcnZlcklzQWxpdmU6IHRydWUsXG4gICAgICAgICAgICAgICAgc2VydmVyRXJyb3JJc0ZhdGFsOiBmYWxzZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBpZiAoc2VydmVyQ29uZmlnICE9PSB0aGlzLmxhdGVzdFNlcnZlckNvbmZpZykgcmV0dXJuOyAvLyBkaXNjYXJkLCBzZXJ2ZXJDb25maWcgY2hhbmdlZCBmcm9tIHVuZGVyIHVzXG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICBidXN5OiBmYWxzZSxcbiAgICAgICAgICAgICAgICAuLi5BdXRvRGlzY292ZXJ5VXRpbHMuYXV0aENvbXBvbmVudFN0YXRlRm9yRXJyb3IoZSwgXCJyZWdpc3RlclwiKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHRoaXMuc3RhdGUuc2VydmVyRXJyb3JJc0ZhdGFsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBTZXJ2ZXIgaXMgZGVhZCAtIGRvIG5vdCBjb250aW51ZS5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNsaSA9IGNyZWF0ZUNsaWVudCh7XG4gICAgICAgICAgICBiYXNlVXJsOiBoc1VybCxcbiAgICAgICAgICAgIGlkQmFzZVVybDogaXNVcmwsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMubG9naW5Mb2dpYy5zZXRIb21lc2VydmVyVXJsKGhzVXJsKTtcbiAgICAgICAgdGhpcy5sb2dpbkxvZ2ljLnNldElkZW50aXR5U2VydmVyVXJsKGlzVXJsKTtcbiAgICAgICAgLy8gaWYgbmF0aXZlIE9JREMgaXMgZW5hYmxlZCBpbiB0aGUgY2xpZW50IHBhc3MgdGhlIHNlcnZlcidzIGRlbGVnYXRlZCBhdXRoIHNldHRpbmdzXG4gICAgICAgIGNvbnN0IGRlbGVnYXRlZEF1dGhlbnRpY2F0aW9uID0gdGhpcy5vaWRjTmF0aXZlRmxvd0VuYWJsZWQgPyBzZXJ2ZXJDb25maWcuZGVsZWdhdGVkQXV0aGVudGljYXRpb24gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgdGhpcy5sb2dpbkxvZ2ljLnNldERlbGVnYXRlZEF1dGhlbnRpY2F0aW9uKGRlbGVnYXRlZEF1dGhlbnRpY2F0aW9uKTtcblxuICAgICAgICBsZXQgc3NvRmxvdzogU1NPRmxvdyB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IG9pZGNOYXRpdmVGbG93OiBPaWRjTmF0aXZlRmxvdyB8IHVuZGVmaW5lZDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGxvZ2luRmxvd3MgPSBhd2FpdCB0aGlzLmxvZ2luTG9naWMuZ2V0Rmxvd3ModHJ1ZSk7XG4gICAgICAgICAgICBpZiAoc2VydmVyQ29uZmlnICE9PSB0aGlzLmxhdGVzdFNlcnZlckNvbmZpZykgcmV0dXJuOyAvLyBkaXNjYXJkLCBzZXJ2ZXJDb25maWcgY2hhbmdlZCBmcm9tIHVuZGVyIHVzXG4gICAgICAgICAgICBzc29GbG93ID0gbG9naW5GbG93cy5maW5kKChmKSA9PiBmLnR5cGUgPT09IFwibS5sb2dpbi5zc29cIiB8fCBmLnR5cGUgPT09IFwibS5sb2dpbi5jYXNcIikgYXMgU1NPRmxvdztcbiAgICAgICAgICAgIG9pZGNOYXRpdmVGbG93ID0gbG9naW5GbG93cy5maW5kKChmKSA9PiBmLnR5cGUgPT09IFwib2lkY05hdGl2ZUZsb3dcIikgYXMgT2lkY05hdGl2ZUZsb3c7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGlmIChzZXJ2ZXJDb25maWcgIT09IHRoaXMubGF0ZXN0U2VydmVyQ29uZmlnKSByZXR1cm47IC8vIGRpc2NhcmQsIHNlcnZlckNvbmZpZyBjaGFuZ2VkIGZyb20gdW5kZXIgdXNcbiAgICAgICAgICAgIGxvZ2dlci5lcnJvcihcIkZhaWxlZCB0byBnZXQgbG9naW4gZmxvd3MgdG8gY2hlY2sgZm9yIFNTTyBzdXBwb3J0XCIsIGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoXG4gICAgICAgICAgICAgICAgKHsgZmxvd3MgfSkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgbWF0cml4Q2xpZW50OiBjbGksXG4gICAgICAgICAgICAgICAgICAgIHNzb0Zsb3csXG4gICAgICAgICAgICAgICAgICAgIG9pZGNOYXRpdmVGbG93LFxuICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBhcmUgdXNpbmcgb2lkYyBuYXRpdmUgd2Ugd29uJ3QgY29udGludWUgd2l0aCBmbG93IGRpc2NvdmVyeSBvbiBIU1xuICAgICAgICAgICAgICAgICAgICAvLyBzbyBzZXQgYW4gZW1wdHkgYXJyYXkgdG8gaW5kaWNhdGUgZmxvd3MgYXJlIG5vIGxvbmdlciBsb2FkaW5nXG4gICAgICAgICAgICAgICAgICAgIGZsb3dzOiBvaWRjTmF0aXZlRmxvdyA/IFtdIDogZmxvd3MsXG4gICAgICAgICAgICAgICAgICAgIGJ1c3k6IGZhbHNlLFxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIHJlc29sdmUsXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBkb24ndCBuZWVkIHRvIGNoZWNrIHdpdGggaG9tZXNlcnZlciBmb3IgbG9naW4gZmxvd3NcbiAgICAgICAgLy8gc2luY2Ugd2UgYXJlIGdvaW5nIHRvIHVzZSBPSURDIG5hdGl2ZSBmbG93XG4gICAgICAgIGlmIChvaWRjTmF0aXZlRmxvdykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdlIGRvIHRoZSBmaXJzdCByZWdpc3RyYXRpb24gcmVxdWVzdCBvdXJzZWx2ZXMgdG8gZGlzY292ZXIgd2hldGhlciB3ZSBuZWVkIHRvXG4gICAgICAgICAgICAvLyBkbyBTU08gaW5zdGVhZC4gSWYgd2UndmUgYWxyZWFkeSBzdGFydGVkIHRoZSBVSSBBdXRoIHByb2Nlc3MgdGhvdWdoLCB3ZSBkb24ndFxuICAgICAgICAgICAgLy8gbmVlZCB0by5cbiAgICAgICAgICAgIGlmICghdGhpcy5zdGF0ZS5kb2luZ1VJQXV0aCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubWFrZVJlZ2lzdGVyUmVxdWVzdChudWxsKTtcbiAgICAgICAgICAgICAgICBpZiAoc2VydmVyQ29uZmlnICE9PSB0aGlzLmxhdGVzdFNlcnZlckNvbmZpZykgcmV0dXJuOyAvLyBkaXNjYXJkLCBzZXJ2ZXJDb25maWcgY2hhbmdlZCBmcm9tIHVuZGVyIHVzXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBzaG91bGQgbmV2ZXIgc3VjY2VlZCBzaW5jZSB3ZSBzcGVjaWZpZWQgbm8gYXV0aCBvYmplY3QuXG4gICAgICAgICAgICAgICAgbG9nZ2VyLmxvZyhcIkV4cGVjdGluZyA0MDEgZnJvbSByZWdpc3RlciByZXF1ZXN0IGJ1dCBnb3Qgc3VjY2VzcyFcIik7XG4gICA