@webex/webex-core
Version:
Plugin handling for Cisco Webex
434 lines (430 loc) • 19.2 kB
JavaScript
"use strict";
var _Array$from = require("@babel/runtime-corejs2/core-js/array/from");
var _Symbol = require("@babel/runtime-corejs2/core-js/symbol");
var _Symbol$iterator = require("@babel/runtime-corejs2/core-js/symbol/iterator");
var _Array$isArray = require("@babel/runtime-corejs2/core-js/array/is-array");
var _Object$keys3 = require("@babel/runtime-corejs2/core-js/object/keys");
var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs2/core-js/object/get-own-property-symbols");
var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptor");
var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs2/core-js/object/get-own-property-descriptors");
var _Object$defineProperties = require("@babel/runtime-corejs2/core-js/object/define-properties");
var _Object$defineProperty = require("@babel/runtime-corejs2/core-js/object/define-property");
var _interopRequireDefault = require("@babel/runtime-corejs2/helpers/interopRequireDefault");
_Object$defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _keys = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/object/keys"));
var _promise = _interopRequireDefault(require("@babel/runtime-corejs2/core-js/promise"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/defineProperty"));
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime-corejs2/helpers/toConsumableArray"));
var _url = _interopRequireDefault(require("url"));
var _ampersandState = _interopRequireDefault(require("ampersand-state"));
var _lodash = require("lodash");
var _serviceUrl = _interopRequireDefault(require("./service-url"));
function ownKeys(e, r) { var t = _Object$keys3(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof _Symbol !== "undefined" && o[_Symbol$iterator] || o["@@iterator"]; if (!it) { if (_Array$isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return _Array$from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
/* eslint-disable no-underscore-dangle */
/**
* @class
*/
var ServiceCatalog = _ampersandState.default.extend({
namespace: 'ServiceCatalog',
props: {
serviceGroups: ['object', true, function () {
return {
discovery: [],
override: [],
preauth: [],
postauth: [],
signin: []
};
}],
status: ['object', true, function () {
return {
discovery: {
ready: false,
collecting: false
},
override: {
ready: false,
collecting: false
},
preauth: {
ready: false,
collecting: false
},
postauth: {
ready: false,
collecting: false
},
signin: {
ready: false,
collecting: false
}
};
}],
isReady: ['boolean', false, false],
allowedDomains: ['array', false, function () {
return [];
}]
},
/**
* @private
* Search the service url array to locate a `ServiceUrl`
* class object based on its name.
* @param {string} name
* @param {string} [serviceGroup]
* @returns {ServiceUrl}
*/
_getUrl: function _getUrl(name, serviceGroup) {
var serviceUrls = typeof serviceGroup === 'string' ? this.serviceGroups[serviceGroup] || [] : [].concat((0, _toConsumableArray2.default)(this.serviceGroups.override), (0, _toConsumableArray2.default)(this.serviceGroups.postauth), (0, _toConsumableArray2.default)(this.serviceGroups.signin), (0, _toConsumableArray2.default)(this.serviceGroups.preauth), (0, _toConsumableArray2.default)(this.serviceGroups.discovery));
return serviceUrls.find(function (serviceUrl) {
return serviceUrl.name === name;
});
},
/**
* @private
* Generate an array of `ServiceUrl`s that is organized from highest auth
* level to lowest auth level.
* @returns {Array<ServiceUrl>} - array of `ServiceUrl`s
*/
_listServiceUrls: function _listServiceUrls() {
return [].concat((0, _toConsumableArray2.default)(this.serviceGroups.override), (0, _toConsumableArray2.default)(this.serviceGroups.postauth), (0, _toConsumableArray2.default)(this.serviceGroups.signin), (0, _toConsumableArray2.default)(this.serviceGroups.preauth), (0, _toConsumableArray2.default)(this.serviceGroups.discovery));
},
/**
* @private
* Safely load one or more `ServiceUrl`s into this `Services` instance.
* @param {string} serviceGroup
* @param {Array<ServiceUrl>} services
* @returns {Services}
*/
_loadServiceUrls: function _loadServiceUrls(serviceGroup, services) {
var _this = this;
// declare namespaces outside of loop
var existingService;
services.forEach(function (service) {
existingService = _this._getUrl(service.name, serviceGroup);
if (!existingService) {
_this.serviceGroups[serviceGroup].push(service);
}
});
return this;
},
/**
* @private
* Safely unload one or more `ServiceUrl`s into this `Services` instance
* @param {string} serviceGroup
* @param {Array<ServiceUrl>} services
* @returns {Services}
*/
_unloadServiceUrls: function _unloadServiceUrls(serviceGroup, services) {
var _this2 = this;
// declare namespaces outside of loop
var existingService;
services.forEach(function (service) {
existingService = _this2._getUrl(service.name, serviceGroup);
if (existingService) {
_this2.serviceGroups[serviceGroup].splice(_this2.serviceGroups[serviceGroup].indexOf(existingService), 1);
}
});
return this;
},
/**
* Clear all collected catalog data and reset catalog status.
*
* @returns {void}
*/
clean: function clean() {
this.serviceGroups.preauth.length = 0;
this.serviceGroups.signin.length = 0;
this.serviceGroups.postauth.length = 0;
this.status.preauth = {
ready: false
};
this.status.signin = {
ready: false
};
this.status.postauth = {
ready: false
};
},
/**
* Search over all service groups to find a cluster id based
* on a given url.
* @param {string} url - Must be parsable by `Url`
* @returns {string} - ClusterId of a given url
*/
findClusterId: function findClusterId(url) {
var incomingUrlObj = _url.default.parse(url);
var serviceUrlObj;
for (var _i = 0, _Object$keys = (0, _keys.default)(this.serviceGroups); _i < _Object$keys.length; _i++) {
var key = _Object$keys[_i];
var _iterator = _createForOfIteratorHelper(this.serviceGroups[key]),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var service = _step.value;
serviceUrlObj = _url.default.parse(service.defaultUrl);
var _iterator2 = _createForOfIteratorHelper(service.hosts),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var _host = _step2.value;
if (incomingUrlObj.hostname === _host.host && _host.id) {
return _host.id;
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
if (serviceUrlObj.hostname === incomingUrlObj.hostname && service.hosts.length > 0) {
// no exact match, so try to grab the first home cluster
var _iterator3 = _createForOfIteratorHelper(service.hosts),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var host = _step3.value;
if (host.homeCluster) {
return host.id;
}
}
// no match found still, so return the first entry
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
return service.hosts[0].id;
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
}
return undefined;
},
/**
* Search over all service groups and return a service value from a provided
* clusterId. Currently, this method will return either a service name, or a
* service url depending on the `value` parameter. If the `value` parameter
* is set to `name`, it will return a service name to be utilized within the
* Services plugin methods.
* @param {object} params
* @param {string} params.clusterId - clusterId of found service
* @param {boolean} [params.priorityHost = true] - returns priority host url if true
* @param {string} [params.serviceGroup] - specify service group
* @returns {object} service
* @returns {string} service.name
* @returns {string} service.url
*/
findServiceFromClusterId: function findServiceFromClusterId() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
clusterId = _ref.clusterId,
_ref$priorityHost = _ref.priorityHost,
priorityHost = _ref$priorityHost === void 0 ? true : _ref$priorityHost,
serviceGroup = _ref.serviceGroup;
var serviceUrls = typeof serviceGroup === 'string' ? this.serviceGroups[serviceGroup] || [] : [].concat((0, _toConsumableArray2.default)(this.serviceGroups.override), (0, _toConsumableArray2.default)(this.serviceGroups.postauth), (0, _toConsumableArray2.default)(this.serviceGroups.signin), (0, _toConsumableArray2.default)(this.serviceGroups.preauth), (0, _toConsumableArray2.default)(this.serviceGroups.discovery));
var identifiedServiceUrl = serviceUrls.find(function (serviceUrl) {
return serviceUrl.hosts.find(function (host) {
return host.id === clusterId;
});
});
if (identifiedServiceUrl) {
return {
name: identifiedServiceUrl.name,
url: identifiedServiceUrl.get(priorityHost, clusterId)
};
}
return undefined;
},
/**
* Find a service based on the provided url.
* @param {string} url - Must be parsable by `Url`
* @returns {serviceUrl} - ServiceUrl assocated with provided url
*/
findServiceUrlFromUrl: function findServiceUrlFromUrl(url) {
var serviceUrls = [].concat((0, _toConsumableArray2.default)(this.serviceGroups.discovery), (0, _toConsumableArray2.default)(this.serviceGroups.preauth), (0, _toConsumableArray2.default)(this.serviceGroups.signin), (0, _toConsumableArray2.default)(this.serviceGroups.postauth), (0, _toConsumableArray2.default)(this.serviceGroups.override));
return serviceUrls.find(function (serviceUrl) {
// Check to see if the URL we are checking starts with the default URL
if (url.startsWith(serviceUrl.defaultUrl)) {
return true;
}
// If not, we check to see if the alternate URLs match
// These are made by swapping the host of the default URL
// with that of an alternate host
var _iterator4 = _createForOfIteratorHelper(serviceUrl.hosts),
_step4;
try {
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
var host = _step4.value;
var alternateUrl = new URL(serviceUrl.defaultUrl);
alternateUrl.host = host.host;
if (url.startsWith(alternateUrl.toString())) {
return true;
}
}
} catch (err) {
_iterator4.e(err);
} finally {
_iterator4.f();
}
return false;
});
},
/**
* Finds an allowed domain that matches a specific url.
*
* @param {string} url - The url to match the allowed domains against.
* @returns {string} - The matching allowed domain.
*/
findAllowedDomain: function findAllowedDomain(url) {
var urlObj = _url.default.parse(url);
if (!urlObj.host) {
return undefined;
}
return this.allowedDomains.find(function (allowedDomain) {
return urlObj.host.includes(allowedDomain);
});
},
/**
* Get a service url from the current services list by name.
* @param {string} name
* @param {boolean} priorityHost
* @param {string} serviceGroup
* @returns {string}
*/
get: function get(name, priorityHost, serviceGroup) {
var serviceUrl = this._getUrl(name, serviceGroup);
return serviceUrl ? serviceUrl.get(priorityHost) : undefined;
},
/**
* Get the current allowed domains list.
*
* @returns {Array<string>} - the current allowed domains list.
*/
getAllowedDomains: function getAllowedDomains() {
return (0, _toConsumableArray2.default)(this.allowedDomains);
},
/**
* Creates an object where the keys are the service names
* and the values are the service urls.
* @param {boolean} priorityHost - use the highest priority if set to `true`
* @param {string} [serviceGroup]
* @returns {Record<string, string>}
*/
list: function list(priorityHost, serviceGroup) {
var output = {};
var serviceUrls = typeof serviceGroup === 'string' ? this.serviceGroups[serviceGroup] || [] : [].concat((0, _toConsumableArray2.default)(this.serviceGroups.discovery), (0, _toConsumableArray2.default)(this.serviceGroups.preauth), (0, _toConsumableArray2.default)(this.serviceGroups.signin), (0, _toConsumableArray2.default)(this.serviceGroups.postauth), (0, _toConsumableArray2.default)(this.serviceGroups.override));
if (serviceUrls) {
serviceUrls.forEach(function (serviceUrl) {
output[serviceUrl.name] = serviceUrl.get(priorityHost);
});
}
return output;
},
/**
* Mark a priority host service url as failed.
* This will mark the host associated with the
* `ServiceUrl` to be removed from the its
* respective host array, and then return the next
* viable host from the `ServiceUrls` host array,
* or the `ServiceUrls` default url if no other priority
* hosts are available, or if `noPriorityHosts` is set to
* `true`.
* @param {string} url
* @param {boolean} noPriorityHosts
* @returns {string}
*/
markFailedUrl: function markFailedUrl(url, noPriorityHosts) {
var _this3 = this;
var serviceUrl = this._getUrl((0, _keys.default)(this.list()).find(function (key) {
return _this3._getUrl(key).failHost(url);
}));
if (!serviceUrl) {
return undefined;
}
return noPriorityHosts ? serviceUrl.get(false) : serviceUrl.get(true);
},
/**
* Set the allowed domains for the catalog.
*
* @param {Array<string>} allowedDomains - allowed domains to be assigned.
* @returns {void}
*/
setAllowedDomains: function setAllowedDomains(allowedDomains) {
this.allowedDomains = (0, _toConsumableArray2.default)(allowedDomains);
},
/**
*
* @param {Array<string>} newAllowedDomains - new allowed domains to add to existing set of allowed domains
* @returns {void}
*/
addAllowedDomains: function addAllowedDomains(newAllowedDomains) {
this.allowedDomains = (0, _lodash.union)(this.allowedDomains, newAllowedDomains);
},
/**
* Update the current list of `ServiceUrl`s against a provided
* service hostmap.
* @emits ServiceCatalog#preauthorized
* @emits ServiceCatalog#postauthorized
* @param {string} serviceGroup
* @param {object} serviceHostmap
* @returns {Services}
*/
updateServiceUrls: function updateServiceUrls(serviceGroup, serviceHostmap) {
var _this4 = this;
var currentServiceUrls = this.serviceGroups[serviceGroup];
var unusedUrls = currentServiceUrls.filter(function (serviceUrl) {
return serviceHostmap.every(function (item) {
return item.name !== serviceUrl.name;
});
});
this._unloadServiceUrls(serviceGroup, unusedUrls);
serviceHostmap.forEach(function (serviceObj) {
var service = _this4._getUrl(serviceObj.name, serviceGroup);
if (service) {
service.defaultUrl = serviceObj.defaultUrl;
service.hosts = serviceObj.hosts || [];
} else {
_this4._loadServiceUrls(serviceGroup, [new _serviceUrl.default(_objectSpread({}, serviceObj))]);
}
});
this.status[serviceGroup].ready = true;
this.trigger(serviceGroup);
return this;
},
/**
* Wait until the service catalog is available,
* or reject after a timeout of 60 seconds.
* @param {string} serviceGroup
* @param {number} [timeout] - in seconds
* @returns {Promise<void>}
*/
waitForCatalog: function waitForCatalog(serviceGroup, timeout) {
var _this5 = this;
return new _promise.default(function (resolve, reject) {
if (_this5.status[serviceGroup].ready) {
resolve();
}
var validatedTimeout = typeof timeout === 'number' && timeout >= 0 ? timeout : 60;
var timeoutTimer = setTimeout(function () {
return reject(new Error("services: timeout occured while waiting for '".concat(serviceGroup, "' catalog to populate")));
}, validatedTimeout * 1000);
_this5.once(serviceGroup, function () {
clearTimeout(timeoutTimer);
resolve();
});
});
}
});
/* eslint-enable no-underscore-dangle */
var _default = exports.default = ServiceCatalog;
//# sourceMappingURL=service-catalog.js.map