@etsoo/appscript 1.1.89 → 1.1.93

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
  }
@@ -1,6 +1,6 @@
1
1
  import { INotifier, NotificationAlign, NotificationCallProps, NotificationContent } from '@etsoo/notificationbase';
2
2
  import { ApiDataError, IApi, IPData } from '@etsoo/restclient';
3
- import { DataTypes, DateUtils } from '@etsoo/shared';
3
+ import { DataTypes, DateUtils, IStorage } from '@etsoo/shared';
4
4
  import { AddressRegion } from '../address/AddressRegion';
5
5
  import { IdLabelDto } from '../dto/IdLabelDto';
6
6
  import { InitCallDto } from '../dto/InitCallDto';
@@ -78,6 +78,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
78
78
  * Country or region, like CN
79
79
  */
80
80
  readonly region: string;
81
+ /**
82
+ * Storage
83
+ */
84
+ readonly storage: IStorage;
81
85
  /**
82
86
  * Is current authorized
83
87
  */
@@ -291,9 +295,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
291
295
  orgList(items?: number, serviceId?: number): Promise<IdLabelDto[] | undefined>;
292
296
  /**
293
297
  * Switch organization
294
- * @param apiOrOrg API URL or organization id
298
+ * @param id Organization id
299
+ * @param serviceId Service id
295
300
  */
296
- switchOrg(apiOrOrg: string | number): Promise<boolean | undefined>;
301
+ switchOrg(id: number, serviceId?: number): Promise<boolean | undefined>;
297
302
  /**
298
303
  * Go to the login page
299
304
  */
@@ -353,6 +358,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
353
358
  * Notifier
354
359
  */
355
360
  readonly notifier: INotifier<N, C>;
361
+ /**
362
+ * Storage
363
+ */
364
+ readonly storage: IStorage;
356
365
  private _culture;
357
366
  /**
358
367
  * Culture, like zh-CN
@@ -373,7 +382,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
373
382
  * Country or region, like CN
374
383
  */
375
384
  get deviceId(): string;
376
- protected set deviceId(value: string);
377
385
  /**
378
386
  * Label delegate
379
387
  */
@@ -390,14 +398,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
390
398
  */
391
399
  get userData(): IUserData | undefined;
392
400
  protected set userData(value: IUserData | undefined);
393
- /**
394
- * Response token header field name
395
- */
396
- readonly headerTokenField = "SmartERPRefreshToken";
397
- /**
398
- * Serverside device id encrypted field name
399
- */
400
- protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
401
401
  private ipDetectCallbacks?;
402
402
  /**
403
403
  * Search input element
@@ -418,18 +418,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
418
418
  * Token refresh count down seed
419
419
  */
420
420
  protected refreshCountdownSeed: number;
421
- /**
422
- * Device id field name
423
- */
424
- private readonly deviceIdField;
425
- /**
426
- * Device passphrase field name
427
- */
428
- private readonly devicePassphraseField;
429
- /**
430
- * Device id update time field name
431
- */
432
- private readonly deviceIdUpdateTimeField;
433
421
  /**
434
422
  * Init call Api URL
435
423
  */
@@ -444,26 +432,17 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
444
432
  * @param settings Settings
445
433
  * @param api API
446
434
  * @param notifier Notifier
435
+ * @param storage Storage
447
436
  * @param name Application name
448
437
  */
449
- protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, name: string);
438
+ protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, storage: IStorage, name: string);
450
439
  protected setApi(api: IApi): void;
451
- /**
452
- * Setup device
453
- * @returns Device id
454
- */
455
- protected setupDevice(): string;
456
440
  /**
457
441
  * Api init call
458
442
  * @param data Data
459
443
  * @returns Result
460
444
  */
461
445
  protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
462
- /**
463
- * Get device last updte miliseconds
464
- * @returns Miliseconds
465
- */
466
- protected getDeviceUpdateTime(): number;
467
446
  /**
468
447
  * Init call
469
448
  * @param callback Callback
@@ -477,10 +456,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
477
456
  */
478
457
  protected initCallUpdate(data: InitCallResultData, timestamp: number): void;
479
458
  /**
480
- * Init call update fields in local storage
459
+ * Init call encrypted fields update
481
460
  * @returns Fields
482
461
  */
