@webex/webex-core 3.11.0-webex-services-ready.1 → 3.12.0-auth-prejoin-fetch.1
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 +5 -2
- package/dist/config.js +24 -0
- package/dist/config.js.map +1 -1
- package/dist/credentials-config.js +12 -0
- package/dist/credentials-config.js.map +1 -1
- package/dist/interceptors/redirect.js +1 -1
- package/dist/interceptors/redirect.js.map +1 -1
- package/dist/lib/batcher.js +23 -7
- package/dist/lib/batcher.js.map +1 -1
- package/dist/lib/credentials/credentials.js +48 -4
- package/dist/lib/credentials/credentials.js.map +1 -1
- package/dist/lib/credentials/token.js +1 -1
- package/dist/lib/domains.js +90 -0
- package/dist/lib/domains.js.map +1 -0
- package/dist/lib/services/service-catalog.js +6 -10
- package/dist/lib/services/service-catalog.js.map +1 -1
- package/dist/lib/services/services.js +244 -57
- package/dist/lib/services/services.js.map +1 -1
- package/dist/lib/services-v2/service-catalog.js +6 -12
- package/dist/lib/services-v2/service-catalog.js.map +1 -1
- package/dist/lib/services-v2/services-v2.js +243 -52
- package/dist/lib/services-v2/services-v2.js.map +1 -1
- package/dist/plugins/logger.js +1 -1
- package/dist/webex-core.js +2 -2
- package/dist/webex-core.js.map +1 -1
- package/package.json +13 -13
- package/src/config.js +27 -0
- package/src/credentials-config.js +13 -0
- package/src/interceptors/redirect.js +4 -1
- package/src/lib/batcher.js +25 -10
- package/src/lib/credentials/credentials.js +50 -3
- package/src/lib/domains.ts +94 -0
- package/src/lib/services/service-catalog.js +6 -10
- package/src/lib/services/services.js +218 -46
- package/src/lib/services-v2/service-catalog.ts +6 -11
- package/src/lib/services-v2/services-v2.ts +218 -42
- package/test/fixtures/activation-email.ts +22 -0
- package/test/integration/spec/services/service-catalog.js +7 -6
- package/test/integration/spec/services/services.js +188 -128
- package/test/integration/spec/services-v2/services-v2.js +174 -114
- package/test/unit/spec/credentials/credentials.js +133 -2
- package/test/unit/spec/interceptors/auth.js +56 -0
- package/test/unit/spec/lib/batcher.js +56 -0
- package/test/unit/spec/services/service-catalog.js +93 -11
- package/test/unit/spec/services/services.js +591 -322
- package/test/unit/spec/services-v2/service-catalog.ts +93 -11
- package/test/unit/spec/services-v2/services-v2.ts +539 -214
- package/test/unit/spec/webex-core.js +0 -2
- package/test/unit/spec/webex-internal-core.js +0 -2
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import '@webex/internal-plugin-device';
|
|
6
6
|
|
|
7
7
|
import {assert} from '@webex/test-helper-chai';
|
|
8
|
-
import {flaky} from '@webex/test-helper-mocha';
|
|
8
|
+
import {flaky, retryOn429} from '@webex/test-helper-mocha';
|
|
9
9
|
import WebexCore, {
|
|
10
10
|
ServiceCatalog,
|
|
11
11
|
ServiceRegistry,
|
|
@@ -20,6 +20,7 @@ import WebexCore, {
|
|
|
20
20
|
import testUsers from '@webex/test-helper-test-users';
|
|
21
21
|
import uuid from 'uuid';
|
|
22
22
|
import sinon from 'sinon';
|
|
23
|
+
import {createActivationEmail} from '../../../fixtures/activation-email';
|
|
23
24
|
|
|
24
25
|
/* eslint-disable no-underscore-dangle */
|
|
25
26
|
describe('webex-core', () => {
|
|
@@ -404,28 +405,19 @@ describe('webex-core', () => {
|
|
|
404
405
|
assert.isTrue(catalog.isReady);
|
|
405
406
|
});
|
|
406
407
|
|
|
407
|
-
it('should call services#initServiceCatalogs() on webex
|
|
408
|
+
it('should call services#initServiceCatalogs() on webex ready', async () => {
|
|
409
|
+
services._loadCatalogFromCache = sinon.stub().resolves(false);
|
|
408
410
|
services.initServiceCatalogs = sinon.stub().resolves();
|
|
409
411
|
services.initialize();
|
|
410
|
-
|
|
411
|
-
//
|
|
412
|
-
|
|
412
|
+
// The mode-specific ('ready'/'loaded') listener is registered inside the
|
|
413
|
+
// change:config handler, so fire change:config first, then 'ready'.
|
|
414
|
+
webex.trigger('change:config');
|
|
415
|
+
webex.trigger('ready');
|
|
416
|
+
// Wait for the async 'ready' handler to complete
|
|
417
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
413
418
|
assert.called(services.initServiceCatalogs);
|
|
414
419
|
});
|
|
415
420
|
|
|
416
|
-
it('should set services.ready to true after initialization completes', async () => {
|
|
417
|
-
// services.ready starts as false
|
|
418
|
-
const newWebex = new WebexCore({credentials: {supertoken: webexUser.token}});
|
|
419
|
-
const newServices = newWebex.internal.services;
|
|
420
|
-
|
|
421
|
-
// Wait for initialization to complete
|
|
422
|
-
await new Promise((resolve) => {
|
|
423
|
-
newServices.on('services:initialized', resolve);
|
|
424
|
-
});
|
|
425
|
-
|
|
426
|
-
assert.isTrue(newServices.ready);
|
|
427
|
-
});
|
|
428
|
-
|
|
429
421
|
it('should collect different catalogs based on OrgId region', () =>
|
|
430
422
|
assert.notDeepEqual(services.list(true), servicesEU.list(true)));
|
|
431
423
|
|
|
@@ -441,6 +433,45 @@ describe('webex-core', () => {
|
|
|
441
433
|
done();
|
|
442
434
|
}, 2000);
|
|
443
435
|
});
|
|
436
|
+
|
|
437
|
+
it('blocks webex.ready until services.ready flips when waitForCatalogInit is enabled', async () => {
|
|
438
|
+
const gatedWebex = new WebexCore({
|
|
439
|
+
credentials: {supertoken: webexUser.token},
|
|
440
|
+
config: {services: {waitForCatalogInit: true}},
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
// Before init settles, webex.ready must be false because services.ready
|
|
444
|
+
// is a dependency and starts false in the gated path.
|
|
445
|
+
assert.isFalse(gatedWebex.internal.services.ready, 'services.ready should start false');
|
|
446
|
+
assert.isFalse(
|
|
447
|
+
gatedWebex.ready,
|
|
448
|
+
'webex.ready should not fire while services.ready is false'
|
|
449
|
+
);
|
|
450
|
+
|
|
451
|
+
// Wait up to 30s for services init to complete and flip ready.
|
|
452
|
+
await new Promise((resolve, reject) => {
|
|
453
|
+
if (gatedWebex.internal.services.ready) {
|
|
454
|
+
resolve();
|
|
455
|
+
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
const timer = setTimeout(
|
|
459
|
+
() => reject(new Error('timed out waiting for services.ready')),
|
|
460
|
+
30_000
|
|
461
|
+
);
|
|
462
|
+
|
|
463
|
+
gatedWebex.internal.services.once('change:ready', () => {
|
|
464
|
+
clearTimeout(timer);
|
|
465
|
+
resolve();
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
assert.isTrue(
|
|
470
|
+
gatedWebex.internal.services.ready,
|
|
471
|
+
'services.ready should flip true after init settles'
|
|
472
|
+
);
|
|
473
|
+
assert.isTrue(gatedWebex.ready, 'webex.ready should fire once services.ready flips');
|
|
474
|
+
});
|
|
444
475
|
});
|
|
445
476
|
|
|
446
477
|
describe('#initServiceCatalogs()', () => {
|
|
@@ -878,18 +909,22 @@ describe('webex-core', () => {
|
|
|
878
909
|
}));
|
|
879
910
|
|
|
880
911
|
it('validates an authorized user and webex instance', () =>
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
912
|
+
retryOn429(() =>
|
|
913
|
+
services.validateUser({email: webexUser.email}).then((r) => {
|
|
914
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
915
|
+
assert.equal(r.activated, true);
|
|
916
|
+
assert.equal(r.exists, true);
|
|
917
|
+
})
|
|
918
|
+
));
|
|
886
919
|
|
|
887
920
|
it('validates an authorized EU user and webex instance', () =>
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
921
|
+
retryOn429(() =>
|
|
922
|
+
servicesEU.validateUser({email: webexUserEU.email}).then((r) => {
|
|
923
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
924
|
+
assert.equal(r.activated, true);
|
|
925
|
+
assert.equal(r.exists, true);
|
|
926
|
+
})
|
|
927
|
+
));
|
|
893
928
|
|
|
894
929
|
it("returns a rejected promise if the provided email isn't valid", () =>
|
|
895
930
|
unauthServices
|
|
@@ -902,131 +937,152 @@ describe('webex-core', () => {
|
|
|
902
937
|
}));
|
|
903
938
|
|
|
904
939
|
it('validates a non-existing user', () =>
|
|
905
|
-
|
|
906
|
-
.validateUser({email:
|
|
907
|
-
.then((r) => {
|
|
940
|
+
retryOn429(() =>
|
|
941
|
+
unauthServices.validateUser({email: createActivationEmail()}).then((r) => {
|
|
908
942
|
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
909
943
|
assert.equal(r.activated, false);
|
|
910
944
|
assert.equal(r.exists, false);
|
|
911
945
|
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
912
946
|
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
913
947
|
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
914
|
-
})
|
|
948
|
+
})
|
|
949
|
+
));
|
|
915
950
|
|
|
916
951
|
it('validates new user with activationOptions suppressEmail false', () =>
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
952
|
+
retryOn429(() =>
|
|
953
|
+
unauthServices
|
|
954
|
+
.validateUser({
|
|
955
|
+
email: createActivationEmail(),
|
|
956
|
+
activationOptions: {suppressEmail: false},
|
|
957
|
+
})
|
|
958
|
+
.then((r) => {
|
|
959
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
960
|
+
assert.equal(r.activated, false);
|
|
961
|
+
assert.equal(r.exists, false);
|
|
962
|
+
assert.equal(r.user.verificationEmailTriggered, true);
|
|
963
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
964
|
+
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
965
|
+
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
966
|
+
})
|
|
967
|
+
));
|
|
931
968
|
|
|
932
969
|
it('validates new user with activationOptions suppressEmail true', () =>
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
970
|
+
retryOn429(() =>
|
|
971
|
+
unauthServices
|
|
972
|
+
.validateUser({
|
|
973
|
+
email: createActivationEmail(),
|
|
974
|
+
activationOptions: {suppressEmail: true},
|
|
975
|
+
})
|
|
976
|
+
.then((r) => {
|
|
977
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
978
|
+
assert.equal(r.activated, false);
|
|
979
|
+
assert.equal(r.exists, false);
|
|
980
|
+
assert.equal(r.user.verificationEmailTriggered, false);
|
|
981
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
982
|
+
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
983
|
+
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
984
|
+
})
|
|
985
|
+
));
|
|
947
986
|
|
|
948
987
|
it('validates an inactive user', () => {
|
|
949
988
|
const inactive = 'webex.web.client+nonactivated@gmail.com';
|
|
950
989
|
|
|
951
|
-
return
|
|
952
|
-
|
|
953
|
-
|
|
990
|
+
return retryOn429(() =>
|
|
991
|
+
unauthServices
|
|
992
|
+
.validateUser({email: inactive, activationOptions: {suppressEmail: true}})
|
|
993
|
+
.then((r) => {
|
|
994
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
995
|
+
assert.equal(r.activated, false, 'activated');
|
|
996
|
+
assert.equal(r.exists, true, 'exists');
|
|
997
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
998
|
+
assert.equal(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
999
|
+
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
1000
|
+
})
|
|
1001
|
+
).catch(() => {
|
|
1002
|
+
assert(true);
|
|
1003
|
+
});
|
|
1004
|
+
});
|
|
1005
|
+
|
|
1006
|
+
it('validates an existing user', () =>
|
|
1007
|
+
retryOn429(() =>
|
|
1008
|
+
unauthServices.validateUser({email: webexUser.email}).then((r) => {
|
|
954
1009
|
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
955
|
-
assert.equal(r.activated,
|
|
956
|
-
assert.equal(r.exists, true
|
|
1010
|
+
assert.equal(r.activated, true);
|
|
1011
|
+
assert.equal(r.exists, true);
|
|
957
1012
|
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
958
|
-
assert.
|
|
1013
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
959
1014
|
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
960
1015
|
})
|
|
961
|
-
|
|
962
|
-
assert(true);
|
|
963
|
-
});
|
|
964
|
-
});
|
|
965
|
-
|
|
966
|
-
it('validates an existing user', () =>
|
|
967
|
-
unauthServices.validateUser({email: webexUser.email}).then((r) => {
|
|
968
|
-
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
969
|
-
assert.equal(r.activated, true);
|
|
970
|
-
assert.equal(r.exists, true);
|
|
971
|
-
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
972
|
-
assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
973
|
-
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
974
|
-
}));
|
|
1016
|
+
));
|
|
975
1017
|
|
|
976
1018
|
it('validates an existing EU user', () =>
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1019
|
+
retryOn429(() =>
|
|
1020
|
+
unauthServices.validateUser({email: webexUserEU.email}).then((r) => {
|
|
1021
|
+
assert.hasAllKeys(r, ['activated', 'exists', 'user', 'details']);
|
|
1022
|
+
assert.equal(r.activated, true);
|
|
1023
|
+
assert.equal(r.exists, true);
|
|
1024
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'preauth')).length, 0);
|
|
1025
|
+
assert.isAbove(Object.keys(unauthServices.list(false, 'signin')).length, 0);
|
|
1026
|
+
assert.equal(Object.keys(unauthServices.list(false, 'postauth')).length, 0);
|
|
1027
|
+
})
|
|
1028
|
+
));
|
|
985
1029
|
|
|
986
1030
|
it('sends the prelogin user id as undefined when not specified', () => {
|
|
987
1031
|
const requestStub = sandbox.spy(unauthServices, 'request');
|
|
988
1032
|
|
|
989
|
-
return
|
|
990
|
-
.
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
1033
|
+
return retryOn429(() => {
|
|
1034
|
+
requestStub.resetHistory();
|
|
1035
|
+
|
|
1036
|
+
return unauthServices
|
|
1037
|
+
.validateUser({
|
|
1038
|
+
email: createActivationEmail(),
|
|
1039
|
+
activationOptions: {suppressEmail: true},
|
|
1040
|
+
})
|
|
1041
|
+
.then(() => {
|
|
1042
|
+
assert.isUndefined(getActivationRequest(requestStub).headers['x-prelogin-userid']);
|
|
1043
|
+
});
|
|
1044
|
+
});
|
|
997
1045
|
});
|
|
998
1046
|
|
|
999
1047
|
it('sends the prelogin user id as provided when specified', () => {
|
|
1000
1048
|
const requestStub = sandbox.spy(unauthServices, 'request');
|
|
1001
1049
|
const preloginUserId = uuid.v4();
|
|
1002
1050
|
|
|
1003
|
-
return
|
|
1004
|
-
.
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1051
|
+
return retryOn429(() => {
|
|
1052
|
+
requestStub.resetHistory();
|
|
1053
|
+
|
|
1054
|
+
return unauthServices
|
|
1055
|
+
.validateUser({
|
|
1056
|
+
email: createActivationEmail(),
|
|
1057
|
+
activationOptions: {suppressEmail: true},
|
|
1058
|
+
preloginUserId,
|
|
1059
|
+
})
|
|
1060
|
+
.then(() => {
|
|
1061
|
+
assert.strictEqual(
|
|
1062
|
+
getActivationRequest(requestStub).headers['x-prelogin-userid'],
|
|
1063
|
+
preloginUserId
|
|
1064
|
+
);
|
|
1065
|
+
});
|
|
1066
|
+
});
|
|
1015
1067
|
});
|
|
1016
1068
|
|
|
1017
1069
|
it('uses the license service by default', () => {
|
|
1018
1070
|
const requestStub = sandbox.spy(unauthServices, 'request');
|
|
1019
1071
|
|
|
1020
|
-
return
|
|
1021
|
-
.
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1072
|
+
return retryOn429(() => {
|
|
1073
|
+
requestStub.resetHistory();
|
|
1074
|
+
|
|
1075
|
+
return unauthServices
|
|
1076
|
+
.validateUser({
|
|
1077
|
+
email: createActivationEmail(),
|
|
1078
|
+
activationOptions: {suppressEmail: true},
|
|
1079
|
+
})
|
|
1080
|
+
.then(() => {
|
|
1081
|
+
const request = getActivationRequest(requestStub, false);
|
|
1082
|
+
assert.strictEqual(request.service, 'license');
|
|
1083
|
+
assert.strictEqual(request.resource, 'users/activations');
|
|
1084
|
+
});
|
|
1085
|
+
});
|
|
1030
1086
|
});
|
|
1031
1087
|
|
|
1032
1088
|
it('uses the user-onboarding service when useUserOnboardingServiceForActivations config is true', () => {
|
|
@@ -1040,16 +1096,20 @@ describe('webex-core', () => {
|
|
|
1040
1096
|
const userOnboardingServices = userOnboardingWebex.internal.services;
|
|
1041
1097
|
const requestStub = sandbox.spy(userOnboardingServices, 'request');
|
|
1042
1098
|
|
|
1043
|
-
return
|
|
1044
|
-
.
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1099
|
+
return retryOn429(() => {
|
|
1100
|
+
requestStub.resetHistory();
|
|
1101
|
+
|
|
1102
|
+
return userOnboardingServices
|
|
1103
|
+
.validateUser({
|
|
1104
|
+
email: createActivationEmail(),
|
|
1105
|
+
activationOptions: {suppressEmail: true},
|
|
1106
|
+
})
|
|
1107
|
+
.then(() => {
|
|
1108
|
+
const request = getActivationRequest(requestStub, true);
|
|
1109
|
+
assert.strictEqual(request.service, 'user-onboarding');
|
|
1110
|
+
assert.strictEqual(request.resource, 'api/v1/users/activations');
|
|
1111
|
+
});
|
|
1112
|
+
});
|
|
1053
1113
|
});
|
|
1054
1114
|
});
|
|
1055
1115
|
|