@etsoo/react 1.3.42 → 1.3.46
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.
- package/lib/app/RefreshTokenRQ.d.ts +4 -0
- package/lib/app/ServiceApp.d.ts +2 -1
- package/lib/app/ServiceApp.js +88 -41
- package/package.json +8 -8
- package/src/app/RefreshTokenRQ.ts +5 -0
- package/src/app/ServiceApp.ts +124 -42
package/lib/app/ServiceApp.d.ts
CHANGED
|
@@ -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
|
package/lib/app/ServiceApp.js
CHANGED
|
@@ -46,7 +46,7 @@ export class ServiceApp extends ReactApp {
|
|
|
46
46
|
*/
|
|
47
47
|
async refreshToken(props) {
|
|
48
48
|
// Destruct
|
|
49
|
-
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 : {};
|
|
50
50
|
// Token
|
|
51
51
|
const token = this.getCacheToken();
|
|
52
52
|
if (token == null || token === '') {
|
|
@@ -71,64 +71,111 @@ export class ServiceApp extends ReactApp {
|
|
|
71
71
|
return false;
|
|
72
72
|
}
|
|
73
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
|
+
};
|
|
74
112
|
// Call API
|
|
75
113
|
const result = await this.coreApi.put('Auth/RefreshToken', rq, payload);
|
|
76
114
|
if (result == null)
|
|
77
115
|
return false;
|
|
78
116
|
if (!result.ok) {
|
|
79
|
-
if (
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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;
|
|
102
146
|
}
|
|
103
|
-
});
|
|
104
|
-
if (serviceResult == null)
|
|
105
|
-
return false;
|
|
106
|
-
if (!serviceResult.ok) {
|
|
107
|
-
if (callback)
|
|
108
|
-
callback(serviceResult);
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
if (serviceResult.data == null) {
|
|
112
147
|
if (callback)
|
|
113
|
-
callback(
|
|
148
|
+
callback(result);
|
|
114
149
|
return false;
|
|
115
150
|
}
|
|
116
|
-
|
|
117
|
-
|
|
151
|
+
return await success(result, callback);
|
|
152
|
+
}
|
|
153
|
+
loginFailed() {
|
|
154
|
+
this.userUnauthorized();
|
|
155
|
+
this.toLoginPage();
|
|
118
156
|
}
|
|
119
157
|
/**
|
|
120
158
|
* Try login
|
|
121
159
|
*/
|
|
122
|
-
async tryLogin() {
|
|
160
|
+
async tryLogin(data) {
|
|
123
161
|
// Reset user state
|
|
124
|
-
const result = await super.tryLogin();
|
|
162
|
+
const result = await super.tryLogin(data);
|
|
125
163
|
if (!result)
|
|
126
164
|
return false;
|
|
127
165
|
// Refresh token
|
|
128
166
|
return await this.refreshToken({
|
|
129
|
-
callback: (
|
|
130
|
-
this.
|
|
131
|
-
|
|
167
|
+
callback: (result) => {
|
|
168
|
+
const message = this.formatRefreshTokenResult(result);
|
|
169
|
+
if (message == null) {
|
|
170
|
+
this.loginFailed();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
this.notifier.alert(message, () => {
|
|
174
|
+
this.loginFailed();
|
|
175
|
+
});
|
|
176
|
+
},
|
|
177
|
+
data,
|
|
178
|
+
relogin: true
|
|
132
179
|
});
|
|
133
180
|
}
|
|
134
181
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/react",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.46",
|
|
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.
|
|
53
|
+
"@etsoo/appscript": "^1.1.65",
|
|
54
54
|
"@etsoo/notificationbase": "^1.0.94",
|
|
55
|
-
"@etsoo/shared": "^1.0.
|
|
56
|
-
"@mui/icons-material": "^5.2.
|
|
57
|
-
"@mui/material": "^5.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",
|
|
@@ -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.
|
|
85
|
-
"@typescript-eslint/parser": "^5.
|
|
84
|
+
"@typescript-eslint/eslint-plugin": "^5.6.0",
|
|
85
|
+
"@typescript-eslint/parser": "^5.6.0",
|
|
86
86
|
"eslint": "^8.4.0",
|
|
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
90
|
"jest": "^27.4.3",
|
|
91
91
|
"react-test-renderer": "^17.0.2",
|
|
92
|
-
"ts-jest": "^27.0
|
|
92
|
+
"ts-jest": "^27.1.0",
|
|
93
93
|
"typescript": "^4.5.2"
|
|
94
94
|
}
|
|
95
95
|
}
|
package/src/app/ServiceApp.ts
CHANGED
|
@@ -2,7 +2,8 @@ import {
|
|
|
2
2
|
createClient,
|
|
3
3
|
IApi,
|
|
4
4
|
IApiPayload,
|
|
5
|
-
RefreshTokenProps
|
|
5
|
+
RefreshTokenProps,
|
|
6
|
+
RefreshTokenResult
|
|
6
7
|
} from '@etsoo/appscript';
|
|
7
8
|
import { DomUtils } from '@etsoo/shared';
|
|
8
9
|
import { CoreConstants } from './CoreConstants';
|
|
@@ -78,7 +79,12 @@ export class ServiceApp<
|
|
|
78
79
|
props?: RefreshTokenProps<D>
|
|
79
80
|
) {
|
|
80
81
|
// Destruct
|
|
81
|
-
const {
|
|
82
|
+
const {
|
|
83
|
+
callback,
|
|
84
|
+
data,
|
|
85
|
+
relogin = false,
|
|
86
|
+
showLoading = false
|
|
87
|
+
} = props ?? {};
|
|
82
88
|
|
|
83
89
|
// Token
|
|
84
90
|
const token = this.getCacheToken();
|
|
@@ -106,6 +112,55 @@ export class ServiceApp<
|
|
|
106
112
|
}
|
|
107
113
|
};
|
|
108
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
|
+
|
|
109
164
|
// Call API
|
|
110
165
|
const result = await this.coreApi.put<SmartERPLoginResult>(
|
|
111
166
|
'Auth/RefreshToken',
|
|
@@ -115,67 +170,94 @@ export class ServiceApp<
|
|
|
115
170
|
if (result == null) return false;
|
|
116
171
|
|
|
117
172
|
if (!result.ok) {
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
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
|
+
}
|
|
121
184
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
185
|
+
// Set password for the action
|
|
186
|
+
rq.pwd = this.encrypt(
|
|
187
|
+
pwd,
|
|
188
|
+
this.settings.serviceId.toString()
|
|
189
|
+
);
|
|
128
190
|
|
|
129
|
-
|
|
130
|
-
|
|
191
|
+
// Submit again
|
|
192
|
+
const result = await this.api.put<SmartERPLoginResult>(
|
|
193
|
+
'Auth/RefreshToken',
|
|
194
|
+
data,
|
|
195
|
+
payload
|
|
196
|
+
);
|
|
131
197
|
|
|
132
|
-
|
|
133
|
-
const serviceResult = await this.api.put<ServiceLoginResult>(
|
|
134
|
-
'Auth/ExchangeToken',
|
|
135
|
-
{
|
|
136
|
-
token: userData.token
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
showLoading,
|
|
140
|
-
onError: (error) => {
|
|
141
|
-
if (callback) callback(error);
|
|
198
|
+
if (result == null) return;
|
|
142
199
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
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
|
+
}
|
|
148
213
|
|
|
149
|
-
|
|
214
|
+
// Popup message
|
|
215
|
+
this.alertResult(result);
|
|
216
|
+
return false;
|
|
217
|
+
},
|
|
218
|
+
labels.login,
|
|
219
|
+
{ type: 'password' }
|
|
220
|
+
);
|
|
150
221
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
222
|
+
// Fake truth to avoid reloading
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
155
225
|
|
|
156
|
-
|
|
157
|
-
if (callback) callback(this.get('noData')!);
|
|
226
|
+
if (callback) callback(result);
|
|
158
227
|
return false;
|
|
159
228
|
}
|
|
160
229
|
|
|
161
|
-
|
|
230
|
+
return await success(result, callback);
|
|
231
|
+
}
|
|
162
232
|
|
|
163
|
-
|
|
233
|
+
private loginFailed() {
|
|
234
|
+
this.userUnauthorized();
|
|
235
|
+
this.toLoginPage();
|
|
164
236
|
}
|
|
165
237
|
|
|
166
238
|
/**
|
|
167
239
|
* Try login
|
|
168
240
|
*/
|
|
169
|
-
override async tryLogin() {
|
|
241
|
+
override async tryLogin<D extends {} = {}>(data?: D) {
|
|
170
242
|
// Reset user state
|
|
171
|
-
const result = await super.tryLogin();
|
|
243
|
+
const result = await super.tryLogin(data);
|
|
172
244
|
if (!result) return false;
|
|
173
245
|
|
|
174
246
|
// Refresh token
|
|
175
247
|
return await this.refreshToken({
|
|
176
|
-
callback: (
|
|
177
|
-
this.
|
|
178
|
-
|
|
248
|
+
callback: (result) => {
|
|
249
|
+
const message = this.formatRefreshTokenResult(result);
|
|
250
|
+
if (message == null) {
|
|
251
|
+
this.loginFailed();
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
this.notifier.alert(message, () => {
|
|
256
|
+
this.loginFailed();
|
|
257
|
+
});
|
|
258
|
+
},
|
|
259
|
+
data,
|
|
260
|
+
relogin: true
|
|
179
261
|
});
|
|
180
262
|
}
|
|
181
263
|
|