@webex/webex-core 2.59.8 → 2.60.0-next.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/dist/config.js +1 -2
- package/dist/config.js.map +1 -1
- package/dist/credentials-config.js +1 -2
- package/dist/credentials-config.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/interceptors/auth.js +4 -3
- package/dist/interceptors/auth.js.map +1 -1
- package/dist/interceptors/default-options.js +4 -3
- package/dist/interceptors/default-options.js.map +1 -1
- package/dist/interceptors/embargo.js +4 -3
- package/dist/interceptors/embargo.js.map +1 -1
- package/dist/interceptors/network-timing.js +4 -3
- package/dist/interceptors/network-timing.js.map +1 -1
- package/dist/interceptors/payload-transformer.js +4 -3
- package/dist/interceptors/payload-transformer.js.map +1 -1
- package/dist/interceptors/rate-limit.js +4 -3
- package/dist/interceptors/rate-limit.js.map +1 -1
- package/dist/interceptors/redirect.js +7 -6
- package/dist/interceptors/redirect.js.map +1 -1
- package/dist/interceptors/request-event.js +9 -8
- package/dist/interceptors/request-event.js.map +1 -1
- package/dist/interceptors/request-logger.js +12 -15
- package/dist/interceptors/request-logger.js.map +1 -1
- package/dist/interceptors/request-timing.js +4 -3
- package/dist/interceptors/request-timing.js.map +1 -1
- package/dist/interceptors/response-logger.js +10 -10
- package/dist/interceptors/response-logger.js.map +1 -1
- package/dist/interceptors/user-agent.js +8 -7
- package/dist/interceptors/user-agent.js.map +1 -1
- package/dist/interceptors/webex-tracking-id.js +4 -3
- package/dist/interceptors/webex-tracking-id.js.map +1 -1
- package/dist/interceptors/webex-user-agent.js +9 -8
- package/dist/interceptors/webex-user-agent.js.map +1 -1
- package/dist/lib/batcher.js +8 -5
- package/dist/lib/batcher.js.map +1 -1
- package/dist/lib/constants.js +13 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/credentials/credentials.js +73 -35
- package/dist/lib/credentials/credentials.js.map +1 -1
- package/dist/lib/credentials/grant-errors.js +5 -5
- package/dist/lib/credentials/grant-errors.js.map +1 -1
- package/dist/lib/credentials/scope.js +21 -2
- package/dist/lib/credentials/scope.js.map +1 -1
- package/dist/lib/credentials/token-collection.js +1 -2
- package/dist/lib/credentials/token-collection.js.map +1 -1
- package/dist/lib/credentials/token.js +11 -10
- package/dist/lib/credentials/token.js.map +1 -1
- package/dist/lib/page.js +1 -2
- package/dist/lib/page.js.map +1 -1
- package/dist/lib/services/constants.js +3 -6
- package/dist/lib/services/constants.js.map +1 -1
- package/dist/lib/services/index.js +2 -2
- package/dist/lib/services/index.js.map +1 -1
- package/dist/lib/services/interceptors/server-error.js +4 -3
- package/dist/lib/services/interceptors/server-error.js.map +1 -1
- package/dist/lib/services/interceptors/service.js +8 -5
- package/dist/lib/services/interceptors/service.js.map +1 -1
- package/dist/lib/services/metrics.js +1 -2
- package/dist/lib/services/metrics.js.map +1 -1
- package/dist/lib/services/service-catalog.js +5 -5
- package/dist/lib/services/service-catalog.js.map +1 -1
- package/dist/lib/services/service-fed-ramp.js +1 -2
- package/dist/lib/services/service-fed-ramp.js.map +1 -1
- package/dist/lib/services/service-host.js +1 -2
- package/dist/lib/services/service-host.js.map +1 -1
- package/dist/lib/services/service-registry.js +3 -4
- package/dist/lib/services/service-registry.js.map +1 -1
- package/dist/lib/services/service-state.js +1 -2
- package/dist/lib/services/service-state.js.map +1 -1
- package/dist/lib/services/service-url.js +1 -2
- package/dist/lib/services/service-url.js.map +1 -1
- package/dist/lib/services/services.js +7 -9
- package/dist/lib/services/services.js.map +1 -1
- package/dist/lib/stateless-webex-plugin.js +1 -2
- package/dist/lib/stateless-webex-plugin.js.map +1 -1
- package/dist/lib/storage/decorators.js +18 -16
- package/dist/lib/storage/decorators.js.map +1 -1
- package/dist/lib/storage/errors.js +5 -5
- package/dist/lib/storage/errors.js.map +1 -1
- package/dist/lib/storage/make-webex-plugin-store.js +8 -10
- package/dist/lib/storage/make-webex-plugin-store.js.map +1 -1
- package/dist/lib/storage/make-webex-store.js.map +1 -1
- package/dist/lib/storage/memory-store-adapter.js +1 -2
- package/dist/lib/storage/memory-store-adapter.js.map +1 -1
- package/dist/lib/webex-core-plugin-mixin.js +13 -14
- package/dist/lib/webex-core-plugin-mixin.js.map +1 -1
- package/dist/lib/webex-http-error.js +4 -3
- package/dist/lib/webex-http-error.js.map +1 -1
- package/dist/lib/webex-internal-core-plugin-mixin.js +13 -14
- package/dist/lib/webex-internal-core-plugin-mixin.js.map +1 -1
- package/dist/lib/webex-plugin.js +5 -8
- package/dist/lib/webex-plugin.js.map +1 -1
- package/dist/plugins/logger.js +2 -3
- package/dist/plugins/logger.js.map +1 -1
- package/dist/webex-core.js +37 -38
- package/dist/webex-core.js.map +1 -1
- package/dist/webex-internal-core.js +1 -2
- package/dist/webex-internal-core.js.map +1 -1
- package/package.json +21 -20
- package/src/lib/constants.js +6 -0
- package/src/lib/credentials/credentials.js +82 -40
- package/src/lib/credentials/scope.js +19 -2
- package/src/lib/services/interceptors/service.js +2 -2
- package/src/lib/services/service-catalog.js +3 -1
- package/src/lib/services/services.js +1 -0
- package/src/webex-core.js +13 -1
- package/test/unit/spec/credentials/credentials.js +169 -13
- package/test/unit/spec/credentials/scope.js +55 -0
- package/test/unit/spec/interceptors/auth.js +3 -0
- package/test/unit/spec/interceptors/webex-user-agent.js +6 -6
- package/test/unit/spec/services/interceptors/service.js +9 -3
- package/test/unit/spec/webex-core.js +12 -0
|
@@ -11,6 +11,7 @@ import {inBrowser} from '@webex/common';
|
|
|
11
11
|
import FakeTimers from '@sinonjs/fake-timers';
|
|
12
12
|
import {skipInBrowser} from '@webex/test-helper-mocha';
|
|
13
13
|
import Logger from '@webex/plugin-logger';
|
|
14
|
+
import Metrics, {config} from '@webex/internal-plugin-metrics';
|
|
14
15
|
|
|
15
16
|
/* eslint camelcase: [0] */
|
|
16
17
|
|
|
@@ -59,6 +60,35 @@ describe('webex-core', () => {
|
|
|
59
60
|
});
|
|
60
61
|
});
|
|
61
62
|
|
|
63
|
+
describe('#isUnverifiedGuest', () => {
|
|
64
|
+
let credentials;
|
|
65
|
+
let webex;
|
|
66
|
+
beforeEach(() => {
|
|
67
|
+
//generate the webex instance
|
|
68
|
+
webex = new MockWebex();
|
|
69
|
+
credentials = new Credentials(undefined, {parent: webex});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should have #isUnverifiedGuest', () => {
|
|
73
|
+
assert.exists(credentials.isUnverifiedGuest);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should get the user status and return as a boolean', () => {
|
|
77
|
+
credentials.set('supertoken', 'AT');
|
|
78
|
+
assert.isFalse(credentials.isUnverifiedGuest);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('should get guest user ', () => {
|
|
82
|
+
credentials.set('supertoken', 'eyJhbGciOiJSUzI1NiJ9.eyJ1c2VyX3R5cGUiOiJndWVzdCJ9');
|
|
83
|
+
assert.isTrue(credentials.isUnverifiedGuest);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should get login user ', () => {
|
|
87
|
+
credentials.set('supertoken', 'dGhpc2lzbm90YXJlYWx1c2VydG9rZW4=');
|
|
88
|
+
assert.isFalse(credentials.isUnverifiedGuest);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
62
92
|
describe('#canAuthorize', () => {
|
|
63
93
|
it('indicates if the current state has enough information to populate an auth header, even if a token refresh or token downscope is required', () => {
|
|
64
94
|
const webex = new MockWebex();
|
|
@@ -417,7 +447,11 @@ describe('webex-core', () => {
|
|
|
417
447
|
});
|
|
418
448
|
|
|
419
449
|
it('schedules a refreshTimer', () => {
|
|
420
|
-
const webex = new MockWebex(
|
|
450
|
+
const webex = new MockWebex({
|
|
451
|
+
children: {
|
|
452
|
+
metrics: Metrics,
|
|
453
|
+
},
|
|
454
|
+
});
|
|
421
455
|
const supertoken = makeToken(webex, {
|
|
422
456
|
access_token: 'ST',
|
|
423
457
|
refresh_token: 'RT',
|
|
@@ -430,6 +464,7 @@ describe('webex-core', () => {
|
|
|
430
464
|
});
|
|
431
465
|
|
|
432
466
|
sinon.stub(supertoken, 'refresh').returns(Promise.resolve(supertoken2));
|
|
467
|
+
sinon.stub(webex.internal.metrics, 'submitClientMetrics').callsFake(() => {});
|
|
433
468
|
const credentials = new Credentials(supertoken, {parent: webex});
|
|
434
469
|
|
|
435
470
|
webex.trigger('change:config');
|
|
@@ -464,7 +499,19 @@ describe('webex-core', () => {
|
|
|
464
499
|
});
|
|
465
500
|
|
|
466
501
|
describe('#getUserToken()', () => {
|
|
467
|
-
|
|
502
|
+
it('resolves with the supertoken if the supertoken matches the requested scopes', () => {
|
|
503
|
+
const webex = new MockWebex();
|
|
504
|
+
const credentials = new Credentials(undefined, {parent: webex});
|
|
505
|
+
|
|
506
|
+
webex.trigger('change:config');
|
|
507
|
+
const st = makeToken(webex, {access_token: 'ST', scope: 'scope1'});
|
|
508
|
+
|
|
509
|
+
credentials.set({
|
|
510
|
+
supertoken: st,
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
return credentials.getUserToken('scope1').then((result) => assert.deepEqual(result, st));
|
|
514
|
+
});
|
|
468
515
|
|
|
469
516
|
it('resolves with the token identified by the specified scopes', () => {
|
|
470
517
|
const webex = new MockWebex();
|
|
@@ -492,6 +539,25 @@ describe('webex-core', () => {
|
|
|
492
539
|
]);
|
|
493
540
|
});
|
|
494
541
|
|
|
542
|
+
it('uses the supertoken.scope instead of the config.scope for downscope', () => {
|
|
543
|
+
const webex = new MockWebex();
|
|
544
|
+
const credentials = new Credentials(undefined, {parent: webex});
|
|
545
|
+
|
|
546
|
+
webex.trigger('change:config');
|
|
547
|
+
const st = makeToken(webex, {access_token: 'ST', scope: 'scope1 spark:kms'});
|
|
548
|
+
|
|
549
|
+
credentials.set({
|
|
550
|
+
supertoken: st,
|
|
551
|
+
scope: 'invalidScope scope1',
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
sinon.stub(credentials, 'downscope').returns(Promise.resolve());
|
|
555
|
+
|
|
556
|
+
return credentials.getUserToken().then(() => {
|
|
557
|
+
assert.calledWith(credentials.downscope, 'scope1');
|
|
558
|
+
});
|
|
559
|
+
});
|
|
560
|
+
|
|
495
561
|
describe('when no matching token is found', () => {
|
|
496
562
|
it('downscopes the supertoken', () => {
|
|
497
563
|
const webex = new MockWebex();
|
|
@@ -529,13 +595,13 @@ describe('webex-core', () => {
|
|
|
529
595
|
it('resolves with a token containing all but the kms scopes', () => {
|
|
530
596
|
const webex = new MockWebex();
|
|
531
597
|
|
|
532
|
-
webex.config.credentials.scope = 'scope1 spark:kms';
|
|
533
598
|
const credentials = new Credentials(undefined, {parent: webex});
|
|
534
599
|
|
|
535
600
|
webex.trigger('change:config');
|
|
536
601
|
|
|
537
602
|
credentials.supertoken = makeToken(webex, {
|
|
538
603
|
access_token: 'ST',
|
|
604
|
+
scope: 'scope1 spark:kms',
|
|
539
605
|
});
|
|
540
606
|
|
|
541
607
|
// const t2 = makeToken(webex, {
|
|
@@ -562,9 +628,11 @@ describe('webex-core', () => {
|
|
|
562
628
|
const webex = new MockWebex({
|
|
563
629
|
children: {
|
|
564
630
|
logger: Logger,
|
|
631
|
+
metrics: Metrics,
|
|
565
632
|
},
|
|
566
633
|
});
|
|
567
634
|
|
|
635
|
+
webex.config.metrics = config.metrics;
|
|
568
636
|
webex.config.credentials.scope = 'scope1 spark:kms';
|
|
569
637
|
const credentials = new Credentials(undefined, {parent: webex});
|
|
570
638
|
|
|
@@ -574,9 +642,11 @@ describe('webex-core', () => {
|
|
|
574
642
|
access_token: 'ST',
|
|
575
643
|
});
|
|
576
644
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
645
|
+
const failReason = 'downscope failed';
|
|
646
|
+
sinon.stub(credentials.supertoken, 'downscope').returns(Promise.reject(failReason));
|
|
647
|
+
|
|
648
|
+
sinon.stub(credentials.logger, 'warn').callsFake(() => {});
|
|
649
|
+
sinon.stub(webex.internal.metrics, 'submitClientMetrics').callsFake(() => {});
|
|
580
650
|
|
|
581
651
|
const t1 = makeToken(webex, {
|
|
582
652
|
access_token: 'AT1',
|
|
@@ -587,14 +657,27 @@ describe('webex-core', () => {
|
|
|
587
657
|
userTokens: [t1],
|
|
588
658
|
});
|
|
589
659
|
|
|
590
|
-
return credentials
|
|
591
|
-
.
|
|
592
|
-
|
|
660
|
+
return credentials.getUserToken('scope2').then((t) => {
|
|
661
|
+
assert.equal(t.access_token, credentials.supertoken.access_token);
|
|
662
|
+
assert.calledWith(
|
|
663
|
+
credentials.logger.warn,
|
|
664
|
+
'credentials: failed to downscope supertoken to "scope2"'
|
|
665
|
+
);
|
|
666
|
+
assert.calledWith(
|
|
667
|
+
webex.internal.metrics.submitClientMetrics,
|
|
668
|
+
'JS_SDK_CREDENTIALS_DOWNSCOPE_FAILED',
|
|
669
|
+
{fields: {failReason, requestedScope: 'scope2'}}
|
|
670
|
+
);
|
|
671
|
+
});
|
|
593
672
|
});
|
|
594
673
|
});
|
|
595
674
|
|
|
596
675
|
it('is blocked while a token refresh is inflight', () => {
|
|
597
|
-
const webex = new MockWebex(
|
|
676
|
+
const webex = new MockWebex({
|
|
677
|
+
children: {
|
|
678
|
+
metrics: Metrics,
|
|
679
|
+
},
|
|
680
|
+
});
|
|
598
681
|
|
|
599
682
|
webex.config.credentials.scope = 'scope1 spark:kms';
|
|
600
683
|
const credentials = new Credentials(undefined, {parent: webex});
|
|
@@ -620,6 +703,7 @@ describe('webex-core', () => {
|
|
|
620
703
|
const at2 = makeToken(webex, {access_token: 'ST2ATD'});
|
|
621
704
|
|
|
622
705
|
sinon.stub(supertoken2, 'downscope').returns(Promise.resolve(at2));
|
|
706
|
+
sinon.stub(webex.internal.metrics, 'submitClientMetrics').callsFake(() => {});
|
|
623
707
|
|
|
624
708
|
return Promise.all([
|
|
625
709
|
credentials.refresh(),
|
|
@@ -751,18 +835,24 @@ describe('webex-core', () => {
|
|
|
751
835
|
|
|
752
836
|
describe('#refresh()', () => {
|
|
753
837
|
it('refreshes and downscopes the supertoken, and revokes previous tokens', () => {
|
|
754
|
-
const webex = new MockWebex(
|
|
838
|
+
const webex = new MockWebex({
|
|
839
|
+
children: {
|
|
840
|
+
metrics: Metrics,
|
|
841
|
+
},
|
|
842
|
+
});
|
|
755
843
|
const credentials = new Credentials(undefined, {parent: webex});
|
|
756
844
|
|
|
757
845
|
webex.trigger('change:config');
|
|
758
846
|
const st = makeToken(webex, {
|
|
759
847
|
access_token: 'ST',
|
|
760
848
|
refresh_token: 'RT',
|
|
849
|
+
scope: 'scope1 scope2',
|
|
761
850
|
});
|
|
762
851
|
|
|
763
852
|
const st2 = makeToken(webex, {
|
|
764
853
|
access_token: 'ST2',
|
|
765
854
|
refresh_token: 'RT2',
|
|
855
|
+
scope: 'scope1 scope2',
|
|
766
856
|
});
|
|
767
857
|
|
|
768
858
|
const t1 = makeToken(webex, {
|
|
@@ -779,6 +869,7 @@ describe('webex-core', () => {
|
|
|
779
869
|
sinon.stub(st, 'refresh').returns(Promise.resolve(st2));
|
|
780
870
|
sinon.stub(t1, 'revoke').returns(Promise.resolve());
|
|
781
871
|
sinon.spy(credentials, 'scheduleRefresh');
|
|
872
|
+
sinon.stub(webex.internal.metrics, 'submitClientMetrics').callsFake(() => {});
|
|
782
873
|
|
|
783
874
|
credentials.set({
|
|
784
875
|
supertoken: st,
|
|
@@ -798,7 +889,11 @@ describe('webex-core', () => {
|
|
|
798
889
|
});
|
|
799
890
|
|
|
800
891
|
it('refreshes and downscopes the supertoken even if revocation of previous token fails', () => {
|
|
801
|
-
const webex = new MockWebex(
|
|
892
|
+
const webex = new MockWebex({
|
|
893
|
+
children: {
|
|
894
|
+
metrics: Metrics,
|
|
895
|
+
},
|
|
896
|
+
});
|
|
802
897
|
const credentials = new Credentials(undefined, {parent: webex});
|
|
803
898
|
|
|
804
899
|
webex.trigger('change:config');
|
|
@@ -810,6 +905,7 @@ describe('webex-core', () => {
|
|
|
810
905
|
const st2 = makeToken(webex, {
|
|
811
906
|
access_token: 'ST2',
|
|
812
907
|
refresh_token: 'RT2',
|
|
908
|
+
scope: 'scope1 scope2',
|
|
813
909
|
});
|
|
814
910
|
|
|
815
911
|
const t1 = makeToken(webex, {
|
|
@@ -826,6 +922,7 @@ describe('webex-core', () => {
|
|
|
826
922
|
sinon.stub(st, 'refresh').returns(Promise.resolve(st2));
|
|
827
923
|
sinon.stub(t1, 'revoke').returns(Promise.reject());
|
|
828
924
|
sinon.spy(credentials, 'scheduleRefresh');
|
|
925
|
+
sinon.stub(webex.internal.metrics, 'submitClientMetrics').callsFake(() => {});
|
|
829
926
|
|
|
830
927
|
credentials.set({
|
|
831
928
|
supertoken: st,
|
|
@@ -848,6 +945,7 @@ describe('webex-core', () => {
|
|
|
848
945
|
const webex = new MockWebex({
|
|
849
946
|
children: {
|
|
850
947
|
logger: Logger,
|
|
948
|
+
metrics: Metrics,
|
|
851
949
|
},
|
|
852
950
|
});
|
|
853
951
|
const credentials = new Credentials(undefined, {parent: webex});
|
|
@@ -856,9 +954,11 @@ describe('webex-core', () => {
|
|
|
856
954
|
const st = makeToken(webex, {
|
|
857
955
|
access_token: 'ST',
|
|
858
956
|
refresh_token: 'RT',
|
|
957
|
+
scope: '',
|
|
859
958
|
});
|
|
860
959
|
|
|
861
960
|
sinon.stub(st, 'refresh').returns(Promise.resolve(makeToken(webex, {access_token: 'ST2'})));
|
|
961
|
+
sinon.stub(webex.internal.metrics, 'submitClientMetrics').callsFake(() => {});
|
|
862
962
|
|
|
863
963
|
const t1 = makeToken(webex, {
|
|
864
964
|
access_token: 'AT1',
|
|
@@ -874,7 +974,7 @@ describe('webex-core', () => {
|
|
|
874
974
|
});
|
|
875
975
|
|
|
876
976
|
it('allows #getUserToken() to be revoked, but #getUserToken() promises will not resolve until the suport token has been refreshed', () => {
|
|
877
|
-
const webex = new MockWebex();
|
|
977
|
+
const webex = new MockWebex({children: {metrics: Metrics}});
|
|
878
978
|
const credentials = new Credentials(undefined, {parent: webex});
|
|
879
979
|
|
|
880
980
|
webex.trigger('change:config');
|
|
@@ -900,6 +1000,7 @@ describe('webex-core', () => {
|
|
|
900
1000
|
|
|
901
1001
|
sinon.stub(st1, 'refresh').returns(Promise.resolve(st2));
|
|
902
1002
|
sinon.stub(st2, 'downscope').returns(Promise.resolve(t2));
|
|
1003
|
+
sinon.stub(webex.internal.metrics, 'submitClientMetrics').callsFake(() => {});
|
|
903
1004
|
|
|
904
1005
|
credentials.set({
|
|
905
1006
|
supertoken: st1,
|
|
@@ -956,6 +1057,61 @@ describe('webex-core', () => {
|
|
|
956
1057
|
assert.calledWith(triggerSpy, sinon.match('client:InvalidRequestError'));
|
|
957
1058
|
});
|
|
958
1059
|
});
|
|
1060
|
+
|
|
1061
|
+
it('exclude invalid scopes from user token, log and call metrics when fetched supertoken scope mismatch with the configured scope', () => {
|
|
1062
|
+
const webex = new MockWebex({
|
|
1063
|
+
children: {
|
|
1064
|
+
logger: Logger,
|
|
1065
|
+
metrics: Metrics,
|
|
1066
|
+
},
|
|
1067
|
+
});
|
|
1068
|
+
const credentials = new Credentials(undefined, {parent: webex});
|
|
1069
|
+
|
|
1070
|
+
webex.trigger('change:config');
|
|
1071
|
+
const st = makeToken(webex, {
|
|
1072
|
+
access_token: 'ST',
|
|
1073
|
+
refresh_token: 'RT',
|
|
1074
|
+
});
|
|
1075
|
+
|
|
1076
|
+
const st2 = makeToken(webex, {
|
|
1077
|
+
access_token: 'ST2',
|
|
1078
|
+
refresh_token: 'RT2',
|
|
1079
|
+
scope: 'scope1',
|
|
1080
|
+
});
|
|
1081
|
+
|
|
1082
|
+
const userToken = makeToken(webex, {
|
|
1083
|
+
access_token: 'AT1',
|
|
1084
|
+
scope: 'scope1 invalidScope1',
|
|
1085
|
+
});
|
|
1086
|
+
|
|
1087
|
+
credentials.set({
|
|
1088
|
+
supertoken: st,
|
|
1089
|
+
userTokens: [userToken],
|
|
1090
|
+
});
|
|
1091
|
+
const invalidScopes = 'invalidScope1 invalidScope2';
|
|
1092
|
+
credentials.config.scope = `scope1 ${invalidScopes}`;
|
|
1093
|
+
|
|
1094
|
+
sinon.stub(st2, 'downscope').returns(Promise.resolve());
|
|
1095
|
+
sinon.stub(st, 'refresh').returns(Promise.resolve(st2));
|
|
1096
|
+
sinon.spy(credentials, 'downscope');
|
|
1097
|
+
sinon.spy(credentials, 'scheduleRefresh');
|
|
1098
|
+
|
|
1099
|
+
sinon.stub(credentials.logger, 'warn').callsFake(() => {});
|
|
1100
|
+
sinon.stub(webex.internal.metrics, 'submitClientMetrics').callsFake(() => {});
|
|
1101
|
+
|
|
1102
|
+
return credentials.refresh().then(() => {
|
|
1103
|
+
assert.calledWith(
|
|
1104
|
+
credentials.logger.warn,
|
|
1105
|
+
`credentials: "${invalidScopes}" scope(s) are invalid because not listed in the supertoken, they will be excluded from user token requests.`
|
|
1106
|
+
);
|
|
1107
|
+
assert.calledWith(
|
|
1108
|
+
webex.internal.metrics.submitClientMetrics,
|
|
1109
|
+
'JS_SDK_CREDENTIALS_TOKEN_REFRESH_SCOPE_MISMATCH',
|
|
1110
|
+
{fields: {invalidScopes}}
|
|
1111
|
+
);
|
|
1112
|
+
assert.calledWith(credentials.downscope, 'scope1');
|
|
1113
|
+
});
|
|
1114
|
+
});
|
|
959
1115
|
});
|
|
960
1116
|
|
|
961
1117
|
describe('#scheduleRefresh()', () => {
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {assert} from '@webex/test-helper-chai';
|
|
2
|
+
import {sortScope, filterScope, diffScopes} from '@webex/webex-core/src/lib/credentials/scope';
|
|
3
|
+
|
|
4
|
+
describe('webex-core', () => {
|
|
5
|
+
describe('scope utils', () => {
|
|
6
|
+
describe('sortScope', () => {
|
|
7
|
+
it('should sort scopes alphabetically', () => {
|
|
8
|
+
assert.equal(sortScope(undefined), '');
|
|
9
|
+
assert.equal(sortScope(''), '');
|
|
10
|
+
assert.equal(sortScope('a'), 'a');
|
|
11
|
+
assert.equal(sortScope('b c a'), 'a b c');
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe('filterScope', () => {
|
|
16
|
+
it('should filter out one scope from the original scope and sort the result', () => {
|
|
17
|
+
assert.equal(filterScope('a', undefined), '');
|
|
18
|
+
assert.equal(filterScope('a', ''), '');
|
|
19
|
+
assert.equal(filterScope('a', 'a'), '');
|
|
20
|
+
assert.equal(filterScope('a', 'a b c'), 'b c');
|
|
21
|
+
assert.equal(filterScope('c', 'a c b'), 'a b');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should filter out a list of scopes from the original scope and sort the result', () => {
|
|
25
|
+
assert.equal(filterScope([], 'a'), 'a');
|
|
26
|
+
assert.equal(filterScope(['a', 'b'], undefined), '');
|
|
27
|
+
assert.equal(filterScope(['a', 'b'], ''), '');
|
|
28
|
+
assert.equal(filterScope(['a', 'b'], 'a'), '');
|
|
29
|
+
assert.equal(filterScope(['a', 'b'], 'a b c'), 'c');
|
|
30
|
+
assert.equal(filterScope(['a', 'd'], 'a c a b'), 'b c');
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe('diffScopes', () => {
|
|
35
|
+
it('should return an empty string, if all items in the first scope are contained in the second scope', () => {
|
|
36
|
+
assert.deepEqual(diffScopes(undefined, undefined), '');
|
|
37
|
+
assert.deepEqual(diffScopes(undefined, ''), '');
|
|
38
|
+
assert.deepEqual(diffScopes('', undefined), '');
|
|
39
|
+
assert.deepEqual(diffScopes('', ''), '');
|
|
40
|
+
assert.deepEqual(diffScopes('a', 'a'), '');
|
|
41
|
+
assert.deepEqual(diffScopes('a b c', 'a b c'), '');
|
|
42
|
+
assert.deepEqual(diffScopes(undefined, 'a b c'), '');
|
|
43
|
+
assert.deepEqual(diffScopes('a b c', 'a b c d'), '');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should return a string containing all items in the first scope that are not in the second scope', () => {
|
|
47
|
+
assert.deepEqual(diffScopes('a', undefined), 'a');
|
|
48
|
+
assert.deepEqual(diffScopes('a', 'b'), 'a');
|
|
49
|
+
assert.deepEqual(diffScopes('a b c', 'a b'), 'c');
|
|
50
|
+
assert.deepEqual(diffScopes('a b c d', 'a b c'), 'd');
|
|
51
|
+
assert.deepEqual(diffScopes('a b c', undefined), 'a b c');
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -12,6 +12,7 @@ import Logger from '@webex/plugin-logger';
|
|
|
12
12
|
import MockWebex from '@webex/test-helper-mock-webex';
|
|
13
13
|
import {AuthInterceptor, config, Credentials, WebexHttpError, Token} from '@webex/webex-core';
|
|
14
14
|
import {cloneDeep, merge} from 'lodash';
|
|
15
|
+
import Metrics from '@webex/internal-plugin-metrics';
|
|
15
16
|
|
|
16
17
|
const {assert} = chai;
|
|
17
18
|
|
|
@@ -28,6 +29,7 @@ describe('webex-core', () => {
|
|
|
28
29
|
children: {
|
|
29
30
|
credentials: Credentials,
|
|
30
31
|
logger: Logger,
|
|
32
|
+
metrics: Metrics,
|
|
31
33
|
},
|
|
32
34
|
config: merge(cloneDeep(config), {credentials: {client_secret: 'fake'}}),
|
|
33
35
|
});
|
|
@@ -41,6 +43,7 @@ describe('webex-core', () => {
|
|
|
41
43
|
);
|
|
42
44
|
|
|
43
45
|
interceptor = Reflect.apply(AuthInterceptor.create, webex, []);
|
|
46
|
+
sinon.stub(webex.internal.metrics, 'submitClientMetrics').callsFake(() => {});
|
|
44
47
|
});
|
|
45
48
|
|
|
46
49
|
describe('#onRequest()', () => {
|
|
@@ -27,7 +27,7 @@ describe('webex-core', () => {
|
|
|
27
27
|
assert.property(options.headers, 'spark-user-agent');
|
|
28
28
|
assert.equal(
|
|
29
29
|
options.headers['spark-user-agent'],
|
|
30
|
-
`webex-js-sdk
|
|
30
|
+
`webex-js-sdk/development (${typeof window === 'undefined' ? 'node' : 'web'})`
|
|
31
31
|
);
|
|
32
32
|
});
|
|
33
33
|
|
|
@@ -47,7 +47,7 @@ describe('webex-core', () => {
|
|
|
47
47
|
assert.property(options.headers, 'spark-user-agent');
|
|
48
48
|
assert.equal(
|
|
49
49
|
options.headers['spark-user-agent'],
|
|
50
|
-
`webex-js-sdk
|
|
50
|
+
`webex-js-sdk/development (${typeof window === 'undefined' ? 'node' : 'web'})`
|
|
51
51
|
);
|
|
52
52
|
});
|
|
53
53
|
|
|
@@ -74,7 +74,7 @@ describe('webex-core', () => {
|
|
|
74
74
|
assert.property(options.headers, 'spark-user-agent');
|
|
75
75
|
assert.equal(
|
|
76
76
|
options.headers['spark-user-agent'],
|
|
77
|
-
`webex-js-sdk
|
|
77
|
+
`webex-js-sdk/development (${
|
|
78
78
|
typeof window === 'undefined' ? 'node' : 'web'
|
|
79
79
|
}) sample/1.0.0`
|
|
80
80
|
);
|
|
@@ -104,7 +104,7 @@ describe('webex-core', () => {
|
|
|
104
104
|
assert.property(options.headers, 'spark-user-agent');
|
|
105
105
|
assert.equal(
|
|
106
106
|
options.headers['spark-user-agent'],
|
|
107
|
-
`webex-js-sdk
|
|
107
|
+
`webex-js-sdk/development (${
|
|
108
108
|
typeof window === 'undefined' ? 'node' : 'web'
|
|
109
109
|
}) sample/1.0.0 custom-label/1.0.0`
|
|
110
110
|
);
|
|
@@ -128,7 +128,7 @@ describe('webex-core', () => {
|
|
|
128
128
|
assert.property(options.headers, 'spark-user-agent');
|
|
129
129
|
assert.equal(
|
|
130
130
|
options.headers['spark-user-agent'],
|
|
131
|
-
`webex
|
|
131
|
+
`webex/development (${typeof window === 'undefined' ? 'node' : 'web'})`
|
|
132
132
|
);
|
|
133
133
|
});
|
|
134
134
|
|
|
@@ -149,7 +149,7 @@ describe('webex-core', () => {
|
|
|
149
149
|
assert.property(options.headers, 'spark-user-agent');
|
|
150
150
|
assert.equal(
|
|
151
151
|
options.headers['spark-user-agent'],
|
|
152
|
-
`webex
|
|
152
|
+
`webex/development (${typeof window === 'undefined' ? 'node' : 'web'})`
|
|
153
153
|
);
|
|
154
154
|
});
|
|
155
155
|
});
|
|
@@ -5,6 +5,7 @@ import chai from 'chai';
|
|
|
5
5
|
import chaiAsPromised from 'chai-as-promised';
|
|
6
6
|
import sinon from 'sinon';
|
|
7
7
|
import {ServiceInterceptor} from '@webex/webex-core';
|
|
8
|
+
import CONFIG from '../../../../../src/config';
|
|
8
9
|
|
|
9
10
|
const {assert} = chai;
|
|
10
11
|
|
|
@@ -26,6 +27,7 @@ describe('webex-core', () => {
|
|
|
26
27
|
service: 'example',
|
|
27
28
|
serviceUrl: 'https://www.example-service.com/',
|
|
28
29
|
uri: 'https://www.example-uri.com/',
|
|
30
|
+
waitForServiceTimeout: 11,
|
|
29
31
|
};
|
|
30
32
|
|
|
31
33
|
options = {};
|
|
@@ -110,6 +112,7 @@ describe('webex-core', () => {
|
|
|
110
112
|
|
|
111
113
|
options.service = fixture.service;
|
|
112
114
|
options.resource = fixture.resource;
|
|
115
|
+
options.timeout = fixture.waitForServiceTimeout;
|
|
113
116
|
});
|
|
114
117
|
|
|
115
118
|
it('should normalize the options', () =>
|
|
@@ -119,9 +122,12 @@ describe('webex-core', () => {
|
|
|
119
122
|
interceptor.onRequest(options).then(() => assert.called(interceptor.validateOptions)));
|
|
120
123
|
|
|
121
124
|
it('should attempt to collect the service url', () =>
|
|
122
|
-
interceptor
|
|
123
|
-
.
|
|
124
|
-
|
|
125
|
+
interceptor.onRequest(options).then(
|
|
126
|
+
assert.calledWith(waitForService, {
|
|
127
|
+
name: options.service,
|
|
128
|
+
timeout: options.waitForServiceTimeout,
|
|
129
|
+
})
|
|
130
|
+
));
|
|
125
131
|
|
|
126
132
|
describe('when the service url was collected successfully', () => {
|
|
127
133
|
it('should attempt to generate the full uri', () =>
|
|
@@ -54,6 +54,18 @@ describe('Webex', () => {
|
|
|
54
54
|
});
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
+
describe('#request', () => {
|
|
58
|
+
it('exists', () => {
|
|
59
|
+
assert.property(webex, 'request');
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
describe('#prepareFetchOptions', () => {
|
|
64
|
+
it('exists', () => {
|
|
65
|
+
assert.property(webex, 'prepareFetchOptions');
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
57
69
|
describe('#initialize()', () => {
|
|
58
70
|
it('initializes without arguments', () => {
|
|
59
71
|
let webex;
|