matrix-react-sdk
Version:
SDK for matrix.org using React
799 lines (785 loc) • 124 kB
JavaScript
"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