aio-login 8.0.1 → 8.0.3
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/index.d.ts +0 -1
- package/index.js +343 -1
- package/package.json +1 -1
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1 +1,343 @@
|
|
|
1
|
-
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { createElement as _createElement } from "react";
|
|
11
|
+
import { Fragment as _Fragment, jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
import { useEffect, useRef, useState } from "react";
|
|
13
|
+
import AIOInput from "aio-input";
|
|
14
|
+
import { AddToAttrs, Storage } from "aio-utils";
|
|
15
|
+
import { Loading, Alert } from "aio-popup";
|
|
16
|
+
import axios from "axios";
|
|
17
|
+
import './index.css';
|
|
18
|
+
export function AIOLogin_updateCatchedUser(loginId, newUser) {
|
|
19
|
+
const storage = new Storage('ai-login' + loginId);
|
|
20
|
+
const storedData = storage.load('data');
|
|
21
|
+
if (!storedData) {
|
|
22
|
+
return newUser;
|
|
23
|
+
}
|
|
24
|
+
const newStoredData = Object.assign(Object.assign({}, storedData), { user: newUser });
|
|
25
|
+
return storage.save('data', newStoredData);
|
|
26
|
+
}
|
|
27
|
+
const AILogin = (props) => {
|
|
28
|
+
const { translate = () => { }, otpLength = 4 } = props;
|
|
29
|
+
const { validation = () => { return undefined; } } = props;
|
|
30
|
+
const [data, setData] = useState();
|
|
31
|
+
const [storage] = useState(new Storage('ai-login' + props.id));
|
|
32
|
+
const [model, setModel] = useState(getModel);
|
|
33
|
+
const [loading] = useState(new Loading());
|
|
34
|
+
const [submitDisabled, setSubmitDisabled] = useState(false);
|
|
35
|
+
const modelRef = useRef(model);
|
|
36
|
+
modelRef.current = model;
|
|
37
|
+
console.log(modelRef.current);
|
|
38
|
+
const [mode, setMode] = useState(getMode());
|
|
39
|
+
function getModeKey() {
|
|
40
|
+
if (props.mode) {
|
|
41
|
+
return props.mode;
|
|
42
|
+
}
|
|
43
|
+
if (props.userpass) {
|
|
44
|
+
return 'userpass';
|
|
45
|
+
}
|
|
46
|
+
if (props.otp) {
|
|
47
|
+
return 'otpnumber';
|
|
48
|
+
}
|
|
49
|
+
return 'userpass';
|
|
50
|
+
}
|
|
51
|
+
function getMode(mode) {
|
|
52
|
+
let res = { inputs: () => null, key: mode || getModeKey(), title: null, submitText: '', shouldReturnsUserAndToken: false };
|
|
53
|
+
if (res.key === 'userpass') {
|
|
54
|
+
res.inputs = () => {
|
|
55
|
+
return (_jsxs(_Fragment, { children: [getInput({ mode: res.key, field: 'username', type: 'text' }), getInput({ mode: res.key, field: 'password', type: 'text' })] }));
|
|
56
|
+
};
|
|
57
|
+
res.shouldReturnsUserAndToken = true;
|
|
58
|
+
}
|
|
59
|
+
else if (res.key === 'register') {
|
|
60
|
+
if (props.register) {
|
|
61
|
+
const inputs = (props.register.inputs || (() => []))(modelRef.current) || [];
|
|
62
|
+
res.inputs = () => {
|
|
63
|
+
return (_jsxs(_Fragment, { children: [getInput({ mode: res.key, field: 'username', type: 'text' }), getInput({ mode: res.key, field: 'password', type: 'password' }), getInput({ mode: res.key, field: 'repassword', type: 'password' }), inputs.map((input) => getInput({ mode: res.key, field: input.field, type: input.type, inputProps: input }))] }));
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (res.key === 'otpnumber') {
|
|
68
|
+
res.inputs = () => getInput({ mode: res.key, field: 'otpnumber', type: 'text' });
|
|
69
|
+
}
|
|
70
|
+
else if (res.key === 'otpcode') {
|
|
71
|
+
res.inputs = () => getInput({ mode: res.key, field: 'otpcode', type: 'text' });
|
|
72
|
+
res.shouldReturnsUserAndToken = true;
|
|
73
|
+
}
|
|
74
|
+
res.submitText = trans(res.key + 'Button');
|
|
75
|
+
res.title = _jsx("div", { className: "ai-login-title", children: trans(res.key + 'Title') });
|
|
76
|
+
return res;
|
|
77
|
+
}
|
|
78
|
+
function getInput(p) {
|
|
79
|
+
const inputProps = p.inputProps || {};
|
|
80
|
+
let model = modelRef.current;
|
|
81
|
+
if (p.mode === 'register') {
|
|
82
|
+
model = model.register;
|
|
83
|
+
}
|
|
84
|
+
const { maxLength = { otpnumber: 11, otpcode: otpLength }[p.mode], filter = p.mode === 'otpnumber' || p.mode === 'otpcode' ? ['number'] : undefined, preview = p.field === 'password', rtl = !!props.fa, label = props.label(p.field) } = inputProps;
|
|
85
|
+
const inputAttrs = Object.assign(Object.assign({}, inputProps), { 'aria-label': `aio-login-${p.field}` });
|
|
86
|
+
const onChange = (v) => {
|
|
87
|
+
let model = modelRef.current;
|
|
88
|
+
if (p.mode === 'register') {
|
|
89
|
+
setModel(Object.assign(Object.assign({}, model), { register: Object.assign(Object.assign({}, model.register), { [p.field]: v }) }));
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
setModel(Object.assign(Object.assign({}, model), { [p.field]: v }));
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
return (_createElement(AIOInput, Object.assign({}, inputProps, { maxLength, filter, preview, rtl, label, onChange, inputAttrs, key: `${p.mode}-${p.field}`, value: model[p.field], type: p.type })));
|
|
96
|
+
}
|
|
97
|
+
function getModel() {
|
|
98
|
+
var _a;
|
|
99
|
+
let model = { username: '', password: '', otpnumber: '', otpcode: '', register: { username: '', password: '', repassword: '' } };
|
|
100
|
+
if (!props.register) {
|
|
101
|
+
return model;
|
|
102
|
+
}
|
|
103
|
+
if ((_a = props.register) === null || _a === void 0 ? void 0 : _a.defaultValue) {
|
|
104
|
+
let register = {};
|
|
105
|
+
for (let prop in props.register.defaultValue) {
|
|
106
|
+
register[prop] = props.register.defaultValue[prop];
|
|
107
|
+
}
|
|
108
|
+
model.register = register;
|
|
109
|
+
}
|
|
110
|
+
return model;
|
|
111
|
+
}
|
|
112
|
+
const [waitingCheckToken, setWeightingCheckToken] = useState(true);
|
|
113
|
+
const [splashing, setSplashing] = useState(!!props.splash);
|
|
114
|
+
function trans(key) {
|
|
115
|
+
const dic = {
|
|
116
|
+
registerButton: { en: 'Register', fa: 'ثبت نام' },
|
|
117
|
+
userpassButton: { en: 'Login', fa: 'ورود' },
|
|
118
|
+
otpnumberButton: { en: 'Send Number', fa: 'ارسال شماره همراه' },
|
|
119
|
+
otpcodeButton: { en: 'Login', fa: 'ورود' },
|
|
120
|
+
registerTitle: { en: 'Register', fa: 'ثبت نام' },
|
|
121
|
+
userpassTitle: { en: 'Login', fa: 'ورود' },
|
|
122
|
+
otpcodeTitle: { en: 'OTP Code', fa: 'کد یکبار مصرف' },
|
|
123
|
+
otpnumberTitle: { en: 'Phone Number', fa: 'شماره همراه' },
|
|
124
|
+
switchuserpass: { en: 'login by user name', fa: 'ورود با نام کاربری' },
|
|
125
|
+
switchregister: { en: 'Go To Register', fa: 'ثبت نام' },
|
|
126
|
+
switchotp: { en: 'login by otp', fa: 'ورود با رمز یکبار مصرف' },
|
|
127
|
+
repasswordMatch: { en: 'Password is not match with Re password', fa: 'رمز عبور با تکرار آن مطابقت ندارد' },
|
|
128
|
+
usernameRequired: { en: 'User Name is required', fa: 'نام کاربری ضروری است' },
|
|
129
|
+
passwordRequired: { en: 'password is required', fa: 'رمز عبور ضروری است' },
|
|
130
|
+
repasswordRequired: { en: 'Re Password is required', fa: 'تکرار رمز عبور ضروری است' },
|
|
131
|
+
otpnumberRequired: { en: 'Phone Number is required', fa: 'شماره همراه ضروری است' },
|
|
132
|
+
otpcodeLength: { en: `otp code should be ${otpLength} digit`, fa: `کد یکبار مصرف باید ${otpLength} رقم باشد` },
|
|
133
|
+
registerError: { en: 'Registeration failed', fa: 'ثبت نام با خطا روبرو شد' },
|
|
134
|
+
userpassError: { en: 'login by username failed', fa: 'ورود با نام کاربری با خطا روبرو شد' },
|
|
135
|
+
otpcodeError: { en: 'login by otp failed', fa: 'ورود با کد یکبار مصرف با خطا روبرو شد' },
|
|
136
|
+
otpnumberError: { en: 'send otp number for receive otp code failed', fa: 'ارسال شماره همراه برای دریافت کد یکبار مصرف با خطا روبرو شد' },
|
|
137
|
+
};
|
|
138
|
+
return props.fa ? dic[key].fa : translate(key) || dic[key].en;
|
|
139
|
+
}
|
|
140
|
+
function success_1(response, mode) {
|
|
141
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
142
|
+
if (!props.userpass) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const { onSuccess } = yield props.userpass.api(modelRef.current, 'userpass');
|
|
146
|
+
loading.show('login0');
|
|
147
|
+
const res = yield onSuccess(response);
|
|
148
|
+
loading.hide('login0');
|
|
149
|
+
if (typeof res !== 'object' || !res.user || typeof res.token !== 'string') {
|
|
150
|
+
const message = `onSuccess of props.${mode}.${mode === 'userpass' ? 'api' : 'codeApi'} should returns {user:any,token:string}`;
|
|
151
|
+
setAlert({ type: 'error', text: trans(`${mode}Error`), subtext: message });
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
if (res.message) {
|
|
155
|
+
setAlert({ type: 'success', text: res.message });
|
|
156
|
+
}
|
|
157
|
+
const { user, token } = res;
|
|
158
|
+
storage.save('data', { user, token });
|
|
159
|
+
setData({ user, token });
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function success_2(response, mode) {
|
|
164
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
165
|
+
if (!props.userpass) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const { onSuccess } = yield props.userpass.api(modelRef.current, 'userpass');
|
|
169
|
+
loading.show('login0');
|
|
170
|
+
const res = yield onSuccess(response);
|
|
171
|
+
loading.hide('login0');
|
|
172
|
+
if (res.message) {
|
|
173
|
+
setAlert({ type: 'success', text: res.message });
|
|
174
|
+
}
|
|
175
|
+
if (mode === 'otpnumber') {
|
|
176
|
+
setMode(getMode('otpcode'));
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
setTimeout(() => window.location.reload(), 1000);
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function success(response) {
|
|
184
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
185
|
+
if (mode.key === 'userpass' || mode.key === 'otpcode') {
|
|
186
|
+
success_1(response, mode.key);
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
success_2(response, mode.key);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
function submit() {
|
|
194
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
195
|
+
loading.show('login0');
|
|
196
|
+
const { url, method, body, onCatch } = yield props[mode.key].api(modelRef.current, mode.key);
|
|
197
|
+
loading.hide('login0');
|
|
198
|
+
axios[method](url, body).then(success).catch(response => {
|
|
199
|
+
if (onCatch) {
|
|
200
|
+
setAlert({ type: 'error', text: 'Error', subtext: onCatch(response) });
|
|
201
|
+
}
|
|
202
|
+
else if (response.message) {
|
|
203
|
+
setAlert({ type: 'error', text: 'Error', subtext: response.message });
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
function changeMode(mode) { setModel(getModel()); setMode(getMode(mode)); }
|
|
209
|
+
function mode_props(key) { return { className: 'ai-login-mode', onClick: () => changeMode(key) }; }
|
|
210
|
+
function mode_layout() {
|
|
211
|
+
return (_jsxs("div", { className: "ai-login-modes", children: [props.userpass && mode.key !== 'userpass' && _jsx("button", Object.assign({}, mode_props('userpass'), { children: trans('switchuserpass') })), props.register && mode.key !== 'register' && _jsx("button", Object.assign({}, mode_props('register'), { children: trans('switchregister') })), props.otp && mode.key !== 'otpnumber' && _jsx("button", Object.assign({}, mode_props('otpnumber'), { children: trans('switchotp') }))] }));
|
|
212
|
+
}
|
|
213
|
+
function validate() {
|
|
214
|
+
const model = modelRef.current;
|
|
215
|
+
if (mode.key === 'otpcode') {
|
|
216
|
+
if ((model.otpcode || '').length !== otpLength) {
|
|
217
|
+
return trans('otpcodeLength');
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (mode.key === 'otpnumber') {
|
|
221
|
+
if (!model.otpnumber) {
|
|
222
|
+
return trans('otpnumberRequired');
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (mode.key === 'userpass') {
|
|
226
|
+
if (!model.username) {
|
|
227
|
+
return trans('usernameRequired');
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (mode.key === 'register') {
|
|
231
|
+
if (!model.register.username) {
|
|
232
|
+
return trans('usernameRequired');
|
|
233
|
+
}
|
|
234
|
+
if (!model.register.password) {
|
|
235
|
+
return trans('passwordRequired');
|
|
236
|
+
}
|
|
237
|
+
if (!model.register.repassword) {
|
|
238
|
+
return trans('repasswordRequired');
|
|
239
|
+
}
|
|
240
|
+
if (model.register.password !== model.register.repassword) {
|
|
241
|
+
return trans('repasswordMatch');
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return validation(model, mode.key);
|
|
245
|
+
}
|
|
246
|
+
function submit_layout() {
|
|
247
|
+
const message = validate();
|
|
248
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "ai-login-errors", children: !!message && _jsx("div", { className: "ai-login-error", children: message }) }), _jsx("button", { className: 'ai-login-submit', disabled: !!message || !!submitDisabled, onClick: () => {
|
|
249
|
+
setSubmitDisabled(true);
|
|
250
|
+
setTimeout(() => setSubmitDisabled(false), 3000);
|
|
251
|
+
submit();
|
|
252
|
+
}, children: mode.submitText })] }));
|
|
253
|
+
}
|
|
254
|
+
function form_layout() {
|
|
255
|
+
const { title, inputs } = mode;
|
|
256
|
+
return (_jsxs("div", { className: "ai-login-form", children: [title, inputs(), submit_layout(), mode_layout()] }));
|
|
257
|
+
}
|
|
258
|
+
const bf_layout = (type) => {
|
|
259
|
+
const fn = props[type];
|
|
260
|
+
let content = null;
|
|
261
|
+
if (fn) {
|
|
262
|
+
content = fn(mode.key);
|
|
263
|
+
}
|
|
264
|
+
return (_jsx("div", { className: `ai-login-${type}`, children: content }));
|
|
265
|
+
};
|
|
266
|
+
function logout() { storage.remove('data'); window.location.reload(); }
|
|
267
|
+
function CheckToken() {
|
|
268
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
269
|
+
if (props.splash) {
|
|
270
|
+
setTimeout(() => { setSplashing(false); }, props.splash.time);
|
|
271
|
+
}
|
|
272
|
+
if (props.mock) {
|
|
273
|
+
setData({ user: props.mock.user, token: props.mock.token });
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const storedData = storage.load('data', {}), { user, token } = storedData;
|
|
277
|
+
loading.show('login0');
|
|
278
|
+
const { url, method, onSuccess, onCatch } = yield props.checkToken(token || '');
|
|
279
|
+
loading.hide('login0');
|
|
280
|
+
if (user && token) {
|
|
281
|
+
axios[method](url, { headers: { authorization: `Bearer ${token}` } })
|
|
282
|
+
.then(response => {
|
|
283
|
+
let res;
|
|
284
|
+
try {
|
|
285
|
+
res = onSuccess(response);
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
setAlert({ type: 'error', text: 'checkToken failed', subtext: err.message });
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (res === true) {
|
|
292
|
+
setData({ user, token });
|
|
293
|
+
}
|
|
294
|
+
else if (res === false) {
|
|
295
|
+
logout();
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
setAlert({ type: 'error', text: 'checkToken failed', subtext: 'checkToken props should return string as error or true as token is valid and false as token is invalid' });
|
|
299
|
+
}
|
|
300
|
+
})
|
|
301
|
+
.catch(response => {
|
|
302
|
+
let res, message = '';
|
|
303
|
+
try {
|
|
304
|
+
res = onCatch(response);
|
|
305
|
+
}
|
|
306
|
+
catch (err) {
|
|
307
|
+
message = err.message;
|
|
308
|
+
}
|
|
309
|
+
if (typeof res === 'string') {
|
|
310
|
+
message = res;
|
|
311
|
+
}
|
|
312
|
+
else if (res === false) {
|
|
313
|
+
logout();
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
message = 'AILogin checkToken onCatch props should returns string as error or false as invalid token';
|
|
317
|
+
}
|
|
318
|
+
if (message) {
|
|
319
|
+
setAlert({ type: 'error', text: 'checkToken failed', subtext: message });
|
|
320
|
+
}
|
|
321
|
+
else if (response.message) {
|
|
322
|
+
setAlert({ type: 'error', text: 'Error', subtext: response.message });
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
setWeightingCheckToken(false);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
useEffect(() => { CheckToken(); }, []);
|
|
330
|
+
function setAlert(p) { Alert(p); }
|
|
331
|
+
function getContent() {
|
|
332
|
+
if (waitingCheckToken || splashing) {
|
|
333
|
+
return props.splash ? props.splash.html : null;
|
|
334
|
+
}
|
|
335
|
+
if (!data) {
|
|
336
|
+
const attrs = AddToAttrs(props.attrs, { className: 'ai-login', style: { direction: !!props.fa ? 'rtl' : undefined } });
|
|
337
|
+
return (_jsxs("div", Object.assign({}, attrs, { children: [bf_layout('before'), " ", form_layout(), " ", bf_layout('after')] })));
|
|
338
|
+
}
|
|
339
|
+
return props.renderApp({ token: data.token, user: data.user, logout });
|
|
340
|
+
}
|
|
341
|
+
return (_jsx(_Fragment, { children: getContent() }));
|
|
342
|
+
};
|
|
343
|
+
export default AILogin;
|