@etsoo/appscript 1.1.85 → 1.1.89

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
@@ -276,9 +280,8 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
276
280
  refreshToken<D extends {} = {}>(props?: RefreshTokenProps<D>): Promise<boolean>;
277
281
  /**
278
282
  * Signout
279
- * @param apiUrl Signout API URL
280
283
  */
281
- signout(apiUrl?: string): Promise<void>;
284
+ signout(): Promise<void>;
282
285
  /**
283
286
  * Get organization list
284
287
  * @param items Max items
@@ -375,18 +378,26 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
375
378
  * Label delegate
376
379
  */
377
380
  get labelDelegate(): <T = string>(key: string) => T | undefined;
381
+ private _ipData?;
378
382
  /**
379
383
  * IP data
380
384
  */
381
- ipData?: IPData;
385
+ get ipData(): IPData | undefined;
386
+ protected set ipData(value: IPData | undefined);
387
+ private _userData?;
382
388
  /**
383
389
  * User data
384
390
  */
385
- userData?: IUserData;
391
+ get userData(): IUserData | undefined;
392
+ protected set userData(value: IUserData | undefined);
386
393
  /**
387
394
  * Response token header field name
388
395
  */
389
- headerTokenField: string;
396
+ readonly headerTokenField = "SmartERPRefreshToken";
397
+ /**
398
+ * Serverside device id encrypted field name
399
+ */
400
+ protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
390
401
  private ipDetectCallbacks?;
391
402
  /**
392
403
  * Search input element
@@ -410,7 +421,15 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
410
421
  /**
411
422
  * Device id field name
412
423
  */
413
- protected deviceIdField: string;
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;
414
433
  /**
415
434
  * Init call Api URL
416
435
  */
@@ -429,12 +448,22 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
429
448
  */
430
449
  protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, name: string);
431
450
  protected setApi(api: IApi): void;
451
+ /**
452
+ * Setup device
453
+ * @returns Device id
454
+ */
455
+ protected setupDevice(): string;
432
456
  /**
433
457
  * Api init call
434
458
  * @param data Data
435
459
  * @returns Result
436
460
  */
437
461
  protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
462
+ /**
463
+ * Get device last updte miliseconds
464
+ * @returns Miliseconds
465
+ */
466
+ protected getDeviceUpdateTime(): number;
438
467
  /**
439
468
  * Init call
440
469
  * @param callback Callback
@@ -473,6 +502,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
473
502
  * @param culture New culture definition
474
503
  */
475
504
  changeCulture(culture: DataTypes.CultureDefinition): void;
505
+ /**
506
+ * Clear cache data
507
+ */
508
+ clearCacheData(): void;
476
509
  /**
477
510
  * Clear cached token
478
511
  */
@@ -579,7 +612,7 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
579
612
  * Get cached token
580
613
  * @returns Cached token
581
614
  */
582
- getCacheToken(): string | null;
615
+ getCacheToken(): string | undefined;
583
616
  /**
584
617
  * Get all regions
585
618
  * @returns Regions
@@ -644,7 +677,7 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
644
677
  * Signout
645
678
  * @param apiUrl Signout API URL
646
679
  */
647
- signout(apiUrl?: string): Promise<void>;
680
+ signout(): Promise<void>;
648
681
  /**
649
682
  * Get organization list
650
683
  * @param items Max items
@@ -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
@@ -710,8 +790,8 @@ class CoreApp {
710
790
  * Signout
711
791
  * @param apiUrl Signout API URL
712
792
  */
