matrix-react-sdk
Version:
SDK for matrix.org using React
205 lines (197 loc) • 34.5 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
exports.shouldShowLogoutDialog = shouldShowLogoutDialog;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireDefault(require("react"));
var _logger = require("matrix-js-sdk/src/logger");
var _Modal = _interopRequireDefault(require("../../../Modal"));
var _dispatcher = _interopRequireDefault(require("../../../dispatcher/dispatcher"));
var _languageHandler = require("../../../languageHandler");
var _MatrixClientPeg = require("../../../MatrixClientPeg");
var _RestoreKeyBackupDialog = _interopRequireDefault(require("./security/RestoreKeyBackupDialog"));
var _QuestionDialog = _interopRequireDefault(require("./QuestionDialog"));
var _BaseDialog = _interopRequireDefault(require("./BaseDialog"));
var _Spinner = _interopRequireDefault(require("../elements/Spinner"));
var _DialogButtons = _interopRequireDefault(require("../elements/DialogButtons"));
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 2020-2022 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.
*/
var BackupStatus = /*#__PURE__*/function (BackupStatus) {
BackupStatus[BackupStatus["LOADING"] = 0] = "LOADING";
BackupStatus[BackupStatus["NO_CRYPTO"] = 1] = "NO_CRYPTO";
BackupStatus[BackupStatus["BACKUP_ACTIVE"] = 2] = "BACKUP_ACTIVE";
BackupStatus[BackupStatus["SERVER_BACKUP_BUT_DISABLED"] = 3] = "SERVER_BACKUP_BUT_DISABLED";
BackupStatus[BackupStatus["NO_BACKUP"] = 4] = "NO_BACKUP";
BackupStatus[BackupStatus["ERROR"] = 5] = "ERROR";
return BackupStatus;
}(BackupStatus || {});
/**
* Checks if the `LogoutDialog` should be shown instead of the simple logout flow.
* The `LogoutDialog` will check the crypto recovery status of the account and
* help the user setup recovery properly if needed.
*/
async function shouldShowLogoutDialog(cli) {
const crypto = cli?.getCrypto();
if (!crypto) return false;
// If any room is encrypted, we need to show the advanced logout flow
const allRooms = cli.getRooms();
for (const room of allRooms) {
const isE2e = await crypto.isEncryptionEnabledInRoom(room.roomId);
if (isE2e) return true;
}
return false;
}
class LogoutDialog extends _react.default.Component {
constructor(props) {
super(props);
(0, _defineProperty2.default)(this, "onExportE2eKeysClicked", () => {
_Modal.default.createDialogAsync(Promise.resolve().then(() => _interopRequireWildcard(require("../../../async-components/views/dialogs/security/ExportE2eKeysDialog"))), {
matrixClient: _MatrixClientPeg.MatrixClientPeg.safeGet()
});
});
(0, _defineProperty2.default)(this, "onFinished", confirmed => {
if (confirmed) {
_dispatcher.default.dispatch({
action: "logout"
});
}
// close dialog
this.props.onFinished(!!confirmed);
});
(0, _defineProperty2.default)(this, "onSetRecoveryMethodClick", () => {
if (this.state.backupStatus === BackupStatus.SERVER_BACKUP_BUT_DISABLED) {
// A key backup exists for this account, but the creating device is not
// verified, so restore the backup which will give us the keys from it and
// allow us to trust it (ie. upload keys to it)
_Modal.default.createDialog(_RestoreKeyBackupDialog.default, undefined, undefined, /* priority = */false, /* static = */true);
} else {
_Modal.default.createDialogAsync(Promise.resolve().then(() => _interopRequireWildcard(require("../../../async-components/views/dialogs/security/CreateKeyBackupDialog"))), undefined, undefined, /* priority = */false, /* static = */true);
}
// close dialog
this.props.onFinished(true);
});
(0, _defineProperty2.default)(this, "onLogoutConfirm", () => {
_dispatcher.default.dispatch({
action: "logout"
});
// close dialog
this.props.onFinished(true);
});
this.state = {
backupStatus: BackupStatus.LOADING
};
// we can't call setState() immediately, so wait a beat
window.setTimeout(() => this.startLoadBackupStatus(), 0);
}
/** kick off the asynchronous calls to populate `state.backupStatus` in the background */
startLoadBackupStatus() {
this.loadBackupStatus().catch(e => {
_logger.logger.log("Unable to fetch key backup status", e);
this.setState({
backupStatus: BackupStatus.ERROR
});
});
}
async loadBackupStatus() {
const client = _MatrixClientPeg.MatrixClientPeg.safeGet();
const crypto = client.getCrypto();
if (!crypto) {
this.setState({
backupStatus: BackupStatus.NO_CRYPTO
});
return;
}
if ((await crypto.getActiveSessionBackupVersion()) !== null) {
this.setState({
backupStatus: BackupStatus.BACKUP_ACTIVE
});
return;
}
// backup is not active. see if there is a backup version on the server we ought to back up to.
const backupInfo = await client.getKeyBackupVersion();
this.setState({
backupStatus: backupInfo ? BackupStatus.SERVER_BACKUP_BUT_DISABLED : BackupStatus.NO_BACKUP
});
}
/**
* Show a dialog prompting the user to set up key backup.
*
* Either there is no backup at all ({@link BackupStatus.NO_BACKUP}), there is a backup on the server but
* we are not connected to it ({@link BackupStatus.SERVER_BACKUP_BUT_DISABLED}), or we were unable to pull the
* backup data ({@link BackupStatus.ERROR}). In all three cases, we should prompt the user to set up key backup.
*/
renderSetupBackupDialog() {
const description = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("auth|logout_dialog|setup_secure_backup_description_1")), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("auth|logout_dialog|setup_secure_backup_description_2")), /*#__PURE__*/_react.default.createElement("p", null, (0, _languageHandler._t)("encryption|setup_secure_backup|explainer")));
let setupButtonCaption;
if (this.state.backupStatus === BackupStatus.SERVER_BACKUP_BUT_DISABLED) {
setupButtonCaption = (0, _languageHandler._t)("settings|security|key_backup_connect");
} else {
// if there's an error fetching the backup info, we'll just assume there's
// no backup for the purpose of the button caption
setupButtonCaption = (0, _languageHandler._t)("auth|logout_dialog|use_key_backup");
}
const dialogContent = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("div", {
className: "mx_Dialog_content",
id: "mx_Dialog_content"
}, description), /*#__PURE__*/_react.default.createElement(_DialogButtons.default, {
primaryButton: setupButtonCaption,
hasCancel: false,
onPrimaryButtonClick: this.onSetRecoveryMethodClick,
focus: true
}, /*#__PURE__*/_react.default.createElement("button", {
onClick: this.onLogoutConfirm
}, (0, _languageHandler._t)("auth|logout_dialog|skip_key_backup"))), /*#__PURE__*/_react.default.createElement("details", null, /*#__PURE__*/_react.default.createElement("summary", {
className: "mx_LogoutDialog_ExportKeyAdvanced"
}, (0, _languageHandler._t)("common|advanced")), /*#__PURE__*/_react.default.createElement("p", null, /*#__PURE__*/_react.default.createElement("button", {
onClick: this.onExportE2eKeysClicked
}, (0, _languageHandler._t)("auth|logout_dialog|megolm_export")))));
// Not quite a standard question dialog as the primary button cancels
// the action and does something else instead, whilst non-default button
// confirms the action.
return /*#__PURE__*/_react.default.createElement(_BaseDialog.default, {
title: (0, _languageHandler._t)("auth|logout_dialog|setup_key_backup_title"),
contentId: "mx_Dialog_content",
hasCancel: true,
onFinished: this.onFinished
}, dialogContent);
}
render() {
switch (this.state.backupStatus) {
case BackupStatus.LOADING:
// while we're deciding if we have backups, show a spinner
return /*#__PURE__*/_react.default.createElement(_BaseDialog.default, {
title: (0, _languageHandler._t)("action|sign_out"),
contentId: "mx_Dialog_content",
hasCancel: true,
onFinished: this.onFinished
}, /*#__PURE__*/_react.default.createElement(_Spinner.default, null));
case BackupStatus.NO_CRYPTO:
case BackupStatus.BACKUP_ACTIVE:
return /*#__PURE__*/_react.default.createElement(_QuestionDialog.default, {
hasCancelButton: true,
title: (0, _languageHandler._t)("action|sign_out"),
description: (0, _languageHandler._t)("auth|logout_dialog|description"),
button: (0, _languageHandler._t)("action|sign_out"),
onFinished: this.onFinished
});
case BackupStatus.NO_BACKUP:
case BackupStatus.SERVER_BACKUP_BUT_DISABLED:
case BackupStatus.ERROR:
return this.renderSetupBackupDialog();
}
}
}
exports.default = LogoutDialog;
(0, _defineProperty2.default)(LogoutDialog, "defaultProps", {
onFinished: function () {}
});
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfcmVhY3QiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwicmVxdWlyZSIsIl9sb2dnZXIiLCJfTW9kYWwiLCJfZGlzcGF0Y2hlciIsIl9sYW5ndWFnZUhhbmRsZXIiLCJfTWF0cml4Q2xpZW50UGVnIiwiX1Jlc3RvcmVLZXlCYWNrdXBEaWFsb2ciLCJfUXVlc3Rpb25EaWFsb2ciLCJfQmFzZURpYWxvZyIsIl9TcGlubmVyIiwiX0RpYWxvZ0J1dHRvbnMiLCJfZ2V0UmVxdWlyZVdpbGRjYXJkQ2FjaGUiLCJlIiwiV2Vha01hcCIsInIiLCJ0IiwiX2ludGVyb3BSZXF1aXJlV2lsZGNhcmQiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImhhcyIsImdldCIsIm4iLCJfX3Byb3RvX18iLCJhIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IiLCJ1IiwiaGFzT3duUHJvcGVydHkiLCJjYWxsIiwiaSIsInNldCIsIkJhY2t1cFN0YXR1cyIsInNob3VsZFNob3dMb2dvdXREaWFsb2ciLCJjbGkiLCJjcnlwdG8iLCJnZXRDcnlwdG8iLCJhbGxSb29tcyIsImdldFJvb21zIiwicm9vbSIsImlzRTJlIiwiaXNFbmNyeXB0aW9uRW5hYmxlZEluUm9vbSIsInJvb21JZCIsIkxvZ291dERpYWxvZyIsIlJlYWN0IiwiQ29tcG9uZW50IiwiY29uc3RydWN0b3IiLCJwcm9wcyIsIl9kZWZpbmVQcm9wZXJ0eTIiLCJNb2RhbCIsImNyZWF0ZURpYWxvZ0FzeW5jIiwiUHJvbWlzZSIsInJlc29sdmUiLCJ0aGVuIiwibWF0cml4Q2xpZW50IiwiTWF0cml4Q2xpZW50UGVnIiwic2FmZUdldCIsImNvbmZpcm1lZCIsImRpcyIsImRpc3BhdGNoIiwiYWN0aW9uIiwib25GaW5pc2hlZCIsInN0YXRlIiwiYmFja3VwU3RhdHVzIiwiU0VSVkVSX0JBQ0tVUF9CVVRfRElTQUJMRUQiLCJjcmVhdGVEaWFsb2ciLCJSZXN0b3JlS2V5QmFja3VwRGlhbG9nIiwidW5kZWZpbmVkIiwiTE9BRElORyIsIndpbmRvdyIsInNldFRpbWVvdXQiLCJzdGFydExvYWRCYWNrdXBTdGF0dXMiLCJsb2FkQmFja3VwU3RhdHVzIiwiY2F0Y2giLCJsb2dnZXIiLCJsb2ciLCJzZXRTdGF0ZSIsIkVSUk9SIiwiY2xpZW50IiwiTk9fQ1JZUFRPIiwiZ2V0QWN0aXZlU2Vzc2lvbkJhY2t1cFZlcnNpb24iLCJCQUNLVVBfQUNUSVZFIiwiYmFja3VwSW5mbyIsImdldEtleUJhY2t1cFZlcnNpb24iLCJOT19CQUNLVVAiLCJyZW5kZXJTZXR1cEJhY2t1cERpYWxvZyIsImRlc2NyaXB0aW9uIiwiY3JlYXRlRWxlbWVudCIsIl90Iiwic2V0dXBCdXR0b25DYXB0aW9uIiwiZGlhbG9nQ29udGVudCIsImNsYXNzTmFtZSIsImlkIiwicHJpbWFyeUJ1dHRvbiIsImhhc0NhbmNlbCIsIm9uUHJpbWFyeUJ1dHRvbkNsaWNrIiwib25TZXRSZWNvdmVyeU1ldGhvZENsaWNrIiwiZm9jdXMiLCJvbkNsaWNrIiwib25Mb2dvdXRDb25maXJtIiwib25FeHBvcnRFMmVLZXlzQ2xpY2tlZCIsInRpdGxlIiwiY29udGVudElkIiwicmVuZGVyIiwiaGFzQ2FuY2VsQnV0dG9uIiwiYnV0dG9uIiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL2RpYWxvZ3MvTG9nb3V0RGlhbG9nLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuQ29weXJpZ2h0IDIwMjQgTmV3IFZlY3RvciBMdGQuXG5Db3B5cmlnaHQgMjAyMC0yMDIyIFRoZSBNYXRyaXgub3JnIEZvdW5kYXRpb24gQy5JLkMuXG5Db3B5cmlnaHQgMjAxOCwgMjAxOSBOZXcgVmVjdG9yIEx0ZFxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgUmVhY3QgZnJvbSBcInJlYWN0XCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbG9nZ2VyXCI7XG5pbXBvcnQgeyBNYXRyaXhDbGllbnQgfSBmcm9tIFwibWF0cml4LWpzLXNkay9zcmMvbWF0cml4XCI7XG5cbmltcG9ydCB0eXBlIENyZWF0ZUtleUJhY2t1cERpYWxvZyBmcm9tIFwiLi4vLi4vLi4vYXN5bmMtY29tcG9uZW50cy92aWV3cy9kaWFsb2dzL3NlY3VyaXR5L0NyZWF0ZUtleUJhY2t1cERpYWxvZ1wiO1xuaW1wb3J0IHR5cGUgRXhwb3J0RTJlS2V5c0RpYWxvZyBmcm9tIFwiLi4vLi4vLi4vYXN5bmMtY29tcG9uZW50cy92aWV3cy9kaWFsb2dzL3NlY3VyaXR5L0V4cG9ydEUyZUtleXNEaWFsb2dcIjtcbmltcG9ydCBNb2RhbCBmcm9tIFwiLi4vLi4vLi4vTW9kYWxcIjtcbmltcG9ydCBkaXMgZnJvbSBcIi4uLy4uLy4uL2Rpc3BhdGNoZXIvZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHsgX3QgfSBmcm9tIFwiLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgeyBNYXRyaXhDbGllbnRQZWcgfSBmcm9tIFwiLi4vLi4vLi4vTWF0cml4Q2xpZW50UGVnXCI7XG5pbXBvcnQgUmVzdG9yZUtleUJhY2t1cERpYWxvZyBmcm9tIFwiLi9zZWN1cml0eS9SZXN0b3JlS2V5QmFja3VwRGlhbG9nXCI7XG5pbXBvcnQgUXVlc3Rpb25EaWFsb2cgZnJvbSBcIi4vUXVlc3Rpb25EaWFsb2dcIjtcbmltcG9ydCBCYXNlRGlhbG9nIGZyb20gXCIuL0Jhc2VEaWFsb2dcIjtcbmltcG9ydCBTcGlubmVyIGZyb20gXCIuLi9lbGVtZW50cy9TcGlubmVyXCI7XG5pbXBvcnQgRGlhbG9nQnV0dG9ucyBmcm9tIFwiLi4vZWxlbWVudHMvRGlhbG9nQnV0dG9uc1wiO1xuXG5pbnRlcmZhY2UgSVByb3BzIHtcbiAgICBvbkZpbmlzaGVkOiAoc3VjY2VzczogYm9vbGVhbikgPT4gdm9pZDtcbn1cblxuZW51bSBCYWNrdXBTdGF0dXMge1xuICAgIC8qKiB3ZSdyZSB0cnlpbmcgdG8gZmlndXJlIG91dCBpZiB0aGVyZSBpcyBhbiBhY3RpdmUgYmFja3VwICovXG4gICAgTE9BRElORyxcblxuICAgIC8qKiBjcnlwdG8gaXMgZGlzYWJsZWQgaW4gdGhpcyBjbGllbnQgKHNvIG5vIG5lZWQgdG8gYmFjayB1cCkgKi9cbiAgICBOT19DUllQVE8sXG5cbiAgICAvKiogS2V5IGJhY2t1cCBpcyBhY3RpdmUgYW5kIHdvcmtpbmcgKi9cbiAgICBCQUNLVVBfQUNUSVZFLFxuXG4gICAgLyoqIHRoZXJlIGlzIGEgYmFja3VwIG9uIHRoZSBzZXJ2ZXIgYnV0IHdlIGFyZSBub3QgYmFja2luZyB1cCB0byBpdCAqL1xuICAgIFNFUlZFUl9CQUNLVVBfQlVUX0RJU0FCTEVELFxuXG4gICAgLyoqIGJhY2t1cCBpcyBub3Qgc2V0IHVwIGxvY2FsbHkgYW5kIHRoZXJlIGlzIG5vIGJhY2t1cCBvbiB0aGUgc2VydmVyICovXG4gICAgTk9fQkFDS1VQLFxuXG4gICAgLyoqIHRoZXJlIHdhcyBhbiBlcnJvciBmZXRjaGluZyB0aGUgc3RhdGUgKi9cbiAgICBFUlJPUixcbn1cblxuaW50ZXJmYWNlIElTdGF0ZSB7XG4gICAgYmFja3VwU3RhdHVzOiBCYWNrdXBTdGF0dXM7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBgTG9nb3V0RGlhbG9nYCBzaG91bGQgYmUgc2hvd24gaW5zdGVhZCBvZiB0aGUgc2ltcGxlIGxvZ291dCBmbG93LlxuICogVGhlIGBMb2dvdXREaWFsb2dgIHdpbGwgY2hlY2sgdGhlIGNyeXB0byByZWNvdmVyeSBzdGF0dXMgb2YgdGhlIGFjY291bnQgYW5kXG4gKiBoZWxwIHRoZSB1c2VyIHNldHVwIHJlY292ZXJ5IHByb3Blcmx5IGlmIG5lZWRlZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNob3VsZFNob3dMb2dvdXREaWFsb2coY2xpOiBNYXRyaXhDbGllbnQpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBjcnlwdG8gPSBjbGk/LmdldENyeXB0bygpO1xuICAgIGlmICghY3J5cHRvKSByZXR1cm4gZmFsc2U7XG5cbiAgICAvLyBJZiBhbnkgcm9vbSBpcyBlbmNyeXB0ZWQsIHdlIG5lZWQgdG8gc2hvdyB0aGUgYWR2YW5jZWQgbG9nb3V0IGZsb3dcbiAgICBjb25zdCBhbGxSb29tcyA9IGNsaSEuZ2V0Um9vbXMoKTtcbiAgICBmb3IgKGNvbnN0IHJvb20gb2YgYWxsUm9vbXMpIHtcbiAgICAgICAgY29uc3QgaXNFMmUgPSBhd2FpdCBjcnlwdG8uaXNFbmNyeXB0aW9uRW5hYmxlZEluUm9vbShyb29tLnJvb21JZCk7XG4gICAgICAgIGlmIChpc0UyZSkgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBMb2dvdXREaWFsb2cgZXh0ZW5kcyBSZWFjdC5Db21wb25lbnQ8SVByb3BzLCBJU3RhdGU+IHtcbiAgICBwdWJsaWMgc3RhdGljIGRlZmF1bHRQcm9wcyA9IHtcbiAgICAgICAgb25GaW5pc2hlZDogZnVuY3Rpb24gKCkge30sXG4gICAgfTtcblxuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcm9wczogSVByb3BzKSB7XG4gICAgICAgIHN1cGVyKHByb3BzKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgYmFja3VwU3RhdHVzOiBCYWNrdXBTdGF0dXMuTE9BRElORyxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyB3ZSBjYW4ndCBjYWxsIHNldFN0YXRlKCkgaW1tZWRpYXRlbHksIHNvIHdhaXQgYSBiZWF0XG4gICAgICAgIHdpbmRvdy5zZXRUaW1lb3V0KCgpID0+IHRoaXMuc3RhcnRMb2FkQmFja3VwU3RhdHVzKCksIDApO1xuICAgIH1cblxuICAgIC8qKiBraWNrIG9mZiB0aGUgYXN5bmNocm9ub3VzIGNhbGxzIHRvIHBvcHVsYXRlIGBzdGF0ZS5iYWNrdXBTdGF0dXNgIGluIHRoZSBiYWNrZ3JvdW5kICovXG4gICAgcHJpdmF0ZSBzdGFydExvYWRCYWNrdXBTdGF0dXMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMubG9hZEJhY2t1cFN0YXR1cygpLmNhdGNoKChlKSA9PiB7XG4gICAgICAgICAgICBsb2dnZXIubG9nKFwiVW5hYmxlIHRvIGZldGNoIGtleSBiYWNrdXAgc3RhdHVzXCIsIGUpO1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgYmFja3VwU3RhdHVzOiBCYWNrdXBTdGF0dXMuRVJST1IsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBsb2FkQmFja3VwU3RhdHVzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICBjb25zdCBjbGllbnQgPSBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpO1xuICAgICAgICBjb25zdCBjcnlwdG8gPSBjbGllbnQuZ2V0Q3J5cHRvKCk7XG4gICAgICAgIGlmICghY3J5cHRvKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHsgYmFja3VwU3RhdHVzOiBCYWNrdXBTdGF0dXMuTk9fQ1JZUFRPIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKChhd2FpdCBjcnlwdG8uZ2V0QWN0aXZlU2Vzc2lvbkJhY2t1cFZlcnNpb24oKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoeyBiYWNrdXBTdGF0dXM6IEJhY2t1cFN0YXR1cy5CQUNLVVBfQUNUSVZFIH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gYmFja3VwIGlzIG5vdCBhY3RpdmUuIHNlZSBpZiB0aGVyZSBpcyBhIGJhY2t1cCB2ZXJzaW9uIG9uIHRoZSBzZXJ2ZXIgd2Ugb3VnaHQgdG8gYmFjayB1cCB0by5cbiAgICAgICAgY29uc3QgYmFja3VwSW5mbyA9IGF3YWl0IGNsaWVudC5nZXRLZXlCYWNrdXBWZXJzaW9uKCk7XG4gICAgICAgIHRoaXMuc2V0U3RhdGUoeyBiYWNrdXBTdGF0dXM6IGJhY2t1cEluZm8gPyBCYWNrdXBTdGF0dXMuU0VSVkVSX0JBQ0tVUF9CVVRfRElTQUJMRUQgOiBCYWNrdXBTdGF0dXMuTk9fQkFDS1VQIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgb25FeHBvcnRFMmVLZXlzQ2xpY2tlZCA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgTW9kYWwuY3JlYXRlRGlhbG9nQXN5bmMoXG4gICAgICAgICAgICBpbXBvcnQoXCIuLi8uLi8uLi9hc3luYy1jb21wb25lbnRzL3ZpZXdzL2RpYWxvZ3Mvc2VjdXJpdHkvRXhwb3J0RTJlS2V5c0RpYWxvZ1wiKSBhcyB1bmtub3duIGFzIFByb21pc2U8XG4gICAgICAgICAgICAgICAgdHlwZW9mIEV4cG9ydEUyZUtleXNEaWFsb2dcbiAgICAgICAgICAgID4sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbWF0cml4Q2xpZW50OiBNYXRyaXhDbGllbnRQZWcuc2FmZUdldCgpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgKTtcbiAgICB9O1xuXG4gICAgcHJpdmF0ZSBvbkZpbmlzaGVkID0gKGNvbmZpcm1lZD86IGJvb2xlYW4pOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKGNvbmZpcm1lZCkge1xuICAgICAgICAgICAgZGlzLmRpc3BhdGNoKHsgYWN0aW9uOiBcImxvZ291dFwiIH0pO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNsb3NlIGRpYWxvZ1xuICAgICAgICB0aGlzLnByb3BzLm9uRmluaXNoZWQoISFjb25maXJtZWQpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uU2V0UmVjb3ZlcnlNZXRob2RDbGljayA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUuYmFja3VwU3RhdHVzID09PSBCYWNrdXBTdGF0dXMuU0VSVkVSX0JBQ0tVUF9CVVRfRElTQUJMRUQpIHtcbiAgICAgICAgICAgIC8vIEEga2V5IGJhY2t1cCBleGlzdHMgZm9yIHRoaXMgYWNjb3VudCwgYnV0IHRoZSBjcmVhdGluZyBkZXZpY2UgaXMgbm90XG4gICAgICAgICAgICAvLyB2ZXJpZmllZCwgc28gcmVzdG9yZSB0aGUgYmFja3VwIHdoaWNoIHdpbGwgZ2l2ZSB1cyB0aGUga2V5cyBmcm9tIGl0IGFuZFxuICAgICAgICAgICAgLy8gYWxsb3cgdXMgdG8gdHJ1c3QgaXQgKGllLiB1cGxvYWQga2V5cyB0byBpdClcbiAgICAgICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZyhcbiAgICAgICAgICAgICAgICBSZXN0b3JlS2V5QmFja3VwRGlhbG9nLFxuICAgICAgICAgICAgICAgIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgLyogcHJpb3JpdHkgPSAqLyBmYWxzZSxcbiAgICAgICAgICAgICAgICAvKiBzdGF0aWMgPSAqLyB0cnVlLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIE1vZGFsLmNyZWF0ZURpYWxvZ0FzeW5jKFxuICAgICAgICAgICAgICAgIGltcG9ydChcIi4uLy4uLy4uL2FzeW5jLWNvbXBvbmVudHMvdmlld3MvZGlhbG9ncy9zZWN1cml0eS9DcmVhdGVLZXlCYWNrdXBEaWFsb2dcIikgYXMgdW5rbm93biBhcyBQcm9taXNlPFxuICAgICAgICAgICAgICAgICAgICB0eXBlb2YgQ3JlYXRlS2V5QmFja3VwRGlhbG9nXG4gICAgICAgICAgICAgICAgPixcbiAgICAgICAgICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIC8qIHByaW9yaXR5ID0gKi8gZmFsc2UsXG4gICAgICAgICAgICAgICAgLyogc3RhdGljID0gKi8gdHJ1ZSxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjbG9zZSBkaWFsb2dcbiAgICAgICAgdGhpcy5wcm9wcy5vbkZpbmlzaGVkKHRydWUpO1xuICAgIH07XG5cbiAgICBwcml2YXRlIG9uTG9nb3V0Q29uZmlybSA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgZGlzLmRpc3BhdGNoKHsgYWN0aW9uOiBcImxvZ291dFwiIH0pO1xuXG4gICAgICAgIC8vIGNsb3NlIGRpYWxvZ1xuICAgICAgICB0aGlzLnByb3BzLm9uRmluaXNoZWQodHJ1ZSk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIFNob3cgYSBkaWFsb2cgcHJvbXB0aW5nIHRoZSB1c2VyIHRvIHNldCB1cCBrZXkgYmFja3VwLlxuICAgICAqXG4gICAgICogRWl0aGVyIHRoZXJlIGlzIG5vIGJhY2t1cCBhdCBhbGwgKHtAbGluayBCYWNrdXBTdGF0dXMuTk9fQkFDS1VQfSksIHRoZXJlIGlzIGEgYmFja3VwIG9uIHRoZSBzZXJ2ZXIgYnV0XG4gICAgICogd2UgYXJlIG5vdCBjb25uZWN0ZWQgdG8gaXQgKHtAbGluayBCYWNrdXBTdGF0dXMuU0VSVkVSX0JBQ0tVUF9CVVRfRElTQUJMRUR9KSwgb3Igd2Ugd2VyZSB1bmFibGUgdG8gcHVsbCB0aGVcbiAgICAgKiBiYWNrdXAgZGF0YSAoe0BsaW5rIEJhY2t1cFN0YXR1cy5FUlJPUn0pLiBJbiBhbGwgdGhyZWUgY2FzZXMsIHdlIHNob3VsZCBwcm9tcHQgdGhlIHVzZXIgdG8gc2V0IHVwIGtleSBiYWNrdXAuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZW5kZXJTZXR1cEJhY2t1cERpYWxvZygpOiBSZWFjdC5SZWFjdE5vZGUge1xuICAgICAgICBjb25zdCBkZXNjcmlwdGlvbiA9IChcbiAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgPHA+e190KFwiYXV0aHxsb2dvdXRfZGlhbG9nfHNldHVwX3NlY3VyZV9iYWNrdXBfZGVzY3JpcHRpb25fMVwiKX08L3A+XG4gICAgICAgICAgICAgICAgPHA+e190KFwiYXV0aHxsb2dvdXRfZGlhbG9nfHNldHVwX3NlY3VyZV9iYWNrdXBfZGVzY3JpcHRpb25fMlwiKX08L3A+XG4gICAgICAgICAgICAgICAgPHA+e190KFwiZW5jcnlwdGlvbnxzZXR1cF9zZWN1cmVfYmFja3VwfGV4cGxhaW5lclwiKX08L3A+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcblxuICAgICAgICBsZXQgc2V0dXBCdXR0b25DYXB0aW9uO1xuICAgICAgICBpZiAodGhpcy5zdGF0ZS5iYWNrdXBTdGF0dXMgPT09IEJhY2t1cFN0YXR1cy5TRVJWRVJfQkFDS1VQX0JVVF9ESVNBQkxFRCkge1xuICAgICAgICAgICAgc2V0dXBCdXR0b25DYXB0aW9uID0gX3QoXCJzZXR0aW5nc3xzZWN1cml0eXxrZXlfYmFja3VwX2Nvbm5lY3RcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBpZiB0aGVyZSdzIGFuIGVycm9yIGZldGNoaW5nIHRoZSBiYWNrdXAgaW5mbywgd2UnbGwganVzdCBhc3N1bWUgdGhlcmUnc1xuICAgICAgICAgICAgLy8gbm8gYmFja3VwIGZvciB0aGUgcHVycG9zZSBvZiB0aGUgYnV0dG9uIGNhcHRpb25cbiAgICAgICAgICAgIHNldHVwQnV0dG9uQ2FwdGlvbiA9IF90KFwiYXV0aHxsb2dvdXRfZGlhbG9nfHVzZV9rZXlfYmFja3VwXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGlhbG9nQ29udGVudCA9IChcbiAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzc05hbWU9XCJteF9EaWFsb2dfY29udGVudFwiIGlkPVwibXhfRGlhbG9nX2NvbnRlbnRcIj5cbiAgICAgICAgICAgICAgICAgICAge2Rlc2NyaXB0aW9ufVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDxEaWFsb2dCdXR0b25zXG4gICAgICAgICAgICAgICAgICAgIHByaW1hcnlCdXR0b249e3NldHVwQnV0dG9uQ2FwdGlvbn1cbiAgICAgICAgICAgICAgICAgICAgaGFzQ2FuY2VsPXtmYWxzZX1cbiAgICAgICAgICAgICAgICAgICAgb25QcmltYXJ5QnV0dG9uQ2xpY2s9e3RoaXMub25TZXRSZWNvdmVyeU1ldGhvZENsaWNrfVxuICAgICAgICAgICAgICAgICAgICBmb2N1cz17dHJ1ZX1cbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gb25DbGljaz17dGhpcy5vbkxvZ291dENvbmZpcm19PntfdChcImF1dGh8bG9nb3V0X2RpYWxvZ3xza2lwX2tleV9iYWNrdXBcIil9PC9idXR0b24+XG4gICAgICAgICAgICAgICAgPC9EaWFsb2dCdXR0b25zPlxuICAgICAgICAgICAgICAgIDxkZXRhaWxzPlxuICAgICAgICAgICAgICAgICAgICA8c3VtbWFyeSBjbGFzc05hbWU9XCJteF9Mb2dvdXREaWFsb2dfRXhwb3J0S2V5QWR2YW5jZWRcIj57X3QoXCJjb21tb258YWR2YW5jZWRcIil9PC9zdW1tYXJ5PlxuICAgICAgICAgICAgICAgICAgICA8cD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gb25DbGljaz17dGhpcy5vbkV4cG9ydEUyZUtleXNDbGlja2VkfT57X3QoXCJhdXRofGxvZ291dF9kaWFsb2d8bWVnb2xtX2V4cG9ydFwiKX08L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgICAgIDwvZGV0YWlscz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICApO1xuICAgICAgICAvLyBOb3QgcXVpdGUgYSBzdGFuZGFyZCBxdWVzdGlvbiBkaWFsb2cgYXMgdGhlIHByaW1hcnkgYnV0dG9uIGNhbmNlbHNcbiAgICAgICAgLy8gdGhlIGFjdGlvbiBhbmQgZG9lcyBzb21ldGhpbmcgZWxzZSBpbnN0ZWFkLCB3aGlsc3Qgbm9uLWRlZmF1bHQgYnV0dG9uXG4gICAgICAgIC8vIGNvbmZpcm1zIHRoZSBhY3Rpb24uXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8QmFzZURpYWxvZ1xuICAgICAgICAgICAgICAgIHRpdGxlPXtfdChcImF1dGh8bG9nb3V0X2RpYWxvZ3xzZXR1cF9rZXlfYmFja3VwX3RpdGxlXCIpfVxuICAgICAgICAgICAgICAgIGNvbnRlbnRJZD1cIm14X0RpYWxvZ19jb250ZW50XCJcbiAgICAgICAgICAgICAgICBoYXNDYW5jZWw9e3RydWV9XG4gICAgICAgICAgICAgICAgb25GaW5pc2hlZD17dGhpcy5vbkZpbmlzaGVkfVxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIHtkaWFsb2dDb250ZW50fVxuICAgICAgICAgICAgPC9CYXNlRGlhbG9nPlxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyByZW5kZXIoKTogUmVhY3QuUmVhY3ROb2RlIHtcbiAgICAgICAgc3dpdGNoICh0aGlzLnN0YXRlLmJhY2t1cFN0YXR1cykge1xuICAgICAgICAgICAgY2FzZSBCYWNrdXBTdGF0dXMuTE9BRElORzpcbiAgICAgICAgICAgICAgICAvLyB3aGlsZSB3ZSdyZSBkZWNpZGluZyBpZiB3ZSBoYXZlIGJhY2t1cHMsIHNob3cgYSBzcGlubmVyXG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgPEJhc2VEaWFsb2dcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlPXtfdChcImFjdGlvbnxzaWduX291dFwiKX1cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRlbnRJZD1cIm14X0RpYWxvZ19jb250ZW50XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc0NhbmNlbD17dHJ1ZX1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9uRmluaXNoZWQ9e3RoaXMub25GaW5pc2hlZH1cbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgPFNwaW5uZXIgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9CYXNlRGlhbG9nPlxuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGNhc2UgQmFja3VwU3RhdHVzLk5PX0NSWVBUTzpcbiAgICAgICAgICAgIGNhc2UgQmFja3VwU3RhdHVzLkJBQ0tVUF9BQ1RJVkU6XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgPFF1ZXN0aW9uRGlhbG9nXG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNDYW5jZWxCdXR0b249e3RydWV9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aXRsZT17X3QoXCJhY3Rpb258c2lnbl9vdXRcIil9XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjcmlwdGlvbj17X3QoXCJhdXRofGxvZ291dF9kaWFsb2d8ZGVzY3JpcHRpb25cIil9XG4gICAgICAgICAgICAgICAgICAgICAgICBidXR0b249e190KFwiYWN0aW9ufHNpZ25fb3V0XCIpfVxuICAgICAgICAgICAgICAgICAgICAgICAgb25GaW5pc2hlZD17dGhpcy5vbkZpbmlzaGVkfVxuICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGNhc2UgQmFja3VwU3RhdHVzLk5PX0JBQ0tVUDpcbiAgICAgICAgICAgIGNhc2UgQmFja3VwU3RhdHVzLlNFUlZFUl9CQUNLVVBfQlVUX0RJU0FCTEVEOlxuICAgICAgICAgICAgY2FzZSBCYWNrdXBTdGF0dXMuRVJST1I6XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVuZGVyU2V0dXBCYWNrdXBEaWFsb2coKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBU0EsSUFBQUEsTUFBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBS0EsSUFBQUUsTUFBQSxHQUFBSCxzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFBQUcsV0FBQSxHQUFBSixzQkFBQSxDQUFBQyxPQUFBO0FBQ0EsSUFB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