483
- protected initCallUpdateFields(): string[];
462
+ protected initCallEncryptedUpdateFields(): string[];
484
463
  /**
485
464
  * Alert action result
486
465
  * @param result Action result
@@ -688,8 +667,9 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
688
667
  /**
689
668
  * Switch organization
690
669
  * @param id Organization id
670
+ * @param serviceId Service id
691
671
  */
692
- switchOrg(id: number): Promise<boolean | undefined>;
672
+ switchOrg(id: number, serviceId?: number): Promise<boolean | undefined>;
693
673
  /**
694
674
  * Go to the login page
695
675
  */
@@ -730,3 +710,21 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
730
710
  */
731
711
  warning(message: NotificationContent<N>, align?: NotificationAlign): void;
732
712
  }
713
+ export declare namespace CoreApp {
714
+ /**
715
+ * Response token header field name
716
+ */
717
+ const headerTokenField = "SmartERPRefreshToken";
718
+ /**
719
+ * Serverside device id encrypted field name
720
+ */
721
+ const serversideDeviceIdField = "SmartERPServersideDeviceId";
722
+ /**
723
+ * Device id field name
724
+ */
725
+ const deviceIdField = "SmartERPDeviceId";
726
+ /**
727
+ * Device passphrase field name
728
+ */
729
+ const devicePassphraseField = "SmartERPDevicePassphrase";
730
+ }
@@ -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
- this._deviceId = '';
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
- this.deviceId = this.setupDevice();
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
- // 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;
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 = shared_1.StorageUtils.getLocalData(this.serversideDeviceIdField);
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: hasDeviceId ? this.deviceId : undefined
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
- shared_1.StorageUtils.setLocalData(this.deviceIdField, null);
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.deviceId = data.deviceId;
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);
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.initCallUpdateFields();
239
+ const fields = this.initCallEncryptedUpdateFields();
283
240
  for (const field of fields) {
284
- const currentValue = shared_1.StorageUtils.getLocalData(field);
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
- shared_1.StorageUtils.setLocalData(field, newValue);
257
+ this.storage.setData(field, newValue);
301
258
  }
302
259
  }
303
260
  }
304
261
  /**
305
- * Init call update fields in local storage
262
+ * Init call encrypted fields update
306
263
  * @returns Fields
307
264
  */
308
- initCallUpdateFields() {
309
- return [this.headerTokenField];
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
- shared_1.StorageUtils.setLocalData(this.headerTokenField, refreshToken);
290
+ this.storage.setData(CoreApp.headerTokenField, refreshToken);
334
291
  }
335
292
  // Reset tryLogin state
336
293
  this._isTryingLogin = false;
@@ -402,18 +359,17 @@ class CoreApp {
402
359
  * Clear cache data
403
360
  */
404
361
  clearCacheData() {
405
- 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);
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
- shared_1.StorageUtils.setLocalData(this.headerTokenField, undefined);
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 shared_1.StorageUtils.getLocalData(this.headerTokenField);
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, this.headerTokenField);
638
+ return this.api.getHeaderValue(response.headers, CoreApp.headerTokenField);
683
639
  }
684
640
  /**
685
641
  * Get time zone
@@ -818,10 +774,15 @@ class CoreApp {
818
774
  /**
819
775
  * Switch organization
820
776
  * @param id Organization id
777
+ * @param serviceId Service id
821
778
  */
