UNPKG

matrix-react-sdk

Version:
458 lines (369 loc) 61.4 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireDefault(require("react")); var languageHandler = _interopRequireWildcard(require("../../../../../languageHandler")); var _ProfileSettings = _interopRequireDefault(require("../../ProfileSettings")); var _SettingsStore = _interopRequireDefault(require("../../../../../settings/SettingsStore")); var _LanguageDropdown = _interopRequireDefault(require("../../../elements/LanguageDropdown")); var _SpellCheckSettings = _interopRequireDefault(require("../../SpellCheckSettings")); var _AccessibleButton = _interopRequireDefault(require("../../../elements/AccessibleButton")); var _DeactivateAccountDialog = _interopRequireDefault(require("../../../dialogs/DeactivateAccountDialog")); var _propTypes = _interopRequireDefault(require("prop-types")); var _PlatformPeg = _interopRequireDefault(require("../../../../../PlatformPeg")); var _MatrixClientPeg = require("../../../../../MatrixClientPeg"); var sdk = _interopRequireWildcard(require("../../../../..")); var _Modal = _interopRequireDefault(require("../../../../../Modal")); var _dispatcher = _interopRequireDefault(require("../../../../../dispatcher/dispatcher")); var _Terms = require("../../../../../Terms"); var _serviceTypes = require("matrix-js-sdk/src/service-types"); var _IdentityAuthClient = _interopRequireDefault(require("../../../../../IdentityAuthClient")); var _UrlUtils = require("../../../../../utils/UrlUtils"); var _boundThreepids = require("../../../../../boundThreepids"); var _Spinner = _interopRequireDefault(require("../../../elements/Spinner")); var _SettingLevel = require("../../../../../settings/SettingLevel"); var _UIFeature = require("../../../../../settings/UIFeature"); var _replaceableComponent = require("../../../../../utils/replaceableComponent"); var _dec, _class, _class2, _temp; let GeneralUserSettingsTab = (_dec = (0, _replaceableComponent.replaceableComponent)("views.settings.tabs.user.GeneralUserSettingsTab"), _dec(_class = (_temp = _class2 = class GeneralUserSettingsTab extends _react.default.Component { constructor() { super(); (0, _defineProperty2.default)(this, "_onAction", payload => { if (payload.action === 'id_server_changed') { this.setState({ haveIdServer: Boolean(_MatrixClientPeg.MatrixClientPeg.get().getIdentityServerUrl()) }); this._getThreepidState(); } }); (0, _defineProperty2.default)(this, "_onEmailsChange", emails => { this.setState({ emails }); }); (0, _defineProperty2.default)(this, "_onMsisdnsChange", msisdns => { this.setState({ msisdns }); }); (0, _defineProperty2.default)(this, "_onLanguageChange", newLanguage => { if (this.state.language === newLanguage) return; _SettingsStore.default.setValue("language", null, _SettingLevel.SettingLevel.DEVICE, newLanguage); this.setState({ language: newLanguage }); const platform = _PlatformPeg.default.get(); if (platform) { platform.setLanguage(newLanguage); platform.reload(); } }); (0, _defineProperty2.default)(this, "_onSpellCheckLanguagesChange", languages => { this.setState({ spellCheckLanguages: languages }); const plaf = _PlatformPeg.default.get(); if (plaf) { plaf.setSpellCheckLanguages(languages); } }); (0, _defineProperty2.default)(this, "_onPasswordChangeError", err => { // TODO: Figure out a design that doesn't involve replacing the current dialog let errMsg = err.error || err.message || ""; if (err.httpStatus === 403) { errMsg = (0, languageHandler._t)("Failed to change password. Is your password correct?"); } else if (!errMsg) { errMsg += ` (HTTP status ${err.httpStatus})`; } const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); console.error("Failed to change password: " + errMsg); _Modal.default.createTrackedDialog('Failed to change password', '', ErrorDialog, { title: (0, languageHandler._t)("Error"), description: errMsg }); }); (0, _defineProperty2.default)(this, "_onPasswordChanged", () => { // TODO: Figure out a design that doesn't involve replacing the current dialog const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); _Modal.default.createTrackedDialog('Password changed', '', ErrorDialog, { title: (0, languageHandler._t)("Success"), description: (0, languageHandler._t)("Your password was successfully changed. You will not receive " + "push notifications on other sessions until you log back in to them") + "." }); }); (0, _defineProperty2.default)(this, "_onDeactivateClicked", () => { _Modal.default.createTrackedDialog('Deactivate Account', '', _DeactivateAccountDialog.default, { onFinished: success => { if (success) this.props.closeSettingsFn(); } }); }); this.state = { language: languageHandler.getCurrentLanguage(), spellCheckLanguages: [], haveIdServer: Boolean(_MatrixClientPeg.MatrixClientPeg.get().getIdentityServerUrl()), serverSupportsSeparateAddAndBind: null, idServerHasUnsignedTerms: false, requiredPolicyInfo: { // This object is passed along to a component for handling hasTerms: false // policiesAndServices, // From the startTermsFlow callback // agreedUrls, // From the startTermsFlow callback // resolve, // Promise resolve function for startTermsFlow callback }, emails: [], msisdns: [], loading3pids: true // whether or not the emails and msisdns have been loaded }; this.dispatcherRef = _dispatcher.default.register(this._onAction); } // TODO: [REACT-WARNING] Move this to constructor async UNSAFE_componentWillMount() { // eslint-disable-line camelcase const cli = _MatrixClientPeg.MatrixClientPeg.get(); const serverSupportsSeparateAddAndBind = await cli.doesServerSupportSeparateAddAndBind(); const capabilities = await cli.getCapabilities(); // this is cached const changePasswordCap = capabilities['m.change_password']; // You can change your password so long as the capability isn't explicitly disabled. The implicit // behaviour is you can change your password when the capability is missing or has not-false as // the enabled flag value. const canChangePassword = !changePasswordCap || changePasswordCap['enabled'] !== false; this.setState({ serverSupportsSeparateAddAndBind, canChangePassword }); this._getThreepidState(); } async componentDidMount() { const plaf = _PlatformPeg.default.get(); if (plaf) { this.setState({ spellCheckLanguages: await plaf.getSpellCheckLanguages() }); } } componentWillUnmount() { _dispatcher.default.unregister(this.dispatcherRef); } async _getThreepidState() { const cli = _MatrixClientPeg.MatrixClientPeg.get(); // Check to see if terms need accepting this._checkTerms(); // Need to get 3PIDs generally for Account section and possibly also for // Discovery (assuming we have an IS and terms are agreed). let threepids = []; try { threepids = await (0, _boundThreepids.getThreepidsWithBindStatus)(cli); } catch (e) { const idServerUrl = _MatrixClientPeg.MatrixClientPeg.get().getIdentityServerUrl(); console.warn(`Unable to reach identity server at ${idServerUrl} to check ` + `for 3PIDs bindings in Settings`); console.warn(e); } this.setState({ emails: threepids.filter(a => a.medium === 'email'), msisdns: threepids.filter(a => a.medium === 'msisdn'), loading3pids: false }); } async _checkTerms() { if (!this.state.haveIdServer) { this.setState({ idServerHasUnsignedTerms: false }); return; } // By starting the terms flow we get the logic for checking which terms the user has signed // for free. So we might as well use that for our own purposes. const idServerUrl = _MatrixClientPeg.MatrixClientPeg.get().getIdentityServerUrl(); const authClient = new _IdentityAuthClient.default(); try { const idAccessToken = await authClient.getAccessToken({ check: false }); await (0, _Terms.startTermsFlow)([new _Terms.Service(_serviceTypes.SERVICE_TYPES.IS, idServerUrl, idAccessToken)], (policiesAndServices, agreedUrls, extraClassNames) => { return new Promise((resolve, reject) => { this.setState({ idServerName: (0, _UrlUtils.abbreviateUrl)(idServerUrl), requiredPolicyInfo: { hasTerms: true, policiesAndServices, agreedUrls, resolve } }); }); }); // User accepted all terms this.setState({ requiredPolicyInfo: { hasTerms: false } }); } catch (e) { console.warn(`Unable to reach identity server at ${idServerUrl} to check ` + `for terms in Settings`); console.warn(e); } } _renderProfileSection() { return /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_section" }, /*#__PURE__*/_react.default.createElement(_ProfileSettings.default, null)); } _renderAccountSection() { const ChangePassword = sdk.getComponent("views.settings.ChangePassword"); const EmailAddresses = sdk.getComponent("views.settings.account.EmailAddresses"); const PhoneNumbers = sdk.getComponent("views.settings.account.PhoneNumbers"); let passwordChangeForm = /*#__PURE__*/_react.default.createElement(ChangePassword, { className: "mx_GeneralUserSettingsTab_changePassword", rowClassName: "", buttonKind: "primary", onError: this._onPasswordChangeError, onFinished: this._onPasswordChanged }); let threepidSection = null; // For older homeservers without separate 3PID add and bind methods (MSC2290), // we use a combo add with bind option API which requires an identity server to // validate 3PID ownership even if we're just adding to the homeserver only. // For newer homeservers with separate 3PID add and bind methods (MSC2290), // there is no such concern, so we can always show the HS account 3PIDs. if (_SettingsStore.default.getValue(_UIFeature.UIFeature.ThirdPartyID) && (this.state.haveIdServer || this.state.serverSupportsSeparateAddAndBind === true)) { const emails = this.state.loading3pids ? /*#__PURE__*/_react.default.createElement(_Spinner.default, null) : /*#__PURE__*/_react.default.createElement(EmailAddresses, { emails: this.state.emails, onEmailsChange: this._onEmailsChange }); const msisdns = this.state.loading3pids ? /*#__PURE__*/_react.default.createElement(_Spinner.default, null) : /*#__PURE__*/_react.default.createElement(PhoneNumbers, { msisdns: this.state.msisdns, onMsisdnsChange: this._onMsisdnsChange }); threepidSection = /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, languageHandler._t)("Email addresses")), emails, /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, languageHandler._t)("Phone numbers")), msisdns); } else if (this.state.serverSupportsSeparateAddAndBind === null) { threepidSection = /*#__PURE__*/_react.default.createElement(_Spinner.default, null); } let passwordChangeText = (0, languageHandler._t)("Set a new account password..."); if (!this.state.canChangePassword) { // Just don't show anything if you can't do anything. passwordChangeText = null; passwordChangeForm = null; } return /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_section mx_GeneralUserSettingsTab_accountSection" }, /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, languageHandler._t)("Account")), /*#__PURE__*/_react.default.createElement("p", { className: "mx_SettingsTab_subsectionText" }, passwordChangeText), passwordChangeForm, threepidSection); } _renderLanguageSection() { // TODO: Convert to new-styled Field return /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_section" }, /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, languageHandler._t)("Language and region")), /*#__PURE__*/_react.default.createElement(_LanguageDropdown.default, { className: "mx_GeneralUserSettingsTab_languageInput", onOptionChange: this._onLanguageChange, value: this.state.language })); } _renderSpellCheckSection() { return /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_section" }, /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, languageHandler._t)("Spell check dictionaries")), /*#__PURE__*/_react.default.createElement(_SpellCheckSettings.default, { languages: this.state.spellCheckLanguages, onLanguagesChange: this._onSpellCheckLanguagesChange })); } _renderDiscoverySection() { const SetIdServer = sdk.getComponent("views.settings.SetIdServer"); if (this.state.requiredPolicyInfo.hasTerms) { const InlineTermsAgreement = sdk.getComponent("views.terms.InlineTermsAgreement"); const intro = /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subsectionText" }, (0, languageHandler._t)("Agree to the identity server (%(serverName)s) Terms of Service to " + "allow yourself to be discoverable by email address or phone number.", { serverName: this.state.idServerName })); return /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(InlineTermsAgreement, { policiesAndServicePairs: this.state.requiredPolicyInfo.policiesAndServices, agreedUrls: this.state.requiredPolicyInfo.agreedUrls, onFinished: this.state.requiredPolicyInfo.resolve, introElement: intro }), /*#__PURE__*/_react.default.createElement(SetIdServer, { missingTerms: true })); } const EmailAddresses = sdk.getComponent("views.settings.discovery.EmailAddresses"); const PhoneNumbers = sdk.getComponent("views.settings.discovery.PhoneNumbers"); const emails = this.state.loading3pids ? /*#__PURE__*/_react.default.createElement(_Spinner.default, null) : /*#__PURE__*/_react.default.createElement(EmailAddresses, { emails: this.state.emails }); const msisdns = this.state.loading3pids ? /*#__PURE__*/_react.default.createElement(_Spinner.default, null) : /*#__PURE__*/_react.default.createElement(PhoneNumbers, { msisdns: this.state.msisdns }); const threepidSection = this.state.haveIdServer ? /*#__PURE__*/_react.default.createElement("div", { className: "mx_GeneralUserSettingsTab_discovery" }, /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, languageHandler._t)("Email addresses")), emails, /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, languageHandler._t)("Phone numbers")), msisdns) : null; return /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_section" }, threepidSection, /*#__PURE__*/_react.default.createElement(SetIdServer, null)); } _renderManagementSection() { // TODO: Improve warning text for account deactivation return /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_section" }, /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subheading" }, (0, languageHandler._t)("Account management")), /*#__PURE__*/_react.default.createElement("span", { className: "mx_SettingsTab_subsectionText" }, (0, languageHandler._t)("Deactivating your account is a permanent action - be careful!")), /*#__PURE__*/_react.default.createElement(_AccessibleButton.default, { onClick: this._onDeactivateClicked, kind: "danger" }, (0, languageHandler._t)("Deactivate Account"))); } _renderIntegrationManagerSection() { if (!_SettingsStore.default.getValue(_UIFeature.UIFeature.Widgets)) return null; const SetIntegrationManager = sdk.getComponent("views.settings.SetIntegrationManager"); return /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_section" }, /*#__PURE__*/_react.default.createElement(SetIntegrationManager, null)); } render() { const plaf = _PlatformPeg.default.get(); const supportsMultiLanguageSpellCheck = plaf.supportsMultiLanguageSpellCheck(); const discoWarning = this.state.requiredPolicyInfo.hasTerms ? /*#__PURE__*/_react.default.createElement("img", { className: "mx_GeneralUserSettingsTab_warningIcon", src: require("../../../../../../res/img/feather-customised/warning-triangle.svg"), width: "18", height: "18", alt: (0, languageHandler._t)("Warning") }) : null; let accountManagementSection; if (_SettingsStore.default.getValue(_UIFeature.UIFeature.Deactivate)) { accountManagementSection = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_heading" }, (0, languageHandler._t)("Deactivate account")), this._renderManagementSection()); } let discoverySection; if (_SettingsStore.default.getValue(_UIFeature.UIFeature.IdentityServer)) { discoverySection = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_heading" }, discoWarning, " ", (0, languageHandler._t)("Discovery")), this._renderDiscoverySection()); } return /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab" }, /*#__PURE__*/_react.default.createElement("div", { className: "mx_SettingsTab_heading" }, (0, languageHandler._t)("General")), this._renderProfileSection(), this._renderAccountSection(), this._renderLanguageSection(), supportsMultiLanguageSpellCheck ? this._renderSpellCheckSection() : null, discoverySection, this._renderIntegrationManagerSection() /* Has its own title */ , accountManagementSection); } }, (0, _defineProperty2.default)(_class2, "propTypes", { closeSettingsFn: _propTypes.default.func.isRequired }), _temp)) || _class); exports.default = GeneralUserSettingsTab; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9jb21wb25lbnRzL3ZpZXdzL3NldHRpbmdzL3RhYnMvdXNlci9HZW5lcmFsVXNlclNldHRpbmdzVGFiLmpzIl0sIm5hbWVzIjpbIkdlbmVyYWxVc2VyU2V0dGluZ3NUYWIiLCJSZWFjdCIsIkNvbXBvbmVudCIsImNvbnN0cnVjdG9yIiwicGF5bG9hZCIsImFjdGlvbiIsInNldFN0YXRlIiwiaGF2ZUlkU2VydmVyIiwiQm9vbGVhbiIsIk1hdHJpeENsaWVudFBlZyIsImdldCIsImdldElkZW50aXR5U2VydmVyVXJsIiwiX2dldFRocmVlcGlkU3RhdGUiLCJlbWFpbHMiLCJtc2lzZG5zIiwibmV3TGFuZ3VhZ2UiLCJzdGF0ZSIsImxhbmd1YWdlIiwiU2V0dGluZ3NTdG9yZSIsInNldFZhbHVlIiwiU2V0dGluZ0xldmVsIiwiREVWSUNFIiwicGxhdGZvcm0iLCJQbGF0Zm9ybVBlZyIsInNldExhbmd1YWdlIiwicmVsb2FkIiwibGFuZ3VhZ2VzIiwic3BlbGxDaGVja0xhbmd1YWdlcyIsInBsYWYiLCJzZXRTcGVsbENoZWNrTGFuZ3VhZ2VzIiwiZXJyIiwiZXJyTXNnIiwiZXJyb3IiLCJtZXNzYWdlIiwiaHR0cFN0YXR1cyIsIkVycm9yRGlhbG9nIiwic2RrIiwiZ2V0Q29tcG9uZW50IiwiY29uc29sZSIsIk1vZGFsIiwiY3JlYXRlVHJhY2tlZERpYWxvZyIsInRpdGxlIiwiZGVzY3JpcHRpb24iLCJEZWFjdGl2YXRlQWNjb3VudERpYWxvZyIsIm9uRmluaXNoZWQiLCJzdWNjZXNzIiwicHJvcHMiLCJjbG9zZVNldHRpbmdzRm4iLCJsYW5ndWFnZUhhbmRsZXIiLCJnZXRDdXJyZW50TGFuZ3VhZ2UiLCJzZXJ2ZXJTdXBwb3J0c1NlcGFyYXRlQWRkQW5kQmluZCIsImlkU2VydmVySGFzVW5zaWduZWRUZXJtcyIsInJlcXVpcmVkUG9saWN5SW5mbyIsImhhc1Rlcm1zIiwibG9hZGluZzNwaWRzIiwiZGlzcGF0Y2hlclJlZiIsImRpcyIsInJlZ2lzdGVyIiwiX29uQWN0aW9uIiwiVU5TQUZFX2NvbXBvbmVudFdpbGxNb3VudCIsImNsaSIsImRvZXNTZXJ2ZXJTdXBwb3J0U2VwYXJhdGVBZGRBbmRCaW5kIiwiY2FwYWJpbGl0aWVzIiwiZ2V0Q2FwYWJpbGl0aWVzIiwiY2hhbmdlUGFzc3dvcmRDYXAiLCJjYW5DaGFuZ2VQYXNzd29yZCIsImNvbXBvbmVudERpZE1vdW50IiwiZ2V0U3BlbGxDaGVja0xhbmd1YWdlcyIsImNvbXBvbmVudFdpbGxVbm1vdW50IiwidW5yZWdpc3RlciIsIl9jaGVja1Rlcm1zIiwidGhyZWVwaWRzIiwiZSIsImlkU2VydmVyVXJsIiwid2FybiIsImZpbHRlciIsImEiLCJtZWRpdW0iLCJhdXRoQ2xpZW50IiwiSWRlbnRpdHlBdXRoQ2xpZW50IiwiaWRBY2Nlc3NUb2tlbiIsImdldEFjY2Vzc1Rva2VuIiwiY2hlY2siLCJTZXJ2aWNlIiwiU0VSVklDRV9UWVBFUyIsIklTIiwicG9saWNpZXNBbmRTZXJ2aWNlcyIsImFncmVlZFVybHMiLCJleHRyYUNsYXNzTmFtZXMiLCJQcm9taXNlIiwicmVzb2x2ZSIsInJlamVjdCIsImlkU2VydmVyTmFtZSIsIl9yZW5kZXJQcm9maWxlU2VjdGlvbiIsIl9yZW5kZXJBY2NvdW50U2VjdGlvbiIsIkNoYW5nZVBhc3N3b3JkIiwiRW1haWxBZGRyZXNzZXMiLCJQaG9uZU51bWJlcnMiLCJwYXNzd29yZENoYW5nZUZvcm0iLCJfb25QYXNzd29yZENoYW5nZUVycm9yIiwiX29uUGFzc3dvcmRDaGFuZ2VkIiwidGhyZWVwaWRTZWN0aW9uIiwiZ2V0VmFsdWUiLCJVSUZlYXR1cmUiLCJUaGlyZFBhcnR5SUQiLCJfb25FbWFpbHNDaGFuZ2UiLCJfb25Nc2lzZG5zQ2hhbmdlIiwicGFzc3dvcmRDaGFuZ2VUZXh0IiwiX3JlbmRlckxhbmd1YWdlU2VjdGlvbiIsIl9vbkxhbmd1YWdlQ2hhbmdlIiwiX3JlbmRlclNwZWxsQ2hlY2tTZWN0aW9uIiwiX29uU3BlbGxDaGVja0xhbmd1YWdlc0NoYW5nZSIsIl9yZW5kZXJEaXNjb3ZlcnlTZWN0aW9uIiwiU2V0SWRTZXJ2ZXIiLCJJbmxpbmVUZXJtc0FncmVlbWVudCIsImludHJvIiwic2VydmVyTmFtZSIsIl9yZW5kZXJNYW5hZ2VtZW50U2VjdGlvbiIsIl9vbkRlYWN0aXZhdGVDbGlja2VkIiwiX3JlbmRlckludGVncmF0aW9uTWFuYWdlclNlY3Rpb24iLCJXaWRnZXRzIiwiU2V0SW50ZWdyYXRpb25NYW5hZ2VyIiwicmVuZGVyIiwic3VwcG9ydHNNdWx0aUxhbmd1YWdlU3BlbGxDaGVjayIsImRpc2NvV2FybmluZyIsInJlcXVpcmUiLCJhY2NvdW50TWFuYWdlbWVudFNlY3Rpb24iLCJEZWFjdGl2YXRlIiwiZGlzY292ZXJ5U2VjdGlvbiIsIklkZW50aXR5U2VydmVyIiwiUHJvcFR5cGVzIiwiZnVuYyIsImlzUmVxdWlyZWQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7QUFrQkE7O0FBQ0E7O0FBQ0E7O0FBRUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7SUFHcUJBLHNCLFdBRHBCLGdEQUFxQixpREFBckIsQyxtQ0FBRCxNQUNxQkEsc0JBRHJCLFNBQ29EQyxlQUFNQyxTQUQxRCxDQUNvRTtBQUtoRUMsRUFBQUEsV0FBVyxHQUFHO0FBQ1Y7QUFEVSxxREF1RERDLE9BQUQsSUFBYTtBQUNyQixVQUFJQSxPQUFPLENBQUNDLE1BQVIsS0FBbUIsbUJBQXZCLEVBQTRDO0FBQ3hDLGFBQUtDLFFBQUwsQ0FBYztBQUFDQyxVQUFBQSxZQUFZLEVBQUVDLE9BQU8sQ0FBQ0MsaUNBQWdCQyxHQUFoQixHQUFzQkMsb0JBQXRCLEVBQUQ7QUFBdEIsU0FBZDs7QUFDQSxhQUFLQyxpQkFBTDtBQUNIO0FBQ0osS0E1RGE7QUFBQSwyREE4REtDLE1BQUQsSUFBWTtBQUMxQixXQUFL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b0JBQUgsQ0FBekMsQ0FEdUIsRUFFdEIsS0FBS1Qsd0JBQUwsRUFGc0IsQ0FBM0I7QUFJSDs7QUFFRCxRQUFJVyxnQkFBSjs7QUFDQSxRQUFJOUcsdUJBQWNvRixRQUFkLENBQXVCQyxxQkFBVTBCLGNBQWpDLENBQUosRUFBc0Q7QUFDbERELE1BQUFBLGdCQUFnQixnQkFBRyx5RUFDZjtBQUFLLFFBQUEsU0FBUyxFQUFDO0FBQWYsU0FBeUNKLFlBQXpDLE9BQXdELHdCQUFHLFdBQUgsQ0FBeEQsQ0FEZSxFQUVkLEtBQUtaLHVCQUFMLEVBRmMsQ0FBbkI7QUFJSDs7QUFFRCx3QkFDSTtBQUFLLE1BQUEsU0FBUyxFQUFDO0FBQWYsb0JBQ0k7QUFBSyxNQUFBLFNBQVMsRUFBQztBQUFmLE9BQXlDLHdCQUFHLFNBQUgsQ0FBekMsQ0FESixFQUVLLEtBQUtuQixxQkFBTCxFQUZMLEVBR0ssS0FBS0MscUJBQUwsRUFITCxFQUlLLEtBQUtjLHNCQUFMLEVBSkwsRUFLS2UsK0JBQStCLEdBQUcsS0FBS2Isd0JBQUwsRUFBSCxHQUFxQyxJQUx6RSxFQU1Na0IsZ0JBTk4sRUFPSyxLQUFLVCxnQ0FBTDtBQUF3QztBQVA3QyxNQVFNTyx3QkFSTixDQURKO0FBWUg7O0FBamErRCxDLHNEQUM3QztBQUNmL0UsRUFBQUEsZUFBZSxFQUFFbUYsbUJBQVVDLElBQVYsQ0FBZUM7QUFEakIsQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG5Db3B5cmlnaHQgMjAxOSBOZXcgVmVjdG9yIEx0ZFxuQ29weXJpZ2h0IDIwMTkgVGhlIE1hdHJpeC5vcmcgRm91bmRhdGlvbiBDLkkuQy5cbkNvcHlyaWdodCAyMDE5IE1pY2hhZWwgVGVsYXR5bnNraSA8N3QzY2hndXlAZ21haWwuY29tPlxuXG5MaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xueW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG5cbiAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcblxuVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG5TZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG5saW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiovXG5cbmltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5pbXBvcnQge190fSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgUHJvZmlsZVNldHRpbmdzIGZyb20gXCIuLi8uLi9Qcm9maWxlU2V0dGluZ3NcIjtcbmltcG9ydCAqIGFzIGxhbmd1YWdlSGFuZGxlciBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vbGFuZ3VhZ2VIYW5kbGVyXCI7XG5pbXBvcnQgU2V0dGluZ3NTdG9yZSBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vc2V0dGluZ3MvU2V0dGluZ3NTdG9yZVwiO1xuaW1wb3J0IExhbmd1YWdlRHJvcGRvd24gZnJvbSBcIi4uLy4uLy4uL2VsZW1lbnRzL0xhbmd1YWdlRHJvcGRvd25cIjtcbmltcG9ydCBTcGVsbENoZWNrU2V0dGluZ3MgZnJvbSBcIi4uLy4uL1NwZWxsQ2hlY2tTZXR0aW5nc1wiO1xuaW1wb3J0IEFjY2Vzc2libGVCdXR0b24gZnJvbSBcIi4uLy4uLy4uL2VsZW1lbnRzL0FjY2Vzc2libGVCdXR0b25cIjtcbmltcG9ydCBEZWFjdGl2YXRlQWNjb3VudERpYWxvZyBmcm9tIFwiLi4vLi4vLi4vZGlhbG9ncy9EZWFjdGl2YXRlQWNjb3VudERpYWxvZ1wiO1xuaW1wb3J0IFByb3BUeXBlcyBmcm9tIFwicHJvcC10eXBlc1wiO1xuaW1wb3J0IFBsYXRmb3JtUGVnIGZyb20gXCIuLi8uLi8uLi8uLi8uLi9QbGF0Zm9ybVBlZ1wiO1xuaW1wb3J0IHtNYXRyaXhDbGllbnRQZWd9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9NYXRyaXhDbGllbnRQZWdcIjtcbmltcG9ydCAqIGFzIHNkayBmcm9tIFwiLi4vLi4vLi4vLi4vLi5cIjtcbmltcG9ydCBNb2RhbCBmcm9tIFwiLi4vLi4vLi4vLi4vLi4vTW9kYWxcIjtcbmltcG9ydCBkaXMgZnJvbSBcIi4uLy4uLy4uLy4uLy4uL2Rpc3BhdGNoZXIvZGlzcGF0Y2hlclwiO1xuaW1wb3J0IHtTZXJ2aWNlLCBzdGFydFRlcm1zRmxvd30gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL1Rlcm1zXCI7XG5pbXBvcnQge1NFUlZJQ0VfVFlQRVN9IGZyb20gXCJtYXRyaXgtanMtc2RrL3NyYy9zZXJ2aWNlLXR5cGVzXCI7XG5pbXBvcnQgSWRlbnRpdHlBdXRoQ2xpZW50IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9JZGVudGl0eUF1dGhDbGllbnRcIjtcbmltcG9ydCB7YWJicmV2aWF0ZVVybH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL3V0aWxzL1VybFV0aWxzXCI7XG5pbXBvcnQgeyBnZXRUaHJlZXBpZHNXaXRoQmluZFN0YXR1cyB9IGZyb20gJy4uLy4uLy4uLy4uLy4uL2JvdW5kVGhyZWVwaWRzJztcbmltcG9ydCBTcGlubmVyIGZyb20gXCIuLi8uLi8uLi9lbGVtZW50cy9TcGlubmVyXCI7XG5pbXBvcnQge1NldHRpbmdMZXZlbH0gZnJvbSBcIi4uLy4uLy4uLy4uLy4uL3NldHRpbmdzL1NldHRpbmdMZXZlbFwiO1xuaW1wb3J0IHtVSUZlYXR1cmV9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi9zZXR0aW5ncy9VSUZlYXR1cmVcIjtcbmltcG9ydCB7cmVwbGFjZWFibGVDb21wb25lbnR9IGZyb20gXCIuLi8uLi8uLi8uLi8uLi91dGlscy9yZXBsYWNlYWJsZUNvbXBvbmVudFwiO1xuXG5AcmVwbGFjZWFibGVDb21wb25lbnQoXCJ2aWV3cy5zZXR0aW5ncy50YWJzLnVzZXIuR2VuZXJhbFVzZXJTZXR0aW5nc1RhYlwiKVxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgR2VuZXJhbFVzZXJTZXR0aW5nc1RhYiBleHRlbmRzIFJlYWN0LkNvbXBvbmVudCB7XG4gICAgc3RhdGljIHByb3BUeXBlcyA9IHtcbiAgICAgICAgY2xvc2VTZXR0aW5nc0ZuOiBQcm9wVHlwZXMuZnVuYy5pc1JlcXVpcmVkLFxuICAgIH07XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcblxuICAgICAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgICAgICAgbGFuZ3VhZ2U6IGxhbmd1YWdlSGFuZGxlci5nZXRDdXJyZW50TGFuZ3VhZ2UoKSxcbiAgICAgICAgICAgIHNwZWxsQ2hlY2tMYW5ndWFnZXM6IFtdLFxuICAgICAgICAgICAgaGF2ZUlkU2VydmVyOiBCb29sZWFuKE1hdHJpeENsaWVudFBlZy5nZXQoKS5nZXRJZGVudGl0eVNlcnZlclVybCgpKSxcbiAgICAgICAgICAgIHNlcnZlclN1cHBvcnRzU2VwYXJhdGVBZGRBbmRCaW5kOiBudWxsLFxuICAgICAgICAgICAgaWRTZXJ2ZXJIYXNVbnNpZ25lZFRlcm1zOiBmYWxzZSxcbiAgICAgICAgICAgIHJlcXVpcmVkUG9saWN5SW5mbzogeyAgICAgICAvLyBUaGlzIG9iamVjdCBpcyBwYXNzZWQgYWxvbmcgdG8gYSBjb21wb25lbnQgZm9yIGhhbmRsaW5nXG4gICAgICAgICAgICAgICAgaGFzVGVybXM6IGZhbHNlLFxuICAgICAgICAgICAgICAgIC8vIHBvbGljaWVzQW5kU2VydmljZXMsIC8vIEZyb20gdGhlIHN0YXJ0VGVybXNGbG93IGNhbGxiYWNrXG4gICAgICAgICAgICAgICAgLy8gYWdyZWVkVXJscywgICAgICAgICAgLy8gRnJvbSB0aGUgc3RhcnRUZXJtc0Zsb3cgY2FsbGJhY2tcbiAgICAgICAgICAgICAgICAvLyByZXNvbHZlLCAgICAgICAgICAgICAvLyBQcm9taXNlIHJlc29sdmUgZnVuY3Rpb24gZm9yIHN0YXJ0VGVybXNGbG93IGNhbGxiYWNrXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW1haWxzOiBbXSxcbiAgICAgICAgICAgIG1zaXNkbnM6IFtdLFxuICAgICAgICAgICAgbG9hZGluZzNwaWRzOiB0cnVlLCAvLyB3aGV0aGVyIG9yIG5vdCB0aGUgZW1haWxzIGFuZCBtc2lzZG5zIGhhdmUgYmVlbiBsb2FkZWRcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmRpc3BhdGNoZXJSZWYgPSBkaXMucmVnaXN0ZXIodGhpcy5fb25BY3Rpb24pO1xuICAgIH1cblxuICAgIC8vIFRPRE86IFtSRUFDVC1XQVJOSU5HXSBNb3ZlIHRoaXMgdG8gY29uc3RydWN0b3JcbiAgICBhc3luYyBVTlNBRkVfY29tcG9uZW50V2lsbE1vdW50KCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGNhbWVsY2FzZVxuICAgICAgICBjb25zdCBjbGkgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG5cbiAgICAgICAgY29uc3Qgc2VydmVyU3VwcG9ydHNTZXBhcmF0ZUFkZEFuZEJpbmQgPSBhd2FpdCBjbGkuZG9lc1NlcnZlclN1cHBvcnRTZXBhcmF0ZUFkZEFuZEJpbmQoKTtcblxuICAgICAgICBjb25zdCBjYXBhYmlsaXRpZXMgPSBhd2FpdCBjbGkuZ2V0Q2FwYWJpbGl0aWVzKCk7IC8vIHRoaXMgaXMgY2FjaGVkXG4gICAgICAgIGNvbnN0IGNoYW5nZVBhc3N3b3JkQ2FwID0gY2FwYWJpbGl0aWVzWydtLmNoYW5nZV9wYXNzd29yZCddO1xuXG4gICAgICAgIC8vIFlvdSBjYW4gY2hhbmdlIHlvdXIgcGFzc3dvcmQgc28gbG9uZyBhcyB0aGUgY2FwYWJpbGl0eSBpc24ndCBleHBsaWNpdGx5IGRpc2FibGVkLiBUaGUgaW1wbGljaXRcbiAgICAgICAgLy8gYmVoYXZpb3VyIGlzIHlvdSBjYW4gY2hhbmdlIHlvdXIgcGFzc3dvcmQgd2hlbiB0aGUgY2FwYWJpbGl0eSBpcyBtaXNzaW5nIG9yIGhhcyBub3QtZmFsc2UgYXNcbiAgICAgICAgLy8gdGhlIGVuYWJsZWQgZmxhZyB2YWx1ZS5cbiAgICAgICAgY29uc3QgY2FuQ2hhbmdlUGFzc3dvcmQgPSAhY2hhbmdlUGFzc3dvcmRDYXAgfHwgY2hhbmdlUGFzc3dvcmRDYXBbJ2VuYWJsZWQnXSAhPT0gZmFsc2U7XG5cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7c2VydmVyU3VwcG9ydHNTZXBhcmF0ZUFkZEFuZEJpbmQsIGNhbkNoYW5nZVBhc3N3b3JkfSk7XG5cbiAgICAgICAgdGhpcy5fZ2V0VGhyZWVwaWRTdGF0ZSgpO1xuICAgIH1cblxuICAgIGFzeW5jIGNvbXBvbmVudERpZE1vdW50KCkge1xuICAgICAgICBjb25zdCBwbGFmID0gUGxhdGZvcm1QZWcuZ2V0KCk7XG4gICAgICAgIGlmIChwbGFmKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtcbiAgICAgICAgICAgICAgICBzcGVsbENoZWNrTGFuZ3VhZ2VzOiBhd2FpdCBwbGFmLmdldFNwZWxsQ2hlY2tMYW5ndWFnZXMoKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgY29tcG9uZW50V2lsbFVubW91bnQoKSB7XG4gICAgICAgIGRpcy51bnJlZ2lzdGVyKHRoaXMuZGlzcGF0Y2hlclJlZik7XG4gICAgfVxuXG4gICAgX29uQWN0aW9uID0gKHBheWxvYWQpID0+IHtcbiAgICAgICAgaWYgKHBheWxvYWQuYWN0aW9uID09PSAnaWRfc2VydmVyX2NoYW5nZWQnKSB7XG4gICAgICAgICAgICB0aGlzLnNldFN0YXRlKHtoYXZlSWRTZXJ2ZXI6IEJvb2xlYW4oTWF0cml4Q2xpZW50UGVnLmdldCgpLmdldElkZW50aXR5U2VydmVyVXJsKCkpfSk7XG4gICAgICAgICAgICB0aGlzLl9nZXRUaHJlZXBpZFN0YXRlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgX29uRW1haWxzQ2hhbmdlID0gKGVtYWlscykgPT4ge1xuICAgICAgICB0aGlzLnNldFN0YXRlKHsgZW1haWxzIH0pO1xuICAgIH07XG5cbiAgICBfb25Nc2lzZG5zQ2hhbmdlID0gKG1zaXNkbnMpID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7IG1zaXNkbnMgfSk7XG4gICAgfTtcblxuICAgIGFzeW5jIF9nZXRUaHJlZXBpZFN0YXRlKCkge1xuICAgICAgICBjb25zdCBjbGkgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCk7XG5cbiAgICAgICAgLy8gQ2hlY2sgdG8gc2VlIGlmIHRlcm1zIG5lZWQgYWNjZXB0aW5nXG4gICAgICAgIHRoaXMuX2NoZWNrVGVybXMoKTtcblxuICAgICAgICAvLyBOZWVkIHRvIGdldCAzUElEcyBnZW5lcmFsbHkgZm9yIEFjY291bnQgc2VjdGlvbiBhbmQgcG9zc2libHkgYWxzbyBmb3JcbiAgICAgICAgLy8gRGlzY292ZXJ5IChhc3N1bWluZyB3ZSBoYXZlIGFuIElTIGFuZCB0ZXJtcyBhcmUgYWdyZWVkKS5cbiAgICAgICAgbGV0IHRocmVlcGlkcyA9IFtdO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdGhyZWVwaWRzID0gYXdhaXQgZ2V0VGhyZWVwaWRzV2l0aEJpbmRTdGF0dXMoY2xpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgY29uc3QgaWRTZXJ2ZXJVcmwgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCkuZ2V0SWRlbnRpdHlTZXJ2ZXJVcmwoKTtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgICBgVW5hYmxlIHRvIHJlYWNoIGlkZW50aXR5IHNlcnZlciBhdCAke2lkU2VydmVyVXJsfSB0byBjaGVjayBgICtcbiAgICAgICAgICAgICAgICBgZm9yIDNQSURzIGJpbmRpbmdzIGluIFNldHRpbmdzYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICBlbWFpbHM6IHRocmVlcGlkcy5maWx0ZXIoKGEpID0+IGEubWVkaXVtID09PSAnZW1haWwnKSxcbiAgICAgICAgICAgIG1zaXNkbnM6IHRocmVlcGlkcy5maWx0ZXIoKGEpID0+IGEubWVkaXVtID09PSAnbXNpc2RuJyksXG4gICAgICAgICAgICBsb2FkaW5nM3BpZHM6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBhc3luYyBfY2hlY2tUZXJtcygpIHtcbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlLmhhdmVJZFNlcnZlcikge1xuICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7aWRTZXJ2ZXJIYXNVbnNpZ25lZFRlcm1zOiBmYWxzZX0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQnkgc3RhcnRpbmcgdGhlIHRlcm1zIGZsb3cgd2UgZ2V0IHRoZSBsb2dpYyBmb3IgY2hlY2tpbmcgd2hpY2ggdGVybXMgdGhlIHVzZXIgaGFzIHNpZ25lZFxuICAgICAgICAvLyBmb3IgZnJlZS4gU28gd2UgbWlnaHQgYXMgd2VsbCB1c2UgdGhhdCBmb3Igb3VyIG93biBwdXJwb3Nlcy5cbiAgICAgICAgY29uc3QgaWRTZXJ2ZXJVcmwgPSBNYXRyaXhDbGllbnRQZWcuZ2V0KCkuZ2V0SWRlbnRpdHlTZXJ2ZXJVcmwoKTtcbiAgICAgICAgY29uc3QgYXV0aENsaWVudCA9IG5ldyBJZGVudGl0eUF1dGhDbGllbnQoKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGlkQWNjZXNzVG9rZW4gPSBhd2FpdCBhdXRoQ2xpZW50LmdldEFjY2Vzc1Rva2VuKHsgY2hlY2s6IGZhbHNlIH0pO1xuICAgICAgICAgICAgYXdhaXQgc3RhcnRUZXJtc0Zsb3coW25ldyBTZXJ2aWNlKFxuICAgICAgICAgICAgICAgIFNFUlZJQ0VfVFlQRVMuSVMsXG4gICAgICAgICAgICAgICAgaWRTZXJ2ZXJVcmwsXG4gICAgICAgICAgICAgICAgaWRBY2Nlc3NUb2tlbixcbiAgICAgICAgICAgICldLCAocG9saWNpZXNBbmRTZXJ2aWNlcywgYWdyZWVkVXJscywgZXh0cmFDbGFzc05hbWVzKSA9PiB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZFNlcnZlck5hbWU6IGFiYnJldmlhdGVVcmwoaWRTZXJ2ZXJVcmwpLFxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZWRQb2xpY3lJbmZvOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGVybXM6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9saWNpZXNBbmRTZXJ2aWNlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhZ3JlZWRVcmxzLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUsXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgLy8gVXNlciBhY2NlcHRlZCBhbGwgdGVybXNcbiAgICAgICAgICAgIHRoaXMuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgIHJlcXVpcmVkUG9saWN5SW5mbzoge1xuICAgICAgICAgICAgICAgICAgICBoYXNUZXJtczogZmFsc2UsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgICAgICAgYFVuYWJsZSB0byByZWFjaCBpZGVudGl0eSBzZXJ2ZXIgYXQgJHtpZFNlcnZlclVybH0gdG8gY2hlY2sgYCArXG4gICAgICAgICAgICAgICAgYGZvciB0ZXJtcyBpbiBTZXR0aW5nc2AsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgX29uTGFuZ3VhZ2VDaGFuZ2UgPSAobmV3TGFuZ3VhZ2UpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGUubGFuZ3VhZ2UgPT09IG5ld0xhbmd1YWdlKSByZXR1cm47XG5cbiAgICAgICAgU2V0dGluZ3NTdG9yZS5zZXRWYWx1ZShcImxhbmd1YWdlXCIsIG51bGwsIFNldHRpbmdMZXZlbC5ERVZJQ0UsIG5ld0xhbmd1YWdlKTtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7bGFuZ3VhZ2U6IG5ld0xhbmd1YWdlfSk7XG4gICAgICAgIGNvbnN0IHBsYXRmb3JtID0gUGxhdGZvcm1QZWcuZ2V0KCk7XG4gICAgICAgIGlmIChwbGF0Zm9ybSkge1xuICAgICAgICAgICAgcGxhdGZvcm0uc2V0TGFuZ3VhZ2UobmV3TGFuZ3VhZ2UpO1xuICAgICAgICAgICAgcGxhdGZvcm0ucmVsb2FkKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgX29uU3BlbGxDaGVja0xhbmd1YWdlc0NoYW5nZSA9IChsYW5ndWFnZXMpID0+IHtcbiAgICAgICAgdGhpcy5zZXRTdGF0ZSh7c3BlbGxDaGVja0xhbmd1YWdlczogbGFuZ3VhZ2VzfSk7XG5cbiAgICAgICAgY29uc3QgcGxhZiA9IFBsYXRmb3JtUGVnLmdldCgpO1xuICAgICAgICBpZiAocGxhZikge1xuICAgICAgICAgICAgcGxhZi5zZXRTcGVsbENoZWNrTGFuZ3VhZ2VzKGxhbmd1YWdlcyk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgX29uUGFzc3dvcmRDaGFuZ2VFcnJvciA9IChlcnIpID0+IHtcbiAgICAgICAgLy8gVE9ETzogRmlndXJlIG91dCBhIGRlc2lnbiB0aGF0IGRvZXNuJ3QgaW52b2x2ZSByZXBsYWNpbmcgdGhlIGN1cnJlbnQgZGlhbG9nXG4gICAgICAgIGxldCBlcnJNc2cgPSBlcnIuZXJyb3IgfHwgZXJyLm1lc3NhZ2UgfHwgXCJcIjtcbiAgICAgICAgaWYgKGVyci5odHRwU3RhdHVzID09PSA0MDMpIHtcbiAgICAgICAgICAgIGVyck1zZyA9IF90KFwiRmFpbGVkIHRvIGNoYW5nZSBwYXNzd29yZC4gSXMgeW91ciBwYXNzd29yZCBjb3JyZWN0P1wiKTtcbiAgICAgICAgfSBlbHNlIGlmICghZXJyTXNnKSB7XG4gICAgICAgICAgICBlcnJNc2cgKz0gYCAoSFRUUCBzdGF0dXMgJHtlcnIuaHR0cFN0YXR1c30pYDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBFcnJvckRpYWxvZyA9IHNkay5nZXRDb21wb25lbnQoXCJkaWFsb2dzLkVycm9yRGlhbG9nXCIpO1xuICAgICAgICBjb25zb2xlLmVycm9yKFwiRmFpbGVkIHRvIGNoYW5nZSBwYXNzd29yZDogXCIgKyBlcnJNc2cpO1xuICAgICAgICBNb2RhbC5jcmVhdGVUcmFja2VkRGlhbG9nKCdGYWlsZWQgdG8gY2hhbmdlIHBhc3N3b3JkJywgJycsIEVycm9yRGlhbG9nLCB7XG4gICAgICAgICAgICB0aXRsZTogX3QoXCJFcnJvclwiKSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBlcnJNc2csXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfb25QYXNzd29yZENoYW5nZWQgPSAoKSA9PiB7XG4gICAgICAgIC8vIFRPRE86IEZpZ3VyZSBvdXQgYSBkZXNpZ24gdGhhdCBkb2Vzbid0IGludm9sdmUgcmVwbGFjaW5nIHRoZSBjdXJyZW50IGRpYWxvZ1xuICAgICAgICBjb25zdCBFcnJvckRpYWxvZyA9IHNkay5nZXRDb21wb25lbnQoXCJkaWFsb2dzLkVycm9yRGlhbG9nXCIpO1xuICAgICAgICBNb2RhbC5jcmVhdGVUcmFja2VkRGlhbG9nKCdQYXNzd29yZCBjaGFuZ2VkJywgJycsIEVycm9yRGlhbG9nLCB7XG4gICAgICAgICAgICB0aXRsZTogX3QoXCJTdWNjZXNzXCIpLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IF90KFxuICAgICAgICAgICAgICAgIFwiWW91ciBwYXNzd29yZCB3YXMgc3VjY2Vzc2Z1bGx5IGNoYW5nZWQuIFlvdSB3aWxsIG5vdCByZWNlaXZlIFwiICtcbiAgICAgICAgICAgICAgICBcInB1c2ggbm90aWZpY2F0aW9ucyBvbiBvdGhlciBzZXNzaW9ucyB1bnRpbCB5b3UgbG9nIGJhY2sgaW4gdG8gdGhlbVwiLFxuICAgICAgICAgICAgKSArIFwiLlwiLFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgX29uRGVhY3RpdmF0ZUNsaWNrZWQgPSAoKSA9PiB7XG4gICAgICAgIE1vZGFsLmNyZWF0ZVRyYWNrZWREaWFsb2coJ0RlYWN0aXZhdGUgQWNjb3VudCcsICcnLCBEZWFjdGl2YXRlQWNjb3VudERpYWxvZywge1xuICAgICAgICAgICAgb25GaW5pc2hlZDogKHN1Y2Nlc3MpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoc3VjY2VzcykgdGhpcy5wcm9wcy5jbG9zZVNldHRpbmdzRm4oKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfcmVuZGVyUHJvZmlsZVNlY3Rpb24oKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICA8ZGl2IGNsYXNzTmFtZT1cIm14X1NldHRpbmdzVGFiX3NlY3Rpb25cIj5cbiAgICAgICAgICAgICAgICA8UHJvZmlsZVNldHRpbmdzIC8+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBfcmVuZGVyQWNjb3VudFNlY3Rpb24oKSB7XG4gICAgICAgIGNvbnN0IENoYW5nZVBhc3N3b3JkID0gc2RrLmdldENvbXBvbmVudChcInZpZXdzLnNldHRpbmdzLkNoYW5nZVBhc3N3b3JkXCIpO1xuICAgICAgICBjb25zdCBFbWFpbEFkZHJlc3NlcyA9IHNkay5nZXRDb21wb25lbnQoXCJ2aWV3cy5zZXR0aW5ncy5hY2NvdW50LkVtYWlsQWRkcmVzc2VzXCIpO1xuICAgICAgICBjb25zdCBQaG9uZU51bWJlcnMgPSBzZGsuZ2V0Q29tcG9uZW50KFwidmlld3Muc2V0dGluZ3MuYWNjb3VudC5QaG9uZU51bWJlcnNcIik7XG5cbiAgICAgICAgbGV0IHBhc3N3b3JkQ2hhbmdlRm9ybSA9IChcbiAgICAgICAgICAgIDxDaGFuZ2VQYXNzd29yZFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZT1cIm14X0dlbmVyYWxVc2VyU2V0dGluZ3NUYWJfY2hhbmdlUGFzc3dvcmRcIlxuICAgICAgICAgICAgICAgIHJvd0NsYXNzTmFtZT1cIlwiXG4gICAgICAgICAgICAgICAgYnV0dG9uS2luZD1cInByaW1hcnlcIlxuICAgICAgICAgICAgICAgIG9uRXJyb3I9e3RoaXMuX29uUGFzc3dvcmRDaGFuZ2VFcnJvcn