UNPKG

matrix-react-sdk

Version:
799 lines (785 loc) • 124 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.TermsAuthEntry = exports.SSOAuthEntry = exports.RegistrationTokenAuthEntry = exports.RecaptchaAuthEntry = exports.PasswordAuthEntry = exports.MsisdnAuthEntry = exports.MasUnlockCrossSigningAuthEntry = exports.FallbackAuthEntry = exports.EmailIdentityAuthEntry = exports.DEFAULT_PHASE = exports.CustomAuthType = void 0; exports.default = getEntryComponentForLoginType; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _classnames = _interopRequireDefault(require("classnames")); var _interactiveAuth = require("matrix-js-sdk/src/interactive-auth"); var _logger = require("matrix-js-sdk/src/logger"); var _react = _interopRequireWildcard(require("react")); var _compoundWeb = require("@vector-im/compound-web"); var _popOut = _interopRequireDefault(require("@vector-im/compound-design-tokens/assets/web/icons/pop-out")); var _emailPrompt = _interopRequireDefault(require("../../../../res/img/element-icons/email-prompt.svg")); var _languageHandler = require("../../../languageHandler"); var _SettingsStore = _interopRequireDefault(require("../../../settings/SettingsStore")); var _AuthHeaderModifier = require("../../structures/auth/header/AuthHeaderModifier"); var _AccessibleButton = _interopRequireDefault(require("../elements/AccessibleButton")); var _Field = _interopRequireDefault(require("../elements/Field")); var _Spinner = _interopRequireDefault(require("../elements/Spinner")); var _CaptchaForm = _interopRequireDefault(require("./CaptchaForm")); var _Flex = require("../../utils/Flex"); 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; } /* Copyright 2024 New Vector Ltd. Copyright 2016-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. */ /* This file contains a collection of components which are used by the * InteractiveAuth to prompt the user to enter the information needed * for an auth stage. (The intention is that they could also be used for other * components, such as the registration flow). * * Call getEntryComponentForLoginType() to get a component suitable for a * particular login type. Each component requires the same properties: * * matrixClient: A matrix client. May be a different one to the one * currently being used generally (eg. to register with * one HS whilst being a guest on another). * loginType: the login type of the auth stage being attempted * authSessionId: session id from the server * clientSecret: The client secret in use for identity server auth sessions * stageParams: params from the server for the stage being attempted * errorText: error message from a previous attempt to authenticate * submitAuthDict: a function which will be called with the new auth dict * busy: a boolean indicating whether the auth logic is doing something * the user needs to wait for. * inputs: Object of inputs provided by the user, as in js-sdk * interactive-auth * stageState: Stage-specific object used for communicating state information * to the UI from the state-specific auth logic. * Defined keys for stages are: * m.login.email.identity: * * emailSid: string representing the sid of the active * verification session from the identity server, * or null if no session is active. * fail: a function which should be called with an error object if an * error occurred during the auth stage. This will cause the auth * session to be failed and the process to go back to the start. * setEmailSid: m.login.email.identity only: a function to be called with the * email sid after a token is requested. * onPhaseChange: A function which is called when the stage's phase changes. If * the stage has no phases, call this with DEFAULT_PHASE. Takes * one argument, the phase, and is always defined/required. * continueText: For stages which have a continue button, the text to use. * continueKind: For stages which have a continue button, the style of button to * use. For example, 'danger' or 'primary'. * onCancel A function with no arguments which is called by the stage if the * user knowingly cancelled/dismissed the authentication attempt. * * Each component may also provide the following functions (beyond the standard React ones): * focus: set the input focus appropriately in the form. */ const DEFAULT_PHASE = exports.DEFAULT_PHASE = 0; class PasswordAuthEntry extends _react.default.Component { constructor(props) { super(props); (0, _defineProperty2.default)(this, "onSubmit", e => { e.preventDefault(); if (this.props.busy) return; this.props.submitAuthDict({ type: _interactiveAuth.AuthType.Password, identifier: { type: "m.id.user", user: this.props.matrixClient.credentials.userId }, password: this.state.password }); }); (0, _defineProperty2.default)(this, "onPasswordFieldChange", ev => { // enable the submit button iff the password is non-empty this.setState({ password: ev.target.value }); }); this.state = { password: "" }; } componentDidMount() { this.props.onPhaseChange(DEFAULT_PHASE); } render() { const passwordBoxClass = (0, _classnames.default)({ error: this.props.errorText }); let submitButtonOrSpinner; if (this.props.busy) { submitButtonOrSpinner = /*#__PURE__*/_react.default.createElement(_Spinner.default, null); } else { submitButtonOrSpinner = /*#__PURE__*/_react.default.createElement("input", { type: "submit", className: "mx_Dialog_primary", disabled: !this.state.password, value: (0, _languageHandler._t)("action|continue") }); } let errorSection; if (this.props.errorText) { errorSection = /*#__PURE__*/_react.default.createElement("div", { className: "error", role: "alert" }, this.props.errorText); } return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("auth|uia|password_prompt")), /*#__PURE__*/_react.default.createElement("form", { onSubmit: this.onSubmit, className: "mx_InteractiveAuthEntryComponents_passwordSection" }, /*#__PURE__*/_react.default.createElement(_Field.default, { className: passwordBoxClass, type: "password", name: "passwordField", label: (0, _languageHandler._t)("common|password"), autoFocus: true, value: this.state.password, onChange: this.onPasswordFieldChange }), errorSection, /*#__PURE__*/_react.default.createElement("div", { className: "mx_button_row" }, submitButtonOrSpinner))); } } /* eslint-disable camelcase */ exports.PasswordAuthEntry = PasswordAuthEntry; (0, _defineProperty2.default)(PasswordAuthEntry, "LOGIN_TYPE", _interactiveAuth.AuthType.Password); /* eslint-enable camelcase */ class RecaptchaAuthEntry extends _react.default.Component { constructor(...args) { super(...args); (0, _defineProperty2.default)(this, "onCaptchaResponse", response => { this.props.submitAuthDict({ type: _interactiveAuth.AuthType.Recaptcha, response: response }); }); } componentDidMount() { this.props.onPhaseChange(DEFAULT_PHASE); } render() { if (this.props.busy) { return /*#__PURE__*/_react.default.createElement(_Spinner.default, null); } let errorText = this.props.errorText; let sitePublicKey; if (!this.props.stageParams || !this.props.stageParams.public_key) { errorText = (0, _languageHandler._t)("auth|uia|recaptcha_missing_params"); } else { sitePublicKey = this.props.stageParams.public_key; } let errorSection; if (errorText) { errorSection = /*#__PURE__*/_react.default.createElement("div", { className: "error", role: "alert" }, errorText); } return /*#__PURE__*/_react.default.createElement("div", null, sitePublicKey && /*#__PURE__*/_react.default.createElement(_CaptchaForm.default, { sitePublicKey: sitePublicKey, onCaptchaResponse: this.onCaptchaResponse }), errorSection); } } exports.RecaptchaAuthEntry = RecaptchaAuthEntry; (0, _defineProperty2.default)(RecaptchaAuthEntry, "LOGIN_TYPE", _interactiveAuth.AuthType.Recaptcha); class TermsAuthEntry extends _react.default.Component { constructor(props) { super(props); // example stageParams: // // { // "policies": { // "privacy_policy": { // "version": "1.0", // "en": { // "name": "Privacy Policy", // "url": "https://example.org/privacy-1.0-en.html", // }, // "fr": { // "name": "Politique de confidentialité", // "url": "https://example.org/privacy-1.0-fr.html", // }, // }, // "other_policy": { ... }, // } // } (0, _defineProperty2.default)(this, "trySubmit", () => { let allChecked = true; for (const policy of this.state.policies) { const checked = this.state.toggledPolicies[policy.id]; allChecked = allChecked && checked; } if (allChecked) { this.props.submitAuthDict({ type: _interactiveAuth.AuthType.Terms }); } else { this.setState({ errorText: (0, _languageHandler._t)("auth|uia|terms_invalid") }); } }); const allPolicies = this.props.stageParams?.policies || {}; const prefLang = _SettingsStore.default.getValue("language"); const initToggles = {}; const pickedPolicies = []; for (const policyId of Object.keys(allPolicies)) { const policy = allPolicies[policyId]; // Pick a language based on the user's language, falling back to english, // and finally to the first language available. If there's still no policy // available then the homeserver isn't respecting the spec. let langPolicy = policy[prefLang]; if (!langPolicy) langPolicy = policy["en"]; if (!langPolicy) { // last resort const firstLang = Object.keys(policy).find(e => e !== "version"); langPolicy = firstLang ? policy[firstLang] : undefined; } if (!langPolicy) throw new Error("Failed to find a policy to show the user"); initToggles[policyId] = false; pickedPolicies.push({ id: policyId, name: langPolicy.name, url: langPolicy.url }); } this.state = { toggledPolicies: initToggles, policies: pickedPolicies }; } componentDidMount() { this.props.onPhaseChange(DEFAULT_PHASE); } togglePolicy(policyId) { const newToggles = {}; for (const policy of this.state.policies) { let checked = this.state.toggledPolicies[policy.id]; if (policy.id === policyId) checked = !checked; newToggles[policy.id] = checked; } this.setState({ toggledPolicies: newToggles }); } render() { if (this.props.busy) { return /*#__PURE__*/_react.default.createElement(_Spinner.default, null); } const checkboxes = []; let allChecked = true; for (const policy of this.state.policies) { const checked = this.state.toggledPolicies[policy.id]; allChecked = allChecked && checked; checkboxes.push( /*#__PURE__*/ // XXX: replace with StyledCheckbox _react.default.createElement("label", { key: "policy_checkbox_" + policy.id, className: "mx_InteractiveAuthEntryComponents_termsPolicy" }, /*#__PURE__*/_react.default.createElement("input", { type: "checkbox", onChange: () => this.togglePolicy(policy.id), checked: checked }), /*#__PURE__*/_react.default.createElement("a", { href: policy.url, target: "_blank", rel: "noreferrer noopener" }, policy.name))); } let errorSection; if (this.props.errorText || this.state.errorText) { errorSection = /*#__PURE__*/_react.default.createElement("div", { className: "error", role: "alert" }, this.props.errorText || this.state.errorText); } let submitButton; if (this.props.showContinue !== false) { submitButton = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "primary", className: "mx_InteractiveAuthEntryComponents_termsSubmit", onClick: this.trySubmit, disabled: !allChecked }, (0, _languageHandler._t)("action|accept")); } return /*#__PURE__*/_react.default.createElement("div", { className: "mx_InteractiveAuthEntryComponents" }, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("auth|uia|terms")), checkboxes, errorSection, submitButton); } } exports.TermsAuthEntry = TermsAuthEntry; (0, _defineProperty2.default)(TermsAuthEntry, "LOGIN_TYPE", _interactiveAuth.AuthType.Terms); class EmailIdentityAuthEntry extends _react.default.Component { constructor(props) { super(props); this.state = { requested: false, requesting: false }; } componentDidMount() { this.props.onPhaseChange(DEFAULT_PHASE); } render() { let errorSection; // ignore the error when errcode is M_UNAUTHORIZED as we expect that error until the link is clicked. if (this.props.errorText && this.props.errorCode !== "M_UNAUTHORIZED") { errorSection = /*#__PURE__*/_react.default.createElement("div", { className: "error", role: "alert" }, this.props.errorText); } // This component is now only displayed once the token has been requested, // so we know the email has been sent. It can also get loaded after the user // has clicked the validation link if the server takes a while to propagate // the validation internally. If we're in the session spawned from clicking // the validation link, we won't know the email address, so if we don't have it, // assume that the link has been clicked and the server will realise when we poll. // We only have a session ID if the user has clicked the link in their email, // so show a loading state instead of "an email has been sent to..." because // that's confusing when you've already read that email. if (this.props.inputs?.emailAddress === undefined || this.props.stageState?.emailSid) { if (errorSection) { return errorSection; } return /*#__PURE__*/_react.default.createElement(_Spinner.default, null); } else { return /*#__PURE__*/_react.default.createElement("div", { className: "mx_InteractiveAuthEntryComponents_emailWrapper" }, /*#__PURE__*/_react.default.createElement(_AuthHeaderModifier.AuthHeaderModifier, { title: (0, _languageHandler._t)("auth|uia|email_auth_header"), icon: /*#__PURE__*/_react.default.createElement("img", { src: _emailPrompt.default, role: "presentation", alt: "", width: 16 }), hideServerPicker: true }), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("auth|uia|email", { emailAddress: /*#__PURE__*/_react.default.createElement("strong", null, this.props.inputs.emailAddress) })), this.state.requesting ? /*#__PURE__*/_react.default.createElement("p", { className: "secondary" }, (0, _languageHandler._t)("auth|uia|email_resend_prompt", {}, { a: text => /*#__PURE__*/_react.default.createElement(_react.Fragment, null, /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "link_inline", onClick: null, disabled: true }, text, " ", /*#__PURE__*/_react.default.createElement(_Spinner.default, { w: 14, h: 14 }))) })) : /*#__PURE__*/_react.default.createElement("p", { className: "secondary" }, (0, _languageHandler._t)("auth|uia|email_resend_prompt", {}, { a: text => /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "link_inline", title: this.state.requested ? (0, _languageHandler._t)("auth|uia|email_resent") : (0, _languageHandler._t)("action|resend"), onTooltipOpenChange: this.state.requested ? open => { if (!open) this.setState({ requested: false }); } : undefined, onClick: async () => { this.setState({ requesting: true }); try { await this.props.requestEmailToken?.(); } catch (e) { _logger.logger.warn("Email token request failed: ", e); } finally { this.setState({ requested: true, requesting: false }); } } }, text) })), errorSection); } } } exports.EmailIdentityAuthEntry = EmailIdentityAuthEntry; (0, _defineProperty2.default)(EmailIdentityAuthEntry, "LOGIN_TYPE", _interactiveAuth.AuthType.Email); class MsisdnAuthEntry extends _react.default.Component { constructor(props) { super(props); (0, _defineProperty2.default)(this, "submitUrl", void 0); (0, _defineProperty2.default)(this, "sid", void 0); (0, _defineProperty2.default)(this, "msisdn", void 0); (0, _defineProperty2.default)(this, "onTokenChange", e => { this.setState({ token: e.target.value }); }); (0, _defineProperty2.default)(this, "onFormSubmit", async e => { e.preventDefault(); if (this.state.token == "") return; this.setState({ errorText: null }); try { let result; if (this.submitUrl && this.sid) { result = await this.props.matrixClient.submitMsisdnTokenOtherUrl(this.submitUrl, this.sid, this.props.clientSecret, this.state.token); } else { throw new Error("The registration with MSISDN flow is misconfigured"); } if (result.success) { const creds = { sid: this.sid, client_secret: this.props.clientSecret }; this.props.submitAuthDict({ type: _interactiveAuth.AuthType.Msisdn, threepid_creds: creds }); } else { this.setState({ errorText: (0, _languageHandler._t)("auth|uia|msisdn_token_incorrect") }); } } catch (e) { this.props.fail(e instanceof Error ? e : new Error("Failed to submit msisdn token")); _logger.logger.log("Failed to submit msisdn token"); } }); this.state = { token: "", requestingToken: false, errorText: "" }; } componentDidMount() { this.props.onPhaseChange(DEFAULT_PHASE); this.setState({ requestingToken: true }); this.requestMsisdnToken().catch(e => { this.props.fail(e); }).finally(() => { this.setState({ requestingToken: false }); }); } /* * Requests a verification token by SMS. */ requestMsisdnToken() { return this.props.matrixClient.requestRegisterMsisdnToken(this.props.inputs?.phoneCountry ?? "", this.props.inputs?.phoneNumber ?? "", this.props.clientSecret, 1 // TODO: Multiple send attempts? ).then(result => { this.submitUrl = result.submit_url; this.sid = result.sid; this.msisdn = result.msisdn; }); } render() { if (this.state.requestingToken) { return /*#__PURE__*/_react.default.createElement(_Spinner.default, null); } else { const enableSubmit = Boolean(this.state.token); const submitClasses = (0, _classnames.default)({ mx_InteractiveAuthEntryComponents_msisdnSubmit: true, mx_GeneralButton: true }); let errorSection; if (this.state.errorText) { errorSection = /*#__PURE__*/_react.default.createElement("div", { className: "error", role: "alert" }, this.state.errorText); } return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("auth|uia|msisdn", { msisdn: /*#__PURE__*/_react.default.createElement("i", null, this.msisdn) })), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("auth|uia|msisdn_token_prompt")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_InteractiveAuthEntryComponents_msisdnWrapper" }, /*#__PURE__*/_react.default.createElement("form", { onSubmit: this.onFormSubmit }, /*#__PURE__*/_react.default.createElement("input", { type: "text", className: "mx_InteractiveAuthEntryComponents_msisdnEntry", value: this.state.token, onChange: this.onTokenChange, "aria-label": (0, _languageHandler._t)("auth|uia|code") }), /*#__PURE__*/_react.default.createElement("br", null), /*#__PURE__*/_react.default.createElement("input", { type: "submit", value: (0, _languageHandler._t)("action|submit"), className: submitClasses, disabled: !enableSubmit })), errorSection)); } } } exports.MsisdnAuthEntry = MsisdnAuthEntry; (0, _defineProperty2.default)(MsisdnAuthEntry, "LOGIN_TYPE", _interactiveAuth.AuthType.Msisdn); class RegistrationTokenAuthEntry extends _react.default.Component { constructor(props) { super(props); (0, _defineProperty2.default)(this, "onSubmit", e => { e.preventDefault(); if (this.props.busy) return; this.props.submitAuthDict({ // Could be AuthType.RegistrationToken or AuthType.UnstableRegistrationToken type: this.props.loginType, token: this.state.registrationToken }); }); (0, _defineProperty2.default)(this, "onRegistrationTokenFieldChange", ev => { // enable the submit button if the registration token is non-empty this.setState({ registrationToken: ev.target.value }); }); this.state = { registrationToken: "" }; } componentDidMount() { this.props.onPhaseChange(DEFAULT_PHASE); } render() { const registrationTokenBoxClass = (0, _classnames.default)({ error: this.props.errorText }); let submitButtonOrSpinner; if (this.props.busy) { submitButtonOrSpinner = /*#__PURE__*/_react.default.createElement(_Spinner.default, null); } else { submitButtonOrSpinner = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { onClick: this.onSubmit, kind: "primary", disabled: !this.state.registrationToken }, (0, _languageHandler._t)("action|continue")); } let errorSection; if (this.props.errorText) { errorSection = /*#__PURE__*/_react.default.createElement("div", { className: "error", role: "alert" }, this.props.errorText); } return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("auth|uia|registration_token_prompt")), /*#__PURE__*/_react.default.createElement("form", { onSubmit: this.onSubmit, className: "mx_InteractiveAuthEntryComponents_registrationTokenSection" }, /*#__PURE__*/_react.default.createElement(_Field.default, { className: registrationTokenBoxClass, type: "text", name: "registrationTokenField", label: (0, _languageHandler._t)("auth|uia|registration_token_label"), autoFocus: true, value: this.state.registrationToken, onChange: this.onRegistrationTokenFieldChange }), errorSection, /*#__PURE__*/_react.default.createElement("div", { className: "mx_button_row" }, submitButtonOrSpinner))); } } // Subset of AccessibleButtonKind which can be specified for the continue button exports.RegistrationTokenAuthEntry = RegistrationTokenAuthEntry; (0, _defineProperty2.default)(RegistrationTokenAuthEntry, "LOGIN_TYPE", _interactiveAuth.AuthType.RegistrationToken); class SSOAuthEntry extends _react.default.Component { constructor(props) { super(props); // button to confirm SSO completed (0, _defineProperty2.default)(this, "ssoUrl", void 0); (0, _defineProperty2.default)(this, "popupWindow", void 0); (0, _defineProperty2.default)(this, "attemptFailed", () => { this.setState({ attemptFailed: true }); }); (0, _defineProperty2.default)(this, "onReceiveMessage", event => { if (event.data === "authDone" && event.source === this.popupWindow) { if (this.popupWindow) { this.popupWindow.close(); this.popupWindow = null; } } }); (0, _defineProperty2.default)(this, "onStartAuthClick", () => { // Note: We don't use PlatformPeg's startSsoAuth functions because we almost // certainly will need to open the thing in a new tab to avoid losing application // context. this.popupWindow = window.open(this.ssoUrl, "_blank"); this.setState({ phase: SSOAuthEntry.PHASE_POSTAUTH }); this.props.onPhaseChange(SSOAuthEntry.PHASE_POSTAUTH); }); (0, _defineProperty2.default)(this, "onConfirmClick", () => { this.props.submitAuthDict({}); }); if (!this.props.authSessionId) throw new Error("This UIA flow requires an authSessionId"); // We actually send the user through fallback auth so we don't have to // deal with a redirect back to us, losing application context. this.ssoUrl = props.matrixClient.getFallbackAuthUrl(this.props.loginType, this.props.authSessionId); this.popupWindow = null; window.addEventListener("message", this.onReceiveMessage); this.state = { phase: SSOAuthEntry.PHASE_PREAUTH, attemptFailed: false }; } componentDidMount() { this.props.onPhaseChange(SSOAuthEntry.PHASE_PREAUTH); } componentWillUnmount() { window.removeEventListener("message", this.onReceiveMessage); if (this.popupWindow) { this.popupWindow.close(); this.popupWindow = null; } } render() { let continueButton; const cancelButton = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { onClick: this.props.onCancel ?? null, kind: this.props.continueKind ? `${this.props.continueKind}_outline` : "primary_outline" }, (0, _languageHandler._t)("action|cancel")); if (this.state.phase === SSOAuthEntry.PHASE_PREAUTH) { continueButton = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { onClick: this.onStartAuthClick, kind: this.props.continueKind || "primary" }, this.props.continueText || (0, _languageHandler._t)("auth|sso")); } else { continueButton = /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { onClick: this.onConfirmClick, kind: this.props.continueKind || "primary" }, this.props.continueText || (0, _languageHandler._t)("action|confirm")); } let errorSection; if (this.props.errorText) { errorSection = /*#__PURE__*/_react.default.createElement("div", { className: "error", role: "alert" }, this.props.errorText); } else if (this.state.attemptFailed) { errorSection = /*#__PURE__*/_react.default.createElement("div", { className: "error", role: "alert" }, (0, _languageHandler._t)("auth|uia|sso_failed")); } return /*#__PURE__*/_react.default.createElement(_react.Fragment, null, errorSection, /*#__PURE__*/_react.default.createElement("div", { className: "mx_InteractiveAuthEntryComponents_sso_buttons" }, this.props.busy ? /*#__PURE__*/_react.default.createElement(_Spinner.default, { w: 24, h: 24 }) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, cancelButton, continueButton))); } } exports.SSOAuthEntry = SSOAuthEntry; (0, _defineProperty2.default)(SSOAuthEntry, "LOGIN_TYPE", _interactiveAuth.AuthType.Sso); (0, _defineProperty2.default)(SSOAuthEntry, "UNSTABLE_LOGIN_TYPE", _interactiveAuth.AuthType.SsoUnstable); (0, _defineProperty2.default)(SSOAuthEntry, "PHASE_PREAUTH", 1); // button to start SSO (0, _defineProperty2.default)(SSOAuthEntry, "PHASE_POSTAUTH", 2); class FallbackAuthEntry extends _react.default.Component { constructor(props) { super(props); // we have to make the user click a button, as browsers will block // the popup if we open it immediately. (0, _defineProperty2.default)(this, "popupWindow", void 0); (0, _defineProperty2.default)(this, "fallbackButton", /*#__PURE__*/(0, _react.createRef)()); (0, _defineProperty2.default)(this, "focus", () => { this.fallbackButton.current?.focus(); }); (0, _defineProperty2.default)(this, "onShowFallbackClick", e => { if (!this.props.authSessionId) return; e.preventDefault(); e.stopPropagation(); const url = this.props.matrixClient.getFallbackAuthUrl(this.props.loginType, this.props.authSessionId); this.popupWindow = window.open(url, "_blank"); }); (0, _defineProperty2.default)(this, "onReceiveMessage", event => { if (event.data === "authDone" && event.source === this.popupWindow) { this.props.submitAuthDict({}); } }); this.popupWindow = null; window.addEventListener("message", this.onReceiveMessage); } componentDidMount() { this.props.onPhaseChange(DEFAULT_PHASE); } componentWillUnmount() { window.removeEventListener("message", this.onReceiveMessage); this.popupWindow?.close(); } render() { let errorSection; if (this.props.errorText) { errorSection = /*#__PURE__*/_react.default.createElement("div", { className: "error", role: "alert" }, this.props.errorText); } return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "link", ref: this.fallbackButton, onClick: this.onShowFallbackClick }, (0, _languageHandler._t)("auth|uia|fallback_button")), errorSection); } } exports.FallbackAuthEntry = FallbackAuthEntry; let CustomAuthType = exports.CustomAuthType = /*#__PURE__*/function (CustomAuthType) { CustomAuthType["MasCrossSigningReset"] = "org.matrix.cross_signing_reset"; return CustomAuthType; }({}); class MasUnlockCrossSigningAuthEntry extends FallbackAuthEntry { constructor(...args) { super(...args); (0, _defineProperty2.default)(this, "onGoToAccountClick", () => { if (!this.props.stageParams?.url) return; this.popupWindow = window.open(this.props.stageParams.url, "_blank"); }); (0, _defineProperty2.default)(this, "onRetryClick", () => { this.props.submitAuthDict({}); }); } render() { return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_compoundWeb.Text, null, (0, _languageHandler._t)("auth|uia|mas_cross_signing_reset_description")), /*#__PURE__*/_react.default.createElement(_Flex.Flex, { gap: "var(--cpd-space-4x)" }, /*#__PURE__*/_react.default.createElement(_compoundWeb.Button, { Icon: _popOut.default, onClick: this.onGoToAccountClick, autoFocus: true, kind: "primary", className: "mx_Dialog_nonDialogButton" }, (0, _languageHandler._t)("auth|uia|mas_cross_signing_reset_cta")), /*#__PURE__*/_react.default.createElement(_compoundWeb.Button, { onClick: this.onRetryClick, kind: "secondary", className: "mx_Dialog_nonDialogButton" }, (0, _languageHandler._t)("action|retry")))); } } exports.MasUnlockCrossSigningAuthEntry = MasUnlockCrossSigningAuthEntry; (0, _defineProperty2.default)(MasUnlockCrossSigningAuthEntry, "LOGIN_TYPE", CustomAuthType.MasCrossSigningReset); function getEntryComponentForLoginType(loginType) { switch (loginType) { case CustomAuthType.MasCrossSigningReset: return MasUnlockCrossSigningAuthEntry; case _interactiveAuth.AuthType.Password: return PasswordAuthEntry; case _interactiveAuth.AuthType.Recaptcha: return RecaptchaAuthEntry; case _interactiveAuth.AuthType.Email: return EmailIdentityAuthEntry; case _interactiveAuth.AuthType.Msisdn: return MsisdnAuthEntry; case _interactiveAuth.AuthType.Terms: return TermsAuthEntry; case _interactiveAuth.AuthType.RegistrationToken: case _interactiveAuth.AuthType.UnstableRegistrationToken: return RegistrationTokenAuthEntry; case _interactiveAuth.AuthType.Sso: case _interactiveAuth.AuthType.SsoUnstable: return SSOAuthEntry; default: return FallbackAuthEntry; } } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY2xhc3NuYW1lcyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiX2ludGVyYWN0aXZlQXV0aCIsIl9sb2dnZXIiLCJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsIl9jb21wb3VuZFdlYiIsIl9wb3BPdXQiLCJfZW1haWxQcm9tcHQiLCJfbGFuZ3VhZ2VIYW5kbGVyIiwiX1NldHRpbmdzU3RvcmUiLCJfQXV0aEhlYWRlck1vZGlmaWVyIiwiX0FjY2Vzc2libGVCdXR0b24iLCJfRmllbGQiLCJfU3Bpbm5lciIsIl9DYXB0Y2hhRm9ybSIsIl9GbGV4IiwiX2dldFJlcXVpcmVXaWxkY2FyZENhY2hlIiwiZSIsIldlYWtNYXAiLCJyIiwidCIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiaGFzIiwiZ2V0IiwibiIsIl9fcHJvdG9fXyIsImEiLCJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldE93blByb3BlcnR5RGVzY3JpcHRvciIsInUiLCJoYXNPd25Qcm9wZXJ0eSIsImNhbGwiLCJpIiwic2V0IiwiREVGQVVMVF9QSEFTRSIsImV4cG9ydHMiLCJQYXNzd29yZEF1dGhFbnRyeSIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJwcmV2ZW50RGVmYXVsdCIsImJ1c3kiLCJzdWJtaXRBdXRoRGljdCIsInR5cGUiLCJBdXRoVHlwZSIsIlBhc3N3b3JkIiwiaWRlbnRpZmllciIsInVzZXIiLCJtYXRyaXhDbGllbnQiLCJjcmVkZW50aWFscyIsInVzZXJJZCIsInBhc3N3b3JkIiwic3RhdGUiLCJldiIsInNldFN0YXRlIiwidGFyZ2V0IiwidmFsdWUiLCJjb21wb25lbnREaWRNb3VudCIsIm9uUGhhc2VDaGFuZ2UiLCJyZW5kZXIiLCJwYXNzd29yZEJveENsYXNzIiwiY2xhc3NOYW1lcyIsImVycm9yIiwiZXJyb3JUZXh0Iiwic3VibWl0QnV0dG9uT3JTcGlubmVyIiwiY3JlYXRlRWxlbWVudCIsImNsYXNzTmFtZSIsImRpc2FibGVkIiwiX3QiLCJlcnJvclNlY3Rpb24iLCJyb2xlIiwib25TdWJtaXQiLCJuYW1lIiwibGFiZWwiLCJhdXRvRm9jdXMiLCJvbkNoYW5nZSIsIm9uUGFzc3dvcmRGaWVsZENoYW5nZSIsIlJlY2FwdGNoYUF1dGhFbnRyeSIsImFyZ3MiLCJyZXNwb25zZSIsIlJlY2FwdGNoYSIsInNpdGVQdWJsaWNLZXkiLCJzdGFnZVBhcmFtcyIsInB1YmxpY19rZXkiLCJvbkNhcHRjaGFSZXNwb25zZSIsIlRlcm1zQXV0aEVudHJ5IiwiYWxsQ2hlY2tlZCIsInBvbGljeSIsInBvbGljaWVzIiwiY2hlY2tlZCIsInRvZ2dsZWRQb2xpY2llcyIsImlkIiwiVGVybXMiLCJhbGxQb2xpY2llcyIsInByZWZMYW5nIiwiU2V0dGluZ3NTdG9yZSIsImdldFZhbHVlIiwiaW5pdFRvZ2dsZXMiLCJwaWNrZWRQb2xpY2llcyIsInBvbGljeUlkIiwia2V5cyIsImxhbmdQb2xpY3kiLCJmaXJzdExhbmciLCJmaW5kIiwidW5kZWZpbmVkIiwiRXJyb3IiLCJwdXNoIiwidXJsIiwidG9nZ2xlUG9saWN5IiwibmV3VG9nZ2xlcyIsImNoZWNrYm94ZXMiLCJrZXkiLCJocmVmIiwicmVsIiwic3VibWl0QnV0dG9uIiwic2hvd0NvbnRpbnVlIiwia2luZCIsIm9uQ2xpY2siLCJ0cnlTdWJtaXQiLCJFbWFpbElkZW50aXR5QXV0aEVudHJ5IiwicmVxdWVzdGVkIiwicmVxdWVzdGluZyIsImVycm9yQ29kZSIsImlucHV0cyIsImVtYWlsQWRkcmVzcyIsInN0YWdlU3RhdGUiLCJlbWFpbFNpZCIsIkF1dGhIZWFkZXJNb2RpZmllciIsInRpdGxlIiwiaWNvbiIsInNyYyIsIkVtYWlsUHJvbXB0SWNvbiIsImFsdCIsIndpZHRoIiwiaGlkZVNlcnZlclBpY2tlciIsInRleHQiLCJGcmFnbWVudCIsInciLCJoIiwib25Ub29sdGlwT3BlbkNoYW5nZSIsIm9wZW4iLCJyZXF1ZXN0RW1haWxUb2tlbiIsImxvZ2dlciIsIndhcm4iLCJFbWFpbCIsIk1zaXNkbkF1dGhFbnRyeSIsInRva2VuIiwicmVzdWx0Iiwic3VibWl0VXJsIiwic2lkIiwic3VibWl0TXNpc2RuVG9rZW5PdGhlclVybCIsImNsaWVudFNlY3JldCIsInN1Y2Nlc3MiLCJjcmVkcyIsImNsaWVudF9zZWNyZXQiLCJNc2lzZG4iLCJ0aHJlZXBpZF9jcmVkcyIsImZhaWwiLCJsb2ciLCJyZXF1ZXN0aW5nVG9rZW4iLCJyZXF1ZXN0TXNpc2RuVG9rZW4iLCJjYXRjaCIsImZpbmFsbHkiLCJyZXF1ZXN0UmVnaXN0ZXJNc2lzZG5Ub2tlbiIsInBob25lQ291bnRyeSIsInBob25lTnVtYmVyIiwidGhlbiIsInN1Ym1pdF91cmwiLCJtc2lzZG4iLCJlbmFibGVTdWJtaXQiLCJCb29sZWFuIiwic3VibWl0Q2xhc3NlcyIsIm14X0ludGVyYWN0aXZlQXV0aEVudHJ5Q29tcG9uZW50c19tc2lzZG5TdWJtaXQiLCJteF9HZW5lcmFsQnV0dG9uIiwib25Gb3JtU3VibWl0Iiwib25Ub2tlbkNoYW5nZSIsIlJlZ2lzdHJhdGlvblRva2VuQXV0aEVudHJ5IiwibG9naW5UeXBlIiwicmVnaXN0cmF0aW9uVG9rZW4iLCJyZWdpc3RyYXRpb25Ub2tlbkJveENsYXNzIiwib25SZWdpc3RyYXRpb25Ub2tlbkZpZWxkQ2hhbmdlIiwiUmVnaXN0cmF0aW9uVG9rZW4iLCJTU09BdXRoRW50cnkiLCJhdHRlbXB0RmFpbGVkIiwiZXZlbnQiLCJkYXRhIiwic291cmNlIiwicG9wdXBXaW5kb3ciLCJjbG9zZSIsIndpbmRvdyIsInNzb1VybCIsInBoYXNlIiwiUEhBU0VfUE9TVEFVVEgiLCJhdXRoU2Vzc2lvbklkIiwiZ2V0RmFsbGJhY2tBdXRoVXJsIiwiYWRkRXZlbnRMaXN0ZW5lciIsIm9uUmVjZWl2ZU1lc3NhZ2UiLCJQSEFTRV9QUkVBVVRIIiwiY29tcG9uZW50V2lsbFVubW91bnQiLCJyZW1vdmVFdmVudExpc3RlbmVyIiwiY29udGludWVCdXR0b24iLCJjYW5jZWxCdXR0b24iLCJvbkNhbmNlbCIsImNvbnRpbnVlS2luZCIsIm9uU3RhcnRBdXRoQ2xpY2siLCJjb250aW51ZVRleHQiLCJvbkNvbmZpcm1DbGljayIsIlNzbyIsIlNzb1Vuc3RhYmxlIiwiRmFsbGJhY2tBdXRoRW50cnkiLCJjcmVhdGVSZWYiLCJmYWxsYmFja0J1dHRvbiIsImN1cnJlbnQiLCJmb2N1cyIsInN0b3BQcm9wYWdhdGlvbiIsInJlZiIsIm9uU2hvd0ZhbGxiYWNrQ2xpY2siLCJDdXN0b21BdXRoVHlwZSIsIk1hc1VubG9ja0Nyb3NzU2lnbmluZ0F1dGhFbnRyeSIsIlRleHQiLCJGbGV4IiwiZ2FwIiwiQnV0dG9uIiwiSWNvbiIsIlBvcE91dEljb24iLCJvbkdvVG9BY2NvdW50Q2xpY2siLCJvblJldHJ5Q2xpY2siLCJNYXNDcm9zc1NpZ25pbmdSZXNldCIsImdldEVudHJ5Q29tcG9uZW50Rm9yTG9naW5UeXBlIiwiVW5zdGFibGVSZWdpc3RyYXRpb25Ub2tlbiJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL2F1dGgvSW50ZXJhY3RpdmVBdXRoRW50cnlDb21wb25lbnRzLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAxNi0yMDIxIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5cblNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBR1BMLTMuMC1vbmx5IE9SIEdQTC0zLjAtb25seVxuUGxlYXNlIHNlZSBMSUNFTlNFIGZpbGVzIGluIHRoZSByZXBvc2l0b3J5IHJvb3QgZm9yIGZ1bGwgZGV0YWlscy5cbiovXG5cbmltcG9ydCBjbGFzc05hbWVzIGZyb20gXCJjbGFzc25hbWVzXCI7XG5pbXBvcnQgeyBNYXRyaXhDbGllbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5pbXBvcnQgeyBBdXRoVHlwZSwgQXV0aERpY3QsIElJbnB1dHMsIElTdGFnZVN0YXR1cyB9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9pbnRlcmFjdGl2ZS1hdXRoXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5pbXBvcnQgUmVhY3QsIHsgQ2hhbmdlRXZlbnQsIGNyZWF0ZVJlZiwgRm9ybUV2ZW50LCBGcmFnbWVudCB9IGZyb20gXCJyZWFjdFwiO1xuaW1wb3J0IHsgQnV0dG9uLCBUZXh0IH0gZnJvbSBcIkB2ZWN0b3ItaW0vY29tcG91bmQtd2ViXCI7XG5pbXBvcnQgUG9wT3V0SWNvbiBmcm9tIFwiQHZlY3Rvci1pbS9jb21wb3VuZC1kZXNpZ24tdG9rZW5zL2Fzc2V0cy93ZWIvaWNvbnMvcG9wLW91dFwiO1xuXG5pbXBvcnQgRW1haWxQcm9tcHRJY29uIGZyb20gXCIuLi8uLi8uLi8uLi9yZXMvaW1nL2VsZW1lbnQtaWNvbnMvZW1haWwtcHJvbXB0LnN2Z1wiO1xuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vLi4vLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IHsgTG9jYWxpc2VkUG9saWN5LCBQb2xpY2llcyB9IGZyb20gXCIuLi8uLi8uLi9UZXJtc1wiO1xuaW1wb3J0IHsgQXV0aEhlYWRlck1vZGlmaWVyIH0gZnJvbSBcIi4uLy4uL3N0cnVjdHVyZXMvYXV0aC9oZWFkZXIvQXV0aEhlYWRlck1vZGlmaWVyXCI7XG5pbXBvcnQgQWNjZXNzaWJsZUJ1dHRvbiwgeyBBY2Nlc3NpYmxlQnV0dG9uS2luZCwgQnV0dG9uRXZlbnQgfSBmcm9tIFwiLi4vZWxlbWVudHMvQWNjZXNzaWJsZUJ1dHRvblwiO1xuaW1wb3J0IEZpZWxkIGZyb20gXCIuLi9lbGVtZW50cy9GaWVsZFwiO1xuaW1wb3J0IFNwaW5uZXIgZnJvbSBcIi4uL2VsZW1lbnRzL1NwaW5uZXJcIjtcbmltcG9ydCBDYXB0Y2hhRm9ybSBmcm9tIFwiLi9DYXB0Y2hhRm9ybVwiO1xuaW1wb3J0IHsgRmxleCB9IGZyb20gXCIuLi8uLi91dGlscy9GbGV4XCI7XG5cbi8qIFRoaXMgZmlsZSBjb250YWlucyBhIGNvbGxlY3Rpb24gb2YgY29tcG9uZW50cyB3aGljaCBhcmUgdXNlZCBieSB0aGVcbiAqIEludGVyYWN0aXZlQXV0aCB0byBwcm9tcHQgdGhlIHVzZXIgdG8gZW50ZXIgdGhlIGluZm9ybWF0aW9uIG5lZWRlZFxuICogZm9yIGFuIGF1dGggc3RhZ2UuIChUaGUgaW50ZW50aW9uIGlzIHRoYXQgdGhleSBjb3VsZCBhbHNvIGJlIHVzZWQgZm9yIG90aGVyXG4gKiBjb21wb25lbnRzLCBzdWNoIGFzIHRoZSByZWdpc3RyYXRpb24gZmxvdykuXG4gKlxuICogQ2FsbCBnZXRFbnRyeUNvbXBvbmVudEZvckxvZ2luVHlwZSgpIHRvIGdldCBhIGNvbXBvbmVudCBzdWl0YWJsZSBmb3IgYVxuICogcGFydGljdWxhciBsb2dpbiB0eXBlLiBFYWNoIGNvbXBvbmVudCByZXF1aXJlcyB0aGUgc2FtZSBwcm9wZXJ0aWVzOlxuICpcbiAqIG1hdHJpeENsaWVudDogICAgICAgICAgIEEgbWF0cml4IGNsaWVudC4gTWF5IGJlIGEgZGlmZmVyZW50IG9uZSB0byB0aGUgb25lXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50bHkgYmVpbmcgdXNlZCBnZW5lcmFsbHkgKGVnLiB0byByZWdpc3RlciB3aXRoXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICBvbmUgSFMgd2hpbHN0IGJlaW5nIGEgZ3Vlc3Qgb24gYW5vdGhlcikuXG4gKiBsb2dpblR5cGU6ICAgICAgICAgICAgICB0aGUgbG9naW4gdHlwZSBvZiB0aGUgYXV0aCBzdGFnZSBiZWluZyBhdHRlbXB0ZWRcbiAqIGF1dGhTZXNzaW9uSWQ6ICAgICAgICAgIHNlc3Npb24gaWQgZnJvbSB0aGUgc2VydmVyXG4gKiBjbGllbnRTZWNyZXQ6ICAgICAgICAgICBUaGUgY2xpZW50IHNlY3JldCBpbiB1c2UgZm9yIGlkZW50aXR5IHNlcnZlciBhdXRoIHNlc3Npb25zXG4gKiBzdGFnZVBhcmFtczogICAgICAgICAgICBwYXJhbXMgZnJvbSB0aGUgc2VydmVyIGZvciB0aGUgc3RhZ2UgYmVpbmcgYXR0ZW1wdGVkXG4gKiBlcnJvclRleHQ6ICAgICAgICAgICAgICBlcnJvciBtZXNzYWdlIGZyb20gYSBwcmV2aW91cyBhdHRlbXB0IHRvIGF1dGhlbnRpY2F0ZVxuICogc3VibWl0QXV0aERpY3Q6ICAgICAgICAgYSBmdW5jdGlvbiB3aGljaCB3aWxsIGJlIGNhbGxlZCB3aXRoIHRoZSBuZXcgYXV0aCBkaWN0XG4gKiBidXN5OiAgICAgICAgICAgICAgICAgICBhIGJvb2xlYW4gaW5kaWNhdGluZyB3aGV0aGVyIHRoZSBhdXRoIGxvZ2ljIGlzIGRvaW5nIHNvbWV0aGluZ1xuICogICAgICAgICAgICAgICAgICAgICAgICAgdGhlIHVzZXIgbmVlZHMgdG8gd2FpdCBmb3IuXG4gKiBpbnB1dHM6ICAgICAgICAgICAgICAgICBPYmplY3Qgb2YgaW5wdXRzIHByb3ZpZGVkIGJ5IHRoZSB1c2VyLCBhcyBpbiBqcy1zZGtcbiAqICAgICAgICAgICAgICAgICAgICAgICAgIGludGVyYWN0aXZlLWF1dGhcbiAqIHN0YWdlU3RhdGU6ICAgICAgICAgICAgIFN0YWdlLXNwZWNpZmljIG9iamVjdCB1c2VkIGZvciBjb21tdW5pY2F0aW5nIHN0YXRlIGluZm9ybWF0aW9uXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICB0byB0aGUgVUkgZnJvbSB0aGUgc3RhdGUtc3BlY2lmaWMgYXV0aCBsb2dpYy5cbiAqICAgICAgICAgICAgICAgICAgICAgICAgIERlZmluZWQga2V5cyBmb3Igc3RhZ2VzIGFyZTpcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtLmxvZ2luLmVtYWlsLmlkZW50aXR5OlxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIGVtYWlsU2lkOiBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBzaWQgb2YgdGhlIGFjdGl2ZVxuICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJpZmljYXRpb24gc2Vzc2lvbiBmcm9tIHRoZSBpZGVudGl0eSBzZXJ2ZXIsXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yIG51bGwgaWYgbm8gc2Vzc2lvbiBpcyBhY3RpdmUuXG4gKiBmYWlsOiAgICAgICAgICAgICAgICAgICBhIGZ1bmN0aW9uIHdoaWNoIHNob3VsZCBiZSBjYWxsZWQgd2l0aCBhbiBlcnJvciBvYmplY3QgaWYgYW5cbiAqICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yIG9jY3VycmVkIGR1cmluZyB0aGUgYXV0aCBzdGFnZS4gVGhpcyB3aWxsIGNhdXNlIHRoZSBhdXRoXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICBzZXNzaW9uIHRvIGJlIGZhaWxlZCBhbmQgdGhlIHByb2Nlc3MgdG8gZ28gYmFjayB0byB0aGUgc3RhcnQuXG4gKiBzZXRFbWFpbFNpZDogICAgICAgICAgICBtLmxvZ2luLmVtYWlsLmlkZW50aXR5IG9ubHk6IGEgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdpdGggdGhlXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICBlbWFpbCBzaWQgYWZ0ZXIgYSB0b2tlbiBpcyByZXF1ZXN0ZWQuXG4gKiBvblBoYXNlQ2hhbmdlOiAgICAgICAgICBBIGZ1bmN0aW9uIHdoaWNoIGlzIGNhbGxlZCB3aGVuIHRoZSBzdGFnZSdzIHBoYXNlIGNoYW5nZXMuIElmXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgc3RhZ2UgaGFzIG5vIHBoYXNlcywgY2FsbCB0aGlzIHdpdGggREVGQVVMVF9QSEFTRS4gVGFrZXNcbiAqICAgICAgICAgICAgICAgICAgICAgICAgIG9uZSBhcmd1bWVudCwgdGhlIHBoYXNlLCBhbmQgaXMgYWx3YXlzIGRlZmluZWQvcmVxdWlyZWQuXG4gKiBjb250aW51ZVRleHQ6ICAgICAgICAgICBGb3Igc3RhZ2VzIHdoaWNoIGhhdmUgYSBjb250aW51ZSBidXR0b24sIHRoZSB0ZXh0IHRvIHVzZS5cbiAqIGNvbnRpbnVlS2luZDogICAgICAgICAgIEZvciBzdGFnZXMgd2hpY2ggaGF2ZSBhIGNvbnRpbnVlIGJ1dHRvbiwgdGhlIHN0eWxlIG9mIGJ1dHRvbiB0b1xuICogICAgICAgICAgICAgICAgICAgICAgICAgdXNlLiBGb3IgZXhhbXBsZSwgJ2Rhbmdlcicgb3IgJ3ByaW1hcnknLlxuICogb25DYW5jZWwgICAgICAgICAgICAgICAgQSBmdW5jdGlvbiB3aXRoIG5vIGFyZ3VtZW50cyB3aGljaCBpcyBjYWxsZWQgYnkgdGhlIHN0YWdlIGlmIHRoZVxuICogICAgICAgICAgICAgICAgICAgICAgICAgdXNlciBrbm93aW5nbHkgY2FuY2VsbGVkL2Rpc21pc3NlZCB0aGUgYXV0aGVudGljYXRpb24gYXR0ZW1wdC5cbiAqXG4gKiBFYWNoIGNvbXBvbmVudCBtYXkgYWxzbyBwcm92aWRlIHRoZSBmb2xsb3dpbmcgZnVuY3Rpb25zIChiZXlvbmQgdGhlIHN0YW5kYXJkIFJlYWN0IG9uZXMpOlxuICogICAgZm9jdXM6IHNldCB0aGUgaW5wdXQgZm9jdXMgYXBwcm9wcmlhdGVseSBpbiB0aGUgZm9ybS5cbiAqL1xuXG5leHBvcnQgY29uc3QgREVGQVVMVF9QSEFTRSA9IDA7XG5cbmludGVyZmFjZSBJQXV0aEVudHJ5UHJvcHMge1xuICAgIG1hdHJpeENsaWVudDogTWF0cml4Q2xpZW50O1xuICAgIGxvZ2luVHlwZTogc3RyaW5nO1xuICAgIGF1dGhTZXNzaW9uSWQ/OiBzdHJpbmc7XG4gICAgZXJyb3JUZXh0Pzogc3RyaW5nO1xuICAgIGVycm9yQ29kZT86IHN0cmluZztcbiAgICAvLyBJcyB0aGUgYXV0aCBsb2dpYyBjdXJyZW50bHkgd2FpdGluZyBmb3Igc29tZXRoaW5nIHRvIGhhcHBlbj9cbiAgICBidXN5PzogYm9vbGVhbjtcbiAgICBvblBoYXNlQ2hhbmdlOiAocGhhc2U6IG51bWJlcikgPT4gdm9pZDtcbiAgICBzdWJtaXRBdXRoRGljdDogKGF1dGg6IEF1dGhEaWN0KSA9PiB2b2lkO1xuICAgIHJlcXVlc3RFbWFpbFRva2VuPzogKCkgPT4gUHJvbWlzZTx2b2lkPjtcbiAgICBmYWlsOiAoZXJyb3I6IEVycm9yKSA9PiB2b2lkO1xuICAgIGNsaWVudFNlY3JldDogc3RyaW5nO1xuICAgIHNob3dDb250aW51ZTogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIElQYXNzd29yZEF1dGhFbnRyeVN0YXRlIHtcbiAgICBwYXNzd29yZDogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgUGFzc3dvcmRBdXRoRW50cnkgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SUF1dGhFbnRyeVByb3BzLCBJUGFzc3dvcmRBdXRoRW50cnlTdGF0ZT4ge1xuICAgIHB1YmxpYyBzdGF0aWMgTE9HSU5fVFlQRSA9IEF1dGhUeXBlLlBhc3N3b3JkO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByb3BzOiBJQXV0aEVudHJ5UHJvcHMpIHtcbiAgICAgICAgc3VwZXIocHJvcHMpO1xuXG4gICAgICAgIHRoaXMuc3RhdGUgPSB7XG4gICAgICAgICAgICBwYXNzd29yZDogXCJcIixcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY29tcG9uZW50RGlkTW91bnQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucHJvcHMub25QaGFzZUNoYW5nZShERUZBVUxUX1BIQVNFKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIG9uU3VibWl0ID0gKGU6IEZvcm1FdmVudCk6IHZvaWQgPT4ge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGlmICh0aGlzLnByb3BzLmJ1c3kpIHJldHVybjtcblxuICAgICAgICB0aGlzLnByb3BzLnN1Ym1pdEF1dGhEaWN0KHtcbiAgICAgICAgICAgIHR5cGU6IEF1dGhUeXBlLlBhc3N3b3JkLFxuICAgICAgICAgICAgaWRlbnRpZmllcjoge1xuICAgICAgICAgICAgICAgIHR5cGU6IFwibS5pZC51c2VyXCIsXG4gICAgICAgICAgICAgICAgdXNlcjogdGhpcy5wcm9wcy5tYXRyaXhDbGllbnQuY3JlZGVudGlhbHMudXNlcklkLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHBhc3N3b3JkOiB0aGlzLnN0YXRlLnBhc3N3b3JkLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvblBhc3N3b3JkRmllbGRDaGFuZ2UgPSAoZXY6IENoYW5nZUV2ZW50PEhUTUxJbnB1dEVsZW1lbnQ+KTogdm9pZCA9PiB7XG4gICAgICAgIC8vIGVuYWJsZSB0aGUgc3VibWl0IGJ1dHRvbiBpZmYgdGhlIHBhc3N3b3JkIGlzIG5vbi1lbXB0eVxuICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgIHBhc3N3b3JkOiBldi50YXJnZXQudmFsdWUsXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBwdWJsaWMgcmVuZGVyKCk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gICAgICAgIGNvbnN0IHBhc3N3b3JkQm94Q2xhc3MgPSBjbGFzc05hbWVzKHtcbiAgICAgICAgICAgIGVycm9yOiB0aGlzLnByb3BzLmVycm9yVGV4dCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgbGV0IHN1Ym1pdEJ1dHRvbk9yU3Bpbm5lcjtcbiAgICAgICAgaWYgKHRoaXMucHJvcHMuYnVzeSkge1xuICAgICAgICAgICAgc3VibWl0QnV0dG9uT3JTcGlubmVyID0gPFNwaW5uZXIgLz47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdWJtaXRCdXR0b25PclNwaW5uZXIgPSAoXG4gICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIHR5cGU9XCJzdWJtaXRcIlxuICAgICAgICAgICAgICAgICAgICBjbGFzc05hbWU9XCJteF9EaWFsb2dfcHJpbWFyeVwiXG4gICAgICAgICAgICAgICAgICAgIGRpc2FibGVkPXshdGhpcy5zdGF0ZS5wYXNzd29yZH1cbiAgICAgICAgICAgICAgICAgICAgdmFsdWU9e190KFwiYWN0aW9ufGNvbnRpbnVlXCIpfVxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGVycm9yU2VjdGlvbjtcbiAgICAgICAgaWYgKHRoaXMucHJvcHMuZXJyb3JUZXh0KSB7XG4gICAgICAgICAgICBlcnJvclNlY3Rpb24gPSAoXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJlcnJvclwiIHJvbGU9XCJhbGVydFwiPlxuICAgICAgICAgICAgICAgICAgICB7dGhpcy5wcm9wcy5lcnJvclRleHR9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgPHA+e190KFwiYXV0aHx1aWF8cGFzc3dvcmRfcHJvbXB0XCIpfTwvcD5cbiAgICAgICAgICAgICAgICA8Zm9ybSBvblN1Ym1pdD17dGhpcy5vblN1Ym1pdH0gY2xhc3NOYW1lPVwibXhfSW50ZXJhY3RpdmVBdXRoRW50cnlDb21wb25lbnRzX3Bhc3N3b3JkU2VjdGlvblwiPlxuICAgICAgICAgICAgICAgICAgICA8RmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT17cGFzc3dvcmRCb3hDbGFzc31cbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJwYXNzd29yZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBuYW1lPVwicGFzc3dvcmRGaWVsZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBsYWJlbD17X3QoXCJjb21tb258cGFzc3dvcmRcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICBhdXRvRm9jdXM9e3RydWV9XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZT17dGhpcy5zdGF0ZS5wYXNzd29yZH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uQ2hhbmdlPXt0aGlzLm9uUGFzc3dvcmRGaWVsZENoYW5nZX1cbiAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAge2Vycm9yU2VjdGlvbn1cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9idXR0b25fcm93XCI+e3N1Ym1pdEJ1dHRvbk9yU3Bpbm5lcn08L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Zvcm0+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcbiAgICB9XG59XG5cbi8qIGVzbGludC1kaXNhYmxlIGNhbWVsY2FzZSAqL1xuaW50ZXJmYWNlIElSZWNhcHRjaGFBdXRoRW50cnlQcm9wcyBleHRlbmRzIElBdXRoRW50cnlQcm9wcyB7XG4gICAgc3RhZ2VQYXJhbXM/OiB7XG4gICAgICAgIHB1YmxpY19rZXk/OiBzdHJpbmc7XG4gICAgfTtcbn1cbi8qIGVzbGludC1lbmFibGUgY2FtZWxjYXNlICovXG5cbmV4cG9ydCBjbGFzcyBSZWNhcHRjaGFBdXRoRW50cnkgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SVJlY2FwdGNoYUF1dGhFbnRyeVByb3BzPiB7XG4gICAgcHVibGljIHN0YXRpYyBMT0dJTl9UWVBFID0gQXV0aFR5cGUuUmVjYXB0Y2hhO1xuXG4gICAgcHVibGljIGNvbXBvbmVudERpZE1vdW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnByb3BzLm9uUGhhc2VDaGFuZ2UoREVGQVVMVF9QSEFTRSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBvbkNhcHRjaGFSZXNwb25zZSA9IChyZXNwb25zZTogc3RyaW5nKTogdm9pZCA9PiB7XG4gICAgICAgIHRoaXMucHJvcHMuc3VibWl0QXV0aERpY3Qoe1xuICAgICAgICAgICAgdHlwZTogQXV0aFR5cGUuUmVjYXB0Y2hhLFxuICAgICAgICAgICAgcmVzcG9uc2U6I