matrix-react-sdk
Version:
SDK for matrix.org using React
174 lines (164 loc) • 24 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TermsNotSignedError = exports.Service = void 0;
exports.dialogTermsInteractionCallback = dialogTermsInteractionCallback;
exports.startTermsFlow = startTermsFlow;
var _classnames = _interopRequireDefault(require("classnames"));
var _logger = require("matrix-js-sdk/src/logger");
var _Modal = _interopRequireDefault(require("./Modal"));
var _TermsDialog = _interopRequireDefault(require("./components/views/dialogs/TermsDialog"));
/*
Copyright 2024 New Vector Ltd.
Copyright 2019-2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
class TermsNotSignedError extends Error {}
/**
* Class representing a service that may have terms & conditions that
* require agreement from the user before the user can use that service.
*/
exports.TermsNotSignedError = TermsNotSignedError;
class Service {
/**
* @param {MatrixClient.SERVICE_TYPES} serviceType The type of service
* @param {string} baseUrl The Base URL of the service (ie. before '/_matrix')
* @param {string} accessToken The user's access token for the service
*/
constructor(serviceType, baseUrl, accessToken) {
this.serviceType = serviceType;
this.baseUrl = baseUrl;
this.accessToken = accessToken;
}
}
exports.Service = Service;
/**
* Start a flow where the user is presented with terms & conditions for some services
*
* @param client The Matrix Client instance of the logged-in user
* @param {Service[]} services Object with keys 'serviceType', 'baseUrl', 'accessToken'
* @param {function} interactionCallback Function called with:
* * an array of { service: {Service}, policies: {terms response from API} }
* * an array of URLs the user has already agreed to
* Must return a Promise which resolves with a list of URLs of documents agreed to
* @returns {Promise} resolves when the user agreed to all necessary terms or rejects
* if they cancel.
*/
async function startTermsFlow(client, services, interactionCallback = dialogTermsInteractionCallback) {
const termsPromises = services.map(s => client.getTerms(s.serviceType, s.baseUrl));
/*
* a /terms response looks like:
* {
* "policies": {
* "terms_of_service": {
* "version": "2.0",
* "en": {
* "name": "Terms of Service",
* "url": "https://example.org/somewhere/terms-2.0-en.html"
* },
* "fr": {
* "name": "Conditions d'utilisation",
* "url": "https://example.org/somewhere/terms-2.0-fr.html"
* }
* }
* }
* }
*/
const terms = await Promise.all(termsPromises);
const policiesAndServicePairs = terms.map((t, i) => {
return {
service: services[i],
policies: t.policies
};
});
// fetch the set of agreed policy URLs from account data
const currentAcceptedTerms = await client.getAccountData("m.accepted_terms");
let agreedUrlSet;
if (!currentAcceptedTerms || !currentAcceptedTerms.getContent() || !currentAcceptedTerms.getContent().accepted) {
agreedUrlSet = new Set();
} else {
agreedUrlSet = new Set(currentAcceptedTerms.getContent().accepted);
}
// remove any policies the user has already agreed to and any services where
// they've already agreed to all the policies
// NB. it could be nicer to show the user stuff they've already agreed to,
// but then they'd assume they can un-check the boxes to un-agree to a policy,
// but that is not a thing the API supports, so probably best to just show
// things they've not agreed to yet.
const unagreedPoliciesAndServicePairs = [];
for (const {
service,
policies
} of policiesAndServicePairs) {
const unagreedPolicies = {};
for (const [policyName, policy] of Object.entries(policies)) {
let policyAgreed = false;
for (const lang of Object.keys(policy)) {
if (lang === "version") continue;
if (agreedUrlSet.has(policy[lang].url)) {
policyAgreed = true;
break;
}
}
if (!policyAgreed) unagreedPolicies[policyName] = policy;
}
if (Object.keys(unagreedPolicies).length > 0) {
unagreedPoliciesAndServicePairs.push({
service,
policies: unagreedPolicies
});
}
}
// if there's anything left to agree to, prompt the user
const numAcceptedBeforeAgreement = agreedUrlSet.size;
if (unagreedPoliciesAndServicePairs.length > 0) {
const newlyAgreedUrls = await interactionCallback(unagreedPoliciesAndServicePairs, [...agreedUrlSet]);
_logger.logger.log("User has agreed to URLs", newlyAgreedUrls);
// Merge with previously agreed URLs
newlyAgreedUrls.forEach(url => agreedUrlSet.add(url));
} else {
_logger.logger.log("User has already agreed to all required policies");
}
// We only ever add to the set of URLs, so if anything has changed then we'd see a different length
if (agreedUrlSet.size !== numAcceptedBeforeAgreement) {
const newAcceptedTerms = {
accepted: Array.from(agreedUrlSet)
};
await client.setAccountData("m.accepted_terms", newAcceptedTerms);
}
const agreePromises = policiesAndServicePairs.map(policiesAndService => {
// filter the agreed URL list for ones that are actually for this service
// (one URL may be used for multiple services)
// Not a particularly efficient loop but probably fine given the numbers involved
const urlsForService = Array.from(agreedUrlSet).filter(url => {
for (const policy of Object.values(policiesAndService.policies)) {
for (const lang of Object.keys(policy)) {
if (lang === "version") continue;
if (policy[lang].url === url) return true;
}
}
return false;
});
if (urlsForService.length === 0) return Promise.resolve();
return client.agreeToTerms(policiesAndService.service.serviceType, policiesAndService.service.baseUrl, policiesAndService.service.accessToken, urlsForService);
});
await Promise.all(agreePromises);
}
async function dialogTermsInteractionCallback(policiesAndServicePairs, agreedUrls, extraClassNames) {
_logger.logger.log("Terms that need agreement", policiesAndServicePairs);
const {
finished
} = _Modal.default.createDialog(_TermsDialog.default, {
policiesAndServicePairs,
agreedUrls
}, (0, _classnames.default)("mx_TermsDialog", extraClassNames));
const [done, _agreedUrls] = await finished;
if (!done || !_agreedUrls) {
throw new TermsNotSignedError();
}
return _agreedUrls;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfY2xhc3NuYW1lcyIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiX2xvZ2dlciIsIl9Nb2RhbCIsIl9UZXJtc0RpYWxvZyIsIlRlcm1zTm90U2lnbmVkRXJyb3IiLCJFcnJvciIsImV4cG9ydHMiLCJTZXJ2aWNlIiwiY29uc3RydWN0b3IiLCJzZXJ2aWNlVHlwZSIsImJhc2VVcmwiLCJhY2Nlc3NUb2tlbiIsInN0YXJ0VGVybXNGbG93IiwiY2xpZW50Iiwic2VydmljZXMiLCJpbnRlcmFjdGlvbkNhbGxiYWNrIiwiZGlhbG9nVGVybXNJbnRlcmFjdGlvbkNhbGxiYWNrIiwidGVybXNQcm9taXNlcyIsIm1hcCIsInMiLCJnZXRUZXJtcyIsInRlcm1zIiwiUHJvbWlzZSIsImFsbCIsInBvbGljaWVzQW5kU2VydmljZVBhaXJzIiwidCIsImkiLCJzZXJ2aWNlIiwicG9saWNpZXMiLCJjdXJyZW50QWNjZXB0ZWRUZXJtcyIsImdldEFjY291bnREYXRhIiwiYWdyZWVkVXJsU2V0IiwiZ2V0Q29udGVudCIsImFjY2VwdGVkIiwiU2V0IiwidW5hZ3JlZWRQb2xpY2llc0FuZFNlcnZpY2VQYWlycyIsInVuYWdyZWVkUG9saWNpZXMiLCJwb2xpY3lOYW1lIiwicG9saWN5IiwiT2JqZWN0IiwiZW50cmllcyIsInBvbGljeUFncmVlZCIsImxhbmciLCJrZXlzIiwiaGFzIiwidXJsIiwibGVuZ3RoIiwicHVzaCIsIm51bUFjY2VwdGVkQmVmb3JlQWdyZWVtZW50Iiwic2l6ZSIsIm5ld2x5QWdyZWVkVXJscyIsImxvZ2dlciIsImxvZyIsImZvckVhY2giLCJhZGQiLCJuZXdBY2NlcHRlZFRlcm1zIiwiQXJyYXkiLCJmcm9tIiwic2V0QWNjb3VudERhdGEiLCJhZ3JlZVByb21pc2VzIiwicG9saWNpZXNBbmRTZXJ2aWNlIiwidXJsc0ZvclNlcnZpY2UiLCJmaWx0ZXIiLCJ2YWx1ZXMiLCJyZXNvbHZlIiwiYWdyZWVUb1Rlcm1zIiwiYWdyZWVkVXJscyIsImV4dHJhQ2xhc3NOYW1lcyIsImZpbmlzaGVkIiwiTW9kYWwiLCJjcmVhdGVEaWFsb2ciLCJUZXJtc0RpYWxvZyIsImNsYXNzTmFtZXMiLCJkb25lIiwiX2FncmVlZFVybHMiXSwic291cmNlcyI6WyIuLi9zcmMvVGVybXMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbkNvcHlyaWdodCAyMDI0IE5ldyBWZWN0b3IgTHRkLlxuQ29weXJpZ2h0IDIwMTktMjAyMSBUaGUgTWF0cml4Lm9yZyBGb3VuZGF0aW9uIEMuSS5DLlxuXG5TUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQUdQTC0zLjAtb25seSBPUiBHUEwtMy4wLW9ubHlcblBsZWFzZSBzZWUgTElDRU5TRSBmaWxlcyBpbiB0aGUgcmVwb3NpdG9yeSByb290IGZvciBmdWxsIGRldGFpbHMuXG4qL1xuXG5pbXBvcnQgY2xhc3NOYW1lcyBmcm9tIFwiY2xhc3NuYW1lc1wiO1xuaW1wb3J0IHsgU0VSVklDRV9UWVBFUywgTWF0cml4Q2xpZW50IH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL21hdHJpeFwiO1xuaW1wb3J0IHsgbG9nZ2VyIH0gZnJvbSBcIm1hdHJpeC1qcy1zZGsvc3JjL2xvZ2dlclwiO1xuXG5pbXBvcnQgTW9kYWwgZnJvbSBcIi4vTW9kYWxcIjtcbmltcG9ydCBUZXJtc0RpYWxvZyBmcm9tIFwiLi9jb21wb25lbnRzL3ZpZXdzL2RpYWxvZ3MvVGVybXNEaWFsb2dcIjtcblxuZXhwb3J0IGNsYXNzIFRlcm1zTm90U2lnbmVkRXJyb3IgZXh0ZW5kcyBFcnJvciB7fVxuXG4vKipcbiAqIENsYXNzIHJlcHJlc2VudGluZyBhIHNlcnZpY2UgdGhhdCBtYXkgaGF2ZSB0ZXJtcyAmIGNvbmRpdGlvbnMgdGhhdFxuICogcmVxdWlyZSBhZ3JlZW1lbnQgZnJvbSB0aGUgdXNlciBiZWZvcmUgdGhlIHVzZXIgY2FuIHVzZSB0aGF0IHNlcnZpY2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXJ2aWNlIHtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge01hdHJpeENsaWVudC5TRVJWSUNFX1RZUEVTfSBzZXJ2aWNlVHlwZSBUaGUgdHlwZSBvZiBzZXJ2aWNlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGJhc2VVcmwgVGhlIEJhc2UgVVJMIG9mIHRoZSBzZXJ2aWNlIChpZS4gYmVmb3JlICcvX21hdHJpeCcpXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGFjY2Vzc1Rva2VuIFRoZSB1c2VyJ3MgYWNjZXNzIHRva2VuIGZvciB0aGUgc2VydmljZVxuICAgICAqL1xuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHVibGljIHNlcnZpY2VUeXBlOiBTRVJWSUNFX1RZUEVTLFxuICAgICAgICBwdWJsaWMgYmFzZVVybDogc3RyaW5nLFxuICAgICAgICBwdWJsaWMgYWNjZXNzVG9rZW46IHN0cmluZyxcbiAgICApIHt9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9jYWxpc2VkUG9saWN5IHtcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgdXJsOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUG9saWN5IHtcbiAgICAvLyBAdHMtaWdub3JlOiBObyBncmVhdCB3YXkgdG8gZXhwcmVzcyBpbmRleGVkIHR5cGVzIHRvZ2V0aGVyIHdpdGggb3RoZXIga2V5c1xuICAgIHZlcnNpb246IHN0cmluZztcbiAgICBbbGFuZzogc3RyaW5nXTogTG9jYWxpc2VkUG9saWN5O1xufVxuXG5leHBvcnQgdHlwZSBQb2xpY2llcyA9IHtcbiAgICBbcG9saWN5OiBzdHJpbmddOiBQb2xpY3k7XG59O1xuXG5leHBvcnQgdHlwZSBTZXJ2aWNlUG9saWN5UGFpciA9IHtcbiAgICBwb2xpY2llczogUG9saWNpZXM7XG4gICAgc2VydmljZTogU2VydmljZTtcbn07XG5cbmV4cG9ydCB0eXBlIFRlcm1zSW50ZXJhY3Rpb25DYWxsYmFjayA9IChcbiAgICBwb2xpY2llc0FuZFNlcnZpY2VQYWlyczogU2VydmljZVBvbGljeVBhaXJbXSxcbiAgICBhZ3JlZWRVcmxzOiBzdHJpbmdbXSxcbiAgICBleHRyYUNsYXNzTmFtZXM/OiBzdHJpbmcsXG4pID0+IFByb21pc2U8c3RyaW5nW10+O1xuXG4vKipcbiAqIFN0YXJ0IGEgZmxvdyB3aGVyZSB0aGUgdXNlciBpcyBwcmVzZW50ZWQgd2l0aCB0ZXJtcyAmIGNvbmRpdGlvbnMgZm9yIHNvbWUgc2VydmljZXNcbiAqXG4gKiBAcGFyYW0gY2xpZW50IFRoZSBNYXRyaXggQ2xpZW50IGluc3RhbmNlIG9mIHRoZSBsb2dnZWQtaW4gdXNlclxuICogQHBhcmFtIHtTZXJ2aWNlW119IHNlcnZpY2VzIE9iamVjdCB3aXRoIGtleXMgJ3NlcnZpY2VUeXBlJywgJ2Jhc2VVcmwnLCAnYWNjZXNzVG9rZW4nXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBpbnRlcmFjdGlvbkNhbGxiYWNrIEZ1bmN0aW9uIGNhbGxlZCB3aXRoOlxuICogICAgICAqIGFuIGFycmF5IG9mIHsgc2VydmljZToge1NlcnZpY2V9LCBwb2xpY2llczoge3Rlcm1zIHJlc3BvbnNlIGZyb20gQVBJfSB9XG4gKiAgICAgICogYW4gYXJyYXkgb2YgVVJMcyB0aGUgdXNlciBoYXMgYWxyZWFkeSBhZ3JlZWQgdG9cbiAqICAgICBNdXN0IHJldHVybiBhIFByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2l0aCBhIGxpc3Qgb2YgVVJMcyBvZiBkb2N1bWVudHMgYWdyZWVkIHRvXG4gKiBAcmV0dXJucyB7UHJvbWlzZX0gcmVzb2x2ZXMgd2hlbiB0aGUgdXNlciBhZ3JlZWQgdG8gYWxsIG5lY2Vzc2FyeSB0ZXJtcyBvciByZWplY3RzXG4gKiAgICAgaWYgdGhleSBjYW5jZWwuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydFRlcm1zRmxvdyhcbiAgICBjbGllbnQ6IE1hdHJpeENsaWVudCxcbiAgICBzZXJ2aWNlczogU2VydmljZVtdLFxuICAgIGludGVyYWN0aW9uQ2FsbGJhY2s6IFRlcm1zSW50ZXJhY3Rpb25DYWxsYmFjayA9IGRpYWxvZ1Rlcm1zSW50ZXJhY3Rpb25DYWxsYmFjayxcbik6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHRlcm1zUHJvbWlzZXMgPSBzZXJ2aWNlcy5tYXAoKHMpID0+IGNsaWVudC5nZXRUZXJtcyhzLnNlcnZpY2VUeXBlLCBzLmJhc2VVcmwpKTtcblxuICAgIC8qXG4gICAgICogYSAvdGVybXMgcmVzcG9uc2UgbG9va3MgbGlrZTpcbiAgICAgKiB7XG4gICAgICogICAgIFwicG9saWNpZXNcIjoge1xuICAgICAqICAgICAgICAgXCJ0ZXJtc19vZl9zZXJ2aWNlXCI6IHtcbiAgICAgKiAgICAgICAgICAgICBcInZlcnNpb25cIjogXCIyLjBcIixcbiAgICAgKiAgICAgICAgICAgICAgXCJlblwiOiB7XG4gICAgICogICAgICAgICAgICAgICAgIFwibmFtZVwiOiBcIlRlcm1zIG9mIFNlcnZpY2VcIixcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJ1cmxcIjogXCJodHRwczovL2V4YW1wbGUub3JnL3NvbWV3aGVyZS90ZXJtcy0yLjAtZW4uaHRtbFwiXG4gICAgICogICAgICAgICAgICAgfSxcbiAgICAgKiAgICAgICAgICAgICBcImZyXCI6IHtcbiAgICAgKiAgICAgICAgICAgICAgICAgXCJuYW1lXCI6IFwiQ29uZGl0aW9ucyBkJ3V0aWxpc2F0aW9uXCIsXG4gICAgICogICAgICAgICAgICAgICAgIFwidXJsXCI6IFwiaHR0cHM6Ly9leGFtcGxlLm9yZy9zb21ld2hlcmUvdGVybXMtMi4wLWZyLmh0bWxcIlxuICAgICAqICAgICAgICAgICAgIH1cbiAgICAgKiAgICAgICAgIH1cbiAgICAgKiAgICAgfVxuICAgICAqIH1cbiAgICAgKi9cblxuICAgIGNvbnN0IHRlcm1zOiB7IHBvbGljaWVzOiBQb2xpY2llcyB9W10gPSBhd2FpdCBQcm9taXNlLmFsbCh0ZXJtc1Byb21pc2VzKTtcbiAgICBjb25zdCBwb2xpY2llc0FuZFNlcnZpY2VQYWlycyA9IHRlcm1zLm1hcCgodCwgaSkgPT4ge1xuICAgICAgICByZXR1cm4geyBzZXJ2aWNlOiBzZXJ2aWNlc1tpXSwgcG9saWNpZXM6IHQucG9saWNpZXMgfTtcbiAgICB9KTtcblxuICAgIC8vIGZldGNoIHRoZSBzZXQgb2YgYWdyZWVkIHBvbGljeSBVUkxzIGZyb20gYWNjb3VudCBkYXRhXG4gICAgY29uc3QgY3VycmVudEFjY2VwdGVkVGVybXMgPSBhd2FpdCBjbGllbnQuZ2V0QWNjb3VudERhdGEoXCJtLmFjY2VwdGVkX3Rlcm1zXCIpO1xuICAgIGxldCBhZ3JlZWRVcmxTZXQ6IFNldDxzdHJpbmc+O1xuICAgIGlmICghY3VycmVudEFjY2VwdGVkVGVybXMgfHwgIWN1cnJlbnRBY2NlcHRlZFRlcm1zLmdldENvbnRlbnQoKSB8fCAhY3VycmVudEFjY2VwdGVkVGVybXMuZ2V0Q29udGVudCgpLmFjY2VwdGVkKSB7XG4gICAgICAgIGFncmVlZFVybFNldCA9IG5ldyBTZXQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBhZ3JlZWRVcmxTZXQgPSBuZXcgU2V0KGN1cnJlbnRBY2NlcHRlZFRlcm1zLmdldENvbnRlbnQoKS5hY2NlcHRlZCk7XG4gICAgfVxuXG4gICAgLy8gcmVtb3ZlIGFueSBwb2xpY2llcyB0aGUgdXNlciBoYXMgYWxyZWFkeSBhZ3JlZWQgdG8gYW5kIGFueSBzZXJ2aWNlcyB3aGVyZVxuICAgIC8vIHRoZXkndmUgYWxyZWFkeSBhZ3JlZWQgdG8gYWxsIHRoZSBwb2xpY2llc1xuICAgIC8vIE5CLiBpdCBjb3VsZCBiZSBuaWNlciB0byBzaG93IHRoZSB1c2VyIHN0dWZmIHRoZXkndmUgYWxyZWFkeSBhZ3JlZWQgdG8sXG4gICAgLy8gYnV0IHRoZW4gdGhleSdkIGFzc3VtZSB0aGV5IGNhbiB1bi1jaGVjayB0aGUgYm94ZXMgdG8gdW4tYWdyZWUgdG8gYSBwb2xpY3ksXG4gICAgLy8gYnV0IHRoYXQgaXMgbm90IGEgdGhpbmcgdGhlIEFQSSBzdXBwb3J0cywgc28gcHJvYmFibHkgYmVzdCB0byBqdXN0IHNob3dcbiAgICAvLyB0aGluZ3MgdGhleSd2ZSBub3QgYWdyZWVkIHRvIHlldC5cbiAgICBjb25zdCB1bmFncmVlZFBvbGljaWVzQW5kU2VydmljZVBhaXJzOiBTZXJ2aWNlUG9saWN5UGFpcltdID0gW107XG4gICAgZm9yIChjb25zdCB7IHNlcnZpY2UsIHBvbGljaWVzIH0gb2YgcG9saWNpZXNBbmRTZXJ2aWNlUGFpcnMpIHtcbiAgICAgICAgY29uc3QgdW5hZ3JlZWRQb2xpY2llczogUG9saWNpZXMgPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCBbcG9saWN5TmFtZSwgcG9saWN5XSBvZiBPYmplY3QuZW50cmllcyhwb2xpY2llcykpIHtcbiAgICAgICAgICAgIGxldCBwb2xpY3lBZ3JlZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAoY29uc3QgbGFuZyBvZiBPYmplY3Qua2V5cyhwb2xpY3kpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxhbmcgPT09IFwidmVyc2lvblwiKSBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBpZiAoYWdyZWVkVXJsU2V0Lmhhcyhwb2xpY3lbbGFuZ10udXJsKSkge1xuICAgICAgICAgICAgICAgICAgICBwb2xpY3lBZ3JlZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXBvbGljeUFncmVlZCkgdW5hZ3JlZWRQb2xpY2llc1twb2xpY3lOYW1lXSA9IHBvbGljeTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoT2JqZWN0LmtleXModW5hZ3JlZWRQb2xpY2llcykubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdW5hZ3JlZWRQb2xpY2llc0FuZFNlcnZpY2VQYWlycy5wdXNoKHsgc2VydmljZSwgcG9saWNpZXM6IHVuYWdyZWVkUG9saWNpZXMgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBpZiB0aGVyZSdzIGFueXRoaW5nIGxlZnQgdG8gYWdyZWUgdG8sIHByb21wdCB0aGUgdXNlclxuICAgIGNvbnN0IG51bUFjY2VwdGVkQmVmb3JlQWdyZWVtZW50ID0gYWdyZWVkVXJsU2V0LnNpemU7XG4gICAgaWYgKHVuYWdyZWVkUG9saWNpZXNBbmRTZXJ2aWNlUGFpcnMubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zdCBuZXdseUFncmVlZFVybHMgPSBhd2FpdCBpbnRlcmFjdGlvbkNhbGxiYWNrKHVuYWdyZWVkUG9saWNpZXNBbmRTZXJ2aWNlUGFpcnMsIFsuLi5hZ3JlZWRVcmxTZXRdKTtcbiAgICAgICAgbG9nZ2VyLmxvZyhcIlVzZXIgaGFzIGFncmVlZCB0byBVUkxzXCIsIG5ld2x5QWdyZWVkVXJscyk7XG4gICAgICAgIC8vIE1lcmdlIHdpdGggcHJldmlvdXNseSBhZ3JlZWQgVVJMc1xuICAgICAgICBuZXdseUFncmVlZFVybHMuZm9yRWFjaCgodXJsKSA9PiBhZ3JlZWRVcmxTZXQuYWRkKHVybCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5sb2coXCJVc2VyIGhhcyBhbHJlYWR5IGFncmVlZCB0byBhbGwgcmVxdWlyZWQgcG9saWNpZXNcIik7XG4gICAgfVxuXG4gICAgLy8gV2Ugb25seSBldmVyIGFkZCB0byB0aGUgc2V0IG9mIFVSTHMsIHNvIGlmIGFueXRoaW5nIGhhcyBjaGFuZ2VkIHRoZW4gd2UnZCBzZWUgYSBkaWZmZXJlbnQgbGVuZ3RoXG4gICAgaWYgKGFncmVlZFVybFNldC5zaXplICE9PSBudW1BY2NlcHRlZEJlZm9yZUFncmVlbWVudCkge1xuICAgICAgICBjb25zdCBuZXdBY2NlcHRlZFRlcm1zID0geyBhY2NlcHRlZDogQXJyYXkuZnJvbShhZ3JlZWRVcmxTZXQpIH07XG4gICAgICAgIGF3YWl0IGNsaWVudC5zZXRBY2NvdW50RGF0YShcIm0uYWNjZXB0ZWRfdGVybXNcIiwgbmV3QWNjZXB0ZWRUZXJtcyk7XG4gICAgfVxuXG4gICAgY29uc3QgYWdyZWVQcm9taXNlcyA9IHBvbGljaWVzQW5kU2VydmljZVBhaXJzLm1hcCgocG9saWNpZXNBbmRTZXJ2aWNlKSA9PiB7XG4gICAgICAgIC8vIGZpbHRlciB0aGUgYWdyZWVkIFVSTCBsaXN0IGZvciBvbmVzIHRoYXQgYXJlIGFjdHVhbGx5IGZvciB0aGlzIHNlcnZpY2VcbiAgICAgICAgLy8gKG9uZSBVUkwgbWF5IGJlIHVzZWQgZm9yIG11bHRpcGxlIHNlcnZpY2VzKVxuICAgICAgICAvLyBOb3QgYSBwYXJ0aWN1bGFybHkgZWZmaWNpZW50IGxvb3AgYnV0IHByb2JhYmx5IGZpbmUgZ2l2ZW4gdGhlIG51bWJlcnMgaW52b2x2ZWRcbiAgICAgICAgY29uc3QgdXJsc0ZvclNlcnZpY2UgPSBBcnJheS5mcm9tKGFncmVlZFVybFNldCkuZmlsdGVyKCh1cmwpID0+IHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcG9saWN5IG9mIE9iamVjdC52YWx1ZXMocG9saWNpZXNBbmRTZXJ2aWNlLnBvbGljaWVzKSkge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbGFuZyBvZiBPYmplY3Qua2V5cyhwb2xpY3kpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYW5nID09PSBcInZlcnNpb25cIikgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwb2xpY3lbbGFuZ10udXJsID09PSB1cmwpIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHVybHNGb3JTZXJ2aWNlLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuXG4gICAgICAgIHJldHVybiBjbGllbnQuYWdyZWVUb1Rlcm1zKFxuICAgICAgICAgICAgcG9saWNpZXNBbmRTZXJ2aWNlLnNlcnZpY2Uuc2VydmljZVR5cGUsXG4gICAgICAgICAgICBwb2xpY2llc0FuZFNlcnZpY2Uuc2VydmljZS5iYXNlVXJsLFxuICAgICAgICAgICAgcG9saWNpZXNBbmRTZXJ2aWNlLnNlcnZpY2UuYWNjZXNzVG9rZW4sXG4gICAgICAgICAgICB1cmxzRm9yU2VydmljZSxcbiAgICAgICAgKTtcbiAgICB9KTtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChhZ3JlZVByb21pc2VzKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRpYWxvZ1Rlcm1zSW50ZXJhY3Rpb25DYWxsYmFjayhcbiAgICBwb2xpY2llc0FuZFNlcnZpY2VQYWlyczoge1xuICAgICAgICBzZXJ2aWNlOiBTZXJ2aWNlO1xuICAgICAgICBwb2xpY2llczogeyBbcG9saWN5OiBzdHJpbmddOiBQb2xpY3kgfTtcbiAgICB9W10sXG4gICAgYWdyZWVkVXJsczogc3RyaW5nW10sXG4gICAgZXh0cmFDbGFzc05hbWVzPzogc3RyaW5nLFxuKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGxvZ2dlci5sb2coXCJUZXJtcyB0aGF0IG5lZWQgYWdyZWVtZW50XCIsIHBvbGljaWVzQW5kU2VydmljZVBhaXJzKTtcblxuICAgIGNvbnN0IHsgZmluaXNoZWQgfSA9IE1vZGFsLmNyZWF0ZURpYWxvZyhcbiAgICAgICAgVGVybXNEaWFsb2csXG4gICAgICAgIHtcbiAgICAgICAgICAgIHBvbGljaWVzQW5kU2VydmljZVBhaXJzLFxuICAgICAgICAgICAgYWdyZWVkVXJscyxcbiAgICAgICAgfSxcbiAgICAgICAgY2xhc3NOYW1lcyhcIm14X1Rlcm1zRGlhbG9nXCIsIGV4dHJhQ2xhc3NOYW1lcyksXG4gICAgKTtcblxuICAgIGNvbnN0IFtkb25lLCBfYWdyZWVkVXJsc10gPSBhd2FpdCBmaW5pc2hlZDtcbiAgICBpZiAoIWRvbmUgfHwgIV9hZ3JlZWRVcmxzKSB7XG4gICAgICAgIHRocm93IG5ldyBUZXJtc05vdFNpZ25lZEVycm9yKCk7XG4gICAgfVxuICAgIHJldHVybiBfYWdyZWVkVXJscztcbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7O0FBUUEsSUFBQUEsV0FBQSxHQUFBQyxzQkFBQSxDQUFBQyxPQUFBO0FBRUEsSUFBQUMsT0FBQSxHQUFBRCxPQUFBO0FBRUEsSUFB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RTtJQUNBO0lBQ0E7SUFDQSxNQUFNQyxjQUFjLEdBQUdMLEtBQUssQ0FBQ0MsSUFBSSxDQUFDMUIsWUFBWSxDQUFDLENBQUMrQixNQUFNLENBQUVqQixHQUFHLElBQUs7TUFDNUQsS0FBSyxNQUFNUCxNQUFNLElBQUlDLE1BQU0sQ0FBQ3dCLE1BQU0sQ0FBQ0gsa0JBQWtCLENBQUNoQyxRQUFRLENBQUMsRUFBRTtRQUM3RCxLQUFLLE1BQU1jLElBQUksSUFBSUgsTUFBTSxDQUFDSSxJQUFJLENBQUNMLE1BQU0sQ0FBQyxFQUFFO1VBQ3BDLElBQUlJLElBQUksS0FBSyxTQUFTLEVBQUU7VUFDeEIsSUFBSUosTUFBTSxDQUFDSSxJQUFJLENBQUMsQ0FBQ0csR0FBRyxLQUFLQSxHQUFHLEVBQUUsT0FBTyxJQUFJO1FBQzdDO01BQ0o7TUFDQSxPQUFPLEtBQUs7SUFDaEIsQ0FBQyxDQUFDO0lBRUYsSUFBSWdCLGNBQWMsQ0FBQ2YsTUFBTSxLQUFLLENBQUMsRUFBRSxPQUFPeEIsT0FBTyxDQUFDMEMsT0FBTyxDQUFDLENBQUM7SUFFekQsT0FBT25ELE1BQU0sQ0FBQ29ELFlBQVksQ0FDdEJMLGtCQUFrQixDQUFDakMsT0FBTyxDQUFDbEIsV0FBVyxFQUN0Q21ELGtCQUFrQixDQUFDakMsT0FBTyxDQUFDakIsT0FBTyxFQUNsQ2tELGtCQUFrQixDQUFDakMsT0FBTyxDQUFDaEIsV0FBVyxFQUN0Q2tELGNBQ0osQ0FBQztFQUNMLENBQUMsQ0FBQztFQUNGLE1BQU12QyxPQUFPLENBQUNDLEdBQUcsQ0FBQ29DLGFBQWEsQ0FBQztBQUNwQztBQUVPLGVBQWUzQyw4QkFBOEJBLENBQ2hEUSx1QkFHRyxFQUNIMEMsVUFBb0IsRUFDcEJDLGVBQXdCLEVBQ1A7RUFDakJoQixjQUFNLENBQUNDLEdBQUcsQ0FBQywyQkFBMkIsRUFBRTVCLHVCQUF1QixDQUFDO0VBRWhFLE1BQU07SUFBRTRDO0VBQVMsQ0FBQyxHQUFHQyxjQUFLLENBQUNDLFlBQVksQ0FDbkNDLG9CQUFXLEVBQ1g7SUFDSS9DLHVCQUF1QjtJQUN2QjBDO0VBQ0osQ0FBQyxFQUNELElBQUFNLG1CQUFVLEVBQUMsZ0JBQWdCLEVBQUVMLGVBQWUsQ0FDaEQsQ0FBQztFQUVELE1BQU0sQ0FBQ00sSUFBSSxFQUFFQyxXQUFXLENBQUMsR0FBRyxNQUFNTixRQUFRO0VBQzFDLElBQUksQ0FBQ0ssSUFBSSxJQUFJLENBQUNDLFdBQVcsRUFBRTtJQUN2QixNQUFNLElBQUl0RSxtQkFBbUIsQ0FBQyxDQUFDO0VBQ25DO0VBQ0EsT0FBT3NFLFdBQVc7QUFDdEIiLCJpZ25vcmVMaXN0IjpbXX0=