@emilgroup/migration-sdk 0.10.1-beta.14 → 0.10.1-beta.17
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 +2 -2
- package/api/migration-api.ts +68 -34
- package/base.ts +157 -43
- package/common.ts +3 -2
- package/configuration.ts +11 -2
- package/dist/api/health-api.d.ts +1 -1
- package/dist/api/migration-api.d.ts +17 -17
- package/dist/api/migration-api.js +104 -63
- package/dist/base.d.ts +22 -1
- package/dist/base.js +161 -58
- package/dist/common.d.ts +1 -1
- package/dist/common.js +1 -0
- package/dist/configuration.d.ts +10 -2
- package/dist/configuration.js +1 -0
- package/dist/models/create-ingest-run-async-request-dto.d.ts +1 -0
- package/dist/models/create-ingest-run-async-request-dto.js +2 -1
- package/dist/models/create-ingest-run-sync-request-dto.d.ts +1 -0
- package/dist/models/create-ingest-run-sync-request-dto.js +2 -1
- package/dist/models/flush-ingested-data-request-dto.d.ts +1 -0
- package/dist/models/flush-ingested-data-request-dto.js +2 -1
- package/models/create-ingest-run-async-request-dto.ts +2 -1
- package/models/create-ingest-run-sync-request-dto.ts +2 -1
- package/models/flush-ingested-data-request-dto.ts +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -17,11 +17,11 @@ Although this package can be used in both TypeScript and JavaScript, it is inten
|
|
|
17
17
|
Navigate to the folder of your consuming project and run one of the following commands:
|
|
18
18
|
|
|
19
19
|
```
|
|
20
|
-
npm install @emilgroup/migration-sdk@0.10.1-beta.
|
|
20
|
+
npm install @emilgroup/migration-sdk@0.10.1-beta.17 --save
|
|
21
21
|
```
|
|
22
22
|
or
|
|
23
23
|
```
|
|
24
|
-
yarn add @emilgroup/migration-sdk@0.10.1-beta.
|
|
24
|
+
yarn add @emilgroup/migration-sdk@0.10.1-beta.17
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
And then you can import ``.
|
package/api/migration-api.ts
CHANGED
|
@@ -101,8 +101,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
101
101
|
// http bearer authentication required
|
|
102
102
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
105
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
106
|
+
if (authorizationValue) {
|
|
107
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
|
|
@@ -152,8 +154,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
152
154
|
// http bearer authentication required
|
|
153
155
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
154
156
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
158
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
159
|
+
if (authorizationValue) {
|
|
160
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
157
161
|
}
|
|
158
162
|
|
|
159
163
|
|
|
@@ -199,8 +203,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
199
203
|
// http bearer authentication required
|
|
200
204
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
201
205
|
|
|
202
|
-
|
|
203
|
-
|
|
206
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
207
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
208
|
+
if (authorizationValue) {
|
|
209
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
204
210
|
}
|
|
205
211
|
|
|
206
212
|
|
|
@@ -246,8 +252,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
246
252
|
// http bearer authentication required
|
|
247
253
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
248
254
|
|
|
249
|
-
|
|
250
|
-
|
|
255
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
256
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
257
|
+
if (authorizationValue) {
|
|
258
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
251
259
|
}
|
|
252
260
|
|
|
253
261
|
|
|
@@ -293,8 +301,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
293
301
|
// http bearer authentication required
|
|
294
302
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
295
303
|
|
|
296
|
-
|
|
297
|
-
|
|
304
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
305
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
306
|
+
if (authorizationValue) {
|
|
307
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
298
308
|
}
|
|
299
309
|
|
|
300
310
|
|
|
@@ -340,8 +350,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
340
350
|
// http bearer authentication required
|
|
341
351
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
342
352
|
|
|
343
|
-
|
|
344
|
-
|
|
353
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
354
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
355
|
+
if (authorizationValue) {
|
|
356
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
345
357
|
}
|
|
346
358
|
|
|
347
359
|
|
|
@@ -388,8 +400,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
388
400
|
// http bearer authentication required
|
|
389
401
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
390
402
|
|
|
391
|
-
|
|
392
|
-
|
|
403
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
404
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
405
|
+
if (authorizationValue) {
|
|
406
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
393
407
|
}
|
|
394
408
|
|
|
395
409
|
|
|
@@ -433,8 +447,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
433
447
|
// http bearer authentication required
|
|
434
448
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
435
449
|
|
|
436
|
-
|
|
437
|
-
|
|
450
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
451
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
452
|
+
if (authorizationValue) {
|
|
453
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
438
454
|
}
|
|
439
455
|
|
|
440
456
|
|
|
@@ -478,8 +494,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
478
494
|
// http bearer authentication required
|
|
479
495
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
480
496
|
|
|
481
|
-
|
|
482
|
-
|
|
497
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
498
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
499
|
+
if (authorizationValue) {
|
|
500
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
483
501
|
}
|
|
484
502
|
|
|
485
503
|
|
|
@@ -554,8 +572,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
554
572
|
localVarQueryParameter['filters'] = filters;
|
|
555
573
|
}
|
|
556
574
|
|
|
557
|
-
|
|
558
|
-
|
|
575
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
576
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
577
|
+
if (authorizationValue) {
|
|
578
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
559
579
|
}
|
|
560
580
|
|
|
561
581
|
|
|
@@ -630,8 +650,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
630
650
|
localVarQueryParameter['filters'] = filters;
|
|
631
651
|
}
|
|
632
652
|
|
|
633
|
-
|
|
634
|
-
|
|
653
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
654
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
655
|
+
if (authorizationValue) {
|
|
656
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
635
657
|
}
|
|
636
658
|
|
|
637
659
|
|
|
@@ -710,8 +732,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
710
732
|
localVarQueryParameter['filters'] = filters;
|
|
711
733
|
}
|
|
712
734
|
|
|
713
|
-
|
|
714
|
-
|
|
735
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
736
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
737
|
+
if (authorizationValue) {
|
|
738
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
715
739
|
}
|
|
716
740
|
|
|
717
741
|
|
|
@@ -790,8 +814,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
790
814
|
localVarQueryParameter['filters'] = filters;
|
|
791
815
|
}
|
|
792
816
|
|
|
793
|
-
|
|
794
|
-
|
|
817
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
818
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
819
|
+
if (authorizationValue) {
|
|
820
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
795
821
|
}
|
|
796
822
|
|
|
797
823
|
|
|
@@ -866,8 +892,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
866
892
|
localVarQueryParameter['filters'] = filters;
|
|
867
893
|
}
|
|
868
894
|
|
|
869
|
-
|
|
870
|
-
|
|
895
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
896
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
897
|
+
if (authorizationValue) {
|
|
898
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
871
899
|
}
|
|
872
900
|
|
|
873
901
|
|
|
@@ -914,8 +942,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
914
942
|
// http bearer authentication required
|
|
915
943
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
916
944
|
|
|
917
|
-
|
|
918
|
-
|
|
945
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
946
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
947
|
+
if (authorizationValue) {
|
|
948
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
919
949
|
}
|
|
920
950
|
|
|
921
951
|
|
|
@@ -965,8 +995,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
965
995
|
// http bearer authentication required
|
|
966
996
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
967
997
|
|
|
968
|
-
|
|
969
|
-
|
|
998
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
999
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
1000
|
+
if (authorizationValue) {
|
|
1001
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
970
1002
|
}
|
|
971
1003
|
|
|
972
1004
|
|
|
@@ -1016,8 +1048,10 @@ export const MigrationApiAxiosParamCreator = function (configuration?: Configura
|
|
|
1016
1048
|
// http bearer authentication required
|
|
1017
1049
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
|
1018
1050
|
|
|
1019
|
-
|
|
1020
|
-
|
|
1051
|
+
// Only Authorization falls back to the configured token; an empty value is never sent.
|
|
1052
|
+
const authorizationValue = 'Authorization'.toLowerCase() === 'authorization' ? (authorization || baseAccessToken) : authorization;
|
|
1053
|
+
if (authorizationValue) {
|
|
1054
|
+
localVarHeaderParameter['Authorization'] = String(authorizationValue);
|
|
1021
1055
|
}
|
|
1022
1056
|
|
|
1023
1057
|
|
package/base.ts
CHANGED
|
@@ -32,9 +32,20 @@ export const COLLECTION_FORMATS = {
|
|
|
32
32
|
pipes: "|",
|
|
33
33
|
};
|
|
34
34
|
|
|
35
|
+
export interface SessionClass {
|
|
36
|
+
sub: string;
|
|
37
|
+
username?: string;
|
|
38
|
+
email?: string;
|
|
39
|
+
tenantSlug?: string;
|
|
40
|
+
permissions?: string;
|
|
41
|
+
expiresAt?: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
35
44
|
export interface LoginClass {
|
|
36
45
|
accessToken: string;
|
|
37
46
|
permissions: string;
|
|
47
|
+
authMode?: string;
|
|
48
|
+
session?: SessionClass;
|
|
38
49
|
}
|
|
39
50
|
|
|
40
51
|
|
|
@@ -68,10 +79,19 @@ interface TokenData {
|
|
|
68
79
|
accessToken?: string;
|
|
69
80
|
username?: string;
|
|
70
81
|
permissions?: string;
|
|
82
|
+
// 'both' or 'session' when authservice keeps the tokens in a server session.
|
|
83
|
+
authMode?: string;
|
|
84
|
+
sub?: string;
|
|
71
85
|
}
|
|
72
86
|
|
|
73
87
|
const NETWORK_ERROR_MESSAGE = "Network Error";
|
|
74
88
|
const TOKEN_DATA = 'APP_TOKEN';
|
|
89
|
+
// Sent only to authservice, to ask for a server session.
|
|
90
|
+
const AUTH_MODE_HEADER = 'X-Emil-Auth-Mode';
|
|
91
|
+
// Names the account on every call; one browser session can hold several.
|
|
92
|
+
const ACCOUNT_HEADER = 'X-Emil-Account';
|
|
93
|
+
const SESSION_MODES = ['both', 'session'];
|
|
94
|
+
const RESEND_SAFE_METHODS = ['get', 'head', 'options'];
|
|
75
95
|
|
|
76
96
|
/**
|
|
77
97
|
*
|
|
@@ -94,7 +114,11 @@ export class BaseAPI {
|
|
|
94
114
|
this.basePath = configuration.basePath || this.basePath;
|
|
95
115
|
|
|
96
116
|
if (configuration.cookieAuth) {
|
|
97
|
-
this.
|
|
117
|
+
this.configuration.username = this.configuration.username || this.tokenData.username;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (this.usesSession()) {
|
|
121
|
+
this.useSessionAuth();
|
|
98
122
|
} else {
|
|
99
123
|
// Use config token if provided, otherwise use tokenData token
|
|
100
124
|
const configToken = this.configuration.accessToken;
|
|
@@ -114,10 +138,105 @@ export class BaseAPI {
|
|
|
114
138
|
this.attachInterceptor(axios);
|
|
115
139
|
}
|
|
116
140
|
|
|
117
|
-
//
|
|
118
|
-
private
|
|
119
|
-
|
|
120
|
-
|
|
141
|
+
// The app's own account wins over APP_TOKEN, which holds whichever tab wrote last.
|
|
142
|
+
private sessionAccount(): string | undefined {
|
|
143
|
+
return this.configuration.account || this.tokenData.sub;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Apps may pass the address as the second argument only; authservice is on the same host.
|
|
147
|
+
private authBasePath(): string {
|
|
148
|
+
return this.configuration.basePath || this.basePath;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private usesSession(): boolean {
|
|
152
|
+
return !!this.configuration.cookieAuth && SESSION_MODES.indexOf(this.tokenData.authMode) !== -1 && !!this.sessionAccount();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
private useSessionAuth() {
|
|
156
|
+
const { headers, ...baseOptions } = this.configuration.baseOptions || {};
|
|
157
|
+
this.configuration.accessToken = '';
|
|
158
|
+
this.configuration.baseOptions = {
|
|
159
|
+
...baseOptions,
|
|
160
|
+
withCredentials: true,
|
|
161
|
+
headers: { ...headers, [ACCOUNT_HEADER]: this.sessionAccount() },
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private useHeaderAuth(accessToken: string) {
|
|
166
|
+
this.configuration.accessToken = accessToken ? `Bearer ${accessToken}` : '';
|
|
167
|
+
this.tokenData.accessToken = accessToken;
|
|
168
|
+
delete this.tokenData.authMode;
|
|
169
|
+
delete this.tokenData.sub;
|
|
170
|
+
if (this.configuration.cookieAuth) {
|
|
171
|
+
const { withCredentials, headers, ...baseOptions } = this.configuration.baseOptions || {};
|
|
172
|
+
const { [ACCOUNT_HEADER]: account, ...otherHeaders } = headers || {};
|
|
173
|
+
this.configuration.baseOptions = { ...baseOptions, headers: otherHeaders };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private applyTokenReply({ accessToken, authMode, session }: LoginClass) {
|
|
178
|
+
if (this.configuration.cookieAuth && SESSION_MODES.indexOf(authMode) !== -1 && session?.sub) {
|
|
179
|
+
this.tokenData.authMode = authMode;
|
|
180
|
+
this.tokenData.sub = session.sub;
|
|
181
|
+
if (this.configuration.account) {
|
|
182
|
+
// A workspace switch moves the app to another account.
|
|
183
|
+
this.configuration.account = session.sub;
|
|
184
|
+
}
|
|
185
|
+
// Both keeps the token for apps not moved yet; session mode keeps no token at all.
|
|
186
|
+
if (authMode === 'both' && accessToken) {
|
|
187
|
+
this.tokenData.accessToken = accessToken;
|
|
188
|
+
} else {
|
|
189
|
+
delete this.tokenData.accessToken;
|
|
190
|
+
}
|
|
191
|
+
this.useSessionAuth();
|
|
192
|
+
} else {
|
|
193
|
+
this.useHeaderAuth(accessToken);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private sessionHeaders(): Record<string, string> {
|
|
198
|
+
if (!this.configuration.cookieAuth) {
|
|
199
|
+
return {};
|
|
200
|
+
}
|
|
201
|
+
return {
|
|
202
|
+
[AUTH_MODE_HEADER]: 'session',
|
|
203
|
+
...(this.usesSession() && { [ACCOUNT_HEADER]: this.sessionAccount() }),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private withCurrentAuth(config: AxiosRequestConfig): AxiosRequestConfig {
|
|
208
|
+
delete config.headers['Authorization'];
|
|
209
|
+
delete config.headers[ACCOUNT_HEADER];
|
|
210
|
+
if (this.usesSession()) {
|
|
211
|
+
config.headers[ACCOUNT_HEADER] = this.sessionAccount();
|
|
212
|
+
config.withCredentials = true;
|
|
213
|
+
} else if (this.configuration.accessToken) {
|
|
214
|
+
config.headers['Authorization'] = this.configuration.accessToken;
|
|
215
|
+
}
|
|
216
|
+
return config;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Both keeps the token, so a session call the browser could not complete can be sent again with it.
|
|
220
|
+
private canRetryWithToken(config: AxiosRequestConfig): boolean {
|
|
221
|
+
return !!config.withCredentials && !!config.headers?.[ACCOUNT_HEADER]
|
|
222
|
+
&& !!this.tokenData.accessToken && this.tokenData.authMode !== 'session';
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// A network error can come after the server ran the call, so only a call that is safe to repeat is sent again.
|
|
226
|
+
private canResend(config: AxiosRequestConfig): boolean {
|
|
227
|
+
return RESEND_SAFE_METHODS.indexOf((config.method || 'get').toLowerCase()) !== -1
|
|
228
|
+
|| Object.keys(config.headers || {}).some((name) => name.toLowerCase() === 'idempotency-key');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private switchToToken() {
|
|
232
|
+
this.useHeaderAuth(this.tokenData.accessToken);
|
|
233
|
+
this.storeTokenData(this.tokenData);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private retryWithToken(axios: AxiosInstance, config: AxiosRequestConfig) {
|
|
237
|
+
this.switchToToken();
|
|
238
|
+
config.withCredentials = false;
|
|
239
|
+
return axios(this.withCurrentAuth(config));
|
|
121
240
|
}
|
|
122
241
|
|
|
123
242
|
selectEnvironment(env: Environment) {
|
|
@@ -139,8 +258,8 @@ export class BaseAPI {
|
|
|
139
258
|
async authorize(username: string, password: string, targetWorkspace?: string): Promise<void> {
|
|
140
259
|
const options: AxiosRequestConfig = {
|
|
141
260
|
method: 'POST',
|
|
142
|
-
url: `${this.
|
|
143
|
-
headers: { 'Content-Type': 'application/json' },
|
|
261
|
+
url: `${this.authBasePath()}/authservice/v1/login`,
|
|
262
|
+
headers: { 'Content-Type': 'application/json', ...(this.configuration.cookieAuth && { [AUTH_MODE_HEADER]: 'session' }) },
|
|
144
263
|
data: {
|
|
145
264
|
username,
|
|
146
265
|
password,
|
|
@@ -150,15 +269,10 @@ export class BaseAPI {
|
|
|
150
269
|
|
|
151
270
|
const response = await globalAxios.request<LoginClass>(options);
|
|
152
271
|
|
|
153
|
-
const { data: { accessToken, permissions } } = response;
|
|
154
|
-
|
|
155
272
|
this.configuration.username = username;
|
|
156
273
|
this.tokenData.username = username;
|
|
157
|
-
this.tokenData.permissions = permissions;
|
|
158
|
-
|
|
159
|
-
this.configuration.accessToken = `Bearer ${accessToken}`;
|
|
160
|
-
this.tokenData.accessToken = accessToken;
|
|
161
|
-
}
|
|
274
|
+
this.tokenData.permissions = response.data.permissions;
|
|
275
|
+
this.applyTokenReply(response.data);
|
|
162
276
|
|
|
163
277
|
}
|
|
164
278
|
|
|
@@ -182,9 +296,10 @@ export class BaseAPI {
|
|
|
182
296
|
|
|
183
297
|
const options: AxiosRequestConfig = {
|
|
184
298
|
method: 'POST',
|
|
185
|
-
url: `${this.
|
|
299
|
+
url: `${this.authBasePath()}/authservice/v1/refresh-token`,
|
|
186
300
|
headers: {
|
|
187
301
|
'Content-Type': 'application/json',
|
|
302
|
+
...this.sessionHeaders(),
|
|
188
303
|
},
|
|
189
304
|
data: { username: username },
|
|
190
305
|
withCredentials: true,
|
|
@@ -196,11 +311,6 @@ export class BaseAPI {
|
|
|
196
311
|
|
|
197
312
|
private storeTokenData(tokenData?: TokenData) {
|
|
198
313
|
if (typeof window !== 'undefined') {
|
|
199
|
-
if (tokenData && this.configuration?.cookieAuth) {
|
|
200
|
-
// Cookie mode saves who is logged in, never the token; a token saved by apps not yet migrated stays.
|
|
201
|
-
const { username, permissions } = tokenData;
|
|
202
|
-
tokenData = { ...(defaultStorage().get<TokenData>(TOKEN_DATA) || {}), username, permissions };
|
|
203
|
-
}
|
|
204
314
|
defaultStorage().set<TokenData>(TOKEN_DATA, tokenData);
|
|
205
315
|
}
|
|
206
316
|
}
|
|
@@ -230,22 +340,22 @@ export class BaseAPI {
|
|
|
230
340
|
&& !originalConfig._retry) {
|
|
231
341
|
originalConfig._retry = true;
|
|
232
342
|
try {
|
|
233
|
-
const
|
|
234
|
-
this.tokenData.permissions = permissions;
|
|
235
|
-
|
|
236
|
-
|
|
343
|
+
const reply = await this.refreshTokenInternal();
|
|
344
|
+
this.tokenData.permissions = reply.permissions;
|
|
345
|
+
this.applyTokenReply(reply);
|
|
346
|
+
this.storeTokenData(this.tokenData);
|
|
237
347
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
const accessToken = `Bearer ${tokenString}`;
|
|
241
|
-
originalConfig.headers['Authorization'] = accessToken;
|
|
242
|
-
this.configuration.accessToken = accessToken;
|
|
243
|
-
this.tokenData.accessToken = tokenString;
|
|
348
|
+
if (!this.usesSession()) {
|
|
349
|
+
return axios(this.withCurrentAuth(originalConfig));
|
|
244
350
|
}
|
|
245
351
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
352
|
+
// Both mode: if the browser does not send the session cookie (another site), use the token.
|
|
353
|
+
return axios(this.withCurrentAuth(originalConfig)).catch((retryError) => {
|
|
354
|
+
if (retryError?.response?.status !== 401 || !this.tokenData.accessToken) {
|
|
355
|
+
return Promise.reject(retryError);
|
|
356
|
+
}
|
|
357
|
+
return this.retryWithToken(axios, originalConfig);
|
|
358
|
+
});
|
|
249
359
|
} catch (_error) {
|
|
250
360
|
if (_error.response && _error.response.data) {
|
|
251
361
|
return Promise.reject(_error.response.data);
|
|
@@ -253,26 +363,30 @@ export class BaseAPI {
|
|
|
253
363
|
return Promise.reject(_error);
|
|
254
364
|
}
|
|
255
365
|
}
|
|
366
|
+
} else if (err.message === NETWORK_ERROR_MESSAGE && this.canRetryWithToken(originalConfig)) {
|
|
367
|
+
// Both mode: the browser blocked the session call or hid its reply; later calls use the token.
|
|
368
|
+
if (!this.canResend(originalConfig)) {
|
|
369
|
+
this.switchToToken();
|
|
370
|
+
return Promise.reject(err);
|
|
371
|
+
}
|
|
372
|
+
return this.retryWithToken(axios, originalConfig);
|
|
256
373
|
} else if (err.message === NETWORK_ERROR_MESSAGE
|
|
257
|
-
&& originalConfig.headers.hasOwnProperty('Authorization')
|
|
374
|
+
&& (originalConfig.headers.hasOwnProperty('Authorization')
|
|
375
|
+
|| (this.configuration.cookieAuth && originalConfig.withCredentials && this.canResend(originalConfig)))
|
|
258
376
|
&& _retry_count < 4
|
|
259
377
|
) {
|
|
260
378
|
_retry_count++;
|
|
261
379
|
try {
|
|
262
|
-
|
|
263
|
-
const
|
|
264
|
-
this.tokenData.permissions = permissions;
|
|
380
|
+
// In session mode an unreadable 401 (no CORS headers on the error reply) also lands here.
|
|
381
|
+
const reply = await this.refreshTokenInternal();
|
|
382
|
+
this.tokenData.permissions = reply.permissions;
|
|
265
383
|
|
|
266
384
|
_retry = true;
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
this.configuration.accessToken = accessToken;
|
|
270
|
-
this.tokenData.accessToken = tokenString;
|
|
271
|
-
|
|
385
|
+
this.applyTokenReply(reply);
|
|
272
386
|
this.storeTokenData(this.tokenData);
|
|
273
387
|
|
|
274
388
|
return axios.request({
|
|
275
|
-
...originalConfig,
|
|
389
|
+
...this.withCurrentAuth(originalConfig),
|
|
276
390
|
});
|
|
277
391
|
} catch (_error) {
|
|
278
392
|
if (_error.response && _error.response.data) {
|
package/common.ts
CHANGED
|
@@ -130,9 +130,10 @@ export const toPathString = function (url: URL) {
|
|
|
130
130
|
* @export
|
|
131
131
|
*/
|
|
132
132
|
export const createRequestFunction = function (axiosArgs: RequestArgs, globalAxios: AxiosInstance, BASE_PATH: string, configuration?: Configuration) {
|
|
133
|
-
|
|
133
|
+
// Typed by hand: since axios 1.20, request() returns an internal axios type that SDK declarations cannot name.
|
|
134
|
+
return <T = unknown, R = AxiosResponse<T>>(axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH): Promise<R> => {
|
|
134
135
|
const axiosRequestArgs = {...axiosArgs.options, url: (configuration?.basePath || basePath) + axiosArgs.url};
|
|
135
|
-
return axios.request<T, R>(axiosRequestArgs)
|
|
136
|
+
return axios.request<T, R>(axiosRequestArgs) as Promise<R>;
|
|
136
137
|
};
|
|
137
138
|
}
|
|
138
139
|
|
package/configuration.ts
CHANGED
|
@@ -22,6 +22,7 @@ export interface ConfigurationParameters {
|
|
|
22
22
|
baseOptions?: any;
|
|
23
23
|
formDataCtor?: new () => any;
|
|
24
24
|
cookieAuth?: boolean;
|
|
25
|
+
account?: string;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export class Configuration {
|
|
@@ -76,13 +77,20 @@ export class Configuration {
|
|
|
76
77
|
formDataCtor?: new () => any;
|
|
77
78
|
|
|
78
79
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
80
|
+
* Use a server session when authservice makes one; otherwise the token, as without this option.
|
|
81
|
+
* Set `account` too, so each SDK object keeps its own account.
|
|
81
82
|
*
|
|
82
83
|
* @type {boolean}
|
|
83
84
|
* @memberof Configuration
|
|
84
85
|
*/
|
|
85
86
|
cookieAuth?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* The session account (Cognito sub) this app shows, so the SDK never takes another tab's account.
|
|
89
|
+
*
|
|
90
|
+
* @type {string}
|
|
91
|
+
* @memberof Configuration
|
|
92
|
+
*/
|
|
93
|
+
account?: string;
|
|
86
94
|
|
|
87
95
|
constructor(param: ConfigurationParameters = {}) {
|
|
88
96
|
this.apiKey = param.apiKey;
|
|
@@ -93,6 +101,7 @@ export class Configuration {
|
|
|
93
101
|
this.baseOptions = param.baseOptions;
|
|
94
102
|
this.formDataCtor = param.formDataCtor;
|
|
95
103
|
this.cookieAuth = param.cookieAuth;
|
|
104
|
+
this.account = param.account;
|
|
96
105
|
}
|
|
97
106
|
|
|
98
107
|
/**
|
package/dist/api/health-api.d.ts
CHANGED
|
@@ -66,5 +66,5 @@ export declare class HealthApi extends BaseAPI {
|
|
|
66
66
|
* @throws {RequiredError}
|
|
67
67
|
* @memberof HealthApi
|
|
68
68
|
*/
|
|
69
|
-
check(options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<InlineResponse200, any, {}>>;
|
|
69
|
+
check(options?: AxiosRequestConfig): Promise<import("axios").AxiosResponse<InlineResponse200, any, {}, any>>;
|
|
70
70
|
}
|