@etsoo/appscript 1.1.84 → 1.1.88

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.
@@ -136,7 +136,6 @@ test('Tests for encryptEnhanced / decryptEnhanced', () => {
136
136
 
137
137
  // Act
138
138
  const encrypted = app.encryptEnhanced(input, passphrase);
139
- console.log(encrypted);
140
139
  const plain = app.decryptEnhanced(encrypted, passphrase);
141
140
  expect(plain).toEqual(input);
142
141
  });
@@ -119,6 +119,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
119
119
  * @param culture New culture definition
120
120
  */
121
121
  changeCulture(culture: DataTypes.CultureDefinition): void;
122
+ /**
123
+ * Clear cache data
124
+ */
125
+ clearCacheData(): void;
122
126
  /**
123
127
  * Clear cached token
124
128
  */
@@ -222,7 +226,7 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
222
226
  * Get cached token
223
227
  * @returns Cached token
224
228
  */
225
- getCacheToken(): string | null;
229
+ getCacheToken(): string | undefined;
226
230
  /**
227
231
  * Get all regions
228
232
  * @returns Regions
@@ -375,18 +379,26 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
375
379
  * Label delegate
376
380
  */
377
381
  get labelDelegate(): <T = string>(key: string) => T | undefined;
382
+ private _ipData?;
378
383
  /**
379
384
  * IP data
380
385
  */
381
- ipData?: IPData;
386
+ get ipData(): IPData | undefined;
387
+ protected set ipData(value: IPData | undefined);
388
+ private _userData?;
382
389
  /**
383
390
  * User data
384
391
  */
385
- userData?: IUserData;
392
+ get userData(): IUserData | undefined;
393
+ protected set userData(value: IUserData | undefined);
386
394
  /**
387
395
  * Response token header field name
388
396
  */
389
- headerTokenField: string;
397
+ readonly headerTokenField = "SmartERPRefreshToken";
398
+ /**
399
+ * Serverside device id encrypted field name
400
+ */
401
+ protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
390
402
  private ipDetectCallbacks?;
391
403
  /**
392
404
  * Search input element
@@ -410,7 +422,15 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
410
422
  /**
411
423
  * Device id field name
412
424
  */
413
- protected deviceIdField: string;
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;
414
434
  /**
415
435
  * Init call Api URL
416
436
  */
@@ -429,12 +449,22 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
429
449
  */
430
450
  protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, name: string);
431
451
  protected setApi(api: IApi): void;
452
+ /**
453
+ * Setup device
454
+ * @returns Device id
455
+ */
456
+ protected setupDevice(): string;
432
457
  /**
433
458
  * Api init call
434
459
  * @param data Data
435
460
  * @returns Result
436
461
  */
437
462
  protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
463
+ /**
464
+ * Get device last updte miliseconds
465
+ * @returns Miliseconds
466
+ */
467
+ protected getDeviceUpdateTime(): number;
438
468
  /**
439
469
  * Init call
440
470
  * @param callback Callback
@@ -473,6 +503,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
473
503
  * @param culture New culture definition
474
504
  */
475
505
  changeCulture(culture: DataTypes.CultureDefinition): void;
506
+ /**
507
+ * Clear cache data
508
+ */
509
+ clearCacheData(): void;
476
510
  /**
477
511
  * Clear cached token
478
512
  */
@@ -579,7 +613,7 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
579
613
  * Get cached token
580
614
  * @returns Cached token
581
615
  */
582
- getCacheToken(): string | null;
616
+ getCacheToken(): string | undefined;
583
617
  /**
584
618
  * Get all regions
585
619
  * @returns Regions
@@ -20,11 +20,15 @@ class CoreApp {
20
20
  * @param name Application name
21
21
  */
