@webex/webex-core 3.8.1 → 3.9.0-multi-llms.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -27
- package/dist/index.js +16 -33
- package/dist/index.js.map +1 -1
- package/dist/{lib/services/interceptors/hostmap.js → interceptors/proxy.js} +58 -25
- package/dist/interceptors/proxy.js.map +1 -0
- package/dist/lib/batcher.js +1 -1
- package/dist/lib/constants.js +10 -1
- package/dist/lib/constants.js.map +1 -1
- package/dist/lib/credentials/credentials.js +1 -1
- package/dist/lib/credentials/token.js +1 -1
- package/dist/lib/{services-v2/interceptors → interceptors}/server-error.js +1 -1
- package/dist/lib/interceptors/server-error.js.map +1 -0
- package/dist/lib/services/index.js +2 -29
- package/dist/lib/services/index.js.map +1 -1
- package/dist/lib/services/service-host.js +1 -1
- package/dist/lib/services/service-host.js.map +1 -1
- package/dist/lib/services/service-registry.js +1 -1
- package/dist/lib/services/service-registry.js.map +1 -1
- package/dist/lib/services/service-state.js +1 -1
- package/dist/lib/services/service-state.js.map +1 -1
- package/dist/lib/services/services.js +3 -3
- package/dist/lib/services/services.js.map +1 -1
- package/dist/lib/services-v2/index.js +0 -29
- package/dist/lib/services-v2/index.js.map +1 -1
- package/dist/lib/services-v2/metrics.js.map +1 -1
- package/dist/lib/services-v2/service-catalog.js +15 -11
- package/dist/lib/services-v2/service-catalog.js.map +1 -1
- package/dist/lib/services-v2/services-v2.js +160 -111
- package/dist/lib/services-v2/services-v2.js.map +1 -1
- package/dist/lib/services-v2/types.js.map +1 -1
- package/dist/plugins/logger.js +1 -1
- package/dist/webex-core.js +53 -60
- package/dist/webex-core.js.map +1 -1
- package/package.json +14 -14
- package/src/index.js +6 -14
- package/src/interceptors/proxy.js +70 -0
- package/src/lib/constants.js +29 -1
- package/src/lib/{services/interceptors → interceptors}/server-error.js +1 -1
- package/src/lib/services/index.js +2 -7
- package/src/lib/services/service-host.js +1 -1
- package/src/lib/services/service-registry.js +1 -1
- package/src/lib/services/service-state.js +1 -1
- package/src/lib/services/services.js +2 -2
- package/src/lib/services-v2/index.ts +0 -16
- package/src/lib/services-v2/service-catalog.ts +27 -19
- package/src/lib/services-v2/{services-v2.js → services-v2.ts} +188 -104
- package/src/lib/services-v2/types.ts +62 -2
- package/src/webex-core.js +12 -3
- package/test/fixtures/host-catalog-v2.ts +30 -122
- package/test/integration/spec/services/services.js +11 -0
- package/test/integration/spec/services-v2/service-catalog.js +664 -0
- package/test/integration/spec/services-v2/services-v2.js +1136 -0
- package/test/unit/spec/interceptors/proxy.js +73 -0
- package/test/unit/spec/services-v2/service-detail.ts +1 -1
- package/test/unit/spec/services-v2/services-v2.ts +579 -442
- package/test/unit/spec/webex-core.js +62 -2
- package/dist/lib/services/constants.js +0 -17
- package/dist/lib/services/constants.js.map +0 -1
- package/dist/lib/services/interceptors/hostmap.js.map +0 -1
- package/dist/lib/services/interceptors/server-error.js +0 -77
- package/dist/lib/services/interceptors/server-error.js.map +0 -1
- package/dist/lib/services/interceptors/service.js +0 -137
- package/dist/lib/services/interceptors/service.js.map +0 -1
- package/dist/lib/services-v2/constants.js +0 -17
- package/dist/lib/services-v2/constants.js.map +0 -1
- package/dist/lib/services-v2/interceptors/server-error.js.map +0 -1
- package/dist/lib/services-v2/service-host.js +0 -300
- package/dist/lib/services-v2/service-host.js.map +0 -1
- package/dist/lib/services-v2/service-registry.js +0 -534
- package/dist/lib/services-v2/service-registry.js.map +0 -1
- package/dist/lib/services-v2/service-state.js +0 -97
- package/dist/lib/services-v2/service-state.js.map +0 -1
- package/dist/lib/services-v2/service-url.js +0 -119
- package/dist/lib/services-v2/service-url.js.map +0 -1
- package/src/lib/services/constants.js +0 -21
- package/src/lib/services/interceptors/hostmap.js +0 -36
- package/src/lib/services/interceptors/service.js +0 -101
- package/src/lib/services-v2/constants.ts +0 -21
- package/src/lib/services-v2/interceptors/server-error.js +0 -48
- /package/dist/lib/{services-v2/interceptors → interceptors}/hostmap.js +0 -0
- /package/dist/lib/{services-v2/interceptors → interceptors}/hostmap.js.map +0 -0
- /package/dist/lib/{services-v2/interceptors → interceptors}/service.js +0 -0
- /package/dist/lib/{services-v2/interceptors → interceptors}/service.js.map +0 -0
- /package/dist/lib/{services/metrics.js → metrics.js} +0 -0
- /package/dist/lib/{services/metrics.js.map → metrics.js.map} +0 -0
- /package/src/lib/{services-v2/interceptors → interceptors}/hostmap.js +0 -0
- /package/src/lib/{services-v2/interceptors → interceptors}/service.js +0 -0
- /package/src/lib/{services-v2/metrics.js → metrics.js} +0 -0
- /package/src/lib/{services/metrics.js → services-v2/metrics.ts} +0 -0
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import sha256 from 'crypto-js/sha256';
|
|
2
2
|
|
|
3
|
-
import {union, unionBy} from 'lodash';
|
|
3
|
+
import {toNumber, union, unionBy} from 'lodash';
|
|
4
4
|
import WebexPlugin from '../webex-plugin';
|
|
5
5
|
|
|
6
|
-
import METRICS from '
|
|
6
|
+
import METRICS from '../metrics';
|
|
7
7
|
import ServiceCatalog from './service-catalog';
|
|
8
8
|
import fedRampServices from './service-fed-ramp';
|
|
9
|
-
import {COMMERCIAL_ALLOWED_DOMAINS} from '
|
|
9
|
+
import {COMMERCIAL_ALLOWED_DOMAINS} from '../constants';
|
|
10
|
+
import {
|
|
11
|
+
ActiveServices,
|
|
12
|
+
IServiceCatalog,
|
|
13
|
+
QueryOptions,
|
|
14
|
+
Service,
|
|
15
|
+
ServiceHostmap,
|
|
16
|
+
ServiceGroup,
|
|
17
|
+
} from './types';
|
|
10
18
|
|
|
11
19
|
const trailingSlashes = /(?:^\/)|(?:\/$)/;
|
|
12
20
|
|
|
@@ -41,9 +49,9 @@ const Services = WebexPlugin.extend({
|
|
|
41
49
|
* @private
|
|
42
50
|
* Get the current catalog based on the assocaited
|
|
43
51
|
* webex instance.
|
|
44
|
-
* @returns {
|
|
52
|
+
* @returns {IServiceCatalog}
|
|
45
53
|
*/
|
|
46
|
-
_getCatalog() {
|
|
54
|
+
_getCatalog(): IServiceCatalog {
|
|
47
55
|
return this._catalogs.get(this.webex);
|
|
48
56
|
},
|
|
49
57
|
|
|
@@ -51,14 +59,23 @@ const Services = WebexPlugin.extend({
|
|
|
51
59
|
* Get a service url from the current services list by name
|
|
52
60
|
* from the associated instance catalog.
|
|
53
61
|
* @param {string} name
|
|
54
|
-
* @param {
|
|
55
|
-
* @param {string} [serviceGroup]
|
|
62
|
+
* @param {ServiceGroup} [serviceGroup]
|
|
56
63
|
* @returns {string|undefined}
|
|
57
64
|
*/
|
|
58
|
-
get(name
|
|
65
|
+
get(name: string, serviceGroup?: ServiceGroup): string | undefined {
|
|
59
66
|
const catalog = this._getCatalog();
|
|
60
67
|
|
|
61
|
-
|
|
68
|
+
const clusterId = this._activeServices[name];
|
|
69
|
+
|
|
70
|
+
const urlById = catalog.get(clusterId, serviceGroup);
|
|
71
|
+
const urlByName = catalog.get(name, serviceGroup);
|
|
72
|
+
|
|
73
|
+
// if both are undefined, then we cannot find the service
|
|
74
|
+
if (!urlById && !urlByName) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return urlById || urlByName;
|
|
62
79
|
},
|
|
63
80
|
|
|
64
81
|
/**
|
|
@@ -66,59 +83,42 @@ const Services = WebexPlugin.extend({
|
|
|
66
83
|
*
|
|
67
84
|
* @returns {boolean} - True if a allowed domains list exists.
|
|
68
85
|
*/
|
|
69
|
-
hasAllowedDomains() {
|
|
86
|
+
hasAllowedDomains(): boolean {
|
|
70
87
|
const catalog = this._getCatalog();
|
|
71
88
|
|
|
72
89
|
return catalog.getAllowedDomains().length > 0;
|
|
73
90
|
},
|
|
74
91
|
|
|
75
|
-
/**
|
|
76
|
-
* Generate a service catalog as an object from
|
|
77
|
-
* the associated instance catalog.
|
|
78
|
-
* @param {boolean} [priorityHost] - use highest priority host if set to `true`
|
|
79
|
-
* @param {string} [serviceGroup]
|
|
80
|
-
* @returns {Record<string, string>}
|
|
81
|
-
*/
|
|
82
|
-
list(priorityHost, serviceGroup) {
|
|
83
|
-
const catalog = this._getCatalog();
|
|
84
|
-
|
|
85
|
-
return catalog.list(priorityHost, serviceGroup);
|
|
86
|
-
},
|
|
87
|
-
|
|
88
92
|
/**
|
|
89
93
|
* Mark a priority host service url as failed.
|
|
90
|
-
* This will mark the
|
|
91
|
-
* `
|
|
92
|
-
* respective
|
|
93
|
-
* viable
|
|
94
|
-
* or the `ServiceUrls` default url if no other priority
|
|
95
|
-
* hosts are available, or if `noPriorityHosts` is set to
|
|
96
|
-
* `true`.
|
|
94
|
+
* This will mark the service url associated with the
|
|
95
|
+
* `ServiceDetail` to be removed from the its
|
|
96
|
+
* respective service url array, and then return the next
|
|
97
|
+
* viable service url from the `ServiceDetail` service url array.
|
|
97
98
|
* @param {string} url
|
|
98
|
-
* @param {boolean} noPriorityHosts
|
|
99
99
|
* @returns {string}
|
|
100
100
|
*/
|
|
101
|
-
markFailedUrl(url
|
|
101
|
+
markFailedUrl(url: string): string | undefined {
|
|
102
102
|
const catalog = this._getCatalog();
|
|
103
103
|
|
|
104
|
-
return catalog.
|
|
104
|
+
return catalog.markFailedServiceUrl(url);
|
|
105
105
|
},
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
108
|
* saves all the services from the pre and post catalog service
|
|
109
|
-
* @param {
|
|
109
|
+
* @param {ActiveServices} activeServices
|
|
110
110
|
* @returns {void}
|
|
111
111
|
*/
|
|
112
|
-
_updateActiveServices(activeServices) {
|
|
112
|
+
_updateActiveServices(activeServices: ActiveServices): void {
|
|
113
113
|
this._activeServices = {...this._activeServices, ...activeServices};
|
|
114
114
|
},
|
|
115
115
|
|
|
116
116
|
/**
|
|
117
117
|
* saves the hostCatalog object
|
|
118
|
-
* @param {
|
|
118
|
+
* @param {Array<Service>} services
|
|
119
119
|
* @returns {void}
|
|
120
120
|
*/
|
|
121
|
-
_updateServices(services) {
|
|
121
|
+
_updateServices(services: Array<Service>): void {
|
|
122
122
|
this._services = unionBy(services, this._services, 'id');
|
|
123
123
|
},
|
|
124
124
|
|
|
@@ -135,7 +135,14 @@ const Services = WebexPlugin.extend({
|
|
|
135
135
|
* @param {string} [param.token] - used for signin catalog
|
|
136
136
|
* @returns {Promise<object>}
|
|
137
137
|
*/
|
|
138
|
-
updateServices(
|
|
138
|
+
updateServices(
|
|
139
|
+
{from, query, token, forceRefresh} = {} as {
|
|
140
|
+
from: string;
|
|
141
|
+
query: QueryOptions;
|
|
142
|
+
token: string;
|
|
143
|
+
forceRefresh: boolean;
|
|
144
|
+
}
|
|
145
|
+
): Promise<object> {
|
|
139
146
|
const catalog = this._getCatalog();
|
|
140
147
|
let formattedQuery;
|
|
141
148
|
let serviceGroup;
|
|
@@ -152,9 +159,8 @@ const Services = WebexPlugin.extend({
|
|
|
152
159
|
serviceGroup = 'postauth';
|
|
153
160
|
break;
|
|
154
161
|
}
|
|
155
|
-
|
|
156
162
|
// confirm catalog update for group is not in progress.
|
|
157
|
-
if (catalog.status[serviceGroup]
|
|
163
|
+
if (catalog.status?.[serviceGroup]?.collecting) {
|
|
158
164
|
return this.waitForCatalog(serviceGroup);
|
|
159
165
|
}
|
|
160
166
|
|
|
@@ -188,8 +194,12 @@ const Services = WebexPlugin.extend({
|
|
|
188
194
|
query: formattedQuery,
|
|
189
195
|
forceRefresh,
|
|
190
196
|
})
|
|
191
|
-
.then((serviceHostMap) => {
|
|
192
|
-
catalog.updateServiceGroups(
|
|
197
|
+
.then((serviceHostMap: ServiceHostmap) => {
|
|
198
|
+
catalog.updateServiceGroups(
|
|
199
|
+
serviceGroup,
|
|
200
|
+
serviceHostMap?.services,
|
|
201
|
+
serviceHostMap?.timestamp
|
|
202
|
+
);
|
|
193
203
|
this.updateCredentialsConfig();
|
|
194
204
|
catalog.status[serviceGroup].collecting = false;
|
|
195
205
|
})
|
|
@@ -283,7 +293,7 @@ const Services = WebexPlugin.extend({
|
|
|
283
293
|
// Retrieve the service url from the updated catalog. This is required
|
|
284
294
|
// since `WebexCore` is usually not fully initialized at the time this
|
|
285
295
|
// request completes.
|
|
286
|
-
const idbrokerService = this.get('idbroker'
|
|
296
|
+
const idbrokerService = this.get('idbroker');
|
|
287
297
|
|
|
288
298
|
// Collect the client auth token.
|
|
289
299
|
return this.webex.credentials.getClientToken({
|
|
@@ -338,7 +348,56 @@ const Services = WebexPlugin.extend({
|
|
|
338
348
|
})
|
|
339
349
|
);
|
|
340
350
|
},
|
|
351
|
+
/**
|
|
352
|
+
* Update cluster id via mercury service update. If the cluster id does not exist,
|
|
353
|
+
* fetch new catalog.
|
|
354
|
+
*
|
|
355
|
+
* @param {ActiveServices} newActiveClusters - The new active clusters to switch to.
|
|
356
|
+
* @returns {Promsie<void>}
|
|
357
|
+
* */
|
|
358
|
+
switchActiveClusterIds(newActiveClusters: ActiveServices): Promise<void> {
|
|
359
|
+
this.logger.info('services: switching active cluster ids');
|
|
360
|
+
|
|
361
|
+
const newActiveClusterIds = Object.values(newActiveClusters);
|
|
362
|
+
|
|
363
|
+
const missingClusterIds = newActiveClusterIds.some((clusterId) => {
|
|
364
|
+
// if the clusterId does not exist in the catalog, fetch the catalog
|
|
365
|
+
return !this._services.find((service) => service.id === clusterId);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
if (missingClusterIds) {
|
|
369
|
+
this.logger.warn(
|
|
370
|
+
'services: some cluster ids do not exist in the catalog, fetching the catalog'
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
// fetch the catalog
|
|
374
|
+
return this.initServiceCatalogs(true);
|
|
375
|
+
}
|
|
376
|
+
// update the active services
|
|
377
|
+
this._updateActiveServices(newActiveClusters);
|
|
378
|
+
this.logger.info('services: active cluster ids updated successfully');
|
|
379
|
+
|
|
380
|
+
return Promise.resolve();
|
|
381
|
+
},
|
|
341
382
|
|
|
383
|
+
/**
|
|
384
|
+
* Invalidate cache via mercury notification. If the timestamp is newer than current,
|
|
385
|
+
* refetch catalog services.
|
|
386
|
+
*
|
|
387
|
+
* @param {string} timestamp - The timestamp of invalidation notification.
|
|
388
|
+
* @returns {Promsie<void>}
|
|
389
|
+
* */
|
|
390
|
+
invalidateCache(timestamp: string): Promise<void> {
|
|
391
|
+
this.logger.info('services: invalidate cache, timestamp:', timestamp);
|
|
392
|
+
const lastTime = toNumber(this._getCatalog()?.timestamp) || 0;
|
|
393
|
+
const invalidateTime = toNumber(timestamp) || 0;
|
|
394
|
+
if (invalidateTime > lastTime) {
|
|
395
|
+
this.logger.info('services: invalidateCache, refresh services');
|
|
396
|
+
this.initServiceCatalogs(true);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
return Promise.resolve();
|
|
400
|
+
},
|
|
342
401
|
/**
|
|
343
402
|
* Get user meeting preferences (preferred webex site).
|
|
344
403
|
*
|
|
@@ -446,16 +505,20 @@ const Services = WebexPlugin.extend({
|
|
|
446
505
|
|
|
447
506
|
/**
|
|
448
507
|
* Updates a given service group i.e. preauth, signin, postauth with a new hostmap.
|
|
449
|
-
* @param {
|
|
450
|
-
* @param {
|
|
508
|
+
* @param {ServiceGroup} serviceGroup - preauth, signin, postauth
|
|
509
|
+
* @param {ServiceHostmap} hostMap - The new hostmap to update the service group with.
|
|
451
510
|
* @returns {Promise<void>}
|
|
452
511
|
*/
|
|
453
|
-
updateCatalog(serviceGroup, hostMap) {
|
|
512
|
+
updateCatalog(serviceGroup: ServiceGroup, hostMap: ServiceHostmap): Promise<void> {
|
|
454
513
|
const catalog = this._getCatalog();
|
|
455
514
|
|
|
456
515
|
const serviceHostMap = this._formatReceivedHostmap(hostMap);
|
|
457
516
|
|
|
458
|
-
return catalog.updateServiceGroups(
|
|
517
|
+
return catalog.updateServiceGroups(
|
|
518
|
+
serviceGroup,
|
|
519
|
+
serviceHostMap?.services,
|
|
520
|
+
serviceHostMap?.timestamp
|
|
521
|
+
);
|
|
459
522
|
},
|
|
460
523
|
|
|
461
524
|
/**
|
|
@@ -467,7 +530,7 @@ const Services = WebexPlugin.extend({
|
|
|
467
530
|
* @param {boolean} forceRefresh - Boolean to bypass u2c cache control header
|
|
468
531
|
* @returns {Promise<void>}
|
|
469
532
|
*/
|
|
470
|
-
collectPreauthCatalog(query, forceRefresh = false) {
|
|
533
|
+
collectPreauthCatalog(query: QueryOptions, forceRefresh = false) {
|
|
471
534
|
if (!query) {
|
|
472
535
|
return this.updateServices({
|
|
473
536
|
from: 'limited',
|
|
@@ -486,7 +549,9 @@ const Services = WebexPlugin.extend({
|
|
|
486
549
|
* @param {string} param.token - must be a client token
|
|
487
550
|
* @returns {Promise<void>}
|
|
488
551
|
*/
|
|
489
|
-
collectSigninCatalog(
|
|
552
|
+
collectSigninCatalog(
|
|
553
|
+
{email, token, forceRefresh} = {} as {email: string; token: string; forceRefresh: boolean}
|
|
554
|
+
): Promise<void> {
|
|
490
555
|
if (!email) {
|
|
491
556
|
return Promise.reject(new Error('`email` is required'));
|
|
492
557
|
}
|
|
@@ -507,25 +572,26 @@ const Services = WebexPlugin.extend({
|
|
|
507
572
|
* urls.
|
|
508
573
|
* @returns {void}
|
|
509
574
|
*/
|
|
510
|
-
updateCredentialsConfig() {
|
|
511
|
-
const
|
|
575
|
+
updateCredentialsConfig(): void {
|
|
576
|
+
const idbrokerUrl = this.get('idbroker');
|
|
577
|
+
const identityUrl = this.get('identity');
|
|
512
578
|
|
|
513
|
-
if (
|
|
579
|
+
if (idbrokerUrl && identityUrl) {
|
|
514
580
|
const {authorizationString, authorizeUrl} = this.webex.config.credentials;
|
|
515
581
|
|
|
516
582
|
// This must be set outside of the setConfig method used to assign the
|
|
517
583
|
// idbroker and identity url values.
|
|
518
584
|
this.webex.config.credentials.authorizeUrl = authorizationString
|
|
519
585
|
? authorizeUrl
|
|
520
|
-
: `${
|
|
586
|
+
: `${idbrokerUrl.replace(trailingSlashes, '')}/idb/oauth2/v1/authorize`;
|
|
521
587
|
|
|
522
588
|
this.webex.setConfig({
|
|
523
589
|
credentials: {
|
|
524
590
|
idbroker: {
|
|
525
|
-
url:
|
|
591
|
+
url: idbrokerUrl.replace(trailingSlashes, ''), // remove trailing slash
|
|
526
592
|
},
|
|
527
593
|
identity: {
|
|
528
|
-
url:
|
|
594
|
+
url: identityUrl.replace(trailingSlashes, ''), // remove trailing slash
|
|
529
595
|
},
|
|
530
596
|
},
|
|
531
597
|
});
|
|
@@ -535,11 +601,11 @@ const Services = WebexPlugin.extend({
|
|
|
535
601
|
/**
|
|
536
602
|
* Wait until the service catalog is available,
|
|
537
603
|
* or reject afte ra timeout of 60 seconds.
|
|
538
|
-
* @param {
|
|
604
|
+
* @param {ServiceGroup} serviceGroup
|
|
539
605
|
* @param {number} [timeout] - in seconds
|
|
540
606
|
* @returns {Promise<void>}
|
|
541
607
|
*/
|
|
542
|
-
waitForCatalog(serviceGroup, timeout) {
|
|
608
|
+
waitForCatalog(serviceGroup: ServiceGroup, timeout: number): Promise<void> {
|
|
543
609
|
const catalog = this._getCatalog();
|
|
544
610
|
const {supertoken} = this.webex.credentials;
|
|
545
611
|
|
|
@@ -576,7 +642,15 @@ const Services = WebexPlugin.extend({
|
|
|
576
642
|
* @param {WaitForServicePTO} - The parameter transfer object.
|
|
577
643
|
* @returns {Promise<string>} - Resolves to the priority host of a service.
|
|
578
644
|
*/
|
|
579
|
-
waitForService({
|
|
645
|
+
waitForService({
|
|
646
|
+
name,
|
|
647
|
+
timeout = 5,
|
|
648
|
+
url,
|
|
649
|
+
}: {
|
|
650
|
+
name: string;
|
|
651
|
+
timeout: number;
|
|
652
|
+
url: string;
|
|
653
|
+
}): Promise<string> {
|
|
580
654
|
const {services} = this.webex.config;
|
|
581
655
|
|
|
582
656
|
// Save memory by grabbing the catalog after there isn't a priortyURL
|
|
@@ -587,10 +661,12 @@ const Services = WebexPlugin.extend({
|
|
|
587
661
|
);
|
|
588
662
|
|
|
589
663
|
if (fetchFromServiceUrl) {
|
|
590
|
-
|
|
664
|
+
const clusterId = this._activeServices[name];
|
|
665
|
+
|
|
666
|
+
return Promise.resolve(this.get(clusterId));
|
|
591
667
|
}
|
|
592
668
|
|
|
593
|
-
const priorityUrl = this.get(name
|
|
669
|
+
const priorityUrl = this.get(name);
|
|
594
670
|
const priorityUrlObj = this.getServiceFromUrl(url);
|
|
595
671
|
|
|
596
672
|
if (priorityUrl || priorityUrlObj) {
|
|
@@ -617,7 +693,7 @@ const Services = WebexPlugin.extend({
|
|
|
617
693
|
catalog
|
|
618
694
|
.waitForCatalog(catalogGroup, timeout)
|
|
619
695
|
.then(() => {
|
|
620
|
-
const scopedPriorityUrl = this.get(name
|
|
696
|
+
const scopedPriorityUrl = this.get(name);
|
|
621
697
|
const scopedPrioriryUrlObj = this.getServiceFromUrl(url);
|
|
622
698
|
|
|
623
699
|
if (scopedPriorityUrl || scopedPrioriryUrlObj) {
|
|
@@ -641,25 +717,12 @@ const Services = WebexPlugin.extend({
|
|
|
641
717
|
* @param {string} uri
|
|
642
718
|
* @returns {string} uri with the host replaced
|
|
643
719
|
*/
|
|
644
|
-
replaceHostFromHostmap(uri) {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
if (!hostCatalog) {
|
|
720
|
+
replaceHostFromHostmap(uri: string): string {
|
|
721
|
+
try {
|
|
722
|
+
return this.convertUrlToPriorityHostUrl(uri);
|
|
723
|
+
} catch {
|
|
649
724
|
return uri;
|
|
650
725
|
}
|
|
651
|
-
|
|
652
|
-
const host = hostCatalog[url.host];
|
|
653
|
-
|
|
654
|
-
if (host && host[0]) {
|
|
655
|
-
const newHost = host[0].host;
|
|
656
|
-
|
|
657
|
-
url.host = newHost;
|
|
658
|
-
|
|
659
|
-
return url.toString();
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
return uri;
|
|
663
726
|
},
|
|
664
727
|
|
|
665
728
|
/**
|
|
@@ -687,12 +750,18 @@ const Services = WebexPlugin.extend({
|
|
|
687
750
|
/**
|
|
688
751
|
* @private
|
|
689
752
|
* Organize a received hostmap from a service
|
|
690
|
-
* @param {
|
|
753
|
+
* @param {ServiceHostmap} serviceHostmap
|
|
691
754
|
* catalog endpoint.
|
|
692
|
-
* @returns {
|
|
755
|
+
* @returns {Array<Service>}
|
|
693
756
|
*/
|
|
694
|
-
_formatReceivedHostmap({services, activeServices}) {
|
|
695
|
-
const formattedHostmap =
|
|
757
|
+
_formatReceivedHostmap({services, activeServices, timestamp, orgId, format}) {
|
|
758
|
+
const formattedHostmap: ServiceHostmap = {
|
|
759
|
+
activeServices,
|
|
760
|
+
services: services.map((service) => this._formatHostMapEntry(service)),
|
|
761
|
+
timestamp,
|
|
762
|
+
orgId,
|
|
763
|
+
format,
|
|
764
|
+
};
|
|
696
765
|
this._updateActiveServices(activeServices);
|
|
697
766
|
this._updateServices(services);
|
|
698
767
|
|
|
@@ -702,9 +771,9 @@ const Services = WebexPlugin.extend({
|
|
|
702
771
|
/**
|
|
703
772
|
* Get the clusterId associated with a URL string.
|
|
704
773
|
* @param {string} url
|
|
705
|
-
* @returns {string} - Cluster ID of url provided
|
|
774
|
+
* @returns {string | undefined} - Cluster ID of url provided
|
|
706
775
|
*/
|
|
707
|
-
getClusterId(url) {
|
|
776
|
+
getClusterId(url: string): string | undefined {
|
|
708
777
|
const catalog = this._getCatalog();
|
|
709
778
|
|
|
710
779
|
return catalog.findClusterId(url);
|
|
@@ -715,13 +784,15 @@ const Services = WebexPlugin.extend({
|
|
|
715
784
|
* return an object containing both the name and url of a found service.
|
|
716
785
|
* @param {object} params
|
|
717
786
|
* @param {string} params.clusterId - clusterId of found service
|
|
718
|
-
* @param {
|
|
719
|
-
* @param {string} [params.serviceGroup] - specify service group
|
|
787
|
+
* @param {ServiceGroup} [params.serviceGroup] - specify service group
|
|
720
788
|
* @returns {object} service
|
|
721
789
|
* @returns {string} service.name
|
|
722
790
|
* @returns {string} service.url
|
|
723
791
|
*/
|
|
724
|
-
getServiceFromClusterId(params
|
|
792
|
+
getServiceFromClusterId(params: {
|
|
793
|
+
clusterId: string;
|
|
794
|
+
serviceGroup?: ServiceGroup;
|
|
795
|
+
}): {name: string; url: string} | undefined {
|
|
725
796
|
const catalog = this._getCatalog();
|
|
726
797
|
|
|
727
798
|
return catalog.findServiceFromClusterId(params);
|
|
@@ -733,7 +804,7 @@ const Services = WebexPlugin.extend({
|
|
|
733
804
|
* If empty, just return the base URL.
|
|
734
805
|
* @returns {String} url of the service
|
|
735
806
|
*/
|
|
736
|
-
getServiceUrlFromClusterId({cluster = 'us'} = {}) {
|
|
807
|
+
getServiceUrlFromClusterId({cluster = 'us'}: {cluster?: string} = {}): string {
|
|
737
808
|
let clusterId = cluster === 'us' ? DEFAULT_CLUSTER_IDENTIFIER : cluster;
|
|
738
809
|
|
|
739
810
|
// Determine if cluster has service name (non-US clusters from hydra do not)
|
|
@@ -758,20 +829,25 @@ const Services = WebexPlugin.extend({
|
|
|
758
829
|
* @param {string} url - The url to be validated.
|
|
759
830
|
* @returns {object} - Service object.
|
|
760
831
|
* @returns {object.name} - The name of the service found.
|
|
761
|
-
* @returns {object.priorityUrl} - The
|
|
832
|
+
* @returns {object.priorityUrl} - The default url of the found service.
|
|
762
833
|
* @returns {object.defaultUrl} - The default url of the found service.
|
|
763
834
|
*/
|
|
764
|
-
getServiceFromUrl(url = '') {
|
|
765
|
-
const service = this._getCatalog().
|
|
835
|
+
getServiceFromUrl(url = ''): {name: string; priorityUrl: string; defaultUrl: string} | undefined {
|
|
836
|
+
const service = this._getCatalog().findServiceDetailFromUrl(url);
|
|
766
837
|
|
|
767
838
|
if (!service) {
|
|
768
839
|
return undefined;
|
|
769
840
|
}
|
|
770
841
|
|
|
842
|
+
const priorityUrl = service.get();
|
|
843
|
+
const defaultUrl = new URL(
|
|
844
|
+
service.serviceUrls.find((serviceUrl) => url.startsWith(serviceUrl.baseUrl)).baseUrl
|
|
845
|
+
).href;
|
|
846
|
+
|
|
771
847
|
return {
|
|
772
|
-
name: service.
|
|
773
|
-
priorityUrl
|
|
774
|
-
defaultUrl
|
|
848
|
+
name: service.serviceName,
|
|
849
|
+
priorityUrl,
|
|
850
|
+
defaultUrl,
|
|
775
851
|
};
|
|
776
852
|
},
|
|
777
853
|
|
|
@@ -781,7 +857,7 @@ const Services = WebexPlugin.extend({
|
|
|
781
857
|
* @param {string} url - The url to match allowed domains against.
|
|
782
858
|
* @returns {boolean} - True if the url provided is allowed.
|
|
783
859
|
*/
|
|
784
|
-
isAllowedDomainUrl(url) {
|
|
860
|
+
isAllowedDomainUrl(url: string): boolean {
|
|
785
861
|
const catalog = this._getCatalog();
|
|
786
862
|
|
|
787
863
|
return !!catalog.findAllowedDomain(url);
|
|
@@ -795,7 +871,7 @@ const Services = WebexPlugin.extend({
|
|
|
795
871
|
* @returns {string} a service url that contains the top priority host.
|
|
796
872
|
* @throws if url isn't a service url
|
|
797
873
|
*/
|
|
798
|
-
convertUrlToPriorityHostUrl(url = '') {
|
|
874
|
+
convertUrlToPriorityHostUrl(url = '' as string): string {
|
|
799
875
|
const data = this.getServiceFromUrl(url);
|
|
800
876
|
|
|
801
877
|
if (!data) {
|
|
@@ -818,10 +894,17 @@ const Services = WebexPlugin.extend({
|
|
|
818
894
|
* @param {string} [param.token] - used for signin catalog
|
|
819
895
|
* @returns {Promise<object>}
|
|
820
896
|
*/
|
|
821
|
-
_fetchNewServiceHostmap(
|
|
897
|
+
_fetchNewServiceHostmap(
|
|
898
|
+
{from, query, token, forceRefresh} = {} as {
|
|
899
|
+
from: string;
|
|
900
|
+
query: QueryOptions;
|
|
901
|
+
token: string;
|
|
902
|
+
forceRefresh: boolean;
|
|
903
|
+
}
|
|
904
|
+
): Promise<object> {
|
|
822
905
|
const service = 'u2c';
|
|
823
906
|
const resource = from ? `/${from}/catalog` : '/catalog';
|
|
824
|
-
const qs = {...(query || {}), format: '
|
|
907
|
+
const qs = {...(query || {}), format: 'U2CV2'};
|
|
825
908
|
|
|
826
909
|
if (forceRefresh) {
|
|
827
910
|
qs.timestamp = new Date().getTime();
|
|
@@ -832,6 +915,7 @@ const Services = WebexPlugin.extend({
|
|
|
832
915
|
service,
|
|
833
916
|
resource,
|
|
834
917
|
qs,
|
|
918
|
+
headers: {},
|
|
835
919
|
};
|
|
836
920
|
|
|
837
921
|
if (token) {
|
|
@@ -848,7 +932,7 @@ const Services = WebexPlugin.extend({
|
|
|
848
932
|
*
|
|
849
933
|
* @returns {void}
|
|
850
934
|
*/
|
|
851
|
-
initConfig() {
|
|
935
|
+
initConfig(): void {
|
|
852
936
|
// Get the catalog and destructure the services config.
|
|
853
937
|
const catalog = this._getCatalog();
|
|
854
938
|
const {services, fedramp} = this.webex.config;
|
|
@@ -905,10 +989,10 @@ const Services = WebexPlugin.extend({
|
|
|
905
989
|
|
|
906
990
|
/**
|
|
907
991
|
* Make the initial requests to collect the root catalogs.
|
|
908
|
-
*
|
|
992
|
+
* @param {boolean} refresh - Is need force update
|
|
909
993
|
* @returns {Promise<void, Error>} - Errors if the token is unavailable.
|
|
910
994
|
*/
|
|
911
|
-
initServiceCatalogs() {
|
|
995
|
+
initServiceCatalogs(refresh = false): Promise<void> {
|
|
912
996
|
this.logger.info('services: initializing initial service catalogs');
|
|
913
997
|
|
|
914
998
|
// Destructure the credentials plugin.
|
|
@@ -921,12 +1005,12 @@ const Services = WebexPlugin.extend({
|
|
|
921
1005
|
// Get the user's OrgId.
|
|
922
1006
|
.then(() => credentials.getOrgId())
|
|
923
1007
|
// Begin collecting the preauth/limited catalog.
|
|
924
|
-
.then((orgId) => this.collectPreauthCatalog({orgId}))
|
|
1008
|
+
.then((orgId) => this.collectPreauthCatalog({orgId}, refresh))
|
|
925
1009
|
.then(() => {
|
|
926
1010
|
// Validate if the token is authorized.
|
|
927
1011
|
if (credentials.canAuthorize) {
|
|
928
1012
|
// Attempt to collect the postauth catalog.
|
|
929
|
-
return this.updateServices().catch(() => {
|
|
1013
|
+
return this.updateServices({forceRefresh: refresh}).catch(() => {
|
|
930
1014
|
this.initFailed = true;
|
|
931
1015
|
this.logger.warn('services: cannot retrieve postauth catalog');
|
|
932
1016
|
});
|
|
@@ -945,7 +1029,7 @@ const Services = WebexPlugin.extend({
|
|
|
945
1029
|
* @memberof Services
|
|
946
1030
|
* @returns {Services}
|
|
947
1031
|
*/
|
|
948
|
-
initialize() {
|
|
1032
|
+
initialize(): typeof Services {
|
|
949
1033
|
const catalog = new ServiceCatalog();
|
|
950
1034
|
this._catalogs.set(this.webex, catalog);
|
|
951
1035
|
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
type ServiceName = string;
|
|
2
|
+
type ClusterId = string;
|
|
3
|
+
export type ServiceGroup = 'discovery' | 'override' | 'preauth' | 'postauth' | 'signin';
|
|
4
|
+
|
|
1
5
|
export type ServiceUrl = {
|
|
2
6
|
baseUrl: string;
|
|
3
7
|
host: string;
|
|
@@ -5,9 +9,65 @@ export type ServiceUrl = {
|
|
|
5
9
|
failed?: boolean;
|
|
6
10
|
};
|
|
7
11
|
|
|
12
|
+
export type ActiveServices = Record<ServiceName, ClusterId>;
|
|
13
|
+
export type Service = {
|
|
14
|
+
id: ClusterId;
|
|
15
|
+
serviceName: ServiceName;
|
|
16
|
+
serviceUrls: Array<ServiceUrl>;
|
|
17
|
+
};
|
|
18
|
+
export type QueryOptions = {
|
|
19
|
+
email?: string;
|
|
20
|
+
orgId?: string;
|
|
21
|
+
userId?: string;
|
|
22
|
+
timestamp?: number;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export interface ServiceHostmap {
|
|
26
|
+
activeServices: ActiveServices;
|
|
27
|
+
services: Array<Service>;
|
|
28
|
+
timestamp: string;
|
|
29
|
+
orgId: string;
|
|
30
|
+
format: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
8
33
|
export interface IServiceDetail {
|
|
9
|
-
id:
|
|
10
|
-
serviceName:
|
|
34
|
+
id: ClusterId;
|
|
35
|
+
serviceName: ServiceName;
|
|
11
36
|
serviceUrls: Array<ServiceUrl>;
|
|
12
37
|
failHost(url: string): boolean;
|
|
38
|
+
get(): string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface IServiceCatalog {
|
|
42
|
+
serviceGroups: {
|
|
43
|
+
discovery: Array<IServiceDetail>;
|
|
44
|
+
override: Array<IServiceDetail>;
|
|
45
|
+
preauth: Array<IServiceDetail>;
|
|
46
|
+
postauth: Array<IServiceDetail>;
|
|
47
|
+
signin: Array<IServiceDetail>;
|
|
48
|
+
};
|
|
49
|
+
status: {
|
|
50
|
+
discovery: {ready: boolean; collecting: boolean};
|
|
51
|
+
override: {ready: boolean; collecting: boolean};
|
|
52
|
+
preauth: {ready: boolean; collecting: boolean};
|
|
53
|
+
postauth: {ready: boolean; collecting: boolean};
|
|
54
|
+
signin: {ready: boolean; collecting: boolean};
|
|
55
|
+
};
|
|
56
|
+
isReady: boolean;
|
|
57
|
+
allowedDomains: string[];
|
|
58
|
+
clean(): void;
|
|
59
|
+
findClusterId(url: string): string | undefined;
|
|
60
|
+
findServiceFromClusterId(params: {
|
|
61
|
+
clusterId: ClusterId;
|
|
62
|
+
serviceGroup?: ServiceGroup;
|
|
63
|
+
}): {name: string; url: string} | undefined;
|
|
64
|
+
findServiceDetailFromUrl(url: string): IServiceDetail | undefined;
|
|
65
|
+
findAllowedDomain(url: string): string | undefined;
|
|
66
|
+
get(clusterId: ClusterId, serviceGroup?: ServiceGroup): string | undefined;
|
|
67
|
+
getAllowedDomains(): string[];
|
|
68
|
+
markFailedServiceUrl(url: string): string | undefined;
|
|
69
|
+
setAllowedDomains(allowedDomains: string[]): void;
|
|
70
|
+
addAllowedDomains(newAllowedDomains: string[]): void;
|
|
71
|
+
updateServiceGroups(serviceGroup: ServiceGroup, serviceDetails: Array<IServiceDetail>): void;
|
|
72
|
+
waitForCatalog(serviceGroup: ServiceGroup, timeout?: number): Promise<void>;
|
|
13
73
|
}
|