UNPKG

matrix-react-sdk

Version:
763 lines (758 loc) 130 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 _react = _interopRequireWildcard(require("react")); var _fileSaver = _interopRequireDefault(require("file-saver")); var _logger = require("matrix-js-sdk/src/logger"); var _matrix = require("matrix-js-sdk/src/matrix"); var _crypto = require("matrix-js-sdk/src/crypto"); var _classnames = _interopRequireDefault(require("classnames")); var _check = _interopRequireDefault(require("@vector-im/compound-design-tokens/assets/web/icons/check")); var _MatrixClientPeg = require("../../../../MatrixClientPeg"); var _languageHandler = require("../../../../languageHandler"); var _Modal = _interopRequireDefault(require("../../../../Modal")); var _strings = require("../../../../utils/strings"); var _InteractiveAuthEntryComponents = require("../../../../components/views/auth/InteractiveAuthEntryComponents"); var _PassphraseField = _interopRequireDefault(require("../../../../components/views/auth/PassphraseField")); var _StyledRadioButton = _interopRequireDefault(require("../../../../components/views/elements/StyledRadioButton")); var _AccessibleButton = _interopRequireDefault(require("../../../../components/views/elements/AccessibleButton")); var _DialogButtons = _interopRequireDefault(require("../../../../components/views/elements/DialogButtons")); var _InlineSpinner = _interopRequireDefault(require("../../../../components/views/elements/InlineSpinner")); var _RestoreKeyBackupDialog = _interopRequireDefault(require("../../../../components/views/dialogs/security/RestoreKeyBackupDialog")); var _WellKnownUtils = require("../../../../utils/WellKnownUtils"); var _ModuleRunner = require("../../../../modules/ModuleRunner"); var _Field = _interopRequireDefault(require("../../../../components/views/elements/Field")); var _BaseDialog = _interopRequireDefault(require("../../../../components/views/dialogs/BaseDialog")); var _Spinner = _interopRequireDefault(require("../../../../components/views/elements/Spinner")); var _InteractiveAuthDialog = _interopRequireDefault(require("../../../../components/views/dialogs/InteractiveAuthDialog")); var _PassphraseConfirmField = _interopRequireDefault(require("../../../../components/views/auth/PassphraseConfirmField")); var _dehydration = require("../../../../utils/device/dehydration"); 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 2019, 2020 , 2023 The Matrix.org Foundation C.I.C. Copyright 2018, 2019 New Vector Ltd SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only Please see LICENSE files in the repository root for full details. */ // I made a mistake while converting this and it has to be fixed! var Phase = /*#__PURE__*/function (Phase) { Phase["Loading"] = "loading"; Phase["LoadError"] = "load_error"; Phase["ChooseKeyPassphrase"] = "choose_key_passphrase"; Phase["Migrate"] = "migrate"; Phase["Passphrase"] = "passphrase"; Phase["PassphraseConfirm"] = "passphrase_confirm"; Phase["ShowKey"] = "show_key"; Phase["Storing"] = "storing"; Phase["Stored"] = "stored"; Phase["ConfirmSkip"] = "confirm_skip"; return Phase; }(Phase || {}); const PASSWORD_MIN_SCORE = 4; // So secure, many characters, much complex, wow, etc, etc. /** * Walks the user through the process of creating a 4S passphrase and bootstrapping secret storage. * * If the user already has a key backup, follows a "migration" flow (aka "Upgrade your encryption") which * prompts the user to enter their backup decryption password (a Curve25519 private key, possibly derived * from a passphrase), and uses that as the (AES) 4S encryption key. */ class CreateSecretStorageDialog extends _react.default.PureComponent { constructor(props) { super(props); (0, _defineProperty2.default)(this, "recoveryKey", void 0); (0, _defineProperty2.default)(this, "recoveryKeyNode", /*#__PURE__*/(0, _react.createRef)()); (0, _defineProperty2.default)(this, "passphraseField", /*#__PURE__*/(0, _react.createRef)()); (0, _defineProperty2.default)(this, "onKeyBackupStatusChange", () => { if (this.state.phase === Phase.Migrate) this.fetchBackupInfo(); }); (0, _defineProperty2.default)(this, "onKeyPassphraseChange", e => { this.setState({ passPhraseKeySelected: e.target.value }); }); (0, _defineProperty2.default)(this, "onChooseKeyPassphraseFormSubmit", async () => { if (this.state.passPhraseKeySelected === _WellKnownUtils.SecureBackupSetupMethod.Key) { this.recoveryKey = await _MatrixClientPeg.MatrixClientPeg.safeGet().getCrypto().createRecoveryKeyFromPassphrase(); this.setState({ copied: false, downloaded: false, setPassphrase: false, phase: Phase.ShowKey }); } else { this.setState({ copied: false, downloaded: false, phase: Phase.Passphrase }); } }); (0, _defineProperty2.default)(this, "onMigrateFormSubmit", e => { e.preventDefault(); if (this.state.backupTrustInfo?.trusted) { this.bootstrapSecretStorage(); } else { this.restoreBackup(); } }); (0, _defineProperty2.default)(this, "onCopyClick", () => { const successful = (0, _strings.copyNode)(this.recoveryKeyNode.current); if (successful) { this.setState({ copied: true }); } }); (0, _defineProperty2.default)(this, "onDownloadClick", () => { if (!this.recoveryKey) return; const blob = new Blob([this.recoveryKey.encodedPrivateKey], { type: "text/plain;charset=us-ascii" }); _fileSaver.default.saveAs(blob, "security-key.txt"); this.setState({ downloaded: true }); }); (0, _defineProperty2.default)(this, "doBootstrapUIAuth", async makeRequest => { if (this.state.canUploadKeysWithPasswordOnly && this.state.accountPassword) { await makeRequest({ type: "m.login.password", identifier: { type: "m.id.user", user: _MatrixClientPeg.MatrixClientPeg.safeGet().getSafeUserId() }, password: this.state.accountPassword }); } else { const dialogAesthetics = { [_InteractiveAuthEntryComponents.SSOAuthEntry.PHASE_PREAUTH]: { title: (0, _languageHandler._t)("auth|uia|sso_title"), body: (0, _languageHandler._t)("auth|uia|sso_preauth_body"), continueText: (0, _languageHandler._t)("auth|sso"), continueKind: "primary" }, [_InteractiveAuthEntryComponents.SSOAuthEntry.PHASE_POSTAUTH]: { title: (0, _languageHandler._t)("encryption|confirm_encryption_setup_title"), body: (0, _languageHandler._t)("encryption|confirm_encryption_setup_body"), continueText: (0, _languageHandler._t)("action|confirm"), continueKind: "primary" } }; const { finished } = _Modal.default.createDialog(_InteractiveAuthDialog.default, { title: (0, _languageHandler._t)("encryption|bootstrap_title"), matrixClient: _MatrixClientPeg.MatrixClientPeg.safeGet(), makeRequest, aestheticsForStagePhases: { [_InteractiveAuthEntryComponents.SSOAuthEntry.LOGIN_TYPE]: dialogAesthetics, [_InteractiveAuthEntryComponents.SSOAuthEntry.UNSTABLE_LOGIN_TYPE]: dialogAesthetics } }); const [confirmed] = await finished; if (!confirmed) { throw new Error("Cross-signing key upload auth canceled"); } } }); (0, _defineProperty2.default)(this, "bootstrapSecretStorage", async () => { this.setState({ phase: Phase.Storing, error: undefined }); const cli = _MatrixClientPeg.MatrixClientPeg.safeGet(); const crypto = cli.getCrypto(); const { forceReset } = this.props; try { if (forceReset) { _logger.logger.log("Forcing secret storage reset"); await crypto.bootstrapSecretStorage({ createSecretStorageKey: async () => this.recoveryKey, setupNewKeyBackup: true, setupNewSecretStorage: true }); } else { // For password authentication users after 2020-09, this cross-signing // step will be a no-op since it is now setup during registration or login // when needed. We should keep this here to cover other cases such as: // * Users with existing sessions prior to 2020-09 changes // * SSO authentication users which require interactive auth to upload // keys (and also happen to skip all post-authentication flows at the // moment via token login) await crypto.bootstrapCrossSigning({ authUploadDeviceSigningKeys: this.doBootstrapUIAuth }); await crypto.bootstrapSecretStorage({ createSecretStorageKey: async () => this.recoveryKey, keyBackupInfo: this.state.backupInfo, setupNewKeyBackup: !this.state.backupInfo }); } await (0, _dehydration.initialiseDehydration)(true); this.setState({ phase: Phase.Stored }); } catch (e) { if (this.state.canUploadKeysWithPasswordOnly && e instanceof _matrix.MatrixError && e.httpStatus === 401 && e.data.flows) { this.setState({ accountPassword: "", accountPasswordCorrect: false, phase: Phase.Migrate }); } else { this.setState({ error: true }); } _logger.logger.error("Error bootstrapping secret storage", e); } }); (0, _defineProperty2.default)(this, "onCancel", () => { this.props.onFinished(false); }); (0, _defineProperty2.default)(this, "restoreBackup", async () => { const keyCallback = k => {}; const { finished } = _Modal.default.createDialog(_RestoreKeyBackupDialog.default, { showSummary: false, keyCallback }, undefined, /* priority = */false, /* static = */false); await finished; const backupTrustInfo = await this.fetchBackupInfo(); if (backupTrustInfo?.trusted && this.state.canUploadKeysWithPasswordOnly && this.state.accountPassword) { this.bootstrapSecretStorage(); } }); (0, _defineProperty2.default)(this, "onLoadRetryClick", () => { this.setState({ phase: Phase.Loading }); this.fetchBackupInfo(); }); (0, _defineProperty2.default)(this, "onShowKeyContinueClick", () => { this.bootstrapSecretStorage(); }); (0, _defineProperty2.default)(this, "onCancelClick", () => { this.setState({ phase: Phase.ConfirmSkip }); }); (0, _defineProperty2.default)(this, "onGoBackClick", () => { this.setState({ phase: Phase.ChooseKeyPassphrase }); }); (0, _defineProperty2.default)(this, "onPassPhraseNextClick", async e => { e.preventDefault(); if (!this.passphraseField.current) return; // unmounting await this.passphraseField.current.validate({ allowEmpty: false }); if (!this.passphraseField.current.state.valid) { this.passphraseField.current.focus(); this.passphraseField.current.validate({ allowEmpty: false, focused: true }); return; } this.setState({ phase: Phase.PassphraseConfirm }); }); (0, _defineProperty2.default)(this, "onPassPhraseConfirmNextClick", async e => { e.preventDefault(); if (this.state.passPhrase !== this.state.passPhraseConfirm) return; this.recoveryKey = await _MatrixClientPeg.MatrixClientPeg.safeGet().getCrypto().createRecoveryKeyFromPassphrase(this.state.passPhrase); this.setState({ copied: false, downloaded: false, setPassphrase: true, phase: Phase.ShowKey }); }); (0, _defineProperty2.default)(this, "onSetAgainClick", () => { this.setState({ passPhrase: "", passPhraseValid: false, passPhraseConfirm: "", phase: Phase.Passphrase }); }); (0, _defineProperty2.default)(this, "onPassPhraseValidate", result => { this.setState({ passPhraseValid: !!result.valid }); }); (0, _defineProperty2.default)(this, "onPassPhraseChange", e => { this.setState({ passPhrase: e.target.value }); }); (0, _defineProperty2.default)(this, "onPassPhraseConfirmChange", e => { this.setState({ passPhraseConfirm: e.target.value }); }); (0, _defineProperty2.default)(this, "onAccountPasswordChange", e => { this.setState({ accountPassword: e.target.value }); }); const _cli = _MatrixClientPeg.MatrixClientPeg.safeGet(); let passPhraseKeySelected; const setupMethods = (0, _WellKnownUtils.getSecureBackupSetupMethods)(_cli); if (setupMethods.includes(_WellKnownUtils.SecureBackupSetupMethod.Key)) { passPhraseKeySelected = _WellKnownUtils.SecureBackupSetupMethod.Key; } else { passPhraseKeySelected = _WellKnownUtils.SecureBackupSetupMethod.Passphrase; } const accountPassword = props.accountPassword || ""; let canUploadKeysWithPasswordOnly = null; if (accountPassword) { // If we have an account password in memory, let's simplify and // assume it means password auth is also supported for device // signing key upload as well. This avoids hitting the server to // test auth flows, which may be slow under high load. canUploadKeysWithPasswordOnly = true; } else { this.queryKeyUploadAuth(); } this.state = { phase: Phase.Loading, passPhrase: "", passPhraseValid: false, passPhraseConfirm: "", copied: false, downloaded: false, setPassphrase: false, backupInfo: null, backupTrustInfo: undefined, // does the server offer a UI auth flow with just m.login.password // for /keys/device_signing/upload? accountPasswordCorrect: null, canSkip: !(0, _WellKnownUtils.isSecureBackupRequired)(_cli), canUploadKeysWithPasswordOnly, passPhraseKeySelected, accountPassword }; _cli.on(_crypto.CryptoEvent.KeyBackupStatus, this.onKeyBackupStatusChange); this.getInitialPhase(); } componentWillUnmount() { _MatrixClientPeg.MatrixClientPeg.get()?.removeListener(_crypto.CryptoEvent.KeyBackupStatus, this.onKeyBackupStatusChange); } getInitialPhase() { const keyFromCustomisations = _ModuleRunner.ModuleRunner.instance.extensions.cryptoSetup.createSecretStorageKey(); if (keyFromCustomisations) { _logger.logger.log("CryptoSetupExtension: Created key via extension, jumping to bootstrap step"); this.recoveryKey = { privateKey: keyFromCustomisations }; this.bootstrapSecretStorage(); return; } this.fetchBackupInfo(); } /** * Attempt to get information on the current backup from the server, and update the state. * * Updates {@link IState.backupInfo} and {@link IState.backupTrustInfo}, and picks an appropriate phase for * {@link IState.phase}. * * @returns If the backup data was retrieved successfully, the trust info for the backup. Otherwise, undefined. */ async fetchBackupInfo() { try { const cli = _MatrixClientPeg.MatrixClientPeg.safeGet(); const backupInfo = await cli.getKeyBackupVersion(); const backupTrustInfo = // we may not have started crypto yet, in which case we definitely don't trust the backup backupInfo ? await cli.getCrypto()?.isKeyBackupTrusted(backupInfo) : undefined; const { forceReset } = this.props; const phase = backupInfo && !forceReset ? Phase.Migrate : Phase.ChooseKeyPassphrase; this.setState({ phase, backupInfo, backupTrustInfo }); return backupTrustInfo; } catch (e) { console.error("Error fetching backup data from server", e); this.setState({ phase: Phase.LoadError }); return undefined; } } async queryKeyUploadAuth() { try { await _MatrixClientPeg.MatrixClientPeg.safeGet().uploadDeviceSigningKeys(undefined, {}); // We should never get here: the server should always require // UI auth to upload device signing keys. If we do, we upload // no keys which would be a no-op. _logger.logger.log("uploadDeviceSigningKeys unexpectedly succeeded without UI auth!"); } catch (error) { if (!(error instanceof _matrix.MatrixError) || !error.data || !error.data.flows) { _logger.logger.log("uploadDeviceSigningKeys advertised no flows!"); return; } const canUploadKeysWithPasswordOnly = error.data.flows.some(f => { return f.stages.length === 1 && f.stages[0] === "m.login.password"; }); this.setState({ canUploadKeysWithPasswordOnly }); } } renderOptionKey() { return /*#__PURE__*/_react.default.createElement(_StyledRadioButton.default, { key: _WellKnownUtils.SecureBackupSetupMethod.Key, value: _WellKnownUtils.SecureBackupSetupMethod.Key, name: "keyPassphrase", checked: this.state.passPhraseKeySelected === _WellKnownUtils.SecureBackupSetupMethod.Key, onChange: this.onKeyPassphraseChange, outlined: true }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_optionTitle" }, /*#__PURE__*/_react.default.createElement("span", { className: "mx_CreateSecretStorageDialog_optionIcon mx_CreateSecretStorageDialog_optionIcon_secureBackup" }), (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|generate_security_key_title")), /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|generate_security_key_description"))); } renderOptionPassphrase() { return /*#__PURE__*/_react.default.createElement(_StyledRadioButton.default, { key: _WellKnownUtils.SecureBackupSetupMethod.Passphrase, value: _WellKnownUtils.SecureBackupSetupMethod.Passphrase, name: "keyPassphrase", checked: this.state.passPhraseKeySelected === _WellKnownUtils.SecureBackupSetupMethod.Passphrase, onChange: this.onKeyPassphraseChange, outlined: true }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_optionTitle" }, /*#__PURE__*/_react.default.createElement("span", { className: "mx_CreateSecretStorageDialog_optionIcon mx_CreateSecretStorageDialog_optionIcon_securePhrase" }), (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|enter_phrase_title")), /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|use_phrase_only_you_know"))); } renderPhaseChooseKeyPassphrase() { const setupMethods = (0, _WellKnownUtils.getSecureBackupSetupMethods)(_MatrixClientPeg.MatrixClientPeg.safeGet()); const optionKey = setupMethods.includes(_WellKnownUtils.SecureBackupSetupMethod.Key) ? this.renderOptionKey() : null; const optionPassphrase = setupMethods.includes(_WellKnownUtils.SecureBackupSetupMethod.Passphrase) ? this.renderOptionPassphrase() : null; return /*#__PURE__*/_react.default.createElement("form", { onSubmit: this.onChooseKeyPassphraseFormSubmit }, /*#__PURE__*/_react.default.createElement("p", { className: "mx_CreateSecretStorageDialog_centeredBody" }, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|description")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_primaryContainer", role: "radiogroup" }, optionKey, optionPassphrase), /*#__PURE__*/_react.default.createElement(_DialogButtons.default, { primaryButton: (0, _languageHandler._t)("action|continue"), onPrimaryButtonClick: this.onChooseKeyPassphraseFormSubmit, onCancel: this.onCancelClick, hasCancel: this.state.canSkip })); } renderPhaseMigrate() { let authPrompt; let nextCaption = (0, _languageHandler._t)("action|next"); if (this.state.canUploadKeysWithPasswordOnly) { authPrompt = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|requires_password_confirmation")), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_Field.default, { id: "mx_CreateSecretStorageDialog_password", type: "password", label: (0, _languageHandler._t)("common|password"), value: this.state.accountPassword, onChange: this.onAccountPasswordChange, forceValidity: this.state.accountPasswordCorrect === false ? false : undefined, autoFocus: true }))); } else if (!this.state.backupTrustInfo?.trusted) { authPrompt = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|requires_key_restore"))); nextCaption = (0, _languageHandler._t)("action|restore"); } else { authPrompt = /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|requires_server_authentication")); } return /*#__PURE__*/_react.default.createElement("form", { onSubmit: this.onMigrateFormSubmit }, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|session_upgrade_description")), /*#__PURE__*/_react.default.createElement("div", null, authPrompt), /*#__PURE__*/_react.default.createElement(_DialogButtons.default, { primaryButton: nextCaption, onPrimaryButtonClick: this.onMigrateFormSubmit, hasCancel: false, primaryDisabled: !!this.state.canUploadKeysWithPasswordOnly && !this.state.accountPassword }, /*#__PURE__*/_react.default.createElement("button", { type: "button", className: "danger", onClick: this.onCancelClick }, (0, _languageHandler._t)("action|skip")))); } renderPhasePassPhrase() { return /*#__PURE__*/_react.default.createElement("form", { onSubmit: this.onPassPhraseNextClick }, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|enter_phrase_description")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_passPhraseContainer" }, /*#__PURE__*/_react.default.createElement(_PassphraseField.default, { id: "mx_passPhraseInput", className: "mx_CreateSecretStorageDialog_passPhraseField", onChange: this.onPassPhraseChange, minScore: PASSWORD_MIN_SCORE, value: this.state.passPhrase, onValidate: this.onPassPhraseValidate, fieldRef: this.passphraseField, autoFocus: true, label: (0, _languageHandler._td)("settings|key_backup|setup_secure_backup|enter_phrase_title"), labelEnterPassword: (0, _languageHandler._td)("settings|key_backup|setup_secure_backup|enter_phrase_title"), labelStrongPassword: (0, _languageHandler._td)("settings|key_backup|setup_secure_backup|phrase_strong_enough"), labelAllowedButUnsafe: (0, _languageHandler._td)("settings|key_backup|setup_secure_backup|phrase_strong_enough") })), /*#__PURE__*/_react.default.createElement(_DialogButtons.default, { primaryButton: (0, _languageHandler._t)("action|continue"), onPrimaryButtonClick: this.onPassPhraseNextClick, hasCancel: false, disabled: !this.state.passPhraseValid }, /*#__PURE__*/_react.default.createElement("button", { type: "button", onClick: this.onCancelClick, className: "danger" }, (0, _languageHandler._t)("action|cancel")))); } renderPhasePassPhraseConfirm() { let matchText; let changeText; if (this.state.passPhraseConfirm === this.state.passPhrase) { matchText = (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|pass_phrase_match_success"); changeText = (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|use_different_passphrase"); } else if (!this.state.passPhrase.startsWith(this.state.passPhraseConfirm)) { // only tell them they're wrong if they've actually gone wrong. // Security conscious readers will note that if you left element-web unattended // on this screen, this would make it easy for a malicious person to guess // your passphrase one letter at a time, but they could get this faster by // just opening the browser's developer tools and reading it. // Note that not having typed anything at all will not hit this clause and // fall through so empty box === no hint. matchText = (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|pass_phrase_match_failed"); changeText = (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|set_phrase_again"); } let passPhraseMatch; if (matchText) { passPhraseMatch = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", null, matchText), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "link", onClick: this.onSetAgainClick }, changeText)); } return /*#__PURE__*/_react.default.createElement("form", { onSubmit: this.onPassPhraseConfirmNextClick }, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|enter_phrase_to_confirm")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_passPhraseContainer" }, /*#__PURE__*/_react.default.createElement(_PassphraseConfirmField.default, { id: "mx_passPhraseInput", onChange: this.onPassPhraseConfirmChange, value: this.state.passPhraseConfirm, className: "mx_CreateSecretStorageDialog_passPhraseField", label: (0, _languageHandler._td)("settings|key_backup|setup_secure_backup|confirm_security_phrase"), labelRequired: (0, _languageHandler._td)("settings|key_backup|setup_secure_backup|confirm_security_phrase"), labelInvalid: (0, _languageHandler._td)("settings|key_backup|setup_secure_backup|pass_phrase_match_failed"), autoFocus: true, password: this.state.passPhrase }), /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_passPhraseMatch" }, passPhraseMatch)), /*#__PURE__*/_react.default.createElement(_DialogButtons.default, { primaryButton: (0, _languageHandler._t)("action|continue"), onPrimaryButtonClick: this.onPassPhraseConfirmNextClick, hasCancel: false, disabled: this.state.passPhrase !== this.state.passPhraseConfirm }, /*#__PURE__*/_react.default.createElement("button", { type: "button", onClick: this.onCancelClick, className: "danger" }, (0, _languageHandler._t)("action|skip")))); } renderPhaseShowKey() { let continueButton; if (this.state.phase === Phase.ShowKey) { continueButton = /*#__PURE__*/_react.default.createElement(_DialogButtons.default, { primaryButton: (0, _languageHandler._t)("action|continue"), disabled: !this.state.downloaded && !this.state.copied && !this.state.setPassphrase, onPrimaryButtonClick: this.onShowKeyContinueClick, hasCancel: false }); } else { continueButton = /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_continueSpinner" }, /*#__PURE__*/_react.default.createElement(_InlineSpinner.default, null)); } return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|security_key_safety_reminder")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_primaryContainer mx_CreateSecretStorageDialog_recoveryKeyPrimarycontainer" }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_recoveryKeyContainer" }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_recoveryKey" }, /*#__PURE__*/_react.default.createElement("code", { ref: this.recoveryKeyNode }, this.recoveryKey?.encodedPrivateKey)), /*#__PURE__*/_react.default.createElement("div", { className: "mx_CreateSecretStorageDialog_recoveryKeyButtons" }, /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "primary", className: "mx_Dialog_primary", onClick: this.onDownloadClick, disabled: this.state.phase === Phase.Storing }, (0, _languageHandler._t)("action|download")), /*#__PURE__*/_react.default.createElement("span", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|download_or_copy", { downloadButton: "", copyButton: "" })), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { kind: "primary", className: "mx_Dialog_primary mx_CreateSecretStorageDialog_recoveryKeyButtons_copyBtn", onClick: this.onCopyClick, disabled: this.state.phase === Phase.Storing }, this.state.copied ? (0, _languageHandler._t)("common|copied") : (0, _languageHandler._t)("action|copy"))))), continueButton); } renderBusyPhase() { return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_Spinner.default, null)); } renderStoredPhase() { return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("p", { className: "mx_Dialog_content" }, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|backup_setup_success_description")), /*#__PURE__*/_react.default.createElement(_DialogButtons.default, { primaryButton: (0, _languageHandler._t)("action|done"), onPrimaryButtonClick: () => this.props.onFinished(true), hasCancel: false })); } renderPhaseLoadError() { return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|secret_storage_query_failure")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_Dialog_buttons" }, /*#__PURE__*/_react.default.createElement(_DialogButtons.default, { primaryButton: (0, _languageHandler._t)("action|retry"), onPrimaryButtonClick: this.onLoadRetryClick, hasCancel: this.state.canSkip, onCancel: this.onCancel }))); } renderPhaseSkipConfirm() { return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|cancel_warning")), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|settings_reminder")), /*#__PURE__*/_react.default.createElement(_DialogButtons.default, { primaryButton: (0, _languageHandler._t)("action|go_back"), onPrimaryButtonClick: this.onGoBackClick, hasCancel: false }, /*#__PURE__*/_react.default.createElement("button", { type: "button", className: "danger", onClick: this.onCancel }, (0, _languageHandler._t)("action|cancel")))); } titleForPhase(phase) { switch (phase) { case Phase.ChooseKeyPassphrase: return (0, _languageHandler._t)("encryption|set_up_toast_title"); case Phase.Migrate: return (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|title_upgrade_encryption"); case Phase.Passphrase: return (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|title_set_phrase"); case Phase.PassphraseConfirm: return (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|title_confirm_phrase"); case Phase.ConfirmSkip: return (0, _languageHandler._t)("common|are_you_sure"); case Phase.ShowKey: return (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|title_save_key"); case Phase.Storing: return (0, _languageHandler._t)("encryption|bootstrap_title"); case Phase.Stored: return (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|backup_setup_success_title"); default: return ""; } } get topComponent() { if (this.state.phase === Phase.Stored) { return /*#__PURE__*/_react.default.createElement(_check.default, { className: "mx_Icon mx_Icon_circle-40 mx_Icon_accent mx_Icon_bg-accent-light" }); } return null; } get classNames() { return (0, _classnames.default)("mx_CreateSecretStorageDialog", { mx_SuccessDialog: this.state.phase === Phase.Stored }); } render() { let content; if (this.state.error) { content = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("settings|key_backup|setup_secure_backup|unable_to_setup")), /*#__PURE__*/_react.default.createElement("div", { className: "mx_Dialog_buttons" }, /*#__PURE__*/_react.default.createElement(_DialogButtons.default, { primaryButton: (0, _languageHandler._t)("action|retry"), onPrimaryButtonClick: this.bootstrapSecretStorage, hasCancel: this.state.canSkip, onCancel: this.onCancel }))); } else { switch (this.state.phase) { case Phase.Loading: content = this.renderBusyPhase(); break; case Phase.LoadError: content = this.renderPhaseLoadError(); break; case Phase.ChooseKeyPassphrase: content = this.renderPhaseChooseKeyPassphrase(); break; case Phase.Migrate: content = this.renderPhaseMigrate(); break; case Phase.Passphrase: content = this.renderPhasePassPhrase(); break; case Phase.PassphraseConfirm: content = this.renderPhasePassPhraseConfirm(); break; case Phase.ShowKey: content = this.renderPhaseShowKey(); break; case Phase.Storing: content = this.renderBusyPhase(); break; case Phase.Stored: content = this.renderStoredPhase(); break; case Phase.ConfirmSkip: content = this.renderPhaseSkipConfirm(); break; } } let titleClass; switch (this.state.phase) { case Phase.Passphrase: case Phase.PassphraseConfirm: titleClass = ["mx_CreateSecretStorageDialog_titleWithIcon", "mx_CreateSecretStorageDialog_securePhraseTitle"]; break; case Phase.ShowKey: titleClass = ["mx_CreateSecretStorageDialog_titleWithIcon", "mx_CreateSecretStorageDialog_secureBackupTitle"]; break; case Phase.ChooseKeyPassphrase: titleClass = "mx_CreateSecretStorageDialog_centeredTitle"; break; } return /*#__PURE__*/_react.default.createElement(_BaseDialog.default, { className: this.classNames, onFinished: this.props.onFinished, top: this.topComponent, title: this.titleForPhase(this.state.phase), titleClass: titleClass, hasCancel: this.props.hasCancel && [Phase.Passphrase].includes(this.state.phase), fixedWidth: false }, /*#__PURE__*/_react.default.createElement("div", null, content)); } } exports.default = CreateSecretStorageDialog; (0, _defineProperty2.default)(CreateSecretStorageDialog, "defaultProps", { hasCancel: true, forceReset: false }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVXaWxkY2FyZCIsInJlcXVpcmUiLCJfZmlsZVNhdmVyIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsIl9sb2dnZXIiLCJfbWF0cml4IiwiX2NyeXB0byIsIl9jbGFzc25hbWVzIiwiX2NoZWNrIiwiX01hdHJpeENsaWVudFBlZyIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfTW9kYWwiLCJfc3RyaW5ncyIsIl9JbnRlcmFjdGl2ZUF1dGhFbnRyeUNvbXBvbmVudHMiLCJfUGFzc3BocmFzZUZpZWxkIiwiX1N0eWxlZFJhZGlvQnV0dG9uIiwiX0FjY2Vzc2libGVCdXR0b24iLCJfRGlhbG9nQnV0dG9ucyIsIl9JbmxpbmVTcGlubmVyIiwiX1Jlc3RvcmVLZXlCYWNrdXBEaWFsb2ciLCJfV2VsbEtub3duVXRpbHMiLCJfTW9kdWxlUnVubmVyIiwiX0ZpZWxkIiwiX0Jhc2VEaWFsb2ciLCJfU3Bpbm5lciIsIl9JbnRlcmFjdGl2ZUF1dGhEaWFsb2ciLCJfUGFzc3BocmFzZUNvbmZpcm1GaWVsZCIsIl9kZWh5ZHJhdGlvbiIsIl9nZXRSZXF1aXJlV2lsZGNhcmRDYWNoZSIsImUiLCJXZWFrTWFwIiwiciIsInQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIlBoYXNlIiwiUEFTU1dPUkRfTUlOX1NDT1JFIiwiQ3JlYXRlU2VjcmV0U3RvcmFnZURpYWxvZyIsIlJlYWN0IiwiUHVyZUNvbXBvbmVudCIsImNvbnN0cnVjdG9yIiwicHJvcHMiLCJfZGVmaW5lUHJvcGVydHkyIiwiY3JlYXRlUmVmIiwic3RhdGUiLCJwaGFzZSIsIk1pZ3JhdGUiLCJmZXRjaEJhY2t1cEluZm8iLCJzZXRTdGF0ZSIsInBhc3NQaHJhc2VLZXlTZWxlY3RlZCIsInRhcmdldCIsInZhbHVlIiwiU2VjdXJlQmFja3VwU2V0dXBNZXRob2QiLCJLZXkiLCJyZWNvdmVyeUtleSIsIk1hdHJpeENsaWVudFBlZyIsInNhZmVHZXQiLCJnZXRDcnlwdG8iLCJjcmVhdGVSZWNvdmVyeUtleUZyb21QYXNzcGhyYXNlIiwiY29waWVkIiwiZG93bmxvYWRlZCIsInNldFBhc3NwaHJhc2UiLCJTaG93S2V5IiwiUGFzc3BocmFzZSIsInByZXZlbnREZWZhdWx0IiwiYmFja3VwVHJ1c3RJbmZvIiwidHJ1c3RlZCIsImJvb3RzdHJhcFNlY3JldFN0b3JhZ2UiLCJyZXN0b3JlQmFja3VwIiwic3VjY2Vzc2Z1bCIsImNvcHlOb2RlIiwicmVjb3ZlcnlLZXlOb2RlIiwiY3VycmVudCIsImJsb2IiLCJCbG9iIiwiZW5jb2RlZFByaXZhdGVLZXkiLCJ0eXBlIiwiRmlsZVNhdmVyIiwic2F2ZUFzIiwibWFrZVJlcXVlc3QiLCJjYW5VcGxvYWRLZXlzV2l0aFBhc3N3b3JkT25seSIsImFjY291bnRQYXNzd29yZCIsImlkZW50aWZpZXIiLCJ1c2VyIiwiZ2V0U2FmZVVzZXJJZCIsInBhc3N3b3JkIiwiZGlhbG9nQWVzdGhldGljcyIsIlNTT0F1dGhFbnRyeSIsIlBIQVNFX1BSRUFVVEgiLCJ0aXRsZSIsIl90IiwiYm9keSIsImNvbnRpbnVlVGV4dCIsImNvbnRpbnVlS2luZCIsIlBIQVNFX1BPU1RBVVRIIiwiZmluaXNoZWQiLCJNb2RhbCIsImNyZWF0ZURpYWxvZyIsIkludGVyYWN0aXZlQXV0aERpYWxvZyIsIm1hdHJpeENsaWVudCIsImFlc3RoZXRpY3NGb3JTdGFnZVBoYXNlcyIsIkxPR0lOX1RZUEUiLCJVTlNUQUJMRV9MT0dJTl9UWVBFIiwiY29uZmlybWVkIiwiRXJyb3IiLCJTdG9yaW5nIiwiZXJyb3IiLCJ1bmRlZmluZWQiLCJjbGkiLCJjcnlwdG8iLCJmb3JjZVJlc2V0IiwibG9nZ2VyIiwibG9nIiwiY3JlYXRlU2VjcmV0U3RvcmFnZUtleSIsInNldHVwTmV3S2V5QmFja3VwIiwic2V0dXBOZXdTZWNyZXRTdG9yYWdlIiwiYm9vdHN0cmFwQ3Jvc3NTaWduaW5nIiwiYXV0aFVwbG9hZERldmljZVNpZ25pbmdLZXlzIiwiZG9Cb290c3RyYXBVSUF1dGgiLCJrZXlCYWNrdXBJbmZvIiwiYmFja3VwSW5mbyIsImluaXRpYWxpc2VEZWh5ZHJhdGlvbiIsIlN0b3JlZCIsIk1hdHJpeEVycm9yIiwiaHR0cFN0YXR1cyIsImRhdGEiLCJmbG93cyIsImFjY291bnRQYXNzd29yZENvcnJlY3QiLCJvbkZpbmlzaGVkIiwia2V5Q2FsbGJhY2siLCJrIiwiUmVzdG9yZUtleUJhY2t1cERpYWxvZyIsInNob3dTdW1tYXJ5IiwiTG9hZGluZyIsIkNvbmZpcm1Ta2lwIiwiQ2hvb3NlS2V5UGFzc3BocmFzZSIsInBhc3NwaHJhc2VGaWVsZCIsInZhbGlkYXRlIiwiYWxsb3dFbXB0eSIsInZhbGlkIiwiZm9jdXMiLCJmb2N1c2VkIiwiUGFzc3BocmFzZUNvbmZpcm0iLCJwYXNzUGhyYXNlIiwicGFzc1BocmFzZUNvbmZpcm0iLCJwYXNzUGhyYXNlVmFsaWQiLCJyZXN1bHQiLCJzZXR1cE1ldGhvZHMiLCJnZXRTZWN1cmVCYWNrdXBTZXR1cE1ldGhvZHMiLCJpbmNsdWRlcyIsInF1ZXJ5S2V5VXBsb2FkQXV0aCIsImNhblNraXAiLCJpc1NlY3VyZUJhY2t1cFJlcXVpcmVkIiwib24iLCJDcnlwdG9FdmVudCIsIktleUJhY2t1cFN0YXR1cyIsIm9uS2V5QmFja3VwU3RhdHVzQ2hhbmdlIiwiZ2V0SW5pdGlhbFBoYXNlIiwiY29tcG9uZW50V2lsbFVubW91bnQiLCJyZW1vdmVMaXN0ZW5lciIsImtleUZyb21DdXN0b21pc2F0aW9ucyIsIk1vZHVsZVJ1bm5lciIsImluc3RhbmNlIiwiZXh0ZW5zaW9ucyIsImNyeXB0b1NldHVwIiwicHJpdmF0ZUtleSIsImdldEtleUJhY2t1cFZlcnNpb24iLCJpc0tleUJhY2t1cFRydXN0ZWQiLCJjb25zb2xlIiwiTG9hZEVycm9yIiwidXBsb2FkRGV2aWNlU2lnbmluZ0tleXMiLCJzb21lIiwiZiIsInN0YWdlcyIsImxlbmd0aCIsInJlbmRlck9wdGlvbktleSIsImNyZWF0ZUVsZW1lbnQiLCJrZXkiLCJuYW1lIiwiY2hlY2tlZCIsIm9uQ2hhbmdlIiwib25LZXlQYXNzcGhyYXNlQ2hhbmdlIiwib3V0bGluZWQiLCJjbGFzc05hbWUiLCJyZW5kZXJPcHRpb25QYXNzcGhyYXNlIiwicmVuZGVyUGhhc2VDaG9vc2VLZXlQYXNzcGhyYXNlIiwib3B0aW9uS2V5Iiwib3B0aW9uUGFzc3BocmFzZSIsIm9uU3VibWl0Iiwib25DaG9vc2VLZXlQYXNzcGhyYXNlRm9ybVN1Ym1pdCIsInJvbGUiLCJwcmltYXJ5QnV0dG9uIiwib25QcmltYXJ5QnV0dG9uQ2xpY2siLCJvbkNhbmNlbCIsIm9uQ2FuY2VsQ2xpY2siLCJoYXNDYW5jZWwiLCJyZW5kZXJQaGFzZU1pZ3JhdGUiLCJhdXRoUHJvbXB0IiwibmV4dENhcHRpb24iLCJpZCIsImxhYmVsIiwib25BY2NvdW50UGFzc3dvcmRDaGFuZ2UiLCJmb3JjZVZhbGlkaXR5IiwiYXV0b0ZvY3VzIiwib25NaWdyYXRlRm9ybVN1Ym1pdCIsInByaW1hcnlEaXNhYmxlZCIsIm9uQ2xpY2siLCJyZW5kZXJQaGFzZVBhc3NQaHJhc2UiLCJvblBhc3NQaHJhc2VOZXh0Q2xpY2siLCJvblBhc3NQaHJhc2VDaGFuZ2UiLCJtaW5TY29yZSIsIm9uVmFsaWRhdGUiLCJvblBhc3NQaHJhc2VWYWxpZGF0ZSIsImZpZWxkUmVmIiwiX3RkIiwibGFiZWxFbnRlclBhc3N3b3JkIiwibGFiZWxTdHJvbmdQYXNzd29yZCIsImxhYmVsQWxsb3dlZEJ1dFVuc2FmZSIsImRpc2FibGVkIiwicmVuZGVyUGhhc2VQYXNzUGhyYXNlQ29uZmlybSIsIm1hdGNoVGV4dCIsImNoYW5nZVRleHQiLCJzdGFydHNXaXRoIiwicGFzc1BocmFzZU1hdGNoIiwia2luZCIsIm9uU2V0QWdhaW5DbGljayIsIm9uUGFzc1BocmFzZUNvbmZpcm1OZXh0Q2xpY2siLCJvblBhc3NQaHJhc2VDb25maXJtQ2hhbmdlIiwibGFiZWxSZXF1aXJlZCIsImxhYmVsSW52YWxpZCIsInJlbmRlclBoYXNlU2hvd0tleSIsImNvbnRpbnVlQnV0dG9uIiwib25TaG93S2V5Q29udGludWVDbGljayIsInJlZiIsIm9uRG93bmxvYWRDbGljayIsImRvd25sb2FkQnV0dG9uIiwiY29weUJ1dHRvbiIsIm9uQ29weUNsaWNrIiwicmVuZGVyQnVzeVBoYXNlIiwicmVuZGVyU3RvcmVkUGhhc2UiLCJGcmFnbWVudCIsInJlbmRlclBoYXNlTG9hZEVycm9yIiwib25Mb2FkUmV0cnlDbGljayIsInJlbmRlclBoYXNlU2tpcENvbmZpcm0iLCJvbkdvQmFja0NsaWNrIiwidGl0bGVGb3JQaGFzZSIsInRvcENvbXBvbmVudCIsImNsYXNzTmFtZXMiLCJteF9TdWNjZXNzRGlhbG9nIiwicmVuZGVyIiwiY29udGVudCIsInRpdGxlQ2xhc3MiLCJ0b3AiLCJmaXhlZFdpZHRoIiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9hc3luYy1jb21wb25lbnRzL3ZpZXdzL2RpYWxvZ3Mvc2VjdXJpdHkvQ3JlYXRlU2VjcmV0U3RvcmFnZURpYWxvZy50c3giXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMTksIDIwMjAgLCAyMDIzIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5Db3B5cmlnaHQgMjAxOCwgMjAxOSBOZXcgVmVjdG9yIEx0ZFxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QsIHsgY3JlYXRlUmVmIH0gZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgRmlsZVNhdmVyIGZyb20gXCJmaWxlLXNhdmVyXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBBdXRoRGljdCwgQ3Jvc3NTaWduaW5nS2V5cywgTWF0cml4RXJyb3IsIFVJQUZsb3csIFVJQVJlc3BvbnNlIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgQ3J5cHRvRXZlbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvY3J5cHRvXCI7XG5pbXBvcnQgY2xhc3NOYW1lcyBmcm9tIFwiY2xhc3NuYW1lc1wiO1xuaW1wb3J0IHsgQmFja3VwVHJ1c3RJbmZvLCBHZW5lcmF0ZWRTZWNyZXRTdG9yYWdlS2V5LCBLZXlCYWNrdXBJbmZvIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2NyeXB0by1hcGlcIjtcbmltcG9ydCBDaGVja21hcmtJY29uIGZyb20gXCJAdmVjdG9yLWltL2NvbXBvdW5kLWRlc2lnbi10b2tlbnMvYXNzZXRzL3dlYi9pY29ucy9jaGVja1wiO1xuXG5pbXBvcnQgeyBNYXRyaXhDbGllbnRQZWcgfSBmcm9tIFwiLi4vLi4vLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgeyBfdCwgX3RkIH0gZnJvbSBcIi4uLy4uLy4uLy4uL2xhbmd1YWdlSGFuZGxlclwiO1xuaW1wb3J0IE1vZGFsIGZyb20gXCIuLi8uLi8uLi8uLi9Nb2RhbFwiO1xuaW1wb3J0IHsgY29weU5vZGUgfSBmcm9tIFwiLi4vLi4vLi4vLi4vdXRpbHMvc3RyaW5nc1wiO1xuaW1wb3J0IHsgU1NPQXV0aEVudHJ5IH0gZnJvbSBcIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvdmlld3MvYXV0aC9JbnRlcmFjdGl2ZUF1dGhFbnRyeUNvbXBvbmVudHNcIjtcbmltcG9ydCBQYXNzcGhyYXNlRmllbGQgZnJvbSBcIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvdmlld3MvYXV0aC9QYXNzcGhyYXNlRmllbGRcIjtcbmltcG9ydCBTdHlsZWRSYWRpb0J1dHRvbiBmcm9tIFwiLi4vLi4vLi4vLi4vY29tcG9uZW50cy92aWV3cy9lbGVtZW50cy9TdHlsZWRSYWRpb0J1dHRvblwiO1xuaW1wb3J0IEFjY2Vzc2libGVCdXR0b24gZnJvbSBcIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvdmlld3MvZWxlbWVudHMvQWNjZXNzaWJsZUJ1dHRvblwiO1xuaW1wb3J0IERpYWxvZ0J1dHRvbnMgZnJvbSBcIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvdmlld3MvZWxlbWVudHMvRGlhbG9nQnV0dG9uc1wiO1xuaW1wb3J0IElubGluZVNwaW5uZXIgZnJvbSBcIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvdmlld3MvZWxlbWVudHMvSW5saW5lU3Bpbm5lclwiO1xuaW1wb3J0IFJlc3RvcmVLZXlCYWNrdXBEaWFsb2cgZnJvbSBcIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvdmlld3MvZGlhbG9ncy9zZWN1cml0eS9SZXN0b3JlS2V5QmFja3VwRGlhbG9nXCI7XG5pbXBvcnQge1xuICAgIGdldFNlY3VyZUJhY2t1cFNldHVwTWV0aG9kcyxcbiAgICBpc1NlY3VyZUJhY2t1cFJlcXVpcmVkLFxuICAgIFNlY3VyZUJhY2t1cFNldHVwTWV0aG9kLFxufSBmcm9tIFwiLi4vLi4vLi4vLi4vdXRpbHMvV2VsbEtub3duVXRpbHNcIjtcbmltcG9ydCB7IE1vZHVsZVJ1bm5lciB9IGZyb20gXCIuLi8uLi8uLi8uLi9tb2R1bGVzL01vZHVsZVJ1bm5lclwiO1xuaW1wb3J0IEZpZWxkIGZyb20gXCIuLi8uLi8uLi8uLi9jb21wb25lbnRzL3ZpZXdzL2VsZW1lbnRzL0ZpZWxkXCI7XG5pbXBvcnQgQmFzZURpYWxvZyBmcm9tIFwiLi4vLi4vLi4vLi4vY29tcG9uZW50cy92aWV3cy9kaWFsb2dzL0Jhc2VEaWFsb2dcIjtcbmltcG9ydCBTcGlubmVyIGZyb20gXCIuLi8uLi8uLi8uLi9jb21wb25lbnRzL3ZpZXdzL2VsZW1lbnRzL1NwaW5uZXJcIjtcbmltcG9ydCBJbnRlcmFjdGl2ZUF1dGhEaWFsb2cgZnJvbSBcIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvdmlld3MvZGlhbG9ncy9JbnRlcmFjdGl2ZUF1dGhEaWFsb2dcIjtcbmltcG9ydCB7IElWYWxpZGF0aW9uUmVzdWx0IH0gZnJvbSBcIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvdmlld3MvZWxlbWVudHMvVmFsaWRhdGlvblwiO1xuaW1wb3J0IFBhc3NwaHJhc2VDb25maXJtRmllbGQgZnJvbSBcIi4uLy4uLy4uLy4uL2NvbXBvbmVudHMvdmlld3MvYXV0aC9QYXNzcGhyYXNlQ29uZmlybUZpZWxkXCI7XG5pbXBvcnQgeyBpbml0aWFsaXNlRGVoeWRyYXRpb24gfSBmcm9tIFwiLi4vLi4vLi4vLi4vdXRpbHMvZGV2aWNlL2RlaHlkcmF0aW9uXCI7XG5cbi8vIEkgbWFkZSBhIG1pc3Rha2Ugd2hpbGUgY29udmVydGluZyB0aGlzIGFuZCBpdCBoYXMgdG8gYmUgZml4ZWQhXG5lbnVtIFBoYXNlIHtcbiAgICBMb2FkaW5nID0gXCJsb2FkaW5nXCIsXG4gICAgTG9hZEVycm9yID0gXCJsb2FkX2Vycm9yXCIsXG4gICAgQ2hvb3NlS2V5UGFzc3BocmFzZSA9IFwiY2hvb3NlX2tleV9wYXNzcGhyYXNlXCIsXG4gICAgTWlncmF0ZSA9IFwibWlncmF0ZVwiLFxuICAgIFBhc3NwaHJhc2UgPSBcInBhc3NwaHJhc2VcIixcbiAgICBQYXNzcGhyYXNlQ29uZmlybSA9IFwicGFzc3BocmFzZV9jb25maXJtXCIsXG4gICAgU2hvd0tleSA9IFwic2hvd19rZXlcIixcbiAgICBTdG9yaW5nID0gXCJzdG9yaW5nXCIsXG4gICAgU3RvcmVkID0gXCJzdG9yZWRcIixcbiAgICBDb25maXJtU2tpcCA9IFwiY29uZmlybV9za2lwXCIsXG59XG5cbmNvbnN0IFBBU1NXT1JEX01JTl9TQ09SRSA9IDQ7IC8vIFNvIHNlY3VyZSwgbWFueSBjaGFyYWN0ZXJzLCBtdWNoIGNvbXBsZXgsIHdvdywgZXRjLCBldGMuXG5cbmludGVyZmFjZSBJUHJvcHMge1xuICAgIGhhc0NhbmNlbD86IGJvb2xlYW47XG4gICAgYWNjb3VudFBhc3N3b3JkPzogc3RyaW5nO1xuICAgIGZvcmNlUmVzZXQ/OiBib29sZWFuO1xuICAgIG9uRmluaXNoZWQob2s/OiBib29sZWFuKTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgcGhhc2U6IFBoYXNlO1xuICAgIHBhc3NQaHJhc2U6IHN0cmluZztcbiAgICBwYXNzUGhyYXNlVmFsaWQ6IGJvb2xlYW47XG4gICAgcGFzc1BocmFzZUNvbmZpcm06IHN0cmluZztcbiAgICBjb3BpZWQ6IGJvb2xlYW47XG4gICAgZG93bmxvYWRlZDogYm9vbGVhbjtcbiAgICBzZXRQYXNzcGhyYXNlOiBib29sZWFuO1xuXG4gICAgLyoqIEluZm9ybWF0aW9uIG9uIHRoZSBjdXJyZW50IGtleSBiYWNrdXAgdmVyc2lvbiwgYXMgcmV0dXJuZWQgYnkgdGhlIHNlcnZlci5cbiAgICAgKlxuICAgICAqIGBudWxsYCBjb3VsZCBtZWFuIGFueSBvZjpcbiAgICAgKiAgICAqIHdlIGhhdmVuJ3QgeWV0IHJlcXVlc3RlZCB0aGUgZGF0YSBmcm9tIHRoZSBzZXJ2ZXIuXG4gICAgICogICAgKiB3ZSB3ZXJlIHVuYWJsZSB0byByZWFjaCB0aGUgc2VydmVyLlxuICAgICAqICAgICogdGhlIHNlcnZlciByZXR1cm5lZCBrZXkgYmFja3VwIHZlcnNpb24gZGF0YSB3ZSBkaWRuJ3QgdW5kZXJzdGFuZCBvciB3YXMgbWFsZm9ybWVkLlxuICAgICAqICAgICogdGhlcmUgaXMgYWN0dWFsbHkgbm8gYmFja3VwIG9uIHRoZSBzZXJ2ZXIuXG4gICAgICovXG4gICAgYmFja3VwSW5mbzogS2V5QmFja3VwSW5mbyB8IG51bGw7XG5cbiAgICAvKipcbiAgICAgKiBJbmZvcm1hdGlvbiBvbiB3aGV0aGVyIHRoZSBiYWNrdXAgaW4gYGJhY2t1cEluZm9gIGlzIGNvcnJlY3RseSBzaWduZWQsIGFuZCB3aGV0aGVyIHdlIGhhdmUgdGhlIHJpZ2h0IGtleSB0b1xuICAgICAqIGRlY3J5cHQgaXQuXG4gICAgICpcbiAgICAgKiBgdW5kZWZpbmVkYCBpZiBgYmFja3VwSW5mb2AgaXMgbnVsbCwgb3IgaWYgY3J5cHRvIGlzIG5vdCBlbmFibGVkIGluIHRoZSBjbGllbnQuXG4gICAgICovXG4gICAgYmFja3VwVHJ1c3RJbmZvOiBCYWNrdXBUcnVzdEluZm8gfCB1bmRlZmluZWQ7XG5cbiAgICAvLyBkb2VzIHRoZSBzZXJ2ZXIgb2ZmZXIgYSBVSSBhdXRoIGZsb3cgd2l0aCBqdXN0IG0ubG9naW4ucGFzc3dvcmRcbiAgICAvLyBmb3IgL2tleXMvZGV2aWNlX3NpZ25pbmcvdXBsb2FkP1xuICAgIGNhblVwbG9hZEtleXNXaXRoUGFzc3dvcmRPbmx5OiBib29sZWFuIHwgbnVsbDtcbiAgICBhY2NvdW50UGFzc3dvcmQ6IHN0cmluZztcbiAgICBhY2NvdW50UGFzc3dvcmRDb3JyZWN0OiBib29sZWFuIHwgbnVsbDtcbiAgICBjYW5Ta2lwOiBib29sZWFuO1xuICAgIHBhc3NQaHJhc2VLZXlTZWxlY3RlZDogc3RyaW5nO1xuICAgIGVycm9yPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBXYWxrcyB0aGUgdXNlciB0aHJvdWdoIHRoZSBwcm9jZXNzIG9mIGNyZWF0aW5nIGEgNFMgcGFzc3BocmFzZSBhbmQgYm9vdHN0cmFwcGluZyBzZWNyZXQgc3RvcmFnZS5cbiAqXG4gKiBJZiB0aGUgdXNlciBhbHJlYWR5IGhhcyBhIGtleSBiYWNrdXAsIGZvbGxvd3MgYSBcIm1pZ3JhdGlvblwiIGZsb3cgKGFrYSBcIlVwZ3JhZGUgeW91ciBlbmNyeXB0aW9uXCIpIHdoaWNoXG4gKiBwcm9tcHRzIHRoZSB1c2VyIHRvIGVudGVyIHRoZWlyIGJhY2t1cCBkZWNyeXB0aW9uIHBhc3N3b3JkIChhIEN1cnZlMjU1MTkgcHJpdmF0ZSBrZXksIHBvc3NpYmx5IGRlcml2ZWRcbiAqIGZyb20gYSBwYXNzcGhyYXNlKSwgYW5kIHVzZXMgdGhhdCBhcyB0aGUgKEFFUykgNFMgZW5jcnlwdGlvbiBrZXkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENyZWF0ZVNlY3JldFN0b3JhZ2VEaWFsb2cgZXh0ZW5kcyBSZWFjdC5QdXJlQ29tcG9uZW50PElQcm9wcywgSVN0YXRlPiB7XG4gICAgcHVibGljIHN0YXRpYyBkZWZhdWx0UHJvcHM6IFBhcnRpYWw8SVByb3BzPiA9IHtcbiAgICAgICAgaGFzQ2FuY2VsOiB0cnVlLFxuICAgICAgICBmb3JjZVJlc2V0OiBmYWxzZSxcbiAgICB9O1xuICAgIHByaXZhdGUgcmVjb3ZlcnlLZXk/OiBHZW5lcmF0ZWRTZWNyZXRTdG9yYWdlS2V5O1xuICAgIHByaXZhdGUgcmVjb3ZlcnlLZXlOb2RlID0gY3JlYXRlUmVmPEhUTUxFbGVtZW50PigpO1xuICAgIHByaXZhdGUgcGFzc3BocmFzZUZpZWxkID0gY3JlYXRlUmVmPEZpZWxkPigpO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKHByb3BzOiBJUHJvcHMpIHtcbiAgICAgICAgc3VwZXIocHJvcHMpO1xuXG4gICAgICAgIGNvbnN0IGNsaSA9IE1hdHJpeENsaWVudFBlZy5zYWZlR2V0KCk7XG5cbiAgICAgICAg