@etsoo/react 1.3.43 → 1.3.47

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.
@@ -2,6 +2,10 @@
2
2
  * Refresh token request data
3
3
  */
4
4
  export declare type RefreshTokenRQ = {
5
+ /**
6
+ * Login password
7
+ */
8
+ pwd?: string;
5
9
  /**
6
10
  * Service id
7
11
  */
@@ -35,10 +35,11 @@ export declare class ServiceApp<P extends IServicePageData = IServicePageData, U
35
35
  * @param props Props
36
36
  */
37
37
  refreshToken<D = RefreshTokenRQ>(props?: RefreshTokenProps<D>): Promise<boolean>;
38
+ private loginFailed;
38
39
  /**
39
40
  * Try login
40
41
  */
41
- tryLogin(): Promise<boolean>;
42
+ tryLogin<D extends {} = {}>(data?: D): Promise<boolean>;
42
43
  /**
43
44
  * User login extended
44
45
  * @param user New user
@@ -1,5 +1,4 @@
1
- import { ActionResultError, createClient } from '@etsoo/appscript';
2
- import { ApiDataError } from '@etsoo/restclient';
1
+ import { createClient } from '@etsoo/appscript';
3
2
  import { DomUtils } from '@etsoo/shared';
4
3
  import { CoreConstants } from './CoreConstants';
5
4
  import { ReactApp } from './ReactApp';
@@ -47,7 +46,7 @@ export class ServiceApp extends ReactApp {
47
46
  */
48
47
  async refreshToken(props) {
49
48
  // Destruct
50
- const { callback, data, showLoading = false } = props !== null && props !== void 0 ? props : {};
49
+ const { callback, data, relogin = false, showLoading = false } = props !== null && props !== void 0 ? props : {};
51
50
  // Token
52
51
  const token = this.getCacheToken();
53
52
  if (token == null || token === '') {
@@ -72,76 +71,111 @@ export class ServiceApp extends ReactApp {
72
71
  return false;
73
72
  }
74
73
  };
74
+ // Success callback
75
+ const success = async (result, failCallback) => {
76
+ // Token
77
+ const refreshToken = this.getResponseToken(payload.response);
78
+ if (refreshToken == null || result.data == null) {
79
+ if (failCallback)
80
+ failCallback(this.get('noData'));
81
+ return false;
82
+ }
83
+ // User data
84
+ const userData = result.data;
85
+ // Use core system access token to service api to exchange service access token
86
+ const serviceResult = await this.api.put('Auth/ExchangeToken', {
87
+ token: userData.token
88
+ }, {
89
+ showLoading,
90
+ onError: (error) => {
91
+ if (failCallback)
92
+ failCallback(error);
93
+ // Prevent further processing
94
+ return false;
95
+ }
96
+ });
97
+ if (serviceResult == null)
98
+ return false;
99
+ if (!serviceResult.ok) {
100
+ if (failCallback)
101
+ failCallback(serviceResult);
102
+ return false;
103
+ }
104
+ if (serviceResult.data == null) {
105
+ if (failCallback)
106
+ failCallback(this.get('noData'));
107
+ return false;
108
+ }
109
+ this.userLoginEx(serviceResult.data, refreshToken, userData);
110
+ return true;
111
+ };
75
112
  // Call API
76
113
  const result = await this.coreApi.put('Auth/RefreshToken', rq, payload);
77
114
  if (result == null)
78
115
  return false;
79
116
  if (!result.ok) {
80
- if (callback)
81
- callback(result);
82
- return false;
83
- }
84
- // Token
85
- const refreshToken = this.getResponseToken(payload.response);
86
- if (refreshToken == null || result.data == null) {
87
- if (callback)
88
- callback(this.get('noData'));
89
- return false;
90
- }
91
- // User data
92
- const userData = result.data;
93
- // Use core system access token to service api to exchange service access token
94
- const serviceResult = await this.api.put('Auth/ExchangeToken', {
95
- token: userData.token
96
- }, {
97
- showLoading,
98
- onError: (error) => {
99
- if (callback)
100
- callback(error);
101
- // Prevent further processing
102
- return false;
117
+ if (result.type === 'TokenExpired' && relogin) {
118
+ // Try login
119
+ // Dialog to receive password
120
+ var labels = this.getLabels('reloginTip', 'login');
121
+ this.notifier.prompt(labels.reloginTip, async (pwd) => {
122
+ if (pwd == null) {
123
+ this.toLoginPage();
124
+ return;
125
+ }
126
+ // Set password for the action
127
+ rq.pwd = this.encrypt(pwd, this.settings.serviceId.toString());
128
+ // Submit again
129
+ const result = await this.api.put('Auth/RefreshToken', data, payload);
130
+ if (result == null)
131
+ return;
132
+ if (result.ok) {
133
+ await success(result, (loginResult) => {
134
+ const message = this.formatRefreshTokenResult(loginResult);
135
+ if (message)
136
+ this.notifier.alert(message);
137
+ });
138
+ return;
139
+ }
140
+ // Popup message
141
+ this.alertResult(result);
142
+ return false;
143
+ }, labels.login, { type: 'password' });
144
+ // Fake truth to avoid reloading
145
+ return true;
103
146
  }
104
- });
105
- if (serviceResult == null)
106
- return false;
107
- if (!serviceResult.ok) {
108
147
  if (callback)
109
- callback(serviceResult);
110
- return false;
111
- }
112
- if (serviceResult.data == null) {
113
- if (callback)
114
- callback(this.get('noData'));
148
+ callback(result);
115
149
  return false;
116
150
  }
117
- this.userLoginEx(serviceResult.data, refreshToken, userData);
118
- return true;
151
+ return await success(result, callback);
152
+ }
153
+ loginFailed() {
154
+ this.userUnauthorized();
155
+ this.toLoginPage();
119
156
  }
120
157
  /**
121
158
  * Try login
122
159
  */
123
- async tryLogin() {
160
+ async tryLogin(data) {
124
161
  // Reset user state
125
- const result = await super.tryLogin();
162
+ const result = await super.tryLogin(data);
126
163
  if (!result)
127
164
  return false;
128
165
  // Refresh token
129
166
  return await this.refreshToken({
130
167
  callback: (result) => {
131
- if (typeof result === 'boolean') {
132
- this.toLoginPage();
168
+ const message = this.formatRefreshTokenResult(result);
169
+ if (message == null) {
170
+ this.loginFailed();
133
171
  return;
134
172
  }
135
- const message = result instanceof ApiDataError
136
- ? this.formatError(result)
137
- : typeof result !== 'string'
138
- ? ActionResultError.format(result)
139
- : result;
140
173
  this.notifier.alert(message, () => {
141
- this.toLoginPage();
174
+ this.loginFailed();
142
175
  });
143
176
  },
144
- showLoading: true
177
+ data,
178
+ relogin: true
145
179
  });
146
180
  }
147
181
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/react",
3
- "version": "1.3.43",
3
+ "version": "1.3.47",
4
4
  "description": "TypeScript ReactJs framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -50,11 +50,11 @@
50
50
  "@emotion/react": "^11.7.0",
51
51
  "@emotion/style": "^0.8.0",
52
52
  "@emotion/styled": "^11.6.0",
53
- "@etsoo/appscript": "^1.1.56",
53
+ "@etsoo/appscript": "^1.1.70",
54
54
  "@etsoo/notificationbase": "^1.0.94",
55
- "@etsoo/shared": "^1.0.75",
56
- "@mui/icons-material": "^5.2.0",
57
- "@mui/material": "^5.2.2",
55
+ "@etsoo/shared": "^1.0.76",
56
+ "@mui/icons-material": "^5.2.1",
57
+ "@mui/material": "^5.2.3",
58
58
  "@reach/router": "^1.3.4",
59
59
  "@types/pica": "^5.1.3",
60
60
  "@types/pulltorefreshjs": "^0.1.5",
@@ -64,7 +64,7 @@
64
64
  "@types/react-dom": "^17.0.11",
65
65
  "@types/react-input-mask": "^3.0.1",
66
66
  "@types/react-window": "^1.8.5",
67
- "pica": "^8.0.0",
67
+ "pica": "^9.0.0",
68
68
  "pulltorefreshjs": "^0.1.22",
69
69
  "react": "^17.0.2",
70
70
  "react-avatar-editor": "^12.0.0",
@@ -81,15 +81,15 @@
81
81
  "@babel/runtime-corejs3": "^7.16.3",
82
82
  "@types/jest": "^27.0.3",
83
83
  "@types/react-test-renderer": "^17.0.1",
84
- "@typescript-eslint/eslint-plugin": "^5.5.0",
85
- "@typescript-eslint/parser": "^5.5.0",
86
- "eslint": "^8.4.0",
84
+ "@typescript-eslint/eslint-plugin": "^5.6.0",
85
+ "@typescript-eslint/parser": "^5.6.0",
86
+ "eslint": "^8.4.1",
87
87
  "eslint-config-airbnb-base": "^15.0.0",
88
88
  "eslint-plugin-import": "^2.25.3",
89
89
  "eslint-plugin-react": "^7.27.1",
90
- "jest": "^27.4.3",
90
+ "jest": "^27.4.4",
91
91
  "react-test-renderer": "^17.0.2",
92
- "ts-jest": "^27.0.7",
93
- "typescript": "^4.5.2"
92
+ "ts-jest": "^27.1.1",
93
+ "typescript": "^4.5.3"
94
94
  }
95
95
  }
@@ -2,6 +2,11 @@
2
2
  * Refresh token request data
3
3
  */
4
4
  export type RefreshTokenRQ = {
5
+ /**
6
+ * Login password
7
+ */
8
+ pwd?: string;
9
+
5
10
  /**
6
11
  * Service id
7
12
  */
@@ -1,11 +1,10 @@
1
1
  import {
2
- ActionResultError,
3
2
  createClient,
4
3
  IApi,
5
4
  IApiPayload,
6
- RefreshTokenProps
5
+ RefreshTokenProps,
6
+ RefreshTokenResult
7
7
  } from '@etsoo/appscript';
8
- import { ApiDataError } from '@etsoo/restclient';
9
8
  import { DomUtils } from '@etsoo/shared';
10
9
  import { CoreConstants } from './CoreConstants';
11
10
  import { IServiceAppSettings } from './IServiceAppSettings';
@@ -80,7 +79,12 @@ export class ServiceApp<
80
79
  props?: RefreshTokenProps<D>
81
80
  ) {
82
81
  // Destruct
83
- const { callback, data, showLoading = false } = props ?? {};
82
+ const {
83
+ callback,
84
+ data,
85
+ relogin = false,
86
+ showLoading = false
87
+ } = props ?? {};
84
88
 
85
89
  // Token
86
90
  const token = this.getCacheToken();
@@ -108,6 +112,55 @@ export class ServiceApp<
108
112
  }
109
113
  };
110
114
 
115
+ // Success callback
116
+ const success = async (
117
+ result: SmartERPLoginResult,
118
+ failCallback?: (result: RefreshTokenResult) => void
119
+ ) => {
120
+ // Token
121
+ const refreshToken = this.getResponseToken(payload.response);
122
+ if (refreshToken == null || result.data == null) {
123
+ if (failCallback) failCallback(this.get('noData')!);
124
+ return false;
125
+ }
126
+
127
+ // User data
128
+ const userData = result.data;
129
+
130
+ // Use core system access token to service api to exchange service access token
131
+ const serviceResult = await this.api.put<ServiceLoginResult>(
132
+ 'Auth/ExchangeToken',
133
+ {
134
+ token: userData.token
135
+ },
136
+ {
137
+ showLoading,
138
+ onError: (error) => {
139
+ if (failCallback) failCallback(error);
140
+
141
+ // Prevent further processing
142
+ return false;
143
+ }
144
+ }
145
+ );
146
+
147
+ if (serviceResult == null) return false;
148
+
149
+ if (!serviceResult.ok) {
150
+ if (failCallback) failCallback(serviceResult);
151
+ return false;
152
+ }
153
+
154
+ if (serviceResult.data == null) {
155
+ if (failCallback) failCallback(this.get('noData')!);
156
+ return false;
157
+ }
158
+
159
+ this.userLoginEx(serviceResult.data, refreshToken, userData);
160
+
161
+ return true;
162
+ };
163
+
111
164
  // Call API
112
165
  const result = await this.coreApi.put<SmartERPLoginResult>(
113
166
  'Auth/RefreshToken',
@@ -117,82 +170,94 @@ export class ServiceApp<
117
170
  if (result == null) return false;
118
171
 
119
172
  if (!result.ok) {
120
- if (callback) callback(result);
121
- return false;
122
- }
173
+ if (result.type === 'TokenExpired' && relogin) {
174
+ // Try login
175
+ // Dialog to receive password
176
+ var labels = this.getLabels('reloginTip', 'login');
177
+ this.notifier.prompt(
178
+ labels.reloginTip,
179
+ async (pwd) => {
180
+ if (pwd == null) {
181
+ this.toLoginPage();
182
+ return;
183
+ }
123
184
 
124
- // Token
125
- const refreshToken = this.getResponseToken(payload.response);
126
- if (refreshToken == null || result.data == null) {
127
- if (callback) callback(this.get('noData')!);
128
- return false;
129
- }
185
+ // Set password for the action
186
+ rq.pwd = this.encrypt(
187
+ pwd,
188
+ this.settings.serviceId.toString()
189
+ );
130
190
 
131
- // User data
132
- const userData = result.data;
191
+ // Submit again
192
+ const result = await this.api.put<SmartERPLoginResult>(
193
+ 'Auth/RefreshToken',
194
+ data,
195
+ payload
196
+ );
133
197
 
134
- // Use core system access token to service api to exchange service access token
135
- const serviceResult = await this.api.put<ServiceLoginResult>(
136
- 'Auth/ExchangeToken',
137
- {
138
- token: userData.token
139
- },
140
- {
141
- showLoading,
142
- onError: (error) => {
143
- if (callback) callback(error);
198
+ if (result == null) return;
144
199
 
145
- // Prevent further processing
146
- return false;
147
- }
148
- }
149
- );
200
+ if (result.ok) {
201
+ await success(
202
+ result,
203
+ (loginResult: RefreshTokenResult) => {
204
+ const message =
205
+ this.formatRefreshTokenResult(
206
+ loginResult
207
+ );
208
+ if (message) this.notifier.alert(message);
209
+ }
210
+ );
211
+ return;
212
+ }
150
213
 
151
- if (serviceResult == null) return false;
214
+ // Popup message
215
+ this.alertResult(result);
216
+ return false;
217
+ },
218
+ labels.login,
219
+ { type: 'password' }
220
+ );
152
221
 
153
- if (!serviceResult.ok) {
154
- if (callback) callback(serviceResult);
155
- return false;
156
- }
222
+ // Fake truth to avoid reloading
223
+ return true;
224
+ }
157
225
 
158
- if (serviceResult.data == null) {
159
- if (callback) callback(this.get('noData')!);
226
+ if (callback) callback(result);
160
227
  return false;
161
228
  }
162
229
 
163
- this.userLoginEx(serviceResult.data, refreshToken, userData);
230
+ return await success(result, callback);
231
+ }
164
232
 
165
- return true;
233
+ private loginFailed() {
234
+ this.userUnauthorized();
235
+ this.toLoginPage();
166
236
  }
167
237
 
168
238
  /**
169
239
  * Try login
170
240
  */
171
- override async tryLogin() {
241
+ override async tryLogin<D extends {} = {}>(data?: D) {
172
242
  // Reset user state
173
- const result = await super.tryLogin();
243
+ const result = await super.tryLogin(data);
174
244
  if (!result) return false;
175
245
 
176
246
  // Refresh token
177
247
  return await this.refreshToken({
178
248
  callback: (result) => {
179
- if (typeof result === 'boolean') {
180
- this.toLoginPage();
249
+ const message = this.formatRefreshTokenResult(result);
250
+ if (message == null) {
251
+ this.loginFailed();
181
252
  return;
182
253
  }
183
254
 
184
- const message =
185
- result instanceof ApiDataError
186
- ? this.formatError(result)
187
- : typeof result !== 'string'
188
- ? ActionResultError.format(result)
189
- : result;
190
-
191
255
  this.notifier.alert(message, () => {
192
- this.toLoginPage();
256
+ this.loginFailed();
193
257
  });
194
258
  },
195
- showLoading: true
259
+ data,
260
+ relogin: true
196
261
  });
197
262
  }
198
263