@etsoo/appscript 1.1.91 → 1.1.95
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 +31 -35
- package/lib/cjs/app/CoreApp.js +62 -88
- package/lib/mjs/app/CoreApp.d.ts +31 -35
- package/lib/mjs/app/CoreApp.js +63 -89
- package/package.json +2 -2
- package/src/app/CoreApp.ts +90 -105
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
|
*/
|
|
@@ -354,6 +358,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
354
358
|
* Notifier
|
|
355
359
|
*/
|
|
356
360
|
readonly notifier: INotifier<N, C>;
|
|
361
|
+
/**
|
|
362
|
+
* Storage
|
|
363
|
+
*/
|
|
364
|
+
readonly storage: IStorage;
|
|
357
365
|
private _culture;
|
|
358
366
|
/**
|
|
359
367
|
* Culture, like zh-CN
|
|
@@ -374,7 +382,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
374
382
|
* Country or region, like CN
|
|
375
383
|
*/
|
|
376
384
|
get deviceId(): string;
|
|
377
|
-
protected set deviceId(value: string);
|
|
378
385
|
/**
|
|
379
386
|
* Label delegate
|
|
380
387
|
*/
|
|
@@ -391,14 +398,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
391
398
|
*/
|
|
392
399
|
get userData(): IUserData | undefined;
|
|
393
400
|
protected set userData(value: IUserData | undefined);
|
|
394
|
-
/**
|
|
395
|
-
* Response token header field name
|
|
396
|
-
*/
|
|
397
|
-
readonly headerTokenField = "SmartERPRefreshToken";
|
|
398
|
-
/**
|
|
399
|
-
* Serverside device id encrypted field name
|
|
400
|
-
*/
|
|
401
|
-
protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
|
|
402
401
|
private ipDetectCallbacks?;
|
|
403
402
|
/**
|
|
404
403
|
* Search input element
|
|
@@ -419,18 +418,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
419
418
|
* Token refresh count down seed
|
|
420
419
|
*/
|
|
421
420
|
protected refreshCountdownSeed: number;
|
|
422
|
-
/**
|
|
423
|
-
* Device id field name
|
|
424
|
-
*/
|
|
425
|
-
private readonly deviceIdField;
|
|
426
|
-
/**
|
|
427
|
-
* Device passphrase field name
|
|
428
|
-
*/
|
|
429
|
-
private readonly devicePassphraseField;
|
|
430
|
-
/**
|
|
431
|
-
* Device id update time field name
|
|
432
|
-
*/
|
|
433
|
-
private readonly deviceIdUpdateTimeField;
|
|
434
421
|
/**
|
|
435
422
|
* Init call Api URL
|
|
436
423
|
*/
|
|
@@ -445,26 +432,17 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
445
432
|
* @param settings Settings
|
|
446
433
|
* @param api API
|
|
447
434
|
* @param notifier Notifier
|
|
435
|
+
* @param storage Storage
|
|
448
436
|
* @param name Application name
|
|
449
437
|
*/
|
|
450
|
-
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);
|
|
451
439
|
protected setApi(api: IApi): void;
|
|
452
|
-
/**
|
|
453
|
-
* Setup device
|
|
454
|
-
* @returns Device id
|
|
455
|
-
*/
|
|
456
|
-
protected setupDevice(): string;
|
|
457
440
|
/**
|
|
458
441
|
* Api init call
|
|
459
442
|
* @param data Data
|
|
460
443
|
* @returns Result
|
|
461
444
|
*/
|
|
462
445
|
protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
|
|
463
|
-
/**
|
|
464
|
-
* Get device last updte miliseconds
|
|
465
|
-
* @returns Miliseconds
|
|
466
|
-
*/
|
|
467
|
-
protected getDeviceUpdateTime(): number;
|
|
468
446
|
/**
|
|
469
447
|
* Init call
|
|
470
448
|
* @param callback Callback
|
|
@@ -478,10 +456,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
478
456
|
*/
|
|
479
457
|
protected initCallUpdate(data: InitCallResultData, timestamp: number): void;
|
|
480
458
|
/**
|
|
481
|
-
* Init call
|
|
459
|
+
* Init call encrypted fields update
|
|
482
460
|
* @returns Fields
|
|
483
461
|
*/
|
|
484
|
-
protected
|
|
462
|
+
protected initCallEncryptedUpdateFields(): string[];
|
|
485
463
|
/**
|
|
486
464
|
* Alert action result
|
|
487
465
|
* @param result Action result
|
|
@@ -732,3 +710,21 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
732
710
|
*/
|
|
733
711
|
warning(message: NotificationContent<N>, align?: NotificationAlign): void;
|
|
734
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;
|
|
@@ -365,7 +322,7 @@ class CoreApp {
|
|
|
365
322
|
if (regionItem == null || !this.settings.regions.includes(regionId))
|
|
366
323
|
return;
|
|
367
324
|
// Save the id to local storage
|
|
368
|
-
shared_1.DomUtils.
|
|
325
|
+
this.storage.setData(shared_1.DomUtils.CountryField, regionId);
|
|
369
326
|
// Set the currency and culture
|
|
370
327
|
this._currency = regionItem.currency;
|
|
371
328
|
this._region = regionId;
|
|
@@ -383,7 +340,7 @@ class CoreApp {
|
|
|
383
340
|
if (this._culture === name)
|
|
384
341
|
return;
|
|
385
342
|
// Save the cultrue to local storage
|
|
386
|
-
shared_1.DomUtils.
|
|
343
|
+
this.storage.setData(shared_1.DomUtils.CultureField, name);
|
|
387
344
|
// Change the API's Content-Language header
|
|
388
345
|
// .net 5 API, UseRequestLocalization, RequestCultureProviders, ContentLanguageHeaderRequestCultureProvider
|
|
389
346
|
this.api.setContentLanguage(name);
|
|
@@ -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
|
|
@@ -879,7 +835,7 @@ class CoreApp {
|
|
|
879
835
|
userLogin(user, refreshToken, keep) {
|
|
880
836
|
this.userData = user;
|
|
881
837
|
// Cache the encrypted serverside device id
|
|
882
|
-
|
|
838
|
+
this.storage.setData(CoreApp.serversideDeviceIdField, user.deviceId);
|
|
883
839
|
if (keep) {
|
|
884
840
|
this.authorize(user.token, refreshToken);
|
|
885
841
|
}
|
|
@@ -917,3 +873,21 @@ class CoreApp {
|
|
|
917
873
|
}
|
|
918
874
|
}
|
|
919
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
|
*/
|
|
@@ -354,6 +358,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
354
358
|
* Notifier
|
|
355
359
|
*/
|
|
356
360
|
readonly notifier: INotifier<N, C>;
|
|
361
|
+
/**
|
|
362
|
+
* Storage
|
|
363
|
+
*/
|
|
364
|
+
readonly storage: IStorage;
|
|
357
365
|
private _culture;
|
|
358
366
|
/**
|
|
359
367
|
* Culture, like zh-CN
|
|
@@ -374,7 +382,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
374
382
|
* Country or region, like CN
|
|
375
383
|
*/
|
|
376
384
|
get deviceId(): string;
|
|
377
|
-
protected set deviceId(value: string);
|
|
378
385
|
/**
|
|
379
386
|
* Label delegate
|
|
380
387
|
*/
|
|
@@ -391,14 +398,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
391
398
|
*/
|
|
392
399
|
get userData(): IUserData | undefined;
|
|
393
400
|
protected set userData(value: IUserData | undefined);
|
|
394
|
-
/**
|
|
395
|
-
* Response token header field name
|
|
396
|
-
*/
|
|
397
|
-
readonly headerTokenField = "SmartERPRefreshToken";
|
|
398
|
-
/**
|
|
399
|
-
* Serverside device id encrypted field name
|
|
400
|
-
*/
|
|
401
|
-
protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
|
|
402
401
|
private ipDetectCallbacks?;
|
|
403
402
|
/**
|
|
404
403
|
* Search input element
|
|
@@ -419,18 +418,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
419
418
|
* Token refresh count down seed
|
|
420
419
|
*/
|
|
421
420
|
protected refreshCountdownSeed: number;
|
|
422
|
-
/**
|
|
423
|
-
* Device id field name
|
|
424
|
-
*/
|
|
425
|
-
private readonly deviceIdField;
|
|
426
|
-
/**
|
|
427
|
-
* Device passphrase field name
|
|
428
|
-
*/
|
|
429
|
-
private readonly devicePassphraseField;
|
|
430
|
-
/**
|
|
431
|
-
* Device id update time field name
|
|
432
|
-
*/
|
|
433
|
-
private readonly deviceIdUpdateTimeField;
|
|
434
421
|
/**
|
|
435
422
|
* Init call Api URL
|
|
436
423
|
*/
|
|
@@ -445,26 +432,17 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
445
432
|
* @param settings Settings
|
|
446
433
|
* @param api API
|
|
447
434
|
* @param notifier Notifier
|
|
435
|
+
* @param storage Storage
|
|
448
436
|
* @param name Application name
|
|
449
437
|
*/
|
|
450
|
-
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);
|
|
451
439
|
protected setApi(api: IApi): void;
|
|
452
|
-
/**
|
|
453
|
-
* Setup device
|
|
454
|
-
* @returns Device id
|
|
455
|
-
*/
|
|
456
|
-
protected setupDevice(): string;
|
|
457
440
|
/**
|
|
458
441
|
* Api init call
|
|
459
442
|
* @param data Data
|
|
460
443
|
* @returns Result
|
|
461
444
|
*/
|
|
462
445
|
protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
|
|
463
|
-
/**
|
|
464
|
-
* Get device last updte miliseconds
|
|
465
|
-
* @returns Miliseconds
|
|
466
|
-
*/
|
|
467
|
-
protected getDeviceUpdateTime(): number;
|
|
468
446
|
/**
|
|
469
447
|
* Init call
|
|
470
448
|
* @param callback Callback
|
|
@@ -478,10 +456,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
478
456
|
*/
|
|
479
457
|
protected initCallUpdate(data: InitCallResultData, timestamp: number): void;
|
|
480
458
|
/**
|
|
481
|
-
* Init call
|
|
459
|
+
* Init call encrypted fields update
|
|
482
460
|
* @returns Fields
|
|
483
461
|
*/
|
|
484
|
-
protected
|
|
462
|
+
protected initCallEncryptedUpdateFields(): string[];
|
|
485
463
|
/**
|
|
486
464
|
* Alert action result
|
|
487
465
|
* @param result Action result
|
|
@@ -732,3 +710,21 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
|
|
|
732
710
|
*/
|
|
733
711
|
warning(message: NotificationContent<N>, align?: NotificationAlign): void;
|
|
734
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;
|
|
@@ -362,7 +319,7 @@ export class CoreApp {
|
|
|
362
319
|
if (regionItem == null || !this.settings.regions.includes(regionId))
|
|
363
320
|
return;
|
|
364
321
|
// Save the id to local storage
|
|
365
|
-
DomUtils.
|
|
322
|
+
this.storage.setData(DomUtils.CountryField, regionId);
|
|
366
323
|
// Set the currency and culture
|
|
367
324
|
this._currency = regionItem.currency;
|
|
368
325
|
this._region = regionId;
|
|
@@ -380,7 +337,7 @@ export class CoreApp {
|
|
|
380
337
|
if (this._culture === name)
|
|
381
338
|
return;
|
|
382
339
|
// Save the cultrue to local storage
|
|
383
|
-
DomUtils.
|
|
340
|
+
this.storage.setData(DomUtils.CultureField, name);
|
|
384
341
|
// Change the API's Content-Language header
|
|
385
342
|
// .net 5 API, UseRequestLocalization, RequestCultureProviders, ContentLanguageHeaderRequestCultureProvider
|
|
386
343
|
this.api.setContentLanguage(name);
|
|
@@ -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
|
|
@@ -876,7 +832,7 @@ export class CoreApp {
|
|
|
876
832
|
userLogin(user, refreshToken, keep) {
|
|
877
833
|
this.userData = user;
|
|
878
834
|
// Cache the encrypted serverside device id
|
|
879
|
-
|
|
835
|
+
this.storage.setData(CoreApp.serversideDeviceIdField, user.deviceId);
|
|
880
836
|
if (keep) {
|
|
881
837
|
this.authorize(user.token, refreshToken);
|
|
882
838
|
}
|
|
@@ -913,3 +869,21 @@ export class CoreApp {
|
|
|
913
869
|
});
|
|
914
870
|
}
|
|
915
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.95",
|
|
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.85",
|
|
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
|
*/
|
|
@@ -480,6 +485,11 @@ export abstract class CoreApp<
|
|
|
480
485
|
*/
|
|
481
486
|
readonly notifier: INotifier<N, C>;
|
|
482
487
|
|
|
488
|
+
/**
|
|
489
|
+
* Storage
|
|
490
|
+
*/
|
|
491
|
+
readonly storage: IStorage;
|
|
492
|
+
|
|
483
493
|
private _culture!: string;
|
|
484
494
|
/**
|
|
485
495
|
* Culture, like zh-CN
|
|
@@ -504,16 +514,13 @@ export abstract class CoreApp<
|
|
|
504
514
|
return this._region;
|
|
505
515
|
}
|
|
506
516
|
|
|
507
|
-
private _deviceId: string
|
|
517
|
+
private _deviceId: string;
|
|
508
518
|
/**
|
|
509
519
|
* Country or region, like CN
|
|
510
520
|
*/
|
|
511
521
|
get deviceId() {
|
|
512
522
|
return this._deviceId;
|
|
513
523
|
}
|
|
514
|
-
protected set deviceId(value: string) {
|
|
515
|
-
this._deviceId = value;
|
|
516
|
-
}
|
|
517
524
|
|
|
518
525
|
/**
|
|
519
526
|
* Label delegate
|
|
@@ -544,16 +551,6 @@ export abstract class CoreApp<
|
|
|
544
551
|
this._userData = value;
|
|
545
552
|
}
|
|
546
553
|
|
|
547
|
-
/**
|
|
548
|
-
* Response token header field name
|
|
549
|
-
*/
|
|
550
|
-
readonly headerTokenField = 'SmartERPRefreshToken';
|
|
551
|
-
|
|
552
|
-
/**
|
|
553
|
-
* Serverside device id encrypted field name
|
|
554
|
-
*/
|
|
555
|
-
protected readonly serversideDeviceIdField = 'SmartERPServersideDeviceId';
|
|
556
|
-
|
|
557
554
|
// IP detect ready callbacks
|
|
558
555
|
private ipDetectCallbacks?: IDetectIPCallback[];
|
|
559
556
|
|
|
@@ -586,22 +583,6 @@ export abstract class CoreApp<
|
|
|
586
583
|
*/
|
|
587
584
|
protected refreshCountdownSeed = 0;
|
|
588
585
|
|
|
589
|
-
/**
|
|
590
|
-
* Device id field name
|
|
591
|
-
*/
|
|
592
|
-
private readonly deviceIdField: string = 'SmartERPDeviceId';
|
|
593
|
-
|
|
594
|
-
/**
|
|
595
|
-
* Device passphrase field name
|
|
596
|
-
*/
|
|
597
|
-
private readonly devicePassphraseField: string = 'SmartERPDevicePassphrase';
|
|
598
|
-
|
|
599
|
-
/**
|
|
600
|
-
* Device id update time field name
|
|
601
|
-
*/
|
|
602
|
-
private readonly deviceIdUpdateTimeField: string =
|
|
603
|
-
'SmartERPDeviceIdUpdateTime';
|
|
604
|
-
|
|
605
586
|
/**
|
|
606
587
|
* Init call Api URL
|
|
607
588
|
*/
|
|
@@ -619,20 +600,24 @@ export abstract class CoreApp<
|
|
|
619
600
|
* @param settings Settings
|
|
620
601
|
* @param api API
|
|
621
602
|
* @param notifier Notifier
|
|
603
|
+
* @param storage Storage
|
|
622
604
|
* @param name Application name
|
|
623
605
|
*/
|
|
624
606
|
protected constructor(
|
|
625
607
|
settings: S,
|
|
626
608
|
api: IApi,
|
|
627
609
|
notifier: INotifier<N, C>,
|
|
610
|
+
storage: IStorage,
|
|
628
611
|
name: string
|
|
629
612
|
) {
|
|
630
613
|
this.settings = settings;
|
|
631
614
|
this.api = api;
|
|
632
615
|
this.notifier = notifier;
|
|
616
|
+
this.storage = storage;
|
|
633
617
|
this.name = name;
|
|
634
618
|
|
|
635
|
-
|
|
619
|
+
// Device id
|
|
620
|
+
this._deviceId = storage.getData<string>(CoreApp.deviceIdField) ?? '';
|
|
636
621
|
|
|
637
622
|
this.setApi(api);
|
|
638
623
|
|
|
@@ -678,33 +663,6 @@ export abstract class CoreApp<
|
|
|
678
663
|
};
|
|
679
664
|
}
|
|
680
665
|
|
|
681
|
-
/**
|
|
682
|
-
* Setup device
|
|
683
|
-
* @returns Device id
|
|
684
|
-
*/
|
|
685
|
-
protected setupDevice() {
|
|
686
|
-
const deviceId = StorageUtils.getLocalData<string>(this.deviceIdField);
|
|
687
|
-
|
|
688
|
-
if (deviceId != null && deviceId !== '') {
|
|
689
|
-
const passphraseEncrypted = StorageUtils.getLocalData<string>(
|
|
690
|
-
this.devicePassphraseField
|
|
691
|
-
);
|
|
692
|
-
if (passphraseEncrypted != null && passphraseEncrypted !== '') {
|
|
693
|
-
const timestamp = this.getDeviceUpdateTime();
|
|
694
|
-
if (timestamp > 0) {
|
|
695
|
-
const passphraseDecrypted = this.decrypt(
|
|
696
|
-
passphraseEncrypted,
|
|
697
|
-
timestamp.toString()
|
|
698
|
-
);
|
|
699
|
-
if (passphraseDecrypted != null)
|
|
700
|
-
this.passphrase = passphraseDecrypted;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
return deviceId ?? '';
|
|
706
|
-
}
|
|
707
|
-
|
|
708
666
|
/**
|
|
709
667
|
* Api init call
|
|
710
668
|
* @param data Data
|
|
@@ -714,44 +672,44 @@ export abstract class CoreApp<
|
|
|
714
672
|
return await this.api.put<InitCallResult>(this.initCallApi, data);
|
|
715
673
|
}
|
|
716
674
|
|
|
717
|
-
/**
|
|
718
|
-
* Get device last updte miliseconds
|
|
719
|
-
* @returns Miliseconds
|
|
720
|
-
*/
|
|
721
|
-
protected getDeviceUpdateTime() {
|
|
722
|
-
return StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
|
|
723
|
-
}
|
|
724
|
-
|
|
725
675
|
/**
|
|
726
676
|
* Init call
|
|
727
677
|
* @param callback Callback
|
|
728
678
|
* @returns Result
|
|
729
679
|
*/
|
|
730
680
|
async initCall(callback?: (result: boolean) => void) {
|
|
731
|
-
//
|
|
732
|
-
|
|
733
|
-
const
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
if (
|
|
742
|
-
|
|
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
|
+
}
|
|
743
696
|
}
|
|
744
697
|
|
|
745
698
|
// Serverside encrypted device id
|
|
746
|
-
const identifier =
|
|
747
|
-
|
|
699
|
+
const identifier = this.storage.getData<string>(
|
|
700
|
+
CoreApp.serversideDeviceIdField
|
|
748
701
|
);
|
|
749
702
|
|
|
703
|
+
// Timestamp
|
|
704
|
+
const timestamp = new Date().getTime();
|
|
705
|
+
|
|
706
|
+
// Request data
|
|
750
707
|
const data: InitCallDto = {
|
|
751
708
|
timestamp,
|
|
752
709
|
identifier,
|
|
753
|
-
deviceId:
|
|
710
|
+
deviceId: this.deviceId ? this.deviceId : undefined
|
|
754
711
|
};
|
|
712
|
+
|
|
755
713
|
const result = await this.apiInitCall(data);
|
|
756
714
|
if (result == null) {
|
|
757
715
|
if (callback) callback(false);
|
|
@@ -784,7 +742,7 @@ export abstract class CoreApp<
|
|
|
784
742
|
if (callback) callback(false);
|
|
785
743
|
|
|
786
744
|
// Clear device id
|
|
787
|
-
|
|
745
|
+
this.storage.setData(CoreApp.deviceIdField, undefined);
|
|
788
746
|
|
|
789
747
|
return;
|
|
790
748
|
}
|
|
@@ -800,6 +758,7 @@ export abstract class CoreApp<
|
|
|
800
758
|
* @param timestamp Timestamp
|
|
801
759
|
*/
|
|
802
760
|
protected initCallUpdate(data: InitCallResultData, timestamp: number) {
|
|
761
|
+
// Data check
|
|
803
762
|
if (data.deviceId == null || data.passphrase == null) return;
|
|
804
763
|
|
|
805
764
|
// Decrypt
|
|
@@ -808,13 +767,15 @@ export abstract class CoreApp<
|
|
|
808
767
|
if (passphrase == null) return;
|
|
809
768
|
|
|
810
769
|
// Update device id and cache it
|
|
811
|
-
this.
|
|
812
|
-
|
|
813
|
-
StorageUtils.setLocalData(this.devicePassphraseField, data.passphrase);
|
|
814
|
-
StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
|
|
770
|
+
this._deviceId = data.deviceId;
|
|
771
|
+
this.storage.setData(CoreApp.deviceIdField, this.deviceId);
|
|
815
772
|
|
|
816
773
|
// Current passphrase
|
|
817
774
|
this.passphrase = passphrase;
|
|
775
|
+
this.storage.setData(
|
|
776
|
+
CoreApp.devicePassphraseField,
|
|
777
|
+
this.encrypt(passphrase, this.name)
|
|
778
|
+
);
|
|
818
779
|
|
|
819
780
|
// Previous passphrase
|
|
820
781
|
if (data.previousPassphrase) {
|
|
@@ -824,9 +785,9 @@ export abstract class CoreApp<
|
|
|
824
785
|
);
|
|
825
786
|
|
|
826
787
|
// Update
|
|
827
|
-
const fields = this.
|
|
788
|
+
const fields = this.initCallEncryptedUpdateFields();
|
|
828
789
|
for (const field of fields) {
|
|
829
|
-
const currentValue =
|
|
790
|
+
const currentValue = this.storage.getData<string>(field);
|
|
830
791
|
if (currentValue == null || currentValue === '') continue;
|
|
831
792
|
|
|
832
793
|
const enhanced = currentValue.indexOf('!') >= 8;
|
|
@@ -848,17 +809,17 @@ export abstract class CoreApp<
|
|
|
848
809
|
? this.encryptEnhanced(newValueSource)
|
|
849
810
|
: this.encrypt(newValueSource);
|
|
850
811
|
|
|
851
|
-
|
|
812
|
+
this.storage.setData(field, newValue);
|
|
852
813
|
}
|
|
853
814
|
}
|
|
854
815
|
}
|
|
855
816
|
|
|
856
817
|
/**
|
|
857
|
-
* Init call
|
|
818
|
+
* Init call encrypted fields update
|
|
858
819
|
* @returns Fields
|
|
859
820
|
*/
|
|
860
|
-
protected
|
|
861
|
-
return [
|
|
821
|
+
protected initCallEncryptedUpdateFields(): string[] {
|
|
822
|
+
return [CoreApp.headerTokenField];
|
|
862
823
|
}
|
|
863
824
|
|
|
864
825
|
/**
|
|
@@ -885,7 +846,7 @@ export abstract class CoreApp<
|
|
|
885
846
|
// Cover the current value
|
|
886
847
|
if (refreshToken !== '') {
|
|
887
848
|
if (refreshToken != null) refreshToken = this.encrypt(refreshToken);
|
|
888
|
-
|
|
849
|
+
this.storage.setData(CoreApp.headerTokenField, refreshToken);
|
|
889
850
|
}
|
|
890
851
|
|
|
891
852
|
// Reset tryLogin state
|
|
@@ -923,7 +884,7 @@ export abstract class CoreApp<
|
|
|
923
884
|
return;
|
|
924
885
|
|
|
925
886
|
// Save the id to local storage
|
|
926
|
-
DomUtils.
|
|
887
|
+
this.storage.setData(DomUtils.CountryField, regionId);
|
|
927
888
|
|
|
928
889
|
// Set the currency and culture
|
|
929
890
|
this._currency = regionItem.currency;
|
|
@@ -945,7 +906,7 @@ export abstract class CoreApp<
|
|
|
945
906
|
if (this._culture === name) return;
|
|
946
907
|
|
|
947
908
|
// Save the cultrue to local storage
|
|
948
|
-
DomUtils.
|
|
909
|
+
this.storage.setData(DomUtils.CultureField, name);
|
|
949
910
|
|
|
950
911
|
// Change the API's Content-Language header
|
|
951
912
|
// .net 5 API, UseRequestLocalization, RequestCultureProviders, ContentLanguageHeaderRequestCultureProvider
|
|
@@ -972,13 +933,12 @@ export abstract class CoreApp<
|
|
|
972
933
|
* Clear cache data
|
|
973
934
|
*/
|
|
974
935
|
clearCacheData() {
|
|
975
|
-
|
|
936
|
+
this.storage.setData(CoreApp.serversideDeviceIdField, undefined);
|
|
976
937
|
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
StorageUtils.setLocalData(this.deviceIdUpdateTimeField, undefined);
|
|
938
|
+
this.storage.setData(CoreApp.deviceIdField, undefined);
|
|
939
|
+
this.storage.setData(CoreApp.devicePassphraseField, undefined);
|
|
980
940
|
|
|
981
|
-
|
|
941
|
+
this.storage.setData(CoreApp.headerTokenField, undefined);
|
|
982
942
|
}
|
|
983
943
|
|
|
984
944
|
/**
|
|
@@ -986,7 +946,7 @@ export abstract class CoreApp<
|
|
|
986
946
|
*/
|
|
987
947
|
clearCacheToken() {
|
|
988
948
|
this.cachedRefreshToken = undefined;
|
|
989
|
-
|
|
949
|
+
this.storage.setData(CoreApp.headerTokenField, undefined);
|
|
990
950
|
}
|
|
991
951
|
|
|
992
952
|
/**
|
|
@@ -1292,7 +1252,7 @@ export abstract class CoreApp<
|
|
|
1292
1252
|
getCacheToken(): string | undefined {
|
|
1293
1253
|
// Temp refresh token
|
|
1294
1254
|
if (this.cachedRefreshToken) return this.cachedRefreshToken;
|
|
1295
|
-
return
|
|
1255
|
+
return this.storage.getData<string>(CoreApp.headerTokenField);
|
|
1296
1256
|
}
|
|
1297
1257
|
|
|
1298
1258
|
/**
|
|
@@ -1312,7 +1272,10 @@ export abstract class CoreApp<
|
|
|
1312
1272
|
*/
|
|
1313
1273
|
getResponseToken(rawResponse: any): string | null {
|
|
1314
1274
|
const response = this.api.transformResponse(rawResponse);
|
|
1315
|
-
return this.api.getHeaderValue(
|
|
1275
|
+
return this.api.getHeaderValue(
|
|
1276
|
+
response.headers,
|
|
1277
|
+
CoreApp.headerTokenField
|
|
1278
|
+
);
|
|
1316
1279
|
}
|
|
1317
1280
|
|
|
1318
1281
|
/**
|
|
@@ -1541,7 +1504,7 @@ export abstract class CoreApp<
|
|
|
1541
1504
|
this.userData = user;
|
|
1542
1505
|
|
|
1543
1506
|
// Cache the encrypted serverside device id
|
|
1544
|
-
|
|
1507
|
+
this.storage.setData(CoreApp.serversideDeviceIdField, user.deviceId);
|
|
1545
1508
|
|
|
1546
1509
|
if (keep) {
|
|
1547
1510
|
this.authorize(user.token, refreshToken);
|
|
@@ -1588,3 +1551,25 @@ export abstract class CoreApp<
|
|
|
1588
1551
|
);
|
|
1589
1552
|
}
|
|
1590
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
|
+
}
|