@etsoo/appscript 1.1.82 → 1.1.86

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.
@@ -129,6 +129,17 @@ test('Tests for encrypt / decrypt', () => {
129
129
  expect(plain).toEqual(input);
130
130
  });
131
131
 
132
+ test('Tests for encryptEnhanced / decryptEnhanced', () => {
133
+ // Arrange
134
+ const input = 'Hello, world!';
135
+ const passphrase = 'My password';
136
+
137
+ // Act
138
+ const encrypted = app.encryptEnhanced(input, passphrase);
139
+ const plain = app.decryptEnhanced(encrypted, passphrase);
140
+ expect(plain).toEqual(input);
141
+ });
142
+
132
143
  test('Tests for initCallUpdateLocal', () => {
133
144
  // Act
134
145
  const passphrase = app.initCallUpdateLocal(
@@ -2,6 +2,7 @@ import { INotifier, NotificationAlign, NotificationCallProps, NotificationConten
2
2
  import { ApiDataError, IApi, IPData } from '@etsoo/restclient';
3
3
  import { DataTypes, DateUtils } from '@etsoo/shared';
4
4
  import { AddressRegion } from '../address/AddressRegion';
5
+ import { IdLabelDto } from '../dto/IdLabelDto';
5
6
  import { InitCallDto } from '../dto/InitCallDto';
6
7
  import { IActionResult } from '../result/IActionResult';
7
8
  import { InitCallResult, InitCallResultData } from '../result/InitCallResult';
@@ -27,7 +28,7 @@ export interface RefreshTokenProps<D extends {}> {
27
28
  /**
28
29
  * Callback
29
30
  */
30
- callback?: (result: RefreshTokenResult) => void;
31
+ callback?: (result: RefreshTokenResult, successData?: string) => void;
31
32
  /**
32
33
  * Data to pass
33
34
  */
@@ -221,7 +222,7 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
221
222
  * Get cached token
222
223
  * @returns Cached token
223
224
  */
224
- getCacheToken(): string | null;
225
+ getCacheToken(): string | undefined;
225
226
  /**
226
227
  * Get all regions
227
228
  * @returns Regions
@@ -278,6 +279,13 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
278
279
  * @param apiUrl Signout API URL
279
280
  */
280
281
  signout(apiUrl?: string): Promise<void>;
282
+ /**
283
+ * Get organization list
284
+ * @param items Max items
285
+ * @param serviceId Service id
286
+ * @returns Result
287
+ */
288
+ orgList(items?: number, serviceId?: number): Promise<IdLabelDto[] | undefined>;
281
289
  /**
282
290
  * Switch organization
283
291
  * @param apiOrOrg API URL or organization id
@@ -367,18 +375,26 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
367
375
  * Label delegate
368
376
  */
369
377
  get labelDelegate(): <T = string>(key: string) => T | undefined;
378
+ private _ipData?;
370
379
  /**
371
380
  * IP data
372
381
  */
373
- ipData?: IPData;
382
+ get ipData(): IPData | undefined;
383
+ protected set ipData(value: IPData | undefined);
384
+ private _userData?;
374
385
  /**
375
386
  * User data
376
387
  */
377
- userData?: IUserData;
388
+ get userData(): IUserData | undefined;
389
+ protected set userData(value: IUserData | undefined);
378
390
  /**
379
391
  * Response token header field name
380
392
  */
381
- headerTokenField: string;
393
+ readonly headerTokenField = "SmartERPRefreshToken";
394
+ /**
395
+ * Serverside device id encrypted field name
396
+ */
397
+ protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
382
398
  private ipDetectCallbacks?;
383
399
  /**
384
400
  * Search input element
@@ -402,7 +418,11 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
402
418
  /**
403
419
  * Device id field name
404
420
  */
405
- protected deviceIdField: string;
421
+ protected readonly deviceIdField: string;
422
+ /**
423
+ * Device id update time field name
424
+ */
425
+ protected readonly deviceIdUpdateTimeField: string;
406
426
  /**
407
427
  * Init call Api URL
408
428
  */
@@ -427,6 +447,11 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
427
447
  * @returns Result
428
448
  */
429
449
  protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
450
+ /**
451
+ * Get device last updte miliseconds
452
+ * @returns Miliseconds
453
+ */
454
+ protected getDeviceUpdateTime(): number;
430
455
  /**
431
456
  * Init call
432
457
  * @param callback Callback
@@ -571,7 +596,7 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
571
596
  * Get cached token
572
597
  * @returns Cached token
573
598
  */
574
- getCacheToken(): string | null;
599
+ getCacheToken(): string | undefined;
575
600
  /**
576
601
  * Get all regions
577
602
  * @returns Regions
@@ -637,11 +662,18 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
637
662
  * @param apiUrl Signout API URL
638
663
  */
639
664
  signout(apiUrl?: string): Promise<void>;
665
+ /**
666
+ * Get organization list
667
+ * @param items Max items
668
+ * @param serviceId Service id
669
+ * @returns Result
670
+ */
671
+ orgList(items?: number, serviceId?: number): Promise<IdLabelDto<number>[] | undefined>;
640
672
  /**
641
673
  * Switch organization
642
- * @param apiOrOrg API URL or organization id
674
+ * @param id Organization id
643
675
  */
644
- switchOrg(apiOrOrg: string | number): Promise<boolean | undefined>;
676
+ switchOrg(id: number): Promise<boolean | undefined>;
645
677
  /**
646
678
  * Go to the login page
647
679
  */
@@ -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,10 @@ class CoreApp {
39
43
  * Device id field name
40
44
  */
41
45
  this.deviceIdField = 'SmartERPDeviceId';
46
+ /**
47
+ * Device id update time field name
48
+ */
49
+ this.deviceIdUpdateTimeField = 'SmartERPDeviceIdUpdateTime';
42
50
  /**
43
51
  * Init call Api URL
44
52
  */
@@ -92,6 +100,24 @@ class CoreApp {
92
100
  get labelDelegate() {
93
101
  return this.get.bind(this);
94
102
  }
103
+ /**
104
+ * IP data
105
+ */
106
+ get ipData() {
107
+ return this._ipData;
108
+ }
109
+ set ipData(value) {
110
+ this._ipData = value;
111
+ }
112
+ /**
113
+ * User data
114
+ */
115
+ get userData() {
116
+ return this._userData;
117
+ }
118
+ set userData(value) {
119
+ this._userData = value;
120
+ }
95
121
  /**
96
122
  * Is current authorized
97
123
  */
@@ -139,6 +165,13 @@ class CoreApp {
139
165
  async apiInitCall(data) {
140
166
  return await this.api.put(this.initCallApi, data);
141
167
  }
168
+ /**
169
+ * Get device last updte miliseconds
170
+ * @returns Miliseconds
171
+ */
172
+ getDeviceUpdateTime() {
173
+ return shared_1.StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
174
+ }
142
175
  /**
143
176
  * Init call
144
177
  * @param callback Callback
@@ -146,9 +179,24 @@ class CoreApp {
146
179
  */
147
180
  async initCall(callback) {
148
181
  var _a;
182
+ // Device
183
+ let hasDeviceId = this.deviceId != null && this.deviceId !== '';
184
+ const timestamp = new Date().getTime();
185
+ const lastTimestamp = this.getDeviceUpdateTime();
186
+ if (hasDeviceId &&
187
+ lastTimestamp > 0 &&
188
+ timestamp - lastTimestamp <= 1296000000) {
189
+ // When deviceId is there and less than 15 days = 1000 * 60 * 60 * 24 * 15
190
+ if (callback)
191
+ callback(true);
192
+ return;
193
+ }
194
+ // Serverside encrypted device id
195
+ const identifier = shared_1.StorageUtils.getLocalData(this.serversideDeviceIdField);
149
196
  const data = {
150
- timestamp: new Date().getTime(),
151
- deviceId: this.deviceId === '' ? undefined : this.deviceId
197
+ timestamp,
198
+ identifier,
199
+ deviceId: hasDeviceId ? this.deviceId : undefined
152
200
  };
153
201
  const result = await this.apiInitCall(data);
154
202
  if (result == null) {
@@ -200,6 +248,7 @@ class CoreApp {
200
248
  // Update device id and cache it
201
249
  this.deviceId = data.deviceId;
202
250
  shared_1.StorageUtils.setLocalData(this.deviceIdField, this.deviceId);
251
+ shared_1.StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
203
252
  // Current passphrase
204
253
  this.passphrase = passphrase;
205
254
  // Previous passphrase
@@ -578,10 +627,7 @@ class CoreApp {
578
627
  // Temp refresh token
579
628
  if (this.cachedRefreshToken)
580
629
  return this.cachedRefreshToken;
581
- const refreshToken = shared_1.StorageUtils.getLocalData(this.headerTokenField, '');
582
- if (refreshToken === '')
583
- return null;
584
- return refreshToken;
630
+ return shared_1.StorageUtils.getLocalData(this.headerTokenField);
585
631
  }
586
632
  /**
587
633
  * Get all regions
@@ -699,7 +745,7 @@ class CoreApp {
699
745
  */
700
746
  async refreshToken(props) {
701
747
  if (props && props.callback)
702
- props.callback(true);
748
+ props.callback(true, undefined);
703
749
  return true;
704
750
  }
705
751
  /**
@@ -723,14 +769,24 @@ class CoreApp {
723
769
  // Go to login page
724
770
  this.toLoginPage();
725
771
  }
772
+ /**
773
+ * Get organization list
774
+ * @param items Max items
775
+ * @param serviceId Service id
776
+ * @returns Result
777
+ */
778
+ async orgList(items, serviceId) {
779
+ return await this.api.post('Organization/List', {
780
+ items,
781
+ serviceId
782
+ }, { defaultValue: [], showLoading: false });
783
+ }
726
784
  /**
727
785
  * Switch organization
728
- * @param apiOrOrg API URL or organization id
786
+ * @param id Organization id
729
787
  */
730
- async switchOrg(apiOrOrg) {
731
- const api = typeof apiOrOrg === 'number'
732
- ? `Organization/Switch/${apiOrOrg}`
733
- : apiOrOrg;
788
+ async switchOrg(id) {
789
+ const api = `Organization/Switch/${id}`;
734
790
  const result = await this.api.put(api);
735
791
  if (result)
736
792
  return await this.refreshToken();
@@ -783,6 +839,8 @@ class CoreApp {
783
839
  */
784
840
  userLogin(user, refreshToken, keep) {
785
841
  this.userData = user;
842
+ // Cache the encrypted serverside device id
843
+ shared_1.StorageUtils.setLocalData(this.serversideDeviceIdField, user.deviceId);
786
844
  if (keep) {
787
845
  this.authorize(user.token, refreshToken);
788
846
  }
@@ -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
  */
@@ -2,6 +2,7 @@ import { INotifier, NotificationAlign, NotificationCallProps, NotificationConten
2
2
  import { ApiDataError, IApi, IPData } from '@etsoo/restclient';
3
3
  import { DataTypes, DateUtils } from '@etsoo/shared';
4
4
  import { AddressRegion } from '../address/AddressRegion';
5
+ import { IdLabelDto } from '../dto/IdLabelDto';
5
6
  import { InitCallDto } from '../dto/InitCallDto';
6
7
  import { IActionResult } from '../result/IActionResult';
7
8
  import { InitCallResult, InitCallResultData } from '../result/InitCallResult';
@@ -27,7 +28,7 @@ export interface RefreshTokenProps<D extends {}> {
27
28
  /**
28
29
  * Callback
29
30
  */
30
- callback?: (result: RefreshTokenResult) => void;
31
+ callback?: (result: RefreshTokenResult, successData?: string) => void;
31
32
  /**
32
33
  * Data to pass
33
34
  */
@@ -221,7 +222,7 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
221
222
  * Get cached token
222
223
  * @returns Cached token
223
224
  */
224
- getCacheToken(): string | null;
225
+ getCacheToken(): string | undefined;
225
226
  /**
226
227
  * Get all regions
227
228
  * @returns Regions
@@ -278,6 +279,13 @@ export interface ICoreApp<S extends IAppSettings, N, C extends NotificationCallP
278
279
  * @param apiUrl Signout API URL
279
280
  */
280
281
  signout(apiUrl?: string): Promise<void>;
282
+ /**
283
+ * Get organization list
284
+ * @param items Max items
285
+ * @param serviceId Service id
286
+ * @returns Result
287
+ */
288
+ orgList(items?: number, serviceId?: number): Promise<IdLabelDto[] | undefined>;
281
289
  /**
282
290
  * Switch organization
283
291
  * @param apiOrOrg API URL or organization id
@@ -367,18 +375,26 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
367
375
  * Label delegate
368
376
  */
369
377
  get labelDelegate(): <T = string>(key: string) => T | undefined;
378
+ private _ipData?;
370
379
  /**
371
380
  * IP data
372
381
  */
373
- ipData?: IPData;
382
+ get ipData(): IPData | undefined;
383
+ protected set ipData(value: IPData | undefined);
384
+ private _userData?;
374
385
  /**
375
386
  * User data
376
387
  */
377
- userData?: IUserData;
388
+ get userData(): IUserData | undefined;
389
+ protected set userData(value: IUserData | undefined);
378
390
  /**
379
391
  * Response token header field name
380
392
  */
381
- headerTokenField: string;
393
+ readonly headerTokenField = "SmartERPRefreshToken";
394
+ /**
395
+ * Serverside device id encrypted field name
396
+ */
397
+ protected readonly serversideDeviceIdField = "SmartERPServersideDeviceId";
382
398
  private ipDetectCallbacks?;
383
399
  /**
384
400
  * Search input element
@@ -402,7 +418,11 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
402
418
  /**
403
419
  * Device id field name
404
420
  */
405
- protected deviceIdField: string;
421
+ protected readonly deviceIdField: string;
422
+ /**
423
+ * Device id update time field name
424
+ */
425
+ protected readonly deviceIdUpdateTimeField: string;
406
426
  /**
407
427
  * Init call Api URL
408
428
  */
@@ -427,6 +447,11 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
427
447
  * @returns Result
428
448
  */
429
449
  protected apiInitCall(data: InitCallDto): Promise<InitCallResult | undefined>;
450
+ /**
451
+ * Get device last updte miliseconds
452
+ * @returns Miliseconds
453
+ */
454
+ protected getDeviceUpdateTime(): number;
430
455
  /**
431
456
  * Init call
432
457
  * @param callback Callback
@@ -571,7 +596,7 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
571
596
  * Get cached token
572
597
  * @returns Cached token
573
598
  */
574
- getCacheToken(): string | null;
599
+ getCacheToken(): string | undefined;
575
600
  /**
576
601
  * Get all regions
577
602
  * @returns Regions
@@ -637,11 +662,18 @@ export declare abstract class CoreApp<S extends IAppSettings, N, C extends Notif
637
662
  * @param apiUrl Signout API URL
638
663
  */
639
664
  signout(apiUrl?: string): Promise<void>;
665
+ /**
666
+ * Get organization list
667
+ * @param items Max items
668
+ * @param serviceId Service id
669
+ * @returns Result
670
+ */
671
+ orgList(items?: number, serviceId?: number): Promise<IdLabelDto<number>[] | undefined>;
640
672
  /**
641
673
  * Switch organization
642
- * @param apiOrOrg API URL or organization id
674
+ * @param id Organization id
643
675
  */
644
- switchOrg(apiOrOrg: string | number): Promise<boolean | undefined>;
676
+ switchOrg(id: number): Promise<boolean | undefined>;
645
677
  /**
646
678
  * Go to the login page
647
679
  */
@@ -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,10 @@ export class CoreApp {
36
40
  * Device id field name
37
41
  */
38
42
  this.deviceIdField = 'SmartERPDeviceId';
43
+ /**
44
+ * Device id update time field name
45
+ */
46
+ this.deviceIdUpdateTimeField = 'SmartERPDeviceIdUpdateTime';
39
47
  /**
40
48
  * Init call Api URL
41
49
  */
@@ -89,6 +97,24 @@ export class CoreApp {
89
97
  get labelDelegate() {
90
98
  return this.get.bind(this);
91
99
  }
100
+ /**
101
+ * IP data
102
+ */
103
+ get ipData() {
104
+ return this._ipData;
105
+ }
106
+ set ipData(value) {
107
+ this._ipData = value;
108
+ }
109
+ /**
110
+ * User data
111
+ */
112
+ get userData() {
113
+ return this._userData;
114
+ }
115
+ set userData(value) {
116
+ this._userData = value;
117
+ }
92
118
  /**
93
119
  * Is current authorized
94
120
  */
@@ -136,6 +162,13 @@ export class CoreApp {
136
162
  async apiInitCall(data) {
137
163
  return await this.api.put(this.initCallApi, data);
138
164
  }
165
+ /**
166
+ * Get device last updte miliseconds
167
+ * @returns Miliseconds
168
+ */
169
+ getDeviceUpdateTime() {
170
+ return StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
171
+ }
139
172
  /**
140
173
  * Init call
141
174
  * @param callback Callback
@@ -143,9 +176,24 @@ export class CoreApp {
143
176
  */
144
177
  async initCall(callback) {
145
178
  var _a;
179
+ // Device
180
+ let hasDeviceId = this.deviceId != null && this.deviceId !== '';
181
+ const timestamp = new Date().getTime();
182
+ const lastTimestamp = this.getDeviceUpdateTime();
183
+ if (hasDeviceId &&
184
+ lastTimestamp > 0 &&
185
+ timestamp - lastTimestamp <= 1296000000) {
186
+ // When deviceId is there and less than 15 days = 1000 * 60 * 60 * 24 * 15
187
+ if (callback)
188
+ callback(true);
189
+ return;
190
+ }
191
+ // Serverside encrypted device id
192
+ const identifier = StorageUtils.getLocalData(this.serversideDeviceIdField);
146
193
  const data = {
147
- timestamp: new Date().getTime(),
148
- deviceId: this.deviceId === '' ? undefined : this.deviceId
194
+ timestamp,
195
+ identifier,
196
+ deviceId: hasDeviceId ? this.deviceId : undefined
149
197
  };
150
198
  const result = await this.apiInitCall(data);
151
199
  if (result == null) {
@@ -197,6 +245,7 @@ export class CoreApp {
197
245
  // Update device id and cache it
198
246
  this.deviceId = data.deviceId;
199
247
  StorageUtils.setLocalData(this.deviceIdField, this.deviceId);
248
+ StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
200
249
  // Current passphrase
201
250
  this.passphrase = passphrase;
202
251
  // Previous passphrase
@@ -575,10 +624,7 @@ export class CoreApp {
575
624
  // Temp refresh token
576
625
  if (this.cachedRefreshToken)
577
626
  return this.cachedRefreshToken;
578
- const refreshToken = StorageUtils.getLocalData(this.headerTokenField, '');
579
- if (refreshToken === '')
580
- return null;
581
- return refreshToken;
627
+ return StorageUtils.getLocalData(this.headerTokenField);
582
628
  }
583
629
  /**
584
630
  * Get all regions
@@ -696,7 +742,7 @@ export class CoreApp {
696
742
  */
697
743
  async refreshToken(props) {
698
744
  if (props && props.callback)
699
- props.callback(true);
745
+ props.callback(true, undefined);
700
746
  return true;
701
747
  }
702
748
  /**
@@ -720,14 +766,24 @@ export class CoreApp {
720
766
  // Go to login page
721
767
  this.toLoginPage();
722
768
  }
769
+ /**
770
+ * Get organization list
771
+ * @param items Max items
772
+ * @param serviceId Service id
773
+ * @returns Result
774
+ */
775
+ async orgList(items, serviceId) {
776
+ return await this.api.post('Organization/List', {
777
+ items,
778
+ serviceId
779
+ }, { defaultValue: [], showLoading: false });
780
+ }
723
781
  /**
724
782
  * Switch organization
725
- * @param apiOrOrg API URL or organization id
783
+ * @param id Organization id
726
784
  */
727
- async switchOrg(apiOrOrg) {
728
- const api = typeof apiOrOrg === 'number'
729
- ? `Organization/Switch/${apiOrOrg}`
730
- : apiOrOrg;
785
+ async switchOrg(id) {
786
+ const api = `Organization/Switch/${id}`;
731
787
  const result = await this.api.put(api);
732
788
  if (result)
733
789
  return await this.refreshToken();
@@ -780,6 +836,8 @@ export class CoreApp {
780
836
  */
781
837
  userLogin(user, refreshToken, keep) {
782
838
  this.userData = user;
839
+ // Cache the encrypted serverside device id
840
+ StorageUtils.setLocalData(this.serversideDeviceIdField, user.deviceId);
783
841
  if (keep) {
784
842
  this.authorize(user.token, refreshToken);
785
843
  }
@@ -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.82",
3
+ "version": "1.1.86",
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",
@@ -28,6 +28,7 @@ import {
28
28
  } from 'crypto-js';
29
29
  import { AddressRegion } from '../address/AddressRegion';
30
30
  import { AddressUtils } from '../address/AddressUtils';
31
+ import { IdLabelDto } from '../dto/IdLabelDto';
31
32
  import { InitCallDto } from '../dto/InitCallDto';
32
33
  import { ActionResultError } from '../result/ActionResultError';
33
34
  import { IActionResult } from '../result/IActionResult';
@@ -61,7 +62,7 @@ export interface RefreshTokenProps<D extends {}> {
61
62
  /**
62
63
  * Callback
63
64
  */
64
- callback?: (result: RefreshTokenResult) => void;
65
+ callback?: (result: RefreshTokenResult, successData?: string) => void;
65
66
 
66
67
  /**
67
68
  * Data to pass
@@ -312,7 +313,7 @@ export interface ICoreApp<
312
313
  * Get cached token
313
314
  * @returns Cached token
314
315
  */
315
- getCacheToken(): string | null;
316
+ getCacheToken(): string | undefined;
316
317
 
317
318
  /**
318
319
  * Get all regions
@@ -382,6 +383,17 @@ export interface ICoreApp<
382
383
  */
383
384
  signout(apiUrl?: string): Promise<void>;
384
385
 
386
+ /**
387
+ * Get organization list
388
+ * @param items Max items
389
+ * @param serviceId Service id
390
+ * @returns Result
391
+ */
392
+ orgList(
393
+ items?: number,
394
+ serviceId?: number
395
+ ): Promise<IdLabelDto[] | undefined>;
396
+
385
397
  /**
386
398
  * Switch organization
387
399
  * @param apiOrOrg API URL or organization id
@@ -487,7 +499,7 @@ export abstract class CoreApp<
487
499
  return this._region;
488
500
  }
489
501
 
490
- private _deviceId: string = '***';
502
+ private _deviceId: string = '';
491
503
  /**
492
504
  * Country or region, like CN
493
505
  */
@@ -505,20 +517,37 @@ export abstract class CoreApp<
505
517
  return this.get.bind(this);
506
518
  }
507
519
 
520
+ private _ipData?: IPData;
508
521
  /**
509
522
  * IP data
510
523
  */
511
- ipData?: IPData;
524
+ get ipData() {
525
+ return this._ipData;
526
+ }
527
+ protected set ipData(value: IPData | undefined) {
528
+ this._ipData = value;
529
+ }
512
530
 
531
+ private _userData?: IUserData;
513
532
  /**
514
533
  * User data
515
534
  */
516
- userData?: IUserData;
535
+ get userData() {
536
+ return this._userData;
537
+ }
538
+ protected set userData(value: IUserData | undefined) {
539
+ this._userData = value;
540
+ }
517
541
 
518
542
  /**
519
543
  * Response token header field name
520
544
  */
521
- headerTokenField = 'SmartERPRefreshToken';
545
+ readonly headerTokenField = 'SmartERPRefreshToken';
546
+
547
+ /**
548
+ * Serverside device id encrypted field name
549
+ */
550
+ protected readonly serversideDeviceIdField = 'SmartERPServersideDeviceId';
522
551
 
523
552
  // IP detect ready callbacks
524
553
  private ipDetectCallbacks?: IDetectIPCallback[];
@@ -555,7 +584,13 @@ export abstract class CoreApp<
555
584
  /**
556
585
  * Device id field name
557
586
  */
558
- protected deviceIdField: string = 'SmartERPDeviceId';
587
+ protected readonly deviceIdField: string = 'SmartERPDeviceId';
588
+
589
+ /**
590
+ * Device id update time field name
591
+ */
592
+ protected readonly deviceIdUpdateTimeField: string =
593
+ 'SmartERPDeviceIdUpdateTime';
559
594
 
560
595
  /**
561
596
  * Init call Api URL
@@ -645,15 +680,43 @@ export abstract class CoreApp<
645
680
  return await this.api.put<InitCallResult>(this.initCallApi, data);
646
681
  }
647
682
 
683
+ /**
684
+ * Get device last updte miliseconds
685
+ * @returns Miliseconds
686
+ */
687
+ protected getDeviceUpdateTime() {
688
+ return StorageUtils.getLocalData(this.deviceIdUpdateTimeField, 0);
689
+ }
690
+
648
691
  /**
649
692
  * Init call
650
693
  * @param callback Callback
651
694
  * @returns Result
652
695
  */
653
696
  async initCall(callback?: (result: boolean) => void) {
697
+ // Device
698
+ let hasDeviceId = this.deviceId != null && this.deviceId !== '';
699
+ const timestamp = new Date().getTime();
700
+ const lastTimestamp = this.getDeviceUpdateTime();
701
+ if (
702
+ hasDeviceId &&
703
+ lastTimestamp > 0 &&
704
+ timestamp - lastTimestamp <= 1296000000
705
+ ) {
706
+ // When deviceId is there and less than 15 days = 1000 * 60 * 60 * 24 * 15
707
+ if (callback) callback(true);
708
+ return;
709
+ }
710
+
711
+ // Serverside encrypted device id
712
+ const identifier = StorageUtils.getLocalData<string>(
713
+ this.serversideDeviceIdField
714
+ );
715
+
654
716
  const data: InitCallDto = {
655
- timestamp: new Date().getTime(),
656
- deviceId: this.deviceId === '' ? undefined : this.deviceId
717
+ timestamp,
718
+ identifier,
719
+ deviceId: hasDeviceId ? this.deviceId : undefined
657
720
  };
658
721
  const result = await this.apiInitCall(data);
659
722
  if (result == null) {
@@ -713,6 +776,7 @@ export abstract class CoreApp<
713
776
  // Update device id and cache it
714
777
  this.deviceId = data.deviceId;
715
778
  StorageUtils.setLocalData(this.deviceIdField, this.deviceId);
779
+ StorageUtils.setLocalData(this.deviceIdUpdateTimeField, timestamp);
716
780
 
717
781
  // Current passphrase
718
782
  this.passphrase = passphrase;
@@ -1180,18 +1244,10 @@ export abstract class CoreApp<
1180
1244
  * Get cached token
1181
1245
  * @returns Cached token
1182
1246
  */
1183
- getCacheToken(): string | null {
1247
+ getCacheToken(): string | undefined {
1184
1248
  // Temp refresh token
1185
1249
  if (this.cachedRefreshToken) return this.cachedRefreshToken;
1186
-
1187
- const refreshToken = StorageUtils.getLocalData<string>(
1188
- this.headerTokenField,
1189
- ''
1190
- );
1191
-
1192
- if (refreshToken === '') return null;
1193
-
1194
- return refreshToken;
1250
+ return StorageUtils.getLocalData<string>(this.headerTokenField);
1195
1251
  }
1196
1252
 
1197
1253
  /**
@@ -1321,7 +1377,7 @@ export abstract class CoreApp<
1321
1377
  * @param props Props
1322
1378
  */
1323
1379
  async refreshToken<D extends {} = {}>(props?: RefreshTokenProps<D>) {
1324
- if (props && props.callback) props.callback(true);
1380
+ if (props && props.callback) props.callback(true, undefined);
1325
1381
  return true;
1326
1382
  }
1327
1383
 
@@ -1350,15 +1406,29 @@ export abstract class CoreApp<
1350
1406
  this.toLoginPage();
1351
1407
  }
1352
1408
 
1409
+ /**
1410
+ * Get organization list
1411
+ * @param items Max items
1412
+ * @param serviceId Service id
1413
+ * @returns Result
1414
+ */
1415
+ async orgList(items?: number, serviceId?: number) {
1416
+ return await this.api.post<IdLabelDto[]>(
1417
+ 'Organization/List',
1418
+ {
1419
+ items,
1420
+ serviceId
1421
+ },
1422
+ { defaultValue: [], showLoading: false }
1423
+ );
1424
+ }
1425
+
1353
1426
  /**
1354
1427
  * Switch organization
1355
- * @param apiOrOrg API URL or organization id
1428
+ * @param id Organization id
1356
1429
  */
1357
- async switchOrg(apiOrOrg: string | number) {
1358
- const api =
1359
- typeof apiOrOrg === 'number'
1360
- ? `Organization/Switch/${apiOrOrg}`
1361
- : apiOrOrg;
1430
+ async switchOrg(id: number) {
1431
+ const api = `Organization/Switch/${id}`;
1362
1432
  const result = await this.api.put<boolean>(api);
1363
1433
  if (result) return await this.refreshToken();
1364
1434
  return result;
@@ -1416,6 +1486,9 @@ export abstract class CoreApp<
1416
1486
  userLogin(user: IUserData, refreshToken: string, keep?: boolean) {
1417
1487
  this.userData = user;
1418
1488
 
1489
+ // Cache the encrypted serverside device id
1490
+ StorageUtils.setLocalData(this.serversideDeviceIdField, user.deviceId);
1491
+
1419
1492
  if (keep) {
1420
1493
  this.authorize(user.token, refreshToken);
1421
1494
  } else {
@@ -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
  */