22
22
  constructor(settings, api, notifier, name) {
23
- this._deviceId = '***';
23
+ this._deviceId = '';
24
24
  /**
25
25
  * Response token header field name
26
26
  */
27
27
  this.headerTokenField = 'SmartERPRefreshToken';
28
+ /**
29
+ * Serverside device id encrypted field name
30
+ */
31
+ this.serversideDeviceIdField = 'SmartERPServersideDeviceId';
28
32
  this._authorized = false;
29
33
  this._isTryingLogin = false;
30
34
  /**
@@ -39,6 +43,14 @@ class CoreApp {
39
43
  * Device id field name
40
44
  */
41
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';
42
54
  /**
43
55
  * Init call Api URL
44
56
  */
@@ -51,7 +63,7 @@ class CoreApp {
51
63
  this.api = api;
52
64
  this.notifier = notifier;
53
65
  this.name = name;
54
- this.deviceId = shared_1.StorageUtils.getLocalData(this.deviceIdField, '');
66
+ this.deviceId = this.setupDevice();
55
67
  this.setApi(api);
56
68
  const { currentCulture, currentRegion } = settings;
57
69
  this.changeCulture(currentCulture);
@@ -92,6 +104,24 @@ class CoreApp {
92
104
  get labelDelegate() {
93
105
  return this.get.bind(this);
94
106
  }
107
+ /**
108
+ * IP data
109
+ */
110
+ get ipData() {
111
+ return this._ipData;
112
+ }
113
+ set ipData(value) {
114
+ this._ipData = value;
115
+ }
116
+ /**
117
+ * User data
118
+ */
119
+ get userData() {
120
+ return this._userData;
121
+ }
122
+ set userData(value) {
123
+ this._userData = value;
124
+ }
95
125
  /**
96
126
  * Is current authorized
97
127
  */
@@ -131,6 +161,25 @@ class CoreApp {
131
161
  }
132
162
  };
133
163
  }
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
+ }
134
183
  /**
135
184
  * Api init call
136
185
  * @param data Data
@@ -139,6 +188,13 @@ class CoreApp {
139
188
  async apiInitCall(data) {
140
189
  return await this.api.put(this.initCallApi, data);
141
190
  }
191
+ /**
192
+ * Get device last updte miliseconds
193
+ * @returns Miliseconds
194
+ */
195
+ getDeviceUpdateTime() {
196
+ return shared_1.StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
197
+ }
142
198
  /**
143
199
  * Init call
144
200
  * @param callback Callback
@@ -146,9 +202,24 @@ class CoreApp {
146
202
  */
