@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.
- package/lib/app/RefreshTokenRQ.d.ts +4 -0
- package/lib/app/ServiceApp.d.ts +2 -1
- package/lib/app/ServiceApp.js +83 -49
- package/package.json +12 -12
- package/src/app/RefreshTokenRQ.ts +5 -0
- package/src/app/ServiceApp.ts +117 -52
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
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
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 (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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(
|
|
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
|
-
|
|
118
|
-
|
|
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
|
-
|
|
132
|
-
|
|
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.
|
|
174
|
+
this.loginFailed();
|
|
142
175
|
});
|
|
143
176
|
},
|
|
144
|
-
|
|
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.
|
|
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.
|
|
53
|
+
"@etsoo/appscript": "^1.1.70",
|
|
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",
|
|
@@ -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": "^
|
|
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.
|
|
85
|
-
"@typescript-eslint/parser": "^5.
|
|
86
|
-
"eslint": "^8.4.
|
|
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.
|
|
90
|
+
"jest": "^27.4.4",
|
|
91
91
|
"react-test-renderer": "^17.0.2",
|
|
92
|
-
"ts-jest": "^27.
|
|
93
|
-
"typescript": "^4.5.
|
|
92
|
+
"ts-jest": "^27.1.1",
|
|
93
|
+
"typescript": "^4.5.3"
|
|
94
94
|
}
|
|
95
95
|
}
|
package/src/app/ServiceApp.ts
CHANGED
|
@@ -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 {
|
|
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 (
|
|
121
|
-
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
185
|
+
// Set password for the action
|
|
186
|
+
rq.pwd = this.encrypt(
|
|
187
|
+
pwd,
|
|
188
|
+
this.settings.serviceId.toString()
|
|
189
|
+
);
|
|
130
190
|
|
|
131
|
-
|
|
132
|
-
|
|
191
|
+
// Submit again
|
|
192
|
+
const result = await this.api.put<SmartERPLoginResult>(
|
|
193
|
+
'Auth/RefreshToken',
|
|
194
|
+
data,
|
|
195
|
+
payload
|
|
196
|
+
);
|
|
133
197
|
|
|
134
|
-
|
|
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
|
-
|
|
146
|
-
|
|
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
|
-
|
|
214
|
+
// Popup message
|
|
215
|
+
this.alertResult(result);
|
|
216
|
+
return false;
|
|
217
|
+
},
|
|
218
|
+
labels.login,
|
|
219
|
+
{ type: 'password' }
|
|
220
|
+
);
|
|
152
221
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
}
|
|
222
|
+
// Fake truth to avoid reloading
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
157
225
|
|
|
158
|
-
|
|
159
|
-
if (callback) callback(this.get('noData')!);
|
|
226
|
+
if (callback) callback(result);
|
|
160
227
|
return false;
|
|
161
228
|
}
|
|
162
229
|
|
|
163
|
-
|
|
230
|
+
return await success(result, callback);
|
|
231
|
+
}
|
|
164
232
|
|
|
165
|
-
|
|
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
|
-
|
|
180
|
-
|
|
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.
|
|
256
|
+
this.loginFailed();
|
|
193
257
|
});
|
|
194
258
|
},
|
|
195
|
-
|
|
259
|
+
data,
|
|
260
|
+
relogin: true
|
|
196
261
|
});
|
|
197
262
|
}
|
|
198
263
|
|