822
- async switchOrg(id) {
823
- const api = `Organization/Switch/${id}`;
824
- const result = await this.api.put(api);
779
+ async switchOrg(id, serviceId) {
780
+ const api = `Organization/Switch`;
781
+ const result = await this.api.put(api, {
782
+ id,
783
+ serviceId,
784
+ deviceId: this.deviceId
785
+ });
825
786
  if (result)
826
787
  return await this.refreshToken();
827
788
  return result;
@@ -874,7 +835,7 @@ class CoreApp {
874
835
  userLogin(user, refreshToken, keep) {
875
836
  this.userData = user;
876
837
  // Cache the encrypted serverside device id
877
- shared_1.StorageUtils.setLocalData(this.serversideDeviceIdField, user.deviceId);
838
+ this.storage.setData(CoreApp.serversideDeviceIdField, user.deviceId);
878
839
  if (keep) {
879
840
  this.authorize(user.token, refreshToken);
880
841
  }
@@ -912,3 +873,21 @@ class CoreApp {
912
873
  }
913
874
  }
914
875
  exports.CoreApp = CoreApp;
876
+ (function (CoreApp) {
877
+ /**
878
+ * Response token header field name
879
+ */
880
+ CoreApp.headerTokenField = 'SmartERPRefreshToken';
881
+ /**
882
+ * Serverside device id encrypted field name
883
+ */
884
+ CoreApp.serversideDeviceIdField = 'SmartERPServersideDeviceId';
885
+ /**
886
+ * Device id field name
887
+ */
888
+ CoreApp.deviceIdField = 'SmartERPDeviceId';
889
+ /**
890
+ * Device passphrase field name
891
+ */
892
+ CoreApp.devicePassphraseField = 'SmartERPDevicePassphrase';
893
+ })(CoreApp = exports.CoreApp || (exports.CoreApp = {}));
@@ -1,6 +1,6 @@
1
1
  import { INotifier, NotificationAlign, NotificationCallProps, NotificationContent } from '@etsoo/notificationbase';
2
2
  import { ApiDataError, IApi, IPData } from '@etsoo/restclient';
3
- import { DataTypes, DateUtils } from '@etsoo/shared';
3
+ import { DataTypes, DateUtils, IStorage } from '@etsoo/shared';
4
4
  import { AddressRegion } from '../address/AddressRegion';
5
5
  import { IdLabelDto } from '../dto/IdLabelDto';
6
6
  import { InitCallDto } from '../dto/InitCallDto';
@@ -78,6 +78,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
78
78
  * Country or region, like CN
79
79
  */
80
80
  readonly region: string;
81
+ /**
82
+ * Storage
83
+ */
84
+ readonly storage: IStorage;
81
85
  /**
82
86
  * Is current authorized
83
87
  */
@@ -291,9 +295,10 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
291
295
  orgList(items?: number, serviceId?: number): Promise<IdLabelDto[] | undefined>;
292
296
  /**
293
297
  * Switch organization
294
- * @param apiOrOrg API URL or organization id
298
+ * @param id Organization id
299
+ * @param serviceId Service id
295
300
  */
296
- switchOrg(apiOrOrg: string | number): Promise<boolean | undefined>;
301
+ switchOrg(id: number, serviceId?: number): Promise<boolean | undefined>;
297
302
  /**
298
303
  * Go to the login page
299
304
  */
@@ -353,6 +358,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
353
358
  * Notifier
354
359
  */
355
360
  readonly notifier: INotifier<N, C>;
361
+ /**
362
+ * Storage
363
+ */
364
+ readonly storage: IStorage;
356
365
  private _culture;
357
366
  /**
358
367
  * Culture, like zh-CN
@@ -373,7 +382,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
373
382
  * Country or region, like CN
374
383
  */
375
384
  get deviceId(): string;
376
- protected set deviceId(value: string);
377
385
  /**
378
386
  * Label delegate
379
387
  */
@@ -390,14 +398,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
390
398
  */
391
399
  get userData(): IUserData | undefined;
392
400
  protected set userData(value: IUserData | undefined);
393
- /**
394
- * Response token header field name
395
- */
396
- readonly headerTokenField = "SmartERPRefreshToken";
397
- /**
398
- * Serverside device id encrypted field name
399
- */
400
- protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
401
401
  private ipDetectCallbacks?;
402
402
  /**
403
403
  * Search input element
@@ -418,18 +418,6 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
418
418
  * Token refresh count down seed
419
419
  */
420
420
  protected refreshCountdownSeed: number;
421
- /**
422
- * Device id field name
423
- */
424
- private readonly deviceIdField;
425
- /**
426
- * Device passphrase field name
427
- */
428
- private readonly devicePassphraseField;
429
- /**
430
- * Device id update time field name
431
- */
432
- private readonly deviceIdUpdateTimeField;
433
421
  /**
434
422
  * Init call Api URL
435
423
  */
@@ -444,26 +432,17 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
444
432
  * @param settings Settings
445
433
  * @param api API
446
434
  * @param notifier Notifier
435
+ * @param storage Storage
447
436
  * @param name Application name
448
437
  */
449
- protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, name: string);
438
+ protected constructor(settings: S, api: IApi, notifier: INotifier<N, C>, storage: IStorage, name: string);
450
439
  protected setApi(api: IApi): void;
451
- /**
452
- * Setup device
453
- * @returns Device id
454
- */
455
- protected setupDevice(): string;
456
440
  /**
457
441
  * Api init call
458
442
  * @param data Data
459
443
  * @returns Result
460
444
  */
461
445
  protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
462
- /**
463
- * Get device last updte miliseconds
464
- * @returns Miliseconds
465
- */
466
- protected getDeviceUpdateTime(): number;
467
446
  /**
468
447
  * Init call
469
448
  * @param callback Callback
@@ -477,10 +456,10 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
477
456
  */
478
457
  protected initCallUpdate(data: InitCallResultData, timestamp: number): void;
479
458
  /**
480
- * Init call update fields in local storage
459
+ * Init call encrypted fields update
481
460
  * @returns Fields
482
461
  */
483
- protected initCallUpdateFields(): string[];
462
+ protected initCallEncryptedUpdateFields(): string[];
484
463
  /**
485
464
  * Alert action result
486
465
  * @param result Action result
@@ -688,8 +667,9 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
688
667
  /**
689
668
  * Switch organization
690
669
  * @param id Organization id
670
+ * @param serviceId Service id
691
671
  */
692
- switchOrg(id: number): Promise<boolean | undefined>;
672
+ switchOrg(id: number, serviceId?: number): Promise<boolean | undefined>;
693
673
  /**
694
674
  * Go to the login page
695
675
  */
@@ -730,3 +710,21 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
730
710
  */
731
711
  warning(message: NotificationContent<N>, align?: NotificationAlign): void;
732
712
  }
713
+ export declare namespace CoreApp {
714
+ /**
715
+ * Response token header field name
716
+ */
717
+ const headerTokenField = "SmartERPRefreshToken";
718
+ /**
719
+ * Serverside device id encrypted field name
720
+ */
721
+ const serversideDeviceIdField = "SmartERPServersideDeviceId";
722
+ /**
723
+ * Device id field name
724
+ */
725
+ const deviceIdField = "SmartERPDeviceId";
726
+ /**
727
+ * Device passphrase field name
728
+ */
729
+ const devicePassphraseField = "SmartERPDevicePassphrase";
730
+ }
@@ -1,6 +1,6 @@
1
1
  import { NotificationAlign, NotificationMessageType } from '@etsoo/notificationbase';
2
2
  import { ApiDataError } from '@etsoo/restclient';
3
- import { DateUtils, DomUtils, NumberUtils, StorageUtils, Utils } from '@etsoo/shared';
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
- this._deviceId = '';
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
- this.deviceId = this.setupDevice();
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
- // 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;
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 = StorageUtils.getLocalData(this.serversideDeviceIdField);
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: hasDeviceId ? this.deviceId : undefined
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
- StorageUtils.setLocalData(this.deviceIdField, null);
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.deviceId = data.deviceId;
270
- StorageUtils.setLocalData(this.deviceIdField, this.deviceId);
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.initCallUpdateFields();
236
+ const fields = this.initCallEncryptedUpdateFields();
280
237
  for (const field of fields) {
281
- const currentValue = StorageUtils.getLocalData(field);
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
- StorageUtils.setLocalData(field, newValue);
254
+ this.storage.setData(field, newValue);
298
255
  }
299
256
  }