147
203
  async initCall(callback) {
148
204
  var _a;
205
+ // Device
206
+ let hasDeviceId = this.deviceId != null && this.deviceId !== '';
207
+ const timestamp = new Date().getTime();
208
+ const lastTimestamp = this.getDeviceUpdateTime();
209
+ if (hasDeviceId &&
210
+ lastTimestamp > 0 &&
211
+ timestamp - lastTimestamp <= 1296000000) {
212
+ // When deviceId is there and less than 15 days = 1000 * 60 * 60 * 24 * 15
213
+ if (callback)
214
+ callback(true);
215
+ return;
216
+ }
217
+ // Serverside encrypted device id
218
+ const identifier = shared_1.StorageUtils.getLocalData(this.serversideDeviceIdField);
149
219
  const data = {
150
- timestamp: new Date().getTime(),
151
- deviceId: this.deviceId === '' ? undefined : this.deviceId
220
+ timestamp,
221
+ identifier,
222
+ deviceId: hasDeviceId ? this.deviceId : undefined
152
223
  };
153
224
  const result = await this.apiInitCall(data);
154
225
  if (result == null) {
@@ -200,6 +271,8 @@ class CoreApp {
200
271
  // Update device id and cache it
201
272
  this.deviceId = data.deviceId;
202
273
  shared_1.StorageUtils.setLocalData(this.deviceIdField, this.deviceId);
274
+ shared_1.StorageUtils.setLocalData(this.devicePassphraseField, data.passphrase);
275
+ shared_1.StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
203
276
  // Current passphrase
204
277
  this.passphrase = passphrase;
205
278
  // Previous passphrase
@@ -208,8 +281,8 @@ class CoreApp {
208
281
  // Update
209
282
  const fields = this.initCallUpdateFields();
210
283
  for (const field of fields) {
211
- const currentValue = shared_1.StorageUtils.getLocalData(field, '');
212
- if (currentValue === '')
284
+ const currentValue = shared_1.StorageUtils.getLocalData(field);
285
+ if (currentValue == null || currentValue === '')
213
286
  continue;
214
287
  const enhanced = currentValue.indexOf('!') >= 8;
215
288
  let newValueSource = null;
@@ -325,6 +398,16 @@ class CoreApp {
325
398
  region.name = AddressUtils_1.AddressUtils.getRegionLabel(id, this.labelDelegate);
326
399
  });
327
400
  }
401
+ /**
402
+ * Clear cache data
403
+ */
404
+ clearCacheData() {
405
+ shared_1.StorageUtils.setLocalData(this.serversideDeviceIdField, undefined);
406
+ shared_1.StorageUtils.setLocalData(this.deviceIdField, undefined);
407
+ shared_1.StorageUtils.setLocalData(this.devicePassphraseField, undefined);
408
+ shared_1.StorageUtils.setLocalData(this.deviceIdUpdateTimeField, undefined);
409
+ shared_1.StorageUtils.setLocalData(this.headerTokenField, undefined);
410
+ }
328
411
  /**
329
412
  * Clear cached token
330
413
  */
@@ -578,10 +661,7 @@ class CoreApp {
578
661
  // Temp refresh token
579
662
  if (this.cachedRefreshToken)
580
663
  return this.cachedRefreshToken;
581
- const refreshToken = shared_1.StorageUtils.getLocalData(this.headerTokenField, '');
582
- if (refreshToken === '')
583
- return null;
584
- return refreshToken;
664
+ return shared_1.StorageUtils.getLocalData(this.headerTokenField);
585
665
  }
586
666
  /**
587
667
  * Get all regions
@@ -793,11 +873,13 @@ class CoreApp {
793
873
  */
794
874
  userLogin(user, refreshToken, keep) {
795
875
  this.userData = user;
876
+ // Cache the encrypted serverside device id
877
+ shared_1.StorageUtils.setLocalData(this.serversideDeviceIdField, user.deviceId);
796
878
  if (keep) {
797
879
  this.authorize(user.token, refreshToken);
798
880
  }
799
881
  else {
800
- this.cachedRefreshToken = refreshToken;
882
+ this.cachedRefreshToken = this.encrypt(refreshToken);
801
883
  this.authorize(user.token, undefined);
802
884
  }
803
885
  }
@@ -3,25 +3,25 @@
3
3
  */
4
4
  export interface IExternalSettings {
5
5
  /**
6
- * API endpoint
6
+ * Core system API endpoint
7
7
  */
8
8
  readonly endpoint: string;
9
9
  /**
10
- * App root url
10
+ * Core system app root url
11
11
  */
12
12
  readonly homepage: string;
13
13
  /**
14
- * Cloud web url
14
+ * Core system web url
15
15
  */
16
16
  readonly webUrl: string;
17
17
  /**
18
- * Core system Url
18
+ * Service API endpoint
19
19
  */
20
- readonly coreUrl?: string;
20
+ readonly serviceEndpoint?: string;
21
21
  /**
22
- * Core system API
22
+ * Service web Url
23
23
  */
24
- readonly coreApi?: string;
24
+ readonly serviceUrl?: string;
25
25
  }
26
26
  /**
27
27
  * External settings namespace
@@ -6,6 +6,10 @@ export declare type InitCallDto = {
6
6
  * Device id
7
7
  */
8
8
  deviceId?: string;
9
+ /**
10
+ * Serverside identifier
11
+ */
12
+ identifier?: string;
9
13
  /**
10
14
  * Timestamp
11
15
  */
@@ -3,6 +3,10 @@ import { IState } from './State';
3
3
  * User data interface
4
4
  */
5
5
  export interface IUserData {
6
+ /**
7
+ * Serverside device id encrypted
8
+ */
9
+ readonly deviceId: string;
6
10
  /**
7
11
  * User name
8
12
  */
@@ -119,6 +119,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
119
119
  * @param culture New culture definition
120
120
  */
121
121
  changeCulture(culture: DataTypes.CultureDefinition): void;
122
+ /**
123
+ * Clear cache data
124
+ */
125
+ clearCacheData(): void;
122
126
  /**
123
127
  * Clear cached token
124
128
  */
@@ -222,7 +226,7 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
222
226
  * Get cached token
223
227
  * @returns Cached token
224
228
  */
225
- getCacheToken(): string | null;
229
+ getCacheToken(): string | undefined;
226
230
  /**
227
231
  * Get all regions
228
232
  * @returns Regions
@@ -375,18 +379,26 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
375
379
  * Label delegate
376
380
  */
377
381
  get labelDelegate(): <T = string>(key: string) => T | undefined;
382
+ private _ipData?;
378
383
  /**
379
384
  * IP data
380
385
  */
381
- ipData?: IPData;
386
+ get ipData(): IPData | undefined;
387
+ protected set ipData(value: IPData | undefined);
388
+ private _userData?;
382
389
  /**
383
390
  * User data
384
391
  */
385
- userData?: IUserData;
392
+ get userData(): IUserData | undefined;
393
+ protected set userData(value: IUserData | undefined);
386
394
  /**
387
395
  * Response token header field name
388
396
  */
389
- headerTokenField: string;
397
+ readonly headerTokenField = "SmartERPRefreshToken";
398
+ /**
399
+ * Serverside device id encrypted field name
400
+ */
401
+ protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
390
402
  private ipDetectCallbacks?;
391
403
  /**
392
404
  * Search input element
@@ -410,7 +422,15 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
410
422
  /**
411
423
  * Device id field name
412
424
  */
413
- protected deviceIdField: string;
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;
414
434
  /**
415
435
  * Init call Api URL
416
436
  */
@@ -429,12 +449,22 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
429
449
  */
430
450
  protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, name: string);
431
451
  protected setApi(api: IApi): void;
452
+ /**
453
+ * Setup device
454
+ * @returns Device id
455
+ */
456
+ protected setupDevice(): string;
432
457
  /**
433
458
  * Api init call
434
459
  * @param data Data
435
460
  * @returns Result
436
461
  */
437
462
  protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
463
+ /**
464
+ * Get device last updte miliseconds
465
+ * @returns Miliseconds
466
+ */
467
+ protected getDeviceUpdateTime(): number;
438
468
  /**
439
469
  * Init call
440
470
  * @param callback Callback
@@ -473,6 +503,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
473
503
  * @param culture New culture definition
474
504
  */
475
505
  changeCulture(culture: DataTypes.CultureDefinition): void;
506
+ /**
507
+ * Clear cache data
508
+ */
509
+ clearCacheData(): void;
476
510
  /**
477
511
  * Clear cached token
478
512
  */
@@ -579,7 +613,7 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
579
613
  * Get cached token
580
614
  * @returns Cached token
581
615
  */
582
- getCacheToken(): string | null;
616
+ getCacheToken(): string | undefined;
583
617
  /**
584
618
  * Get all regions
585
619
  * @returns Regions
@@ -17,11 +17,15 @@ export class CoreApp {
17
17
  * @param name Application name
18
18
  */
19
19
  constructor(settings, api, notifier, name) {
20
- this._deviceId = '***';
20
+ this._deviceId = '';
21
21
  /**
22
22
  * Response token header field name
23
23
  */
24
24
  this.headerTokenField = 'SmartERPRefreshToken';
25
+ /**
26
+ * Serverside device id encrypted field name
27
+ */
28
+ this.serversideDeviceIdField = 'SmartERPServersideDeviceId';
25
29
  this._authorized = false;
26
30
  this._isTryingLogin = false;
27
31
  /**
@@ -36,6 +40,14 @@ export class CoreApp {
36
40
  * Device id field name
37
41
  */
38
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';
39
51
  /**
40
52
  * Init call Api URL
41
53
  */
@@ -48,7 +60,7 @@ export class CoreApp {
48
60
  this.api = api;
49
61
  this.notifier = notifier;
50
62
  this.name = name;
51
- this.deviceId = StorageUtils.getLocalData(this.deviceIdField, '');
63
+ this.deviceId = this.setupDevice();
52
64
  this.setApi(api);
53
65
  const { currentCulture, currentRegion } = settings;
54
66
  this.changeCulture(currentCulture);
@@ -89,6 +101,24 @@ export class CoreApp {
89
101
  get labelDelegate() {
90
102
  return this.get.bind(this);
91
103
  }
104
+ /**
105
+ * IP data
106
+ */
107
+ get ipData() {
108
+ return this._ipData;
109
+ }
110
+ set ipData(value) {
111
+ this._ipData = value;
112
+ }
113
+ /**
114
+ * User data
115
+ */
116
+ get userData() {
117
+ return this._userData;
118
+ }
119
+ set userData(value) {
120
+ this._userData = value;
121
+ }
92
122
  /**
93
123
  * Is current authorized
94
124
  */
@@ -128,6 +158,25 @@ export class CoreApp {
128
158
  }
129
159
  };
130
160
  }
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
+ }
131
180
  /**
132
181
  * Api init call
133
182
  * @param data Data
@@ -136,6 +185,13 @@ export class CoreApp {
136
185
  async apiInitCall(data) {
137
186
  return await this.api.put(this.initCallApi, data);
138
187
  }
188
+ /**
189
+ * Get device last updte miliseconds
190
+ * @returns Miliseconds
191
+ */
192
+ getDeviceUpdateTime() {
193
+ return StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
194
+ }
139
195
  /**
140
196
  * Init call
141
197
  * @param callback Callback
@@ -143,9 +199,24 @@ export class CoreApp {
143
199
  */
144
200
  async initCall(callback) {
145
201
  var _a;
202
+ // Device
203
+ let hasDeviceId = this.deviceId != null && this.deviceId !== '';
204
+ const timestamp = new Date().getTime();
205
+ const lastTimestamp = this.getDeviceUpdateTime();
206
+ if (hasDeviceId &&
207
+ lastTimestamp > 0 &&
208
+ timestamp - lastTimestamp <= 1296000000) {
209
+ // When deviceId is there and less than 15 days = 1000 * 60 * 60 * 24 * 15
210
+ if (callback)
211
+ callback(true);
212
+ return;
213
+ }
214
+ // Serverside encrypted device id
215
+ const identifier = StorageUtils.getLocalData(this.serversideDeviceIdField);
146
216
  const data = {
147
- timestamp: new Date().getTime(),
148
- deviceId: this.deviceId === '' ? undefined : this.deviceId
217
+ timestamp,
218
+ identifier,
219
+ deviceId: hasDeviceId ? this.deviceId : undefined
149
220
  };
150
221
  const result = await this.apiInitCall(data);
151
222
  if (result == null) {
@@ -197,6 +268,8 @@ export class CoreApp {
197
268
  // Update device id and cache it
198
269
  this.deviceId = data.deviceId;
199
270
  StorageUtils.setLocalData(this.deviceIdField, this.deviceId);
271
+ StorageUtils.setLocalData(this.devicePassphraseField, data.passphrase);
272
+ StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
200
273
  // Current passphrase
201
274
  this.passphrase = passphrase;
202
275
  // Previous passphrase
@@ -205,8 +278,8 @@ export class CoreApp {
205
278
  // Update
206
279
  const fields = this.initCallUpdateFields();
207
280
  for (const field of fields) {
208
- const currentValue = StorageUtils.getLocalData(field, '');
209
- if (currentValue === '')
281
+ const currentValue = StorageUtils.getLocalData(field);
282
+ if (currentValue == null || currentValue === '')
210
283
  continue;
211
284
  const enhanced = currentValue.indexOf('!') >= 8;
212
285
  let newValueSource = null;
@@ -322,6 +395,16 @@ export class CoreApp {
322
395
  region.name = AddressUtils.getRegionLabel(id, this.labelDelegate);
323
396
  });
324
397
  }
398
+ /**
399
+ * Clear cache data
400
+ */
401
+ clearCacheData() {
402
+ StorageUtils.setLocalData(this.serversideDeviceIdField, undefined);
403
+ StorageUtils.setLocalData(this.deviceIdField, undefined);
404
+ StorageUtils.setLocalData(this.devicePassphraseField, undefined);
405
+ StorageUtils.setLocalData(this.deviceIdUpdateTimeField, undefined);
406
+ StorageUtils.setLocalData(this.headerTokenField, undefined);
407
+ }
325
408
  /**
326
409
  * Clear cached token
327
410
  */
@@ -575,10 +658,7 @@ export class CoreApp {
575
658
  // Temp refresh token
576
659
  if (this.cachedRefreshToken)
577
660
  return this.cachedRefreshToken;
578
- const refreshToken = StorageUtils.getLocalData(this.headerTokenField, '');
579
- if (refreshToken === '')
580
- return null;
581
- return refreshToken;
661
+ return StorageUtils.getLocalData(this.headerTokenField);
582
662
  }
583
663
  /**
584
664
  * Get all regions
@@ -790,11 +870,13 @@ export class CoreApp {
790
870
  */
791
871
  userLogin(user, refreshToken, keep) {
792
872
  this.userData = user;
873
+ // Cache the encrypted serverside device id
874
+ StorageUtils.setLocalData(this.serversideDeviceIdField, user.deviceId);
793
875
  if (keep) {
794
876
  this.authorize(user.token, refreshToken);
795
877
  }
796
878
  else {
797
- this.cachedRefreshToken = refreshToken;
879
+ this.cachedRefreshToken = this.encrypt(refreshToken);
798
880
  this.authorize(user.token, undefined);
799
881
  }
800
882
  }
@@ -3,25 +3,25 @@
3
3
  */
4
4
  export interface IExternalSettings {
5
5
  /**
6
- * API endpoint
6
+ * Core system API endpoint
7
7
  */
8
8
  readonly endpoint: string;
9
9
  /**
10
- * App root url
10
+ * Core system app root url
11
11
  */
12
12
  readonly homepage: string;
13
13
  /**
14
- * Cloud web url
14
+ * Core system web url
15
15
  */
16
16
  readonly webUrl: string;
17
17
  /**
18
- * Core system Url
18
+ * Service API endpoint
19
19
  */
20
- readonly coreUrl?: string;
20
+ readonly serviceEndpoint?: string;
21
21
  /**
22
- * Core system API
22
+ * Service web Url
23
23
  */
24
- readonly coreApi?: string;
24
+ readonly serviceUrl?: string;
25
25
  }
26
26
  /**
27
27
  * External settings namespace
@@ -6,6 +6,10 @@ export declare type InitCallDto = {
6
6
  * Device id
7
7
  */
8
8
  deviceId?: string;
9
+ /**
10
+ * Serverside identifier
11
+ */
12
+ identifier?: string;
9
13
  /**
10
14
  * Timestamp
11
15
  */
@@ -3,6 +3,10 @@ import { IState } from './State';
3
3
  * User data interface
4
4
  */
5
5
  export interface IUserData {
6
+ /**
7
+ * Serverside device id encrypted
8
+ */
9
+ readonly deviceId: string;
6
10
  /**
7
11
  * User name
8
12
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/appscript",
3
- "version": "1.1.84",
3
+ "version": "1.1.88",
4
4
  "description": "Applications shared TypeScript framework",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -52,9 +52,9 @@
52
52
  },
53
53
  "homepage": "https://github.com/ETSOO/AppScript#readme",
54
54
  "dependencies": {
55
- "@etsoo/notificationbase": "^1.0.94",
56
- "@etsoo/restclient": "^1.0.62",
57
- "@etsoo/shared": "^1.0.78",
55
+ "@etsoo/notificationbase": "^1.0.95",
56
+ "@etsoo/restclient": "^1.0.63",
57
+ "@etsoo/shared": "^1.0.82",
58
58
  "@types/crypto-js": "^4.0.2",
59
59
  "crypto-js": "^4.1.1"
60
60
  },
@@ -65,8 +65,8 @@
65
65
  "@babel/preset-env": "^7.16.5",
66
66
  "@babel/runtime-corejs3": "^7.16.5",
67
67
  "@types/jest": "^27.0.3",
68
- "@typescript-eslint/eslint-plugin": "^5.7.0",
69
- "@typescript-eslint/parser": "^5.7.0",
68
+ "@typescript-eslint/eslint-plugin": "^5.8.0",
69
+ "@typescript-eslint/parser": "^5.8.0",
70
70
  "eslint": "^8.5.0",
71
71
  "eslint-config-airbnb-base": "^15.0.0",
72
72
  "eslint-plugin-import": "^2.25.3",
@@ -178,6 +178,11 @@ export interface ICoreApp<
178
178
  */
179
179
  changeCulture(culture: DataTypes.CultureDefinition): void;
180
180
 
181
+ /**
182
+ * Clear cache data
183
+ */
184
+ clearCacheData(): void;
185
+
181
186
  /**
182
187
  * Clear cached token
183
188
  */
@@ -313,7 +318,7 @@ export interface ICoreApp<
313
318
  * Get cached token
314
319
  * @returns Cached token
315
320
  */
316
- getCacheToken(): string | null;
321
+ getCacheToken(): string | undefined;
317
322
 
318
323
  /**
319
324
  * Get all regions
@@ -499,7 +504,7 @@ export abstract class CoreApp<
499
504
  return this._region;
500
505
  }
501
506
 
502
- private _deviceId: string = '***';
507
+ private _deviceId: string = '';
503
508
  /**
504
509
  * Country or region, like CN
505
510
  */
@@ -517,20 +522,37 @@ export abstract class CoreApp<
517
522
  return this.get.bind(this);
518
523
  }
519
524
 
525
+ private _ipData?: IPData;
520
526
  /**
521
527
  * IP data
522
528
  */
523
- ipData?: IPData;
529
+ get ipData() {
530
+ return this._ipData;
531
+ }
532
+ protected set ipData(value: IPData | undefined) {
533
+ this._ipData = value;
534
+ }
524
535
 
536
+ private _userData?: IUserData;
525
537
  /**
526
538
  * User data
527
539
  */
528
- userData?: IUserData;
540
+ get userData() {
541
+ return this._userData;
542
+ }
543
+ protected set userData(value: IUserData | undefined) {
544
+ this._userData = value;
545
+ }
529
546
 
530
547
  /**
531
548
  * Response token header field name
532
549
  */
533
- headerTokenField = 'SmartERPRefreshToken';
550
+ readonly headerTokenField = 'SmartERPRefreshToken';
551
+
552
+ /**
553
+ * Serverside device id encrypted field name
554
+ */
555
+ protected readonly serversideDeviceIdField = 'SmartERPServersideDeviceId';
534
556
 
535
557
  // IP detect ready callbacks
536
558
  private ipDetectCallbacks?: IDetectIPCallback[];
@@ -567,7 +589,18 @@ export abstract class CoreApp<
567
589
  /**
568
590
  * Device id field name
569
591
  */
570
- protected deviceIdField: string = 'SmartERPDeviceId';
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';
571
604
 
572
605
  /**
573
606
  * Init call Api URL
@@ -599,10 +632,7 @@ export abstract class CoreApp<
599
632
  this.notifier = notifier;
600
633
  this.name = name;
601
634
 
602
- this.deviceId = StorageUtils.getLocalData<string>(
603
- this.deviceIdField,
604
- ''
605
- );
635
+ this.deviceId = this.setupDevice();
606
636
 
607
637
  this.setApi(api);
608
638
 
@@ -648,6 +678,33 @@ export abstract class CoreApp<
648
678
  };
649
679
  }
650
680
 
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
+
651
708
  /**
652
709
  * Api init call
653
710
  * @param data Data
@@ -657,15 +714,43 @@ export abstract class CoreApp<
657
714
  return await this.api.put<InitCallResult>(this.initCallApi, data);
658
715
  }
659
716
 
717
+ /**
718
+ * Get device last updte miliseconds
719
+ * @returns Miliseconds
720
+ */
721
+ protected getDeviceUpdateTime() {
722
+ return StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
723
+ }
724
+
660
725
  /**
661
726
  * Init call
662
727
  * @param callback Callback
663
728
  * @returns Result
664
729
  */
665
730
  async initCall(callback?: (result: boolean) => void) {
731
+ // Device
732
+ let hasDeviceId = this.deviceId != null && this.deviceId !== '';
733
+ const timestamp = new Date().getTime();
734
+ const lastTimestamp = this.getDeviceUpdateTime();
735
+ if (
736
+ hasDeviceId &&
737
+ lastTimestamp > 0 &&
738
+ timestamp - lastTimestamp <= 1296000000
739
+ ) {
740
+ // When deviceId is there and less than 15 days = 1000 * 60 * 60 * 24 * 15
741
+ if (callback) callback(true);
742
+ return;
743
+ }
744
+
745
+ // Serverside encrypted device id
746
+ const identifier = StorageUtils.getLocalData<string>(
747
+ this.serversideDeviceIdField
748
+ );
749
+
666
750
  const data: InitCallDto = {
667
- timestamp: new Date().getTime(),
668
- deviceId: this.deviceId === '' ? undefined : this.deviceId
751
+ timestamp,
752
+ identifier,
753
+ deviceId: hasDeviceId ? this.deviceId : undefined
669
754
  };
670
755
  const result = await this.apiInitCall(data);
671
756
  if (result == null) {
@@ -725,6 +810,8 @@ export abstract class CoreApp<
725
810
  // Update device id and cache it
726
811
  this.deviceId = data.deviceId;
727
812
  StorageUtils.setLocalData(this.deviceIdField, this.deviceId);
813
+ StorageUtils.setLocalData(this.devicePassphraseField, data.passphrase);
814
+ StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
728
815
 
729
816
  // Current passphrase
730
817
  this.passphrase = passphrase;
@@ -739,11 +826,8 @@ export abstract class CoreApp<
739
826
  // Update
740
827
  const fields = this.initCallUpdateFields();
741
828
  for (const field of fields) {
742
- const currentValue = StorageUtils.getLocalData<string>(
743
- field,
744
- ''
745
- );
746
- if (currentValue === '') continue;
829
+ const currentValue = StorageUtils.getLocalData<string>(field);
830
+ if (currentValue == null || currentValue === '') continue;
747
831
 
748
832
  const enhanced = currentValue.indexOf('!') >= 8;
749
833
  let newValueSource = null;
@@ -884,6 +968,19 @@ export abstract class CoreApp<
884
968
  });
885
969
  }
886
970
 
971
+ /**
972
+ * Clear cache data
973
+ */
974
+ clearCacheData() {
975
+ StorageUtils.setLocalData(this.serversideDeviceIdField, undefined);
976
+
977
+ StorageUtils.setLocalData(this.deviceIdField, undefined);
978
+ StorageUtils.setLocalData(this.devicePassphraseField, undefined);
979
+ StorageUtils.setLocalData(this.deviceIdUpdateTimeField, undefined);
980
+
981
+ StorageUtils.setLocalData(this.headerTokenField, undefined);
982
+ }
983
+
887
984
  /**
888
985
  * Clear cached token
889
986
  */
@@ -1192,18 +1289,10 @@ export abstract class CoreApp<
1192
1289
  * Get cached token
1193
1290
  * @returns Cached token
1194
1291
  */
1195
- getCacheToken(): string | null {
1292
+ getCacheToken(): string | undefined {
1196
1293
  // Temp refresh token
1197
1294
  if (this.cachedRefreshToken) return this.cachedRefreshToken;
1198
-
1199
- const refreshToken = StorageUtils.getLocalData<string>(
1200
- this.headerTokenField,
1201
- ''
1202
- );
1203
-
1204
- if (refreshToken === '') return null;
1205
-
1206
- return refreshToken;
1295
+ return StorageUtils.getLocalData<string>(this.headerTokenField);
1207
1296
  }
1208
1297
 
1209
1298
  /**
@@ -1442,10 +1531,13 @@ export abstract class CoreApp<
1442
1531
  userLogin(user: IUserData, refreshToken: string, keep?: boolean) {
1443
1532
  this.userData = user;
1444
1533
 
1534
+ // Cache the encrypted serverside device id
1535
+ StorageUtils.setLocalData(this.serversideDeviceIdField, user.deviceId);
1536
+
1445
1537
  if (keep) {
1446
1538
  this.authorize(user.token, refreshToken);
1447
1539
  } else {
1448
- this.cachedRefreshToken = refreshToken;
1540
+ this.cachedRefreshToken = this.encrypt(refreshToken);
1449
1541
  this.authorize(user.token, undefined);
1450
1542
  }
1451
1543
  }
@@ -3,29 +3,29 @@
3
3
  */
4
4
  export interface IExternalSettings {
5
5
  /**
6
- * API endpoint
6
+ * Core system API endpoint
7
7
  */
8
8
  readonly endpoint: string;
9
9
 
10
10
  /**
11
- * App root url
11
+ * Core system app root url
12
12
  */
13
13
  readonly homepage: string;
14
14
 
15
15
  /**
16
- * Cloud web url
16
+ * Core system web url
17
17
  */
18
18
  readonly webUrl: string;
19
19
 
20
20
  /**
21
- * Core system Url
21
+ * Service API endpoint
22
22
  */
23
- readonly coreUrl?: string;
23
+ readonly serviceEndpoint?: string;
24
24
 
25
25
  /**
26
- * Core system API
26
+ * Service web Url
27
27
  */
28
- readonly coreApi?: string;
28
+ readonly serviceUrl?: string;
29
29
  }
30
30
 
31
31
  /**
@@ -7,6 +7,11 @@ export type InitCallDto = {
7
7
  */
8
8
  deviceId?: string;
9
9
 
10
+ /**
11
+ * Serverside identifier
12
+ */
13
+ identifier?: string;
14
+
10
15
  /**
11
16
  * Timestamp
12
17
  */
package/src/state/User.ts CHANGED
@@ -4,6 +4,11 @@ import { IState } from './State';
4
4
  * User data interface
5
5
  */
6
6
  export interface IUserData {
7
+ /**
8
+ * Serverside device id encrypted
9
+ */
10
+ readonly deviceId: string;
11
+
7
12
  /**
8
13
  * User name
9
14
  */