713
- async signout(apiUrl) {
714
- await this.api.put(apiUrl !== null && apiUrl !== void 0 ? apiUrl : 'User/Signout', undefined, {
793
+ async signout() {
794
+ await this.api.put('User/Signout', { deviceId: this.deviceId }, {
715
795
  onError: (error) => {
716
796
  console.log(error);
717
797
  // Prevent further processing
@@ -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
  }
@@ -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
@@ -276,9 +280,8 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
276
280
  refreshToken<D extends {} = {}>(props?: RefreshTokenProps<D>): Promise<boolean>;
277
281
  /**
278
282
  * Signout
279
- * @param apiUrl Signout API URL
280
283
  */
281
- signout(apiUrl?: string): Promise<void>;
284
+ signout(): Promise<void>;
282
285
  /**
283
286
  * Get organization list
284
287
  * @param items Max items
@@ -375,18 +378,26 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
375
378
  * Label delegate
376
379
  */
377
380
  get labelDelegate(): <T = string>(key: string) => T | undefined;
381
+ private _ipData?;
378
382
  /**
379
383
  * IP data
380
384
  */
381
- ipData?: IPData;
385
+ get ipData(): IPData | undefined;
386
+ protected set ipData(value: IPData | undefined);
387
+ private _userData?;
382
388
  /**
383
389
  * User data
384
390
  */
385
- userData?: IUserData;
391
+ get userData(): IUserData | undefined;
392
+ protected set userData(value: IUserData | undefined);
386
393
  /**
387
394
  * Response token header field name
388
395
  */
389
- headerTokenField: string;
396
+ readonly headerTokenField = "SmartERPRefreshToken";
397
+ /**
398
+ * Serverside device id encrypted field name
399
+ */
400
+ protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
390
401
  private ipDetectCallbacks?;
391
402
  /**
392
403
  * Search input element
@@ -410,7 +421,15 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
410
421
  /**
411
422
  * Device id field name
412
423
  */
413
- protected deviceIdField: string;
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;
414
433
  /**
415
434
  * Init call Api URL
416
435
  */
@@ -429,12 +448,22 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
429
448
  */
430
449
  protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, name: string);
431
450
  protected setApi(api: IApi): void;
451
+ /**
452
+ * Setup device
453
+ * @returns Device id
454
+ */
455
+ protected setupDevice(): string;
432
456
  /**
433
457
  * Api init call
434
458
  * @param data Data
435
459
  * @returns Result
436
460
  */
437
461
  protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
462
+ /**
463
+ * Get device last updte miliseconds
464
+ * @returns Miliseconds
465
+ */
466
+ protected getDeviceUpdateTime(): number;
438
467
  /**
439
468
  * Init call
440
469
  * @param callback Callback
@@ -473,6 +502,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
473
502
  * @param culture New culture definition
474
503
  */
475
504
  changeCulture(culture: DataTypes.CultureDefinition): void;
505
+ /**
506
+ * Clear cache data
507
+ */
508
+ clearCacheData(): void;
476
509
  /**
477
510
  * Clear cached token
478
511
  */
@@ -579,7 +612,7 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
579
612
  * Get cached token
580
613
  * @returns Cached token
581
614
  */
582
- getCacheToken(): string | null;
615
+ getCacheToken(): string | undefined;
583
616
  /**
584
617
  * Get all regions
585
618
  * @returns Regions
@@ -644,7 +677,7 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
644
677
  * Signout
645
678
  * @param apiUrl Signout API URL
646
679
  */
647
- signout(apiUrl?: string): Promise<void>;
680
+ signout(): Promise<void>;
648
681
  /**
649
682
  * Get organization list
650
683
  * @param items Max items
@@ -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
@@ -707,8 +787,8 @@ export class CoreApp {
707
787
  * Signout
708
788
  * @param apiUrl Signout API URL
709
789
  */
710
- async signout(apiUrl) {
711
- await this.api.put(apiUrl !== null && apiUrl !== void 0 ? apiUrl : 'User/Signout', undefined, {
790
+ async signout() {
791
+ await this.api.put('User/Signout', { deviceId: this.deviceId }, {
712
792
  onError: (error) => {
713
793
  console.log(error);
714
794
  // Prevent further processing
@@ -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
  }
@@ -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.85",
3
+ "version": "1.1.89",
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
@@ -379,9 +384,8 @@ export interface ICoreApp<
379
384
 
380
385
  /**
381
386
  * Signout
382
- * @param apiUrl Signout API URL
383
387
  */
384
- signout(apiUrl?: string): Promise<void>;
388
+ signout(): Promise<void>;
385
389
 
386
390
  /**
387
391
  * Get organization list
@@ -499,7 +503,7 @@ export abstract class CoreApp<
499
503
  return this._region;
500
504
  }
501
505
 
502
- private _deviceId: string = '***';
506
+ private _deviceId: string = '';
503
507
  /**
504
508
  * Country or region, like CN
505
509
  */
@@ -517,20 +521,37 @@ export abstract class CoreApp<
517
521
  return this.get.bind(this);
518
522
  }
519
523
 
524
+ private _ipData?: IPData;
520
525
  /**
521
526
  * IP data
522
527
  */
523
- ipData?: IPData;
528
+ get ipData() {
529
+ return this._ipData;
530
+ }
531
+ protected set ipData(value: IPData | undefined) {
532
+ this._ipData = value;
533
+ }
524
534
 
535
+ private _userData?: IUserData;
525
536
  /**
526
537
  * User data
527
538
  */
528
- userData?: IUserData;
539
+ get userData() {
540
+ return this._userData;
541
+ }
542
+ protected set userData(value: IUserData | undefined) {
543
+ this._userData = value;
544
+ }
529
545
 
530
546
  /**
531
547
  * Response token header field name
532
548
  */
533
- headerTokenField = 'SmartERPRefreshToken';
549
+ readonly headerTokenField = 'SmartERPRefreshToken';
550
+
551
+ /**
552
+ * Serverside device id encrypted field name
553
+ */
554
+ protected readonly serversideDeviceIdField = 'SmartERPServersideDeviceId';
534
555
 
535
556
  // IP detect ready callbacks
536
557
  private ipDetectCallbacks?: IDetectIPCallback[];
@@ -567,7 +588,18 @@ export abstract class CoreApp<
567
588
  /**
568
589
  * Device id field name
569
590
  */
570
- protected deviceIdField: string = 'SmartERPDeviceId';
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';
571
603
 
572
604
  /**
573
605
  * Init call Api URL
@@ -599,10 +631,7 @@ export abstract class CoreApp<
599
631
  this.notifier = notifier;
600
632
  this.name = name;
601
633
 
602
- this.deviceId = StorageUtils.getLocalData<string>(
603
- this.deviceIdField,
604
- ''
605
- );
634
+ this.deviceId = this.setupDevice();
606
635
 
607
636
  this.setApi(api);
608
637
 
@@ -648,6 +677,33 @@ export abstract class CoreApp<
648
677
  };
649
678
  }
650
679
 
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
+
651
707
  /**
652
708
  * Api init call
653
709
  * @param data Data
@@ -657,15 +713,43 @@ export abstract class CoreApp<
657
713
  return await this.api.put<InitCallResult>(this.initCallApi, data);
658
714
  }
659
715
 
716
+ /**
717
+ * Get device last updte miliseconds
718
+ * @returns Miliseconds
719
+ */
720
+ protected getDeviceUpdateTime() {
721
+ return StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
722
+ }
723
+
660
724
  /**
661
725
  * Init call
662
726
  * @param callback Callback
663
727
  * @returns Result
664
728
  */
665
729
  async initCall(callback?: (result: boolean) => void) {
730
+ // Device
731
+ let hasDeviceId = this.deviceId != null && this.deviceId !== '';
732
+ const timestamp = new Date().getTime();
733
+ const lastTimestamp = this.getDeviceUpdateTime();
734
+ if (
735
+ hasDeviceId &&
736
+ lastTimestamp > 0 &&
737
+ timestamp - lastTimestamp <= 1296000000
738
+ ) {
739
+ // When deviceId is there and less than 15 days = 1000 * 60 * 60 * 24 * 15
740
+ if (callback) callback(true);
741
+ return;
742
+ }
743
+
744
+ // Serverside encrypted device id
745
+ const identifier = StorageUtils.getLocalData<string>(
746
+ this.serversideDeviceIdField
747
+ );
748
+
666
749
  const data: InitCallDto = {
667
- timestamp: new Date().getTime(),
668
- deviceId: this.deviceId === '' ? undefined : this.deviceId
750
+ timestamp,
751
+ identifier,
752
+ deviceId: hasDeviceId ? this.deviceId : undefined
669
753
  };
670
754
  const result = await this.apiInitCall(data);
671
755
  if (result == null) {
@@ -725,6 +809,8 @@ export abstract class CoreApp<
725
809
  // Update device id and cache it
726
810
  this.deviceId = data.deviceId;
727
811
  StorageUtils.setLocalData(this.deviceIdField, this.deviceId);
812
+ StorageUtils.setLocalData(this.devicePassphraseField, data.passphrase);
813
+ StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
728
814
 
729
815
  // Current passphrase
730
816
  this.passphrase = passphrase;
@@ -739,11 +825,8 @@ export abstract class CoreApp<
739
825
  // Update
740
826
  const fields = this.initCallUpdateFields();
741
827
  for (const field of fields) {
742
- const currentValue = StorageUtils.getLocalData<string>(
743
- field,
744
- ''
745
- );
746
- if (currentValue === '') continue;
828
+ const currentValue = StorageUtils.getLocalData<string>(field);
829
+ if (currentValue == null || currentValue === '') continue;
747
830
 
748
831
  const enhanced = currentValue.indexOf('!') >= 8;
749
832
  let newValueSource = null;
@@ -884,6 +967,19 @@ export abstract class CoreApp<
884
967
  });
885
968
  }
886
969
 
970
+ /**
971
+ * Clear cache data
972
+ */
973
+ clearCacheData() {
974
+ StorageUtils.setLocalData(this.serversideDeviceIdField, undefined);
975
+
976
+ StorageUtils.setLocalData(this.deviceIdField, undefined);
977
+ StorageUtils.setLocalData(this.devicePassphraseField, undefined);
978
+ StorageUtils.setLocalData(this.deviceIdUpdateTimeField, undefined);
979
+
980
+ StorageUtils.setLocalData(this.headerTokenField, undefined);
981
+ }
982
+
887
983
  /**
888
984
  * Clear cached token
889
985
  */
@@ -1192,18 +1288,10 @@ export abstract class CoreApp<
1192
1288
  * Get cached token
1193
1289
  * @returns Cached token
1194
1290
  */
1195
- getCacheToken(): string | null {
1291
+ getCacheToken(): string | undefined {
1196
1292
  // Temp refresh token
1197
1293
  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;
1294
+ return StorageUtils.getLocalData<string>(this.headerTokenField);
1207
1295
  }
1208
1296
 
1209
1297
  /**
@@ -1346,14 +1434,18 @@ export abstract class CoreApp<
1346
1434
  * Signout
1347
1435
  * @param apiUrl Signout API URL
1348
1436
  */
1349
- async signout(apiUrl?: string) {
1350
- await this.api.put<boolean>(apiUrl ?? 'User/Signout', undefined, {
1351
- onError: (error) => {
1352
- console.log(error);
1353
- // Prevent further processing
1354
- return false;
1437
+ async signout() {
1438
+ await this.api.put<boolean>(
1439
+ 'User/Signout',
1440
+ { deviceId: this.deviceId },
1441
+ {
1442
+ onError: (error) => {
1443
+ console.log(error);
1444
+ // Prevent further processing
1445
+ return false;
1446
+ }
1355
1447
  }
1356
- });
1448
+ );
1357
1449
 
1358
1450
  // Clear
1359
1451
  this.userLogout();
@@ -1442,10 +1534,13 @@ export abstract class CoreApp<
1442
1534
  userLogin(user: IUserData, refreshToken: string, keep?: boolean) {
1443
1535
  this.userData = user;
1444
1536
 
1537
+ // Cache the encrypted serverside device id
1538
+ StorageUtils.setLocalData(this.serversideDeviceIdField, user.deviceId);
1539
+
1445
1540
  if (keep) {
1446
1541
  this.authorize(user.token, refreshToken);
1447
1542
  } else {
1448
- this.cachedRefreshToken = refreshToken;
1543
+ this.cachedRefreshToken = this.encrypt(refreshToken);
1449
1544
  this.authorize(user.token, undefined);
1450
1545
  }
1451
1546
  }
@@ -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
  */