300
257
  }
301
258
  /**
302
- * Init call update fields in local storage
259
+ * Init call encrypted fields update
303
260
  * @returns Fields
304
261
  */
305
- initCallUpdateFields() {
306
- return [this.headerTokenField];
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
- StorageUtils.setLocalData(this.headerTokenField, refreshToken);
287
+ this.storage.setData(CoreApp.headerTokenField, refreshToken);
331
288
  }
332
289
  // Reset tryLogin state
333
290
  this._isTryingLogin = false;
@@ -399,18 +356,17 @@ export class CoreApp {
399
356
  * Clear cache data
400
357
  */
401
358
  clearCacheData() {
402
- 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);
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
- StorageUtils.setLocalData(this.headerTokenField, undefined);
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 StorageUtils.getLocalData(this.headerTokenField);
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, this.headerTokenField);
635
+ return this.api.getHeaderValue(response.headers, CoreApp.headerTokenField);
680
636
  }
681
637
  /**
682
638
  * Get time zone
@@ -815,10 +771,15 @@ export class CoreApp {
815
771
  /**
816
772
  * Switch organization
817
773
  * @param id Organization id
774
+ * @param serviceId Service id
818
775
  */
819
- async switchOrg(id) {
820
- const api = `Organization/Switch/${id}`;
821
- const result = await this.api.put(api);
776
+ async switchOrg(id, serviceId) {
777
+ const api = `Organization/Switch`;
778
+ const result = await this.api.put(api, {
779
+ id,
780
+ serviceId,
781
+ deviceId: this.deviceId
782
+ });
822
783
  if (result)
823
784
  return await this.refreshToken();
824
785
  return result;
@@ -871,7 +832,7 @@ export class CoreApp {
871
832
  userLogin(user, refreshToken, keep) {
872
833
  this.userData = user;
873
834
  // Cache the encrypted serverside device id
874
- StorageUtils.setLocalData(this.serversideDeviceIdField, user.deviceId);
835
+ this.storage.setData(CoreApp.serversideDeviceIdField, user.deviceId);
875
836
  if (keep) {
876
837
  this.authorize(user.token, refreshToken);
877
838
  }
@@ -908,3 +869,21 @@ export class CoreApp {
908
869
  });
909
870
  }
910
871
  }
872
+ (function (CoreApp) {
873
+ /**
874
+ * Response token header field name
875
+ */
876
+ CoreApp.headerTokenField = 'SmartERPRefreshToken';
877
+ /**
878
+ * Serverside device id encrypted field name
879
+ */
880
+ CoreApp.serversideDeviceIdField = 'SmartERPServersideDeviceId';
881
+ /**
882
+ * Device id field name
883
+ */
884
+ CoreApp.deviceIdField = 'SmartERPDeviceId';
885
+ /**
886
+ * Device passphrase field name
887
+ */
888
+ CoreApp.devicePassphraseField = 'SmartERPDevicePassphrase';
889
+ })(CoreApp || (CoreApp = {}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/appscript",
3
- "version": "1.1.89",
3
+ "version": "1.1.93",
4
4
  "description": "Applications shared TypeScript framework",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -54,7 +54,7 @@
54
54
  "dependencies": {
55
55
  "@etsoo/notificationbase": "^1.0.95",
56
56
  "@etsoo/restclient": "^1.0.63",
57
- "@etsoo/shared": "^1.0.82",
57
+ "@etsoo/shared": "^1.0.83",
58
58
  "@types/crypto-js": "^4.0.2",
59
59
  "crypto-js": "^4.1.1"
60
60
  },
@@ -11,8 +11,8 @@ import {
11
11
  DataTypes,
12
12
  DateUtils,
13
13
  DomUtils,
14
+ IStorage,
14
15
  NumberUtils,
15
- StorageUtils,
16
16
  Utils
17
17
  } from '@etsoo/shared';
18
18
  import {
@@ -128,6 +128,11 @@ export interface ICoreApp<
128
128
  */
129
129
  readonly region: string;
130
130
 
131
+ /**
132
+ * Storage
133
+ */
134
+ readonly storage: IStorage;
135
+
131
136
  /**
132
137
  * Is current authorized
133
138
  */
@@ -400,9 +405,10 @@ export interface ICoreApp<
400
405
 
401
406
  /**
402
407
  * Switch organization
403
- * @param apiOrOrg API URL or organization id
408
+ * @param id Organization id
409
+ * @param serviceId Service id
404
410
  */
405
- switchOrg(apiOrOrg: string | number): Promise<boolean | undefined>;
411
+ switchOrg(id: number, serviceId?: number): Promise<boolean | undefined>;
406
412
 
407
413
  /**
408
414
  * Go to the login page
@@ -479,6 +485,11 @@ export abstract class CoreApp<
479
485
  */
480
486
  readonly notifier: INotifier<N, C>;
481
487
 
488
+ /**
489
+ * Storage
490
+ */
491
+ readonly storage: IStorage;
492
+
482
493
  private _culture!: string;
483
494
  /**
484
495
  * Culture, like zh-CN
@@ -503,16 +514,13 @@ export abstract class CoreApp<
503
514
  return this._region;
504
515
  }
505
516
 
506
- private _deviceId: string = '';
517
+ private _deviceId: string;
507
518
  /**
508
519
  * Country or region, like CN
509
520
  */
510
521
  get deviceId() {
511
522
  return this._deviceId;
512
523
  }
513
- protected set deviceId(value: string) {
514
- this._deviceId = value;
515
- }
516
524
 
517
525
  /**
518
526
  * Label delegate
@@ -543,16 +551,6 @@ export abstract class CoreApp<
543
551
  this._userData = value;
544
552
  }
545
553
 
546
- /**
547
- * Response token header field name
548
- */
549
- readonly headerTokenField = 'SmartERPRefreshToken';
550
-
551
- /**
552
- * Serverside device id encrypted field name
553
- */
554
- protected readonly serversideDeviceIdField = 'SmartERPServersideDeviceId';
555
-
556
554
  // IP detect ready callbacks
557
555
  private ipDetectCallbacks?: IDetectIPCallback[];
558
556
 
@@ -585,22 +583,6 @@ export abstract class CoreApp<
585
583
  */
586
584
  protected refreshCountdownSeed = 0;
587
585
 
588
- /**
589
- * Device id field name
590
- */
591
- private readonly deviceIdField: string = 'SmartERPDeviceId';
592
-
593
- /**
594
- * Device passphrase field name
595
- */
596
- private readonly devicePassphraseField: string = 'SmartERPDevicePassphrase';
597
-
598
- /**
599
- * Device id update time field name
600
- */
601
- private readonly deviceIdUpdateTimeField: string =
602
- 'SmartERPDeviceIdUpdateTime';
603
-
604
586
  /**
605
587
  * Init call Api URL
606
588
  */
@@ -618,20 +600,24 @@ export abstract class CoreApp<
618
600
  * @param settings Settings
619
601
  * @param api API
620
602
  * @param notifier Notifier
603
+ * @param storage Storage
621
604
  * @param name Application name
622
605
  */
623
606
  protected constructor(
624
607
  settings: S,
625
608
  api: IApi,
626
609
  notifier: INotifier<N, C>,
610
+ storage: IStorage,
627
611
  name: string
628
612
  ) {
629
613
  this.settings = settings;
630
614
  this.api = api;
631
615
  this.notifier = notifier;
616
+ this.storage = storage;
632
617
  this.name = name;
633
618
 
634
- this.deviceId = this.setupDevice();
619
+ // Device id
620
+ this._deviceId = storage.getData<string>(CoreApp.deviceIdField) ?? '';
635
621
 
636
622
  this.setApi(api);
637
623
 
@@ -677,33 +663,6 @@ export abstract class CoreApp<
677
663
  };
678
664
  }
679
665
 
680
- /**
681
- * Setup device
682
- * @returns Device id
683
- */
684
- protected setupDevice() {
685
- const deviceId = StorageUtils.getLocalData<string>(this.deviceIdField);
686
-
687
- if (deviceId != null && deviceId !== '') {
688
- const passphraseEncrypted = StorageUtils.getLocalData<string>(
689
- this.devicePassphraseField
690
- );
691
- if (passphraseEncrypted != null && passphraseEncrypted !== '') {
692
- const timestamp = this.getDeviceUpdateTime();
693
- if (timestamp > 0) {
694
- const passphraseDecrypted = this.decrypt(
695
- passphraseEncrypted,
696
- timestamp.toString()
697
- );
698
- if (passphraseDecrypted != null)
699
- this.passphrase = passphraseDecrypted;
700
- }
701
- }
702
- }
703
-
704
- return deviceId ?? '';
705
- }
706
-
707
666
  /**
708
667
  * Api init call
709
668
  * @param data Data
@@ -713,44 +672,44 @@ export abstract class CoreApp<
713
672
  return await this.api.put<InitCallResult>(this.initCallApi, data);
714
673
  }
715
674
 
716
- /**
717
- * Get device last updte miliseconds
718
- * @returns Miliseconds
719
- */
720
- protected getDeviceUpdateTime() {
721
- return StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
722
- }
723
-
724
675
  /**
725
676
  * Init call
726
677
  * @param callback Callback
727
678
  * @returns Result
728
679
  */
729
680
  async initCall(callback?: (result: boolean) => void) {
730
- // 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;
681
+ // Passphrase exists?
682
+ // Same session should avoid multiple init calls
683
+ const passphraseEncrypted = this.storage.getData<string>(
684
+ CoreApp.devicePassphraseField
685
+ );
686
+ if (passphraseEncrypted) {
687
+ const passphraseDecrypted = this.decrypt(
688
+ passphraseEncrypted,
689
+ this.name
690
+ );
691
+ if (passphraseDecrypted != null) {
692
+ this.passphrase = passphraseDecrypted;
693
+ if (callback) callback(true);
694
+ return;
695
+ }
742
696
  }
743
697
 
744
698
  // Serverside encrypted device id
745
- const identifier = StorageUtils.getLocalData<string>(
746
- this.serversideDeviceIdField
699
+ const identifier = this.storage.getData<string>(
700
+ CoreApp.serversideDeviceIdField
747
701
  );
748
702
 
703
+ // Timestamp
704
+ const timestamp = new Date().getTime();
705
+
706
+ // Request data
749
707
  const data: InitCallDto = {
750
708
  timestamp,
751
709
  identifier,
752
- deviceId: hasDeviceId ? this.deviceId : undefined
710
+ deviceId: this.deviceId ? this.deviceId : undefined
753
711
  };
712
+
754
713
  const result = await this.apiInitCall(data);
755
714
  if (result == null) {
756
715
  if (callback) callback(false);
@@ -783,7 +742,7 @@ export abstract class CoreApp<
783
742
  if (callback) callback(false);
784
743
 
785
744
  // Clear device id
786
- StorageUtils.setLocalData(this.deviceIdField, null);
745
+ this.storage.setData(CoreApp.deviceIdField, undefined);
787
746
 
788
747
  return;
789
748
  }
@@ -799,6 +758,7 @@ export abstract class CoreApp<
799
758
  * @param timestamp Timestamp
800
759
  */
801
760
  protected initCallUpdate(data: InitCallResultData, timestamp: number) {
761
+ // Data check
802
762
  if (data.deviceId == null || data.passphrase == null) return;
803
763
 
804
764
  // Decrypt
@@ -807,13 +767,15 @@ export abstract class CoreApp<
807
767
  if (passphrase == null) return;
808
768
 
809
769
  // Update device id and cache it
810
- this.deviceId = data.deviceId;
811
- StorageUtils.setLocalData(this.deviceIdField, this.deviceId);
812
- StorageUtils.setLocalData(this.devicePassphraseField, data.passphrase);
813
- StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
770
+ this._deviceId = data.deviceId;
771
+ this.storage.setData(CoreApp.deviceIdField, this.deviceId);
814
772
 
815
773
  // Current passphrase
816
774
  this.passphrase = passphrase;
775
+ this.storage.setData(
776
+ CoreApp.devicePassphraseField,
777
+ this.encrypt(passphrase, this.name)
778
+ );
817
779
 
818
780
  // Previous passphrase
819
781
  if (data.previousPassphrase) {
@@ -823,9 +785,9 @@ export abstract class CoreApp<
823
785
  );
824
786
 
825
787
  // Update
826
- const fields = this.initCallUpdateFields();
788
+ const fields = this.initCallEncryptedUpdateFields();
827
789
  for (const field of fields) {
828
- const currentValue = StorageUtils.getLocalData<string>(field);
790
+ const currentValue = this.storage.getData<string>(field);
829
791
  if (currentValue == null || currentValue === '') continue;
830
792
 
831
793
  const enhanced = currentValue.indexOf('!') >= 8;
@@ -847,17 +809,17 @@ export abstract class CoreApp<
847
809
  ? this.encryptEnhanced(newValueSource)
848
810
  : this.encrypt(newValueSource);
849
811
 
850
- StorageUtils.setLocalData(field, newValue);
812
+ this.storage.setData(field, newValue);
851
813
  }
852
814
  }
853
815
  }
854
816
 
855
817
  /**
856
- * Init call update fields in local storage
818
+ * Init call encrypted fields update
857
819
  * @returns Fields
858
820
  */
859
- protected initCallUpdateFields(): string[] {
860
- return [this.headerTokenField];
821
+ protected initCallEncryptedUpdateFields(): string[] {
822
+ return [CoreApp.headerTokenField];
861
823
  }
862
824
 
863
825
  /**
@@ -884,7 +846,7 @@ export abstract class CoreApp<
884
846
  // Cover the current value
885
847
  if (refreshToken !== '') {
886
848
  if (refreshToken != null) refreshToken = this.encrypt(refreshToken);
887
- StorageUtils.setLocalData(this.headerTokenField, refreshToken);
849
+ this.storage.setData(CoreApp.headerTokenField, refreshToken);
888
850
  }
889
851
 
890
852
  // Reset tryLogin state
@@ -971,13 +933,12 @@ export abstract class CoreApp<
971
933
  * Clear cache data
972
934
  */
973
935
  clearCacheData() {
974
- StorageUtils.setLocalData(this.serversideDeviceIdField, undefined);
936
+ this.storage.setData(CoreApp.serversideDeviceIdField, undefined);
975
937
 
976
- StorageUtils.setLocalData(this.deviceIdField, undefined);
977
- StorageUtils.setLocalData(this.devicePassphraseField, undefined);
978
- StorageUtils.setLocalData(this.deviceIdUpdateTimeField, undefined);
938
+ this.storage.setData(CoreApp.deviceIdField, undefined);
939
+ this.storage.setData(CoreApp.devicePassphraseField, undefined);
979
940
 
980
- StorageUtils.setLocalData(this.headerTokenField, undefined);
941
+ this.storage.setData(CoreApp.headerTokenField, undefined);
981
942
  }
982
943
 
983
944
  /**
@@ -985,7 +946,7 @@ export abstract class CoreApp<
985
946
  */
986
947
  clearCacheToken() {
987
948
  this.cachedRefreshToken = undefined;
988
- StorageUtils.setLocalData(this.headerTokenField, undefined);
949
+ this.storage.setData(CoreApp.headerTokenField, undefined);
989
950
  }
990
951
 
991
952
  /**
@@ -1291,7 +1252,7 @@ export abstract class CoreApp<
1291
1252
  getCacheToken(): string | undefined {
1292
1253
  // Temp refresh token
1293
1254
  if (this.cachedRefreshToken) return this.cachedRefreshToken;
1294
- return StorageUtils.getLocalData<string>(this.headerTokenField);
1255
+ return this.storage.getData<string>(CoreApp.headerTokenField);
1295
1256
  }
1296
1257
 
1297
1258
  /**
@@ -1311,7 +1272,10 @@ export abstract class CoreApp<
1311
1272
  */
1312
1273
  getResponseToken(rawResponse: any): string | null {
1313
1274
  const response = this.api.transformResponse(rawResponse);
1314
- return this.api.getHeaderValue(response.headers, this.headerTokenField);
1275
+ return this.api.getHeaderValue(
1276
+ response.headers,
1277
+ CoreApp.headerTokenField
1278
+ );
1315
1279
  }
1316
1280
 
1317
1281
  /**
@@ -1474,10 +1438,15 @@ export abstract class CoreApp<
1474
1438
  /**
1475
1439
  * Switch organization
1476
1440
  * @param id Organization id
1441
+ * @param serviceId Service id
1477
1442
  */
1478
- async switchOrg(id: number) {
1479
- const api = `Organization/Switch/${id}`;
1480
- const result = await this.api.put<boolean>(api);
1443
+ async switchOrg(id: number, serviceId?: number) {
1444
+ const api = `Organization/Switch`;
1445
+ const result = await this.api.put<boolean>(api, {
1446
+ id,
1447
+ serviceId,
1448
+ deviceId: this.deviceId
1449
+ });
1481
1450
  if (result) return await this.refreshToken();
1482
1451
  return result;
1483
1452
  }
@@ -1535,7 +1504,7 @@ export abstract class CoreApp<
1535
1504
  this.userData = user;
1536
1505
 
1537
1506
  // Cache the encrypted serverside device id
1538
- StorageUtils.setLocalData(this.serversideDeviceIdField, user.deviceId);
1507
+ this.storage.setData(CoreApp.serversideDeviceIdField, user.deviceId);
1539
1508
 
1540
1509
  if (keep) {
1541
1510
  this.authorize(user.token, refreshToken);
@@ -1582,3 +1551,25 @@ export abstract class CoreApp<
1582
1551
  );
1583
1552
  }
1584
1553
  }
1554
+
1555
+ export namespace CoreApp {
1556
+ /**
1557
+ * Response token header field name
1558
+ */
1559
+ export const headerTokenField = 'SmartERPRefreshToken';
1560
+
1561
+ /**
1562
+ * Serverside device id encrypted field name
1563
+ */
1564
+ export const serversideDeviceIdField = 'SmartERPServersideDeviceId';
1565
+
1566
+ /**
1567
+ * Device id field name
1568
+ */
1569
+ export const deviceIdField = 'SmartERPDeviceId';
1570
+
1571
+ /**
1572
+ * Device passphrase field name
1573
+ */
1574
+ export const devicePassphraseField = 'SmartERPDevicePassphrase';
1575
+ }