@etsoo/appscript 1.1.89 → 1.1.93
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/__tests__/app/CoreApp.ts +2 -1
- package/lib/cjs/app/CoreApp.d.ts +36 -38
- package/lib/cjs/app/CoreApp.js +68 -89
- package/lib/mjs/app/CoreApp.d.ts +36 -38
- package/lib/mjs/app/CoreApp.js +69 -90
- package/package.json +2 -2
- package/src/app/CoreApp.ts +99 -108
package/__tests__/app/CoreApp.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
NotificationRenderProps
|
|
8
8
|
} from '@etsoo/notificationbase';
|
|
9
9
|
import { ApiAuthorizationScheme, createClient } from '@etsoo/restclient';
|
|
10
|
-
import { DataTypes, DomUtils, Utils } from '@etsoo/shared';
|
|
10
|
+
import { DataTypes, DomUtils, Utils, WindowStorage } from '@etsoo/shared';
|
|
11
11
|
import { AddressUtils } from '../../src/address/AddressUtils';
|
|
12
12
|
import { IAppSettings } from '../../src/app/AppSettings';
|
|
13
13
|
import { CoreApp } from '../../src/app/CoreApp';
|
|
@@ -102,6 +102,7 @@ class CoreAppTest extends CoreApp<IAppSettings, {}, NotificationCallProps> {
|
|
|
102
102
|
},
|
|
103
103
|
createClient(),
|
|
104
104
|
container,
|
|
105
|
+
new WindowStorage([]),
|
|
105
106
|
'SmartERP'
|
|
106
107
|
);
|
|
107
108
|
}
|
package/lib/cjs/app/CoreApp.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { INotifier, NotificationAlign, NotificationCallProps, NotificationContent } from '@etsoo/notificationbase';
|
|
2
2
|
import { ApiDataError, IApi, IPData } from '@etsoo/restclient';
|
|
3
|
-
import { DataTypes, DateUtils } from '@etsoo/shared';
|
|
3
|
+
import { DataTypes, DateUtils, IStorage } from '@etsoo/shared';
|
|
4
4
|
import { AddressRegion } from '../address/AddressRegion';
|
|
5
5
|
import { IdLabelDto } from '../dto/IdLabelDto';
|
|
6
6
|
import { InitCallDto } from '../dto/InitCallDto';
|
|
@@ -78,6 +78,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
|
|
|
78
78
|
* Country or region, like CN
|
|
79
79
|
*/
|
|
80
80
|
readonly region: string;
|
|
81
|
+
/**
|
|
82
|
+
* Storage
|
|
83
|
+
*/
|
|
84
|
+
readonly storage: IStorage;
|
|
81
85
|
/**
|
|
82
86
|
* Is current authorized
|
|
83
87
|
*/
|
|
@@ -291,9 +295,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
|
|
|
291
295
|
orgList(items?: number, serviceId?: number): Promise<IdLabelDto[] | undefined>;
|
|
292
296
|
/**
|
|
293
297
|
* Switch organization
|
|
294
|
-
* @param
|
|
298
|
+
* @param id Organization id
|
|
299
|
+
* @param serviceId Service id
|
|
295
300
|
*/
|
|
296
|
-
switchOrg(
|
|
301
|
+
switchOrg(id: number, serviceId?: number): Promise<boolean | undefined>;
|
|
297
302
|
/**
|
|
298
303
|
* Go to the login page
|
|
299
304
|
*/
|
|
@@ -353,6 +358,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
353
358
|
* Notifier
|
|
354
359
|
*/
|
|
355
360
|
readonly notifier: INotifier<N, C>;
|
|
361
|
+
/**
|
|
362
|
+
* Storage
|
|
363
|
+
*/
|
|
364
|
+
readonly storage: IStorage;
|
|
356
365
|
private _culture;
|
|
357
366
|
/**
|
|
358
367
|
* Culture, like zh-CN
|
|
@@ -373,7 +382,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
373
382
|
* Country or region, like CN
|
|
374
383
|
*/
|
|
375
384
|
get deviceId(): string;
|
|
376
|
-
protected set deviceId(value: string);
|
|
377
385
|
/**
|
|
378
386
|
* Label delegate
|
|
379
387
|
*/
|
|
@@ -390,14 +398,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
390
398
|
*/
|
|
391
399
|
get userData(): IUserData | undefined;
|
|
392
400
|
protected set userData(value: IUserData | undefined);
|
|
393
|
-
/**
|
|
394
|
-
* Response token header field name
|
|
395
|
-
*/
|
|
396
|
-
readonly headerTokenField = "SmartERPRefreshToken";
|
|
397
|
-
/**
|
|
398
|
-
* Serverside device id encrypted field name
|
|
399
|
-
*/
|
|
400
|
-
protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
|
|
401
401
|
private ipDetectCallbacks?;
|
|
402
402
|
/**
|
|
403
403
|
* Search input element
|
|
@@ -418,18 +418,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
418
418
|
* Token refresh count down seed
|
|
419
419
|
*/
|
|
420
420
|
protected refreshCountdownSeed: number;
|
|
421
|
-
/**
|
|
422
|
-
* Device id field name
|
|
423
|
-
*/
|
|
424
|
-
private readonly deviceIdField;
|
|
425
|
-
/**
|
|
426
|
-
* Device passphrase field name
|
|
427
|
-
*/
|
|
428
|
-
private readonly devicePassphraseField;
|
|
429
|
-
/**
|
|
430
|
-
* Device id update time field name
|
|
431
|
-
*/
|
|
432
|
-
private readonly deviceIdUpdateTimeField;
|
|
433
421
|
/**
|
|
434
422
|
* Init call Api URL
|
|
435
423
|
*/
|
|
@@ -444,26 +432,17 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
444
432
|
* @param settings Settings
|
|
445
433
|
* @param api API
|
|
446
434
|
* @param notifier Notifier
|
|
435
|
+
* @param storage Storage
|
|
447
436
|
* @param name Application name
|
|
448
437
|
*/
|
|
449
|
-
protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, name: string);
|
|
438
|
+
protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, storage: IStorage, name: string);
|
|
450
439
|
protected setApi(api: IApi): void;
|
|
451
|
-
/**
|
|
452
|
-
* Setup device
|
|
453
|
-
* @returns Device id
|
|
454
|
-
*/
|
|
455
|
-
protected setupDevice(): string;
|
|
456
440
|
/**
|
|
457
441
|
* Api init call
|
|
458
442
|
* @param data Data
|
|
459
443
|
* @returns Result
|
|
460
444
|
*/
|
|
461
445
|
protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
|
|
462
|
-
/**
|
|
463
|
-
* Get device last updte miliseconds
|
|
464
|
-
* @returns Miliseconds
|
|
465
|
-
*/
|
|
466
|
-
protected getDeviceUpdateTime(): number;
|
|
467
446
|
/**
|
|
468
447
|
* Init call
|
|
469
448
|
* @param callback Callback
|
|
@@ -477,10 +456,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
477
456
|
*/
|
|
478
457
|
protected initCallUpdate(data: InitCallResultData, timestamp: number): void;
|
|
479
458
|
/**
|
|
480
|
-
* Init call
|
|
459
|
+
* Init call encrypted fields update
|
|
481
460
|
* @returns Fields
|
|
482
461
|
*/
|
|
483
|
-
protected
|
|
462
|
+
protected initCallEncryptedUpdateFields(): string[];
|
|
484
463
|
/**
|
|
485
464
|
* Alert action result
|
|
486
465
|
* @param result Action result
|
|
@@ -688,8 +667,9 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
688
667
|
/**
|
|
689
668
|
* Switch organization
|
|
690
669
|
* @param id Organization id
|
|
670
|
+
* @param serviceId Service id
|
|
691
671
|
*/
|
|
692
|
-
switchOrg(id: number): Promise<boolean | undefined>;
|
|
672
|
+
switchOrg(id: number, serviceId?: number): Promise<boolean | undefined>;
|
|
693
673
|
/**
|
|
694
674
|
* Go to the login page
|
|
695
675
|
*/
|
|
@@ -730,3 +710,21 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
730
710
|
*/
|
|
731
711
|
warning(message: NotificationContent<N>, align?: NotificationAlign): void;
|
|
732
712
|
}
|
|
713
|
+
export declare namespace CoreApp {
|
|
714
|
+
/**
|
|
715
|
+
* Response token header field name
|
|
716
|
+
*/
|
|
717
|
+
const headerTokenField = "SmartERPRefreshToken";
|
|
718
|
+
/**
|
|
719
|
+
* Serverside device id encrypted field name
|
|
720
|
+
*/
|
|
721
|
+
const serversideDeviceIdField = "SmartERPServersideDeviceId";
|
|
722
|
+
/**
|
|
723
|
+
* Device id field name
|
|
724
|
+
*/
|
|
725
|
+
const deviceIdField = "SmartERPDeviceId";
|
|
726
|
+
/**
|
|
727
|
+
* Device passphrase field name
|
|
728
|
+
*/
|
|
729
|
+
const devicePassphraseField = "SmartERPDevicePassphrase";
|
|
730
|
+
}
|
package/lib/cjs/app/CoreApp.js
CHANGED
|
@@ -17,18 +17,11 @@ class CoreApp {
|
|
|
17
17
|
* @param settings Settings
|
|
18
18
|
* @param api API
|
|
19
19
|
* @param notifier Notifier
|
|
20
|
+
* @param storage Storage
|
|
20
21
|
* @param name Application name
|
|
21
22
|
*/
|
|
22
|
-
constructor(settings, api, notifier, name) {
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Response token header field name
|
|
26
|
-
*/
|
|
27
|
-
this.headerTokenField = 'SmartERPRefreshToken';
|
|
28
|
-
/**
|
|
29
|
-
* Serverside device id encrypted field name
|
|
30
|
-
*/
|
|
31
|
-
this.serversideDeviceIdField = 'SmartERPServersideDeviceId';
|
|
23
|
+
constructor(settings, api, notifier, storage, name) {
|
|
24
|
+
var _a;
|
|
32
25
|
this._authorized = false;
|
|
33
26
|
this._isTryingLogin = false;
|
|
34
27
|
/**
|
|
@@ -39,18 +32,6 @@ class CoreApp {
|
|
|
39
32
|
* Token refresh count down seed
|
|
40
33
|
*/
|
|
41
34
|
this.refreshCountdownSeed = 0;
|
|
42
|
-
/**
|
|
43
|
-
* Device id field name
|
|
44
|
-
*/
|
|
45
|
-
this.deviceIdField = 'SmartERPDeviceId';
|
|
46
|
-
/**
|
|
47
|
-
* Device passphrase field name
|
|
48
|
-
*/
|
|
49
|
-
this.devicePassphraseField = 'SmartERPDevicePassphrase';
|
|
50
|
-
/**
|
|
51
|
-
* Device id update time field name
|
|
52
|
-
*/
|
|
53
|
-
this.deviceIdUpdateTimeField = 'SmartERPDeviceIdUpdateTime';
|
|
54
35
|
/**
|
|
55
36
|
* Init call Api URL
|
|
56
37
|
*/
|
|
@@ -62,8 +43,10 @@ class CoreApp {
|
|
|
62
43
|
this.settings = settings;
|
|
63
44
|
this.api = api;
|
|
64
45
|
this.notifier = notifier;
|
|
46
|
+
this.storage = storage;
|
|
65
47
|
this.name = name;
|
|
66
|
-
|
|
48
|
+
// Device id
|
|
49
|
+
this._deviceId = (_a = storage.getData(CoreApp.deviceIdField)) !== null && _a !== void 0 ? _a : '';
|
|
67
50
|
this.setApi(api);
|
|
68
51
|
const { currentCulture, currentRegion } = settings;
|
|
69
52
|
this.changeCulture(currentCulture);
|
|
@@ -95,9 +78,6 @@ class CoreApp {
|
|
|
95
78
|
get deviceId() {
|
|
96
79
|
return this._deviceId;
|
|
97
80
|
}
|
|
98
|
-
set deviceId(value) {
|
|
99
|
-
this._deviceId = value;
|
|
100
|
-
}
|
|
101
81
|
/**
|
|
102
82
|
* Label delegate
|
|
103
83
|
*/
|
|
@@ -161,25 +141,6 @@ class CoreApp {
|
|
|
161
141
|
}
|
|
162
142
|
};
|
|
163
143
|
}
|
|
164
|
-
/**
|
|
165
|
-
* Setup device
|
|
166
|
-
* @returns Device id
|
|
167
|
-
*/
|
|
168
|
-
setupDevice() {
|
|
169
|
-
const deviceId = shared_1.StorageUtils.getLocalData(this.deviceIdField);
|
|
170
|
-
if (deviceId != null && deviceId !== '') {
|
|
171
|
-
const passphraseEncrypted = shared_1.StorageUtils.getLocalData(this.devicePassphraseField);
|
|
172
|
-
if (passphraseEncrypted != null && passphraseEncrypted !== '') {
|
|
173
|
-
const timestamp = this.getDeviceUpdateTime();
|
|
174
|
-
if (timestamp > 0) {
|
|
175
|
-
const passphraseDecrypted = this.decrypt(passphraseEncrypted, timestamp.toString());
|
|
176
|
-
if (passphraseDecrypted != null)
|
|
177
|
-
this.passphrase = passphraseDecrypted;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
return deviceId !== null && deviceId !== void 0 ? deviceId : '';
|
|
182
|
-
}
|
|
183
144
|
/**
|
|
184
145
|
* Api init call
|
|
185
146
|
* @param data Data
|
|
@@ -188,13 +149,6 @@ class CoreApp {
|
|
|
188
149
|
async apiInitCall(data) {
|
|
189
150
|
return await this.api.put(this.initCallApi, data);
|
|
190
151
|
}
|
|
191
|
-
/**
|
|
192
|
-
* Get device last updte miliseconds
|
|
193
|
-
* @returns Miliseconds
|
|
194
|
-
*/
|
|
195
|
-
getDeviceUpdateTime() {
|
|
196
|
-
return shared_1.StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
|
|
197
|
-
}
|
|
198
152
|
/**
|
|
199
153
|
* Init call
|
|
200
154
|
* @param callback Callback
|
|
@@ -202,24 +156,27 @@ class CoreApp {
|
|
|
202
156
|
*/
|
|
203
157
|
async initCall(callback) {
|
|
204
158
|
var _a;
|
|
205
|
-
//
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
159
|
+
// Passphrase exists?
|
|
160
|
+
// Same session should avoid multiple init calls
|
|
161
|
+
const passphraseEncrypted = this.storage.getData(CoreApp.devicePassphraseField);
|
|
162
|
+
if (passphraseEncrypted) {
|
|
163
|
+
const passphraseDecrypted = this.decrypt(passphraseEncrypted, this.name);
|
|
164
|
+
if (passphraseDecrypted != null) {
|
|
165
|
+
this.passphrase = passphraseDecrypted;
|
|
166
|
+
if (callback)
|
|
167
|
+
callback(true);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
216
170
|
}
|
|
217
171
|
// Serverside encrypted device id
|
|
218
|
-
const identifier =
|
|
172
|
+
const identifier = this.storage.getData(CoreApp.serversideDeviceIdField);
|
|
173
|
+
// Timestamp
|
|
174
|
+
const timestamp = new Date().getTime();
|
|
175
|
+
// Request data
|
|
219
176
|
const data = {
|
|
220
177
|
timestamp,
|
|
221
178
|
identifier,
|
|
222
|
-
deviceId:
|
|
179
|
+
deviceId: this.deviceId ? this.deviceId : undefined
|
|
223
180
|
};
|
|
224
181
|
const result = await this.apiInitCall(data);
|
|
225
182
|
if (result == null) {
|
|
@@ -248,7 +205,7 @@ class CoreApp {
|
|
|
248
205
|
if (callback)
|
|
249
206
|
callback(false);
|
|
250
207
|
// Clear device id
|
|
251
|
-
|
|
208
|
+
this.storage.setData(CoreApp.deviceIdField, undefined);
|
|
252
209
|
return;
|
|
253
210
|
}
|
|
254
211
|
this.initCallUpdate(result.data, data.timestamp);
|
|
@@ -261,6 +218,7 @@ class CoreApp {
|
|
|
261
218
|
* @param timestamp Timestamp
|
|
262
219
|
*/
|
|
263
220
|
initCallUpdate(data, timestamp) {
|
|
221
|
+
// Data check
|
|
264
222
|
if (data.deviceId == null || data.passphrase == null)
|
|
265
223
|
return;
|
|
266
224
|
// Decrypt
|
|
@@ -269,19 +227,18 @@ class CoreApp {
|
|
|
269
227
|
if (passphrase == null)
|
|
270
228
|
return;
|
|
271
229
|
// Update device id and cache it
|
|
272
|
-
this.
|
|
273
|
-
|
|
274
|
-
shared_1.StorageUtils.setLocalData(this.devicePassphraseField, data.passphrase);
|
|
275
|
-
shared_1.StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
|
|
230
|
+
this._deviceId = data.deviceId;
|
|
231
|
+
this.storage.setData(CoreApp.deviceIdField, this.deviceId);
|
|
276
232
|
// Current passphrase
|
|
277
233
|
this.passphrase = passphrase;
|
|
234
|
+
this.storage.setData(CoreApp.devicePassphraseField, this.encrypt(passphrase, this.name));
|
|
278
235
|
// Previous passphrase
|
|
279
236
|
if (data.previousPassphrase) {
|
|
280
237
|
const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
|
|
281
238
|
// Update
|
|
282
|
-
const fields = this.
|
|
239
|
+
const fields = this.initCallEncryptedUpdateFields();
|
|
283
240
|
for (const field of fields) {
|
|
284
|
-
const currentValue =
|
|
241
|
+
const currentValue = this.storage.getData(field);
|
|
285
242
|
if (currentValue == null || currentValue === '')
|
|
286
243
|
continue;
|
|
287
244
|
const enhanced = currentValue.indexOf('!') >= 8;
|
|
@@ -297,16 +254,16 @@ class CoreApp {
|
|
|
297
254
|
const newValue = enhanced
|
|
298
255
|
? this.encryptEnhanced(newValueSource)
|
|
299
256
|
: this.encrypt(newValueSource);
|
|
300
|
-
|
|
257
|
+
this.storage.setData(field, newValue);
|
|
301
258
|
}
|
|
302
259
|
}
|
|
303
260
|
}
|
|
304
261
|
/**
|
|
305
|
-
* Init call
|
|
262
|
+
* Init call encrypted fields update
|
|
306
263
|
* @returns Fields
|
|
307
264
|
*/
|
|
308
|
-
|
|
309
|
-
return [
|
|
265
|
+
initCallEncryptedUpdateFields() {
|
|
266
|
+
return [CoreApp.headerTokenField];
|
|
310
267
|
}
|
|
311
268
|
/**
|
|
312
269
|
* Alert action result
|
|
@@ -330,7 +287,7 @@ class CoreApp {
|
|
|
330
287
|
if (refreshToken !== '') {
|
|
331
288
|
if (refreshToken != null)
|
|
332
289
|
refreshToken = this.encrypt(refreshToken);
|
|
333
|
-
|
|
290
|
+
this.storage.setData(CoreApp.headerTokenField, refreshToken);
|
|
334
291
|
}
|
|
335
292
|
// Reset tryLogin state
|
|
336
293
|
this._isTryingLogin = false;
|
|
@@ -402,18 +359,17 @@ class CoreApp {
|
|
|
402
359
|
* Clear cache data
|
|
403
360
|
*/
|
|
404
361
|
clearCacheData() {
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
shared_1.StorageUtils.setLocalData(this.headerTokenField, undefined);
|
|
362
|
+
this.storage.setData(CoreApp.serversideDeviceIdField, undefined);
|
|
363
|
+
this.storage.setData(CoreApp.deviceIdField, undefined);
|
|
364
|
+
this.storage.setData(CoreApp.devicePassphraseField, undefined);
|
|
365
|
+
this.storage.setData(CoreApp.headerTokenField, undefined);
|
|
410
366
|
}
|
|
411
367
|
/**
|
|
412
368
|
* Clear cached token
|
|
413
369
|
*/
|
|
414
370
|
clearCacheToken() {
|
|
415
371
|
this.cachedRefreshToken = undefined;
|
|
416
|
-
|
|
372
|
+
this.storage.setData(CoreApp.headerTokenField, undefined);
|
|
417
373
|
}
|
|
418
374
|
/**
|
|
419
375
|
* Decrypt message
|
|
@@ -661,7 +617,7 @@ class CoreApp {
|
|
|
661
617
|
// Temp refresh token
|
|
662
618
|
if (this.cachedRefreshToken)
|
|
663
619
|
return this.cachedRefreshToken;
|
|
664
|
-
return
|
|
620
|
+
return this.storage.getData(CoreApp.headerTokenField);
|
|
665
621
|
}
|
|
666
622
|
/**
|
|
667
623
|
* Get all regions
|
|
@@ -679,7 +635,7 @@ class CoreApp {
|
|
|
679
635
|
*/
|
|
680
636
|
getResponseToken(rawResponse) {
|
|
681
637
|
const response = this.api.transformResponse(rawResponse);
|
|
682
|
-
return this.api.getHeaderValue(response.headers,
|
|
638
|
+
return this.api.getHeaderValue(response.headers, CoreApp.headerTokenField);
|
|
683
639
|
}
|
|
684
640
|
/**
|
|
685
641
|
* Get time zone
|
|
@@ -818,10 +774,15 @@ class CoreApp {
|
|
|
818
774
|
/**
|
|
819
775
|
* Switch organization
|
|
820
776
|
* @param id Organization id
|
|
777
|
+
* @param serviceId Service id
|
|
821
778
|
*/
|
|
822
|
-
async switchOrg(id) {
|
|
823
|
-
const api = `Organization/Switch
|
|
824
|
-
const result = await this.api.put(api
|
|
779
|
+
async switchOrg(id, serviceId) {
|
|
780
|
+
const api = `Organization/Switch`;
|
|
781
|
+
const result = await this.api.put(api, {
|
|
782
|
+
id,
|
|
783
|
+
serviceId,
|
|
784
|
+
deviceId: this.deviceId
|
|
785
|
+
});
|
|
825
786
|
if (result)
|
|
826
787
|
return await this.refreshToken();
|
|
827
788
|
return result;
|
|
@@ -874,7 +835,7 @@ class CoreApp {
|
|
|
874
835
|
userLogin(user, refreshToken, keep) {
|
|
875
836
|
this.userData = user;
|
|
876
837
|
// Cache the encrypted serverside device id
|
|
877
|
-
|
|
838
|
+
this.storage.setData(CoreApp.serversideDeviceIdField, user.deviceId);
|
|
878
839
|
if (keep) {
|
|
879
840
|
this.authorize(user.token, refreshToken);
|
|
880
841
|
}
|
|
@@ -912,3 +873,21 @@ class CoreApp {
|
|
|
912
873
|
}
|
|
913
874
|
}
|
|
914
875
|
exports.CoreApp = CoreApp;
|
|
876
|
+
(function (CoreApp) {
|
|
877
|
+
/**
|
|
878
|
+
* Response token header field name
|
|
879
|
+
*/
|
|
880
|
+
CoreApp.headerTokenField = 'SmartERPRefreshToken';
|
|
881
|
+
/**
|
|
882
|
+
* Serverside device id encrypted field name
|
|
883
|
+
*/
|
|
884
|
+
CoreApp.serversideDeviceIdField = 'SmartERPServersideDeviceId';
|
|
885
|
+
/**
|
|
886
|
+
* Device id field name
|
|
887
|
+
*/
|
|
888
|
+
CoreApp.deviceIdField = 'SmartERPDeviceId';
|
|
889
|
+
/**
|
|
890
|
+
* Device passphrase field name
|
|
891
|
+
*/
|
|
892
|
+
CoreApp.devicePassphraseField = 'SmartERPDevicePassphrase';
|
|
893
|
+
})(CoreApp = exports.CoreApp || (exports.CoreApp = {}));
|
package/lib/mjs/app/CoreApp.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { INotifier, NotificationAlign, NotificationCallProps, NotificationContent } from '@etsoo/notificationbase';
|
|
2
2
|
import { ApiDataError, IApi, IPData } from '@etsoo/restclient';
|
|
3
|
-
import { DataTypes, DateUtils } from '@etsoo/shared';
|
|
3
|
+
import { DataTypes, DateUtils, IStorage } from '@etsoo/shared';
|
|
4
4
|
import { AddressRegion } from '../address/AddressRegion';
|
|
5
5
|
import { IdLabelDto } from '../dto/IdLabelDto';
|
|
6
6
|
import { InitCallDto } from '../dto/InitCallDto';
|
|
@@ -78,6 +78,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
|
|
|
78
78
|
* Country or region, like CN
|
|
79
79
|
*/
|
|
80
80
|
readonly region: string;
|
|
81
|
+
/**
|
|
82
|
+
* Storage
|
|
83
|
+
*/
|
|
84
|
+
readonly storage: IStorage;
|
|
81
85
|
/**
|
|
82
86
|
* Is current authorized
|
|
83
87
|
*/
|
|
@@ -291,9 +295,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
|
|
|
291
295
|
orgList(items?: number, serviceId?: number): Promise<IdLabelDto[] | undefined>;
|
|
292
296
|
/**
|
|
293
297
|
* Switch organization
|
|
294
|
-
* @param
|
|
298
|
+
* @param id Organization id
|
|
299
|
+
* @param serviceId Service id
|
|
295
300
|
*/
|
|
296
|
-
switchOrg(
|
|
301
|
+
switchOrg(id: number, serviceId?: number): Promise<boolean | undefined>;
|
|
297
302
|
/**
|
|
298
303
|
* Go to the login page
|
|
299
304
|
*/
|
|
@@ -353,6 +358,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
353
358
|
* Notifier
|
|
354
359
|
*/
|
|
355
360
|
readonly notifier: INotifier<N, C>;
|
|
361
|
+
/**
|
|
362
|
+
* Storage
|
|
363
|
+
*/
|
|
364
|
+
readonly storage: IStorage;
|
|
356
365
|
private _culture;
|
|
357
366
|
/**
|
|
358
367
|
* Culture, like zh-CN
|
|
@@ -373,7 +382,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
373
382
|
* Country or region, like CN
|
|
374
383
|
*/
|
|
375
384
|
get deviceId(): string;
|
|
376
|
-
protected set deviceId(value: string);
|
|
377
385
|
/**
|
|
378
386
|
* Label delegate
|
|
379
387
|
*/
|
|
@@ -390,14 +398,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
390
398
|
*/
|
|
391
399
|
get userData(): IUserData | undefined;
|
|
392
400
|
protected set userData(value: IUserData | undefined);
|
|
393
|
-
/**
|
|
394
|
-
* Response token header field name
|
|
395
|
-
*/
|
|
396
|
-
readonly headerTokenField = "SmartERPRefreshToken";
|
|
397
|
-
/**
|
|
398
|
-
* Serverside device id encrypted field name
|
|
399
|
-
*/
|
|
400
|
-
protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
|
|
401
401
|
private ipDetectCallbacks?;
|
|
402
402
|
/**
|
|
403
403
|
* Search input element
|
|
@@ -418,18 +418,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
418
418
|
* Token refresh count down seed
|
|
419
419
|
*/
|
|
420
420
|
protected refreshCountdownSeed: number;
|
|
421
|
-
/**
|
|
422
|
-
* Device id field name
|
|
423
|
-
*/
|
|
424
|
-
private readonly deviceIdField;
|
|
425
|
-
/**
|
|
426
|
-
* Device passphrase field name
|
|
427
|
-
*/
|
|
428
|
-
private readonly devicePassphraseField;
|
|
429
|
-
/**
|
|
430
|
-
* Device id update time field name
|
|
431
|
-
*/
|
|
432
|
-
private readonly deviceIdUpdateTimeField;
|
|
433
421
|
/**
|
|
434
422
|
* Init call Api URL
|
|
435
423
|
*/
|
|
@@ -444,26 +432,17 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
444
432
|
* @param settings Settings
|
|
445
433
|
* @param api API
|
|
446
434
|
* @param notifier Notifier
|
|
435
|
+
* @param storage Storage
|
|
447
436
|
* @param name Application name
|
|
448
437
|
*/
|
|
449
|
-
protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, name: string);
|
|
438
|
+
protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, storage: IStorage, name: string);
|
|
450
439
|
protected setApi(api: IApi): void;
|
|
451
|
-
/**
|
|
452
|
-
* Setup device
|
|
453
|
-
* @returns Device id
|
|
454
|
-
*/
|
|
455
|
-
protected setupDevice(): string;
|
|
456
440
|
/**
|
|
457
441
|
* Api init call
|
|
458
442
|
* @param data Data
|
|
459
443
|
* @returns Result
|
|
460
444
|
*/
|
|
461
445
|
protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
|
|
462
|
-
/**
|
|
463
|
-
* Get device last updte miliseconds
|
|
464
|
-
* @returns Miliseconds
|
|
465
|
-
*/
|
|
466
|
-
protected getDeviceUpdateTime(): number;
|
|
467
446
|
/**
|
|
468
447
|
* Init call
|
|
469
448
|
* @param callback Callback
|
|
@@ -477,10 +456,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
477
456
|
*/
|
|
478
457
|
protected initCallUpdate(data: InitCallResultData, timestamp: number): void;
|
|
479
458
|
/**
|
|
480
|
-
* Init call
|
|
459
|
+
* Init call encrypted fields update
|
|
481
460
|
* @returns Fields
|
|
482
461
|
*/
|
|
483
|
-
protected
|
|
462
|
+
protected initCallEncryptedUpdateFields(): string[];
|
|
484
463
|
/**
|
|
485
464
|
* Alert action result
|
|
486
465
|
* @param result Action result
|
|
@@ -688,8 +667,9 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
688
667
|
/**
|
|
689
668
|
* Switch organization
|
|
690
669
|
* @param id Organization id
|
|
670
|
+
* @param serviceId Service id
|
|
691
671
|
*/
|
|
692
|
-
switchOrg(id: number): Promise<boolean | undefined>;
|
|
672
|
+
switchOrg(id: number, serviceId?: number): Promise<boolean | undefined>;
|
|
693
673
|
/**
|
|
694
674
|
* Go to the login page
|
|
695
675
|
*/
|
|
@@ -730,3 +710,21 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
730
710
|
*/
|
|
731
711
|
warning(message: NotificationContent<N>, align?: NotificationAlign): void;
|
|
732
712
|
}
|
|
713
|
+
export declare namespace CoreApp {
|
|
714
|
+
/**
|
|
715
|
+
* Response token header field name
|
|
716
|
+
*/
|
|
717
|
+
const headerTokenField = "SmartERPRefreshToken";
|
|
718
|
+
/**
|
|
719
|
+
* Serverside device id encrypted field name
|
|
720
|
+
*/
|
|
721
|
+
const serversideDeviceIdField = "SmartERPServersideDeviceId";
|
|
722
|
+
/**
|
|
723
|
+
* Device id field name
|
|
724
|
+
*/
|
|
725
|
+
const deviceIdField = "SmartERPDeviceId";
|
|
726
|
+
/**
|
|
727
|
+
* Device passphrase field name
|
|
728
|
+
*/
|
|
729
|
+
const devicePassphraseField = "SmartERPDevicePassphrase";
|
|
730
|
+
}
|
package/lib/mjs/app/CoreApp.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NotificationAlign, NotificationMessageType } from '@etsoo/notificationbase';
|
|
2
2
|
import { ApiDataError } from '@etsoo/restclient';
|
|
3
|
-
import { DateUtils, DomUtils, NumberUtils,
|
|
3
|
+
import { DateUtils, DomUtils, NumberUtils, Utils } from '@etsoo/shared';
|
|
4
4
|
import { AES, algo, enc, HmacSHA512, lib, mode, pad, PBKDF2, SHA3 } from 'crypto-js';
|
|
5
5
|
import { AddressRegion } from '../address/AddressRegion';
|
|
6
6
|
import { AddressUtils } from '../address/AddressUtils';
|
|
@@ -14,18 +14,11 @@ export class CoreApp {
|
|
|
14
14
|
* @param settings Settings
|
|
15
15
|
* @param api API
|
|
16
16
|
* @param notifier Notifier
|
|
17
|
+
* @param storage Storage
|
|
17
18
|
* @param name Application name
|
|
18
19
|
*/
|
|
19
|
-
constructor(settings, api, notifier, name) {
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Response token header field name
|
|
23
|
-
*/
|
|
24
|
-
this.headerTokenField = 'SmartERPRefreshToken';
|
|
25
|
-
/**
|
|
26
|
-
* Serverside device id encrypted field name
|
|
27
|
-
*/
|
|
28
|
-
this.serversideDeviceIdField = 'SmartERPServersideDeviceId';
|
|
20
|
+
constructor(settings, api, notifier, storage, name) {
|
|
21
|
+
var _a;
|
|
29
22
|
this._authorized = false;
|
|
30
23
|
this._isTryingLogin = false;
|
|
31
24
|
/**
|
|
@@ -36,18 +29,6 @@ export class CoreApp {
|
|
|
36
29
|
* Token refresh count down seed
|
|
37
30
|
*/
|
|
38
31
|
this.refreshCountdownSeed = 0;
|
|
39
|
-
/**
|
|
40
|
-
* Device id field name
|
|
41
|
-
*/
|
|
42
|
-
this.deviceIdField = 'SmartERPDeviceId';
|
|
43
|
-
/**
|
|
44
|
-
* Device passphrase field name
|
|
45
|
-
*/
|
|
46
|
-
this.devicePassphraseField = 'SmartERPDevicePassphrase';
|
|
47
|
-
/**
|
|
48
|
-
* Device id update time field name
|
|
49
|
-
*/
|
|
50
|
-
this.deviceIdUpdateTimeField = 'SmartERPDeviceIdUpdateTime';
|
|
51
32
|
/**
|
|
52
33
|
* Init call Api URL
|
|
53
34
|
*/
|
|
@@ -59,8 +40,10 @@ export class CoreApp {
|
|
|
59
40
|
this.settings = settings;
|
|
60
41
|
this.api = api;
|
|
61
42
|
this.notifier = notifier;
|
|
43
|
+
this.storage = storage;
|
|
62
44
|
this.name = name;
|
|
63
|
-
|
|
45
|
+
// Device id
|
|
46
|
+
this._deviceId = (_a = storage.getData(CoreApp.deviceIdField)) !== null && _a !== void 0 ? _a : '';
|
|
64
47
|
this.setApi(api);
|
|
65
48
|
const { currentCulture, currentRegion } = settings;
|
|
66
49
|
this.changeCulture(currentCulture);
|
|
@@ -92,9 +75,6 @@ export class CoreApp {
|
|
|
92
75
|
get deviceId() {
|
|
93
76
|
return this._deviceId;
|
|
94
77
|
}
|
|
95
|
-
set deviceId(value) {
|
|
96
|
-
this._deviceId = value;
|
|
97
|
-
}
|
|
98
78
|
/**
|
|
99
79
|
* Label delegate
|
|
100
80
|
*/
|
|
@@ -158,25 +138,6 @@ export class CoreApp {
|
|
|
158
138
|
}
|
|
159
139
|
};
|
|
160
140
|
}
|
|
161
|
-
/**
|
|
162
|
-
* Setup device
|
|
163
|
-
* @returns Device id
|
|
164
|
-
*/
|
|
165
|
-
setupDevice() {
|
|
166
|
-
const deviceId = StorageUtils.getLocalData(this.deviceIdField);
|
|
167
|
-
if (deviceId != null && deviceId !== '') {
|
|
168
|
-
const passphraseEncrypted = StorageUtils.getLocalData(this.devicePassphraseField);
|
|
169
|
-
if (passphraseEncrypted != null && passphraseEncrypted !== '') {
|
|
170
|
-
const timestamp = this.getDeviceUpdateTime();
|
|
171
|
-
if (timestamp > 0) {
|
|
172
|
-
const passphraseDecrypted = this.decrypt(passphraseEncrypted, timestamp.toString());
|
|
173
|
-
if (passphraseDecrypted != null)
|
|
174
|
-
this.passphrase = passphraseDecrypted;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
return deviceId !== null && deviceId !== void 0 ? deviceId : '';
|
|
179
|
-
}
|
|
180
141
|
/**
|
|
181
142
|
* Api init call
|
|
182
143
|
* @param data Data
|
|
@@ -185,13 +146,6 @@ export class CoreApp {
|
|
|
185
146
|
async apiInitCall(data) {
|
|
186
147
|
return await this.api.put(this.initCallApi, data);
|
|
187
148
|
}
|
|
188
|
-
/**
|
|
189
|
-
* Get device last updte miliseconds
|
|
190
|
-
* @returns Miliseconds
|
|
191
|
-
*/
|
|
192
|
-
getDeviceUpdateTime() {
|
|
193
|
-
return StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
|
|
194
|
-
}
|
|
195
149
|
/**
|
|
196
150
|
* Init call
|
|
197
151
|
* @param callback Callback
|
|
@@ -199,24 +153,27 @@ export class CoreApp {
|
|
|
199
153
|
*/
|
|
200
154
|
async initCall(callback) {
|
|
201
155
|
var _a;
|
|
202
|
-
//
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
156
|
+
// Passphrase exists?
|
|
157
|
+
// Same session should avoid multiple init calls
|
|
158
|
+
const passphraseEncrypted = this.storage.getData(CoreApp.devicePassphraseField);
|
|
159
|
+
if (passphraseEncrypted) {
|
|
160
|
+
const passphraseDecrypted = this.decrypt(passphraseEncrypted, this.name);
|
|
161
|
+
if (passphraseDecrypted != null) {
|
|
162
|
+
this.passphrase = passphraseDecrypted;
|
|
163
|
+
if (callback)
|
|
164
|
+
callback(true);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
213
167
|
}
|
|
214
168
|
// Serverside encrypted device id
|
|
215
|
-
const identifier =
|
|
169
|
+
const identifier = this.storage.getData(CoreApp.serversideDeviceIdField);
|
|
170
|
+
// Timestamp
|
|
171
|
+
const timestamp = new Date().getTime();
|
|
172
|
+
// Request data
|
|
216
173
|
const data = {
|
|
217
174
|
timestamp,
|
|
218
175
|
identifier,
|
|
219
|
-
deviceId:
|
|
176
|
+
deviceId: this.deviceId ? this.deviceId : undefined
|
|
220
177
|
};
|
|
221
178
|
const result = await this.apiInitCall(data);
|
|
222
179
|
if (result == null) {
|
|
@@ -245,7 +202,7 @@ export class CoreApp {
|
|
|
245
202
|
if (callback)
|
|
246
203
|
callback(false);
|
|
247
204
|
// Clear device id
|
|
248
|
-
|
|
205
|
+
this.storage.setData(CoreApp.deviceIdField, undefined);
|
|
249
206
|
return;
|
|
250
207
|
}
|
|
251
208
|
this.initCallUpdate(result.data, data.timestamp);
|
|
@@ -258,6 +215,7 @@ export class CoreApp {
|
|
|
258
215
|
* @param timestamp Timestamp
|
|
259
216
|
*/
|
|
260
217
|
initCallUpdate(data, timestamp) {
|
|
218
|
+
// Data check
|
|
261
219
|
if (data.deviceId == null || data.passphrase == null)
|
|
262
220
|
return;
|
|
263
221
|
// Decrypt
|
|
@@ -266,19 +224,18 @@ export class CoreApp {
|
|
|
266
224
|
if (passphrase == null)
|
|
267
225
|
return;
|
|
268
226
|
// Update device id and cache it
|
|
269
|
-
this.
|
|
270
|
-
|
|
271
|
-
StorageUtils.setLocalData(this.devicePassphraseField, data.passphrase);
|
|
272
|
-
StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
|
|
227
|
+
this._deviceId = data.deviceId;
|
|
228
|
+
this.storage.setData(CoreApp.deviceIdField, this.deviceId);
|
|
273
229
|
// Current passphrase
|
|
274
230
|
this.passphrase = passphrase;
|
|
231
|
+
this.storage.setData(CoreApp.devicePassphraseField, this.encrypt(passphrase, this.name));
|
|
275
232
|
// Previous passphrase
|
|
276
233
|
if (data.previousPassphrase) {
|
|
277
234
|
const prev = this.decrypt(data.previousPassphrase, timestamp.toString());
|
|
278
235
|
// Update
|
|
279
|
-
const fields = this.
|
|
236
|
+
const fields = this.initCallEncryptedUpdateFields();
|
|
280
237
|
for (const field of fields) {
|
|
281
|
-
const currentValue =
|
|
238
|
+
const currentValue = this.storage.getData(field);
|
|
282
239
|
if (currentValue == null || currentValue === '')
|
|
283
240
|
continue;
|
|
284
241
|
const enhanced = currentValue.indexOf('!') >= 8;
|
|
@@ -294,16 +251,16 @@ export class CoreApp {
|
|
|
294
251
|
const newValue = enhanced
|
|
295
252
|
? this.encryptEnhanced(newValueSource)
|
|
296
253
|
: this.encrypt(newValueSource);
|
|
297
|
-
|
|
254
|
+
this.storage.setData(field, newValue);
|
|
298
255
|
}
|
|
299
256
|
}
|
|
300
257
|
}
|
|
301
258
|
/**
|
|
302
|
-
* Init call
|
|
259
|
+
* Init call encrypted fields update
|
|
303
260
|
* @returns Fields
|
|
304
261
|
*/
|
|
305
|
-
|
|
306
|
-
return [
|
|
262
|
+
initCallEncryptedUpdateFields() {
|
|
263
|
+
return [CoreApp.headerTokenField];
|
|
307
264
|
}
|
|
308
265
|
/**
|
|
309
266
|
* Alert action result
|
|
@@ -327,7 +284,7 @@ export class CoreApp {
|
|
|
327
284
|
if (refreshToken !== '') {
|
|
328
285
|
if (refreshToken != null)
|
|
329
286
|
refreshToken = this.encrypt(refreshToken);
|
|
330
|
-
|
|
287
|
+
this.storage.setData(CoreApp.headerTokenField, refreshToken);
|
|
331
288
|
}
|
|
332
289
|
// Reset tryLogin state
|
|
333
290
|
this._isTryingLogin = false;
|
|
@@ -399,18 +356,17 @@ export class CoreApp {
|
|
|
399
356
|
* Clear cache data
|
|
400
357
|
*/
|
|
401
358
|
clearCacheData() {
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
StorageUtils.setLocalData(this.headerTokenField, undefined);
|
|
359
|
+
this.storage.setData(CoreApp.serversideDeviceIdField, undefined);
|
|
360
|
+
this.storage.setData(CoreApp.deviceIdField, undefined);
|
|
361
|
+
this.storage.setData(CoreApp.devicePassphraseField, undefined);
|
|
362
|
+
this.storage.setData(CoreApp.headerTokenField, undefined);
|
|
407
363
|
}
|
|
408
364
|
/**
|
|
409
365
|
* Clear cached token
|
|
410
366
|
*/
|
|
411
367
|
clearCacheToken() {
|
|
412
368
|
this.cachedRefreshToken = undefined;
|
|
413
|
-
|
|
369
|
+
this.storage.setData(CoreApp.headerTokenField, undefined);
|
|
414
370
|
}
|
|
415
371
|
/**
|
|
416
372
|
* Decrypt message
|
|
@@ -658,7 +614,7 @@ export class CoreApp {
|
|
|
658
614
|
// Temp refresh token
|
|
659
615
|
if (this.cachedRefreshToken)
|
|
660
616
|
return this.cachedRefreshToken;
|
|
661
|
-
return
|
|
617
|
+
return this.storage.getData(CoreApp.headerTokenField);
|
|
662
618
|
}
|
|
663
619
|
/**
|
|
664
620
|
* Get all regions
|
|
@@ -676,7 +632,7 @@ export class CoreApp {
|
|
|
676
632
|
*/
|
|
677
633
|
getResponseToken(rawResponse) {
|
|
678
634
|
const response = this.api.transformResponse(rawResponse);
|
|
679
|
-
return this.api.getHeaderValue(response.headers,
|
|
635
|
+
return this.api.getHeaderValue(response.headers, CoreApp.headerTokenField);
|
|
680
636
|
}
|
|
681
637
|
/**
|
|
682
638
|
* Get time zone
|
|
@@ -815,10 +771,15 @@ export class CoreApp {
|
|
|
815
771
|
/**
|
|
816
772
|
* Switch organization
|
|
817
773
|
* @param id Organization id
|
|
774
|
+
* @param serviceId Service id
|
|
818
775
|
*/
|
|
819
|
-
async switchOrg(id) {
|
|
820
|
-
const api = `Organization/Switch
|
|
821
|
-
const result = await this.api.put(api
|
|
776
|
+
async switchOrg(id, serviceId) {
|
|
777
|
+
const api = `Organization/Switch`;
|
|
778
|
+
const result = await this.api.put(api, {
|
|
779
|
+
id,
|
|
780
|
+
serviceId,
|
|
781
|
+
deviceId: this.deviceId
|
|
782
|
+
});
|
|
822
783
|
if (result)
|
|
823
784
|
return await this.refreshToken();
|
|
824
785
|
return result;
|
|
@@ -871,7 +832,7 @@ export class CoreApp {
|
|
|
871
832
|
userLogin(user, refreshToken, keep) {
|
|
872
833
|
this.userData = user;
|
|
873
834
|
// Cache the encrypted serverside device id
|
|
874
|
-
|
|
835
|
+
this.storage.setData(CoreApp.serversideDeviceIdField, user.deviceId);
|
|
875
836
|
if (keep) {
|
|
876
837
|
this.authorize(user.token, refreshToken);
|
|
877
838
|
}
|
|
@@ -908,3 +869,21 @@ export class CoreApp {
|
|
|
908
869
|
});
|
|
909
870
|
}
|
|
910
871
|
}
|
|
872
|
+
(function (CoreApp) {
|
|
873
|
+
/**
|
|
874
|
+
* Response token header field name
|
|
875
|
+
*/
|
|
876
|
+
CoreApp.headerTokenField = 'SmartERPRefreshToken';
|
|
877
|
+
/**
|
|
878
|
+
* Serverside device id encrypted field name
|
|
879
|
+
*/
|
|
880
|
+
CoreApp.serversideDeviceIdField = 'SmartERPServersideDeviceId';
|
|
881
|
+
/**
|
|
882
|
+
* Device id field name
|
|
883
|
+
*/
|
|
884
|
+
CoreApp.deviceIdField = 'SmartERPDeviceId';
|
|
885
|
+
/**
|
|
886
|
+
* Device passphrase field name
|
|
887
|
+
*/
|
|
888
|
+
CoreApp.devicePassphraseField = 'SmartERPDevicePassphrase';
|
|
889
|
+
})(CoreApp || (CoreApp = {}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/appscript",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.93",
|
|
4
4
|
"description": "Applications shared TypeScript framework",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/mjs/index.js",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@etsoo/notificationbase": "^1.0.95",
|
|
56
56
|
"@etsoo/restclient": "^1.0.63",
|
|
57
|
-
"@etsoo/shared": "^1.0.
|
|
57
|
+
"@etsoo/shared": "^1.0.83",
|
|
58
58
|
"@types/crypto-js": "^4.0.2",
|
|
59
59
|
"crypto-js": "^4.1.1"
|
|
60
60
|
},
|
package/src/app/CoreApp.ts
CHANGED
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
DataTypes,
|
|
12
12
|
DateUtils,
|
|
13
13
|
DomUtils,
|
|
14
|
+
IStorage,
|
|
14
15
|
NumberUtils,
|
|
15
|
-
StorageUtils,
|
|
16
16
|
Utils
|
|
17
17
|
} from '@etsoo/shared';
|
|
18
18
|
import {
|
|
@@ -128,6 +128,11 @@ export interface ICoreApp<
|
|
|
128
128
|
*/
|
|
129
129
|
readonly region: string;
|
|
130
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Storage
|
|
133
|
+
*/
|
|
134
|
+
readonly storage: IStorage;
|
|
135
|
+
|
|
131
136
|
/**
|
|
132
137
|
* Is current authorized
|
|
133
138
|
*/
|
|
@@ -400,9 +405,10 @@ export interface ICoreApp<
|
|
|
400
405
|
|
|
401
406
|
/**
|
|
402
407
|
* Switch organization
|
|
403
|
-
* @param
|
|
408
|
+
* @param id Organization id
|
|
409
|
+
* @param serviceId Service id
|
|
404
410
|
*/
|
|
405
|
-
switchOrg(
|
|
411
|
+
switchOrg(id: number, serviceId?: number): Promise<boolean | undefined>;
|
|
406
412
|
|
|
407
413
|
/**
|
|
408
414
|
* Go to the login page
|
|
@@ -479,6 +485,11 @@ export abstract class CoreApp<
|
|
|
479
485
|
*/
|
|
480
486
|
readonly notifier: INotifier<N, C>;
|
|
481
487
|
|
|
488
|
+
/**
|
|
489
|
+
* Storage
|
|
490
|
+
*/
|
|
491
|
+
readonly storage: IStorage;
|
|
492
|
+
|
|
482
493
|
private _culture!: string;
|
|
483
494
|
/**
|
|
484
495
|
* Culture, like zh-CN
|
|
@@ -503,16 +514,13 @@ export abstract class CoreApp<
|
|
|
503
514
|
return this._region;
|
|
504
515
|
}
|
|
505
516
|
|
|
506
|
-
private _deviceId: string
|
|
517
|
+
private _deviceId: string;
|
|
507
518
|
/**
|
|
508
519
|
* Country or region, like CN
|
|
509
520
|
*/
|
|
510
521
|
get deviceId() {
|
|
511
522
|
return this._deviceId;
|
|
512
523
|
}
|
|
513
|
-
protected set deviceId(value: string) {
|
|
514
|
-
this._deviceId = value;
|
|
515
|
-
}
|
|
516
524
|
|
|
517
525
|
/**
|
|
518
526
|
* Label delegate
|
|
@@ -543,16 +551,6 @@ export abstract class CoreApp<
|
|
|
543
551
|
this._userData = value;
|
|
544
552
|
}
|
|
545
553
|
|
|
546
|
-
/**
|
|
547
|
-
* Response token header field name
|
|
548
|
-
*/
|
|
549
|
-
readonly headerTokenField = 'SmartERPRefreshToken';
|
|
550
|
-
|
|
551
|
-
/**
|
|
552
|
-
* Serverside device id encrypted field name
|
|
553
|
-
*/
|
|
554
|
-
protected readonly serversideDeviceIdField = 'SmartERPServersideDeviceId';
|
|
555
|
-
|
|
556
554
|
// IP detect ready callbacks
|
|
557
555
|
private ipDetectCallbacks?: IDetectIPCallback[];
|
|
558
556
|
|
|
@@ -585,22 +583,6 @@ export abstract class CoreApp<
|
|
|
585
583
|
*/
|
|
586
584
|
protected refreshCountdownSeed = 0;
|
|
587
585
|
|
|
588
|
-
/**
|
|
589
|
-
* Device id field name
|
|
590
|
-
*/
|
|
591
|
-
private readonly deviceIdField: string = 'SmartERPDeviceId';
|
|
592
|
-
|
|
593
|
-
/**
|
|
594
|
-
* Device passphrase field name
|
|
595
|
-
*/
|
|
596
|
-
private readonly devicePassphraseField: string = 'SmartERPDevicePassphrase';
|
|
597
|
-
|
|
598
|
-
/**
|
|
599
|
-
* Device id update time field name
|
|
600
|
-
*/
|
|
601
|
-
private readonly deviceIdUpdateTimeField: string =
|
|
602
|
-
'SmartERPDeviceIdUpdateTime';
|
|
603
|
-
|
|
604
586
|
/**
|
|
605
587
|
* Init call Api URL
|
|
606
588
|
*/
|
|
@@ -618,20 +600,24 @@ export abstract class CoreApp<
|
|
|
618
600
|
* @param settings Settings
|
|
619
601
|
* @param api API
|
|
620
602
|
* @param notifier Notifier
|
|
603
|
+
* @param storage Storage
|
|
621
604
|
* @param name Application name
|
|
622
605
|
*/
|
|
623
606
|
protected constructor(
|
|
624
607
|
settings: S,
|
|
625
608
|
api: IApi,
|
|
626
609
|
notifier: INotifier<N, C>,
|
|
610
|
+
storage: IStorage,
|
|
627
611
|
name: string
|
|
628
612
|
) {
|
|
629
613
|
this.settings = settings;
|
|
630
614
|
this.api = api;
|
|
631
615
|
this.notifier = notifier;
|
|
616
|
+
this.storage = storage;
|
|
632
617
|
this.name = name;
|
|
633
618
|
|
|
634
|
-
|
|
619
|
+
// Device id
|
|
620
|
+
this._deviceId = storage.getData<string>(CoreApp.deviceIdField) ?? '';
|
|
635
621
|
|
|
636
622
|
this.setApi(api);
|
|
637
623
|
|
|
@@ -677,33 +663,6 @@ export abstract class CoreApp<
|
|
|
677
663
|
};
|
|
678
664
|
}
|
|
679
665
|
|
|
680
|
-
/**
|
|
681
|
-
* Setup device
|
|
682
|
-
* @returns Device id
|
|
683
|
-
*/
|
|
684
|
-
protected setupDevice() {
|
|
685
|
-
const deviceId = StorageUtils.getLocalData<string>(this.deviceIdField);
|
|
686
|
-
|
|
687
|
-
if (deviceId != null && deviceId !== '') {
|
|
688
|
-
const passphraseEncrypted = StorageUtils.getLocalData<string>(
|
|
689
|
-
this.devicePassphraseField
|
|
690
|
-
);
|
|
691
|
-
if (passphraseEncrypted != null && passphraseEncrypted !== '') {
|
|
692
|
-
const timestamp = this.getDeviceUpdateTime();
|
|
693
|
-
if (timestamp > 0) {
|
|
694
|
-
const passphraseDecrypted = this.decrypt(
|
|
695
|
-
passphraseEncrypted,
|
|
696
|
-
timestamp.toString()
|
|
697
|
-
);
|
|
698
|
-
if (passphraseDecrypted != null)
|
|
699
|
-
this.passphrase = passphraseDecrypted;
|
|
700
|
-
}
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
return deviceId ?? '';
|
|
705
|
-
}
|
|
706
|
-
|
|
707
666
|
/**
|
|
708
667
|
* Api init call
|
|
709
668
|
* @param data Data
|
|
@@ -713,44 +672,44 @@ export abstract class CoreApp<
|
|
|
713
672
|
return await this.api.put<InitCallResult>(this.initCallApi, data);
|
|
714
673
|
}
|
|
715
674
|
|
|
716
|
-
/**
|
|
717
|
-
* Get device last updte miliseconds
|
|
718
|
-
* @returns Miliseconds
|
|
719
|
-
*/
|
|
720
|
-
protected getDeviceUpdateTime() {
|
|
721
|
-
return StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
|
|
722
|
-
}
|
|
723
|
-
|
|
724
675
|
/**
|
|
725
676
|
* Init call
|
|
726
677
|
* @param callback Callback
|
|
727
678
|
* @returns Result
|
|
728
679
|
*/
|
|
729
680
|
async initCall(callback?: (result: boolean) => void) {
|
|
730
|
-
//
|
|
731
|
-
|
|
732
|
-
const
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
if (
|
|
741
|
-
|
|
681
|
+
// Passphrase exists?
|
|
682
|
+
// Same session should avoid multiple init calls
|
|
683
|
+
const passphraseEncrypted = this.storage.getData<string>(
|
|
684
|
+
CoreApp.devicePassphraseField
|
|
685
|
+
);
|
|
686
|
+
if (passphraseEncrypted) {
|
|
687
|
+
const passphraseDecrypted = this.decrypt(
|
|
688
|
+
passphraseEncrypted,
|
|
689
|
+
this.name
|
|
690
|
+
);
|
|
691
|
+
if (passphraseDecrypted != null) {
|
|
692
|
+
this.passphrase = passphraseDecrypted;
|
|
693
|
+
if (callback) callback(true);
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
742
696
|
}
|
|
743
697
|
|
|
744
698
|
// Serverside encrypted device id
|
|
745
|
-
const identifier =
|
|
746
|
-
|
|
699
|
+
const identifier = this.storage.getData<string>(
|
|
700
|
+
CoreApp.serversideDeviceIdField
|
|
747
701
|
);
|
|
748
702
|
|
|
703
|
+
// Timestamp
|
|
704
|
+
const timestamp = new Date().getTime();
|
|
705
|
+
|
|
706
|
+
// Request data
|
|
749
707
|
const data: InitCallDto = {
|
|
750
708
|
timestamp,
|
|
751
709
|
identifier,
|
|
752
|
-
deviceId:
|
|
710
|
+
deviceId: this.deviceId ? this.deviceId : undefined
|
|
753
711
|
};
|
|
712
|
+
|
|
754
713
|
const result = await this.apiInitCall(data);
|
|
755
714
|
if (result == null) {
|
|
756
715
|
if (callback) callback(false);
|
|
@@ -783,7 +742,7 @@ export abstract class CoreApp<
|
|
|
783
742
|
if (callback) callback(false);
|
|
784
743
|
|
|
785
744
|
// Clear device id
|
|
786
|
-
|
|
745
|
+
this.storage.setData(CoreApp.deviceIdField, undefined);
|
|
787
746
|
|
|
788
747
|
return;
|
|
789
748
|
}
|
|
@@ -799,6 +758,7 @@ export abstract class CoreApp<
|
|
|
799
758
|
* @param timestamp Timestamp
|
|
800
759
|
*/
|
|
801
760
|
protected initCallUpdate(data: InitCallResultData, timestamp: number) {
|
|
761
|
+
// Data check
|
|
802
762
|
if (data.deviceId == null || data.passphrase == null) return;
|
|
803
763
|
|
|
804
764
|
// Decrypt
|
|
@@ -807,13 +767,15 @@ export abstract class CoreApp<
|
|
|
807
767
|
if (passphrase == null) return;
|
|
808
768
|
|
|
809
769
|
// Update device id and cache it
|
|
810
|
-
this.
|
|
811
|
-
|
|
812
|
-
StorageUtils.setLocalData(this.devicePassphraseField, data.passphrase);
|
|
813
|
-
StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
|
|
770
|
+
this._deviceId = data.deviceId;
|
|
771
|
+
this.storage.setData(CoreApp.deviceIdField, this.deviceId);
|
|
814
772
|
|
|
815
773
|
// Current passphrase
|
|
816
774
|
this.passphrase = passphrase;
|
|
775
|
+
this.storage.setData(
|
|
776
|
+
CoreApp.devicePassphraseField,
|
|
777
|
+
this.encrypt(passphrase, this.name)
|
|
778
|
+
);
|
|
817
779
|
|
|
818
780
|
// Previous passphrase
|
|
819
781
|
if (data.previousPassphrase) {
|
|
@@ -823,9 +785,9 @@ export abstract class CoreApp<
|
|
|
823
785
|
);
|
|
824
786
|
|
|
825
787
|
// Update
|
|
826
|
-
const fields = this.
|
|
788
|
+
const fields = this.initCallEncryptedUpdateFields();
|
|
827
789
|
for (const field of fields) {
|
|
828
|
-
const currentValue =
|
|
790
|
+
const currentValue = this.storage.getData<string>(field);
|
|
829
791
|
if (currentValue == null || currentValue === '') continue;
|
|
830
792
|
|
|
831
793
|
const enhanced = currentValue.indexOf('!') >= 8;
|
|
@@ -847,17 +809,17 @@ export abstract class CoreApp<
|
|
|
847
809
|
? this.encryptEnhanced(newValueSource)
|
|
848
810
|
: this.encrypt(newValueSource);
|
|
849
811
|
|
|
850
|
-
|
|
812
|
+
this.storage.setData(field, newValue);
|
|
851
813
|
}
|
|
852
814
|
}
|
|
853
815
|
}
|
|
854
816
|
|
|
855
817
|
/**
|
|
856
|
-
* Init call
|
|
818
|
+
* Init call encrypted fields update
|
|
857
819
|
* @returns Fields
|
|
858
820
|
*/
|
|
859
|
-
protected
|
|
860
|
-
return [
|
|
821
|
+
protected initCallEncryptedUpdateFields(): string[] {
|
|
822
|
+
return [CoreApp.headerTokenField];
|
|
861
823
|
}
|
|
862
824
|
|
|
863
825
|
/**
|
|
@@ -884,7 +846,7 @@ export abstract class CoreApp<
|
|
|
884
846
|
// Cover the current value
|
|
885
847
|
if (refreshToken !== '') {
|
|
886
848
|
if (refreshToken != null) refreshToken = this.encrypt(refreshToken);
|
|
887
|
-
|
|
849
|
+
this.storage.setData(CoreApp.headerTokenField, refreshToken);
|
|
888
850
|
}
|
|
889
851
|
|
|
890
852
|
// Reset tryLogin state
|
|
@@ -971,13 +933,12 @@ export abstract class CoreApp<
|
|
|
971
933
|
* Clear cache data
|
|
972
934
|
*/
|
|
973
935
|
clearCacheData() {
|
|
974
|
-
|
|
936
|
+
this.storage.setData(CoreApp.serversideDeviceIdField, undefined);
|
|
975
937
|
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
StorageUtils.setLocalData(this.deviceIdUpdateTimeField, undefined);
|
|
938
|
+
this.storage.setData(CoreApp.deviceIdField, undefined);
|
|
939
|
+
this.storage.setData(CoreApp.devicePassphraseField, undefined);
|
|
979
940
|
|
|
980
|
-
|
|
941
|
+
this.storage.setData(CoreApp.headerTokenField, undefined);
|
|
981
942
|
}
|
|
982
943
|
|
|
983
944
|
/**
|
|
@@ -985,7 +946,7 @@ export abstract class CoreApp<
|
|
|
985
946
|
*/
|
|
986
947
|
clearCacheToken() {
|
|
987
948
|
this.cachedRefreshToken = undefined;
|
|
988
|
-
|
|
949
|
+
this.storage.setData(CoreApp.headerTokenField, undefined);
|
|
989
950
|
}
|
|
990
951
|
|
|
991
952
|
/**
|
|
@@ -1291,7 +1252,7 @@ export abstract class CoreApp<
|
|
|
1291
1252
|
getCacheToken(): string | undefined {
|
|
1292
1253
|
// Temp refresh token
|
|
1293
1254
|
if (this.cachedRefreshToken) return this.cachedRefreshToken;
|
|
1294
|
-
return
|
|
1255
|
+
return this.storage.getData<string>(CoreApp.headerTokenField);
|
|
1295
1256
|
}
|
|
1296
1257
|
|
|
1297
1258
|
/**
|
|
@@ -1311,7 +1272,10 @@ export abstract class CoreApp<
|
|
|
1311
1272
|
*/
|
|
1312
1273
|
getResponseToken(rawResponse: any): string | null {
|
|
1313
1274
|
const response = this.api.transformResponse(rawResponse);
|
|
1314
|
-
return this.api.getHeaderValue(
|
|
1275
|
+
return this.api.getHeaderValue(
|
|
1276
|
+
response.headers,
|
|
1277
|
+
CoreApp.headerTokenField
|
|
1278
|
+
);
|
|
1315
1279
|
}
|
|
1316
1280
|
|
|
1317
1281
|
/**
|
|
@@ -1474,10 +1438,15 @@ export abstract class CoreApp<
|
|
|
1474
1438
|
/**
|
|
1475
1439
|
* Switch organization
|
|
1476
1440
|
* @param id Organization id
|
|
1441
|
+
* @param serviceId Service id
|
|
1477
1442
|
*/
|
|
1478
|
-
async switchOrg(id: number) {
|
|
1479
|
-
const api = `Organization/Switch
|
|
1480
|
-
const result = await this.api.put<boolean>(api
|
|
1443
|
+
async switchOrg(id: number, serviceId?: number) {
|
|
1444
|
+
const api = `Organization/Switch`;
|
|
1445
|
+
const result = await this.api.put<boolean>(api, {
|
|
1446
|
+
id,
|
|
1447
|
+
serviceId,
|
|
1448
|
+
deviceId: this.deviceId
|
|
1449
|
+
});
|
|
1481
1450
|
if (result) return await this.refreshToken();
|
|
1482
1451
|
return result;
|
|
1483
1452
|
}
|
|
@@ -1535,7 +1504,7 @@ export abstract class CoreApp<
|
|
|
1535
1504
|
this.userData = user;
|
|
1536
1505
|
|
|
1537
1506
|
// Cache the encrypted serverside device id
|
|
1538
|
-
|
|
1507
|
+
this.storage.setData(CoreApp.serversideDeviceIdField, user.deviceId);
|
|
1539
1508
|
|
|
1540
1509
|
if (keep) {
|
|
1541
1510
|
this.authorize(user.token, refreshToken);
|
|
@@ -1582,3 +1551,25 @@ export abstract class CoreApp<
|
|
|
1582
1551
|
);
|
|
1583
1552
|
}
|
|
1584
1553
|
}
|
|
1554
|
+
|
|
1555
|
+
export namespace CoreApp {
|
|
1556
|
+
/**
|
|
1557
|
+
* Response token header field name
|
|
1558
|
+
*/
|
|
1559
|
+
export const headerTokenField = 'SmartERPRefreshToken';
|
|
1560
|
+
|
|
1561
|
+
/**
|
|
1562
|
+
* Serverside device id encrypted field name
|
|
1563
|
+
*/
|
|
1564
|
+
export const serversideDeviceIdField = 'SmartERPServersideDeviceId';
|
|
1565
|
+
|
|
1566
|
+
/**
|
|
1567
|
+
* Device id field name
|
|
1568
|
+
*/
|
|
1569
|
+
export const deviceIdField = 'SmartERPDeviceId';
|
|
1570
|
+
|
|
1571
|
+
/**
|
|
1572
|
+
* Device passphrase field name
|
|
1573
|
+
*/
|
|
1574
|
+
export const devicePassphraseField = 'SmartERPDevicePassphrase';
|
|
1575
|
+
}
|