free-be-account 0.0.15 → 0.0.17
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.js +170 -49
- package/package-lock.json +1539 -0
- package/package.json +13 -8
- package/routers/mgmt/route.js +10 -11
- package/routers/uc/info/route.js +5 -5
- package/routers/uc/noty/index.js +4 -0
- package/routers/uc/noty/route.js +61 -0
- package/sms/index.js +10 -4
package/index.js
CHANGED
|
@@ -7,12 +7,23 @@ var svgCaptcha = require('svg-captcha');
|
|
|
7
7
|
const passport = require('passport');
|
|
8
8
|
const LocalStrategy = require('passport-local').Strategy;
|
|
9
9
|
const {v1: uuidv1} = require('uuid');
|
|
10
|
+
const RedisStore = require("connect-redis").default;
|
|
11
|
+
const session = require("express-session");
|
|
12
|
+
|
|
10
13
|
const crypto = require("./crypto");
|
|
11
14
|
const { clearPermission, getPermissionPathList, verifyPassword, encryptPwd } = require('./utils');
|
|
12
15
|
const { AccountAuditStatus } = require('./enum');
|
|
13
16
|
const sms = require('./sms');
|
|
14
17
|
const wx = require('./platforms/wx/index');
|
|
15
18
|
|
|
19
|
+
const eis = {};
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
Object.assign(eis, require('../../global.js').eis);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
console.log('No global eis found!');
|
|
25
|
+
}
|
|
26
|
+
|
|
16
27
|
let __app_service_list_saved = false;
|
|
17
28
|
let __saved_service_list;
|
|
18
29
|
|
|
@@ -205,6 +216,10 @@ module.exports = (app) => ({
|
|
|
205
216
|
accountDefaultPassword: '12345678',
|
|
206
217
|
accountDefaultPasswordRandom: false,
|
|
207
218
|
accountDefaultPasswordRandomLength: 6,
|
|
219
|
+
|
|
220
|
+
autoCreateNewUser: false,
|
|
221
|
+
recoverNoSamePwd: false,
|
|
222
|
+
|
|
208
223
|
// accountDefaultPermissions: [
|
|
209
224
|
// // could from system config
|
|
210
225
|
// // {
|
|
@@ -227,6 +242,7 @@ module.exports = (app) => ({
|
|
|
227
242
|
|
|
228
243
|
dataScopes: [],
|
|
229
244
|
permissionControls: [],
|
|
245
|
+
smsFormat: '6n',
|
|
230
246
|
captcha: {
|
|
231
247
|
cache: 5 * 60 * 1000,
|
|
232
248
|
login: false,
|
|
@@ -315,12 +331,19 @@ module.exports = (app) => ({
|
|
|
315
331
|
Label: '邮箱',
|
|
316
332
|
Name: 'Profile.Email',
|
|
317
333
|
Index: 3,
|
|
334
|
+
Rules: ['validatorEmail'],
|
|
318
335
|
},
|
|
319
336
|
{
|
|
320
337
|
Type: 'String',
|
|
321
338
|
Label: '职务',
|
|
322
339
|
Name: 'Profile.Title',
|
|
323
340
|
Index: 4,
|
|
341
|
+
Rules: ['validatorOnlyCC'],
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
Name: 'Profile.Avatar',
|
|
345
|
+
Type: 'Image',
|
|
346
|
+
Label: '头像',
|
|
324
347
|
},
|
|
325
348
|
],
|
|
326
349
|
},
|
|
@@ -399,6 +422,14 @@ module.exports = (app) => ({
|
|
|
399
422
|
// label could be nagtive, means a user with it will DO NOT has it's permissions
|
|
400
423
|
Negative: { type: 'Boolean', default: false },
|
|
401
424
|
},
|
|
425
|
+
|
|
426
|
+
system_notification: {
|
|
427
|
+
User: { type: 'String', refer: 'account' },
|
|
428
|
+
Title: { type: 'String', required: true },
|
|
429
|
+
Content: { type: 'String' },
|
|
430
|
+
Read: { type: 'Boolean', default: false },
|
|
431
|
+
Category: { type: 'String' },
|
|
432
|
+
},
|
|
402
433
|
},
|
|
403
434
|
utils: {
|
|
404
435
|
verify_api_permission,
|
|
@@ -850,12 +881,16 @@ module.exports = (app) => ({
|
|
|
850
881
|
{
|
|
851
882
|
// 'Profile.WxOpenId': wxResult.openid,
|
|
852
883
|
...openidFilter,
|
|
853
|
-
Enabled: true,
|
|
854
|
-
Deleted: false,
|
|
884
|
+
// Enabled: true,
|
|
885
|
+
// Deleted: false,
|
|
855
886
|
}).then((user) => {
|
|
856
887
|
if (user) {
|
|
857
|
-
user.
|
|
858
|
-
|
|
888
|
+
if (!user.Enabled || user.Deleted) {
|
|
889
|
+
done(null, false);
|
|
890
|
+
} else {
|
|
891
|
+
user.isWx = true;
|
|
892
|
+
done(null, user);
|
|
893
|
+
}
|
|
859
894
|
} else {
|
|
860
895
|
// create new
|
|
861
896
|
const profile = {};
|
|
@@ -895,12 +930,12 @@ module.exports = (app) => ({
|
|
|
895
930
|
{
|
|
896
931
|
$or: [{ PhoneNumber: username }, { UserName: username }],
|
|
897
932
|
// Password: password,
|
|
898
|
-
Enabled: true,
|
|
899
|
-
Deleted: false,
|
|
933
|
+
// Enabled: true,
|
|
934
|
+
// Deleted: false,
|
|
900
935
|
}).then(async (user) => {
|
|
901
936
|
if (!user) {
|
|
902
937
|
// auto create new user
|
|
903
|
-
if (m.config.autoCreateNewUser) {
|
|
938
|
+
if (m.config.autoCreateNewUser && await app.modules['account'].verify(username, password)) {
|
|
904
939
|
const valid_phone = (d) => {
|
|
905
940
|
return /^(0|86|17951)?(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])[0-9]{8}$/.test(d);
|
|
906
941
|
};
|
|
@@ -936,10 +971,14 @@ module.exports = (app) => ({
|
|
|
936
971
|
}
|
|
937
972
|
}
|
|
938
973
|
|
|
974
|
+
if (!user.Enabled || user.Deleted) {
|
|
975
|
+
return done(null, false);
|
|
976
|
+
}
|
|
977
|
+
|
|
939
978
|
const pwdVerified = verifyPassword(password, user.Password, m.config.pwdEncryptMethod || 'md5');
|
|
940
979
|
|
|
941
|
-
return Promise.resolve(app.
|
|
942
|
-
if (!pwdVerified && cachePwd
|
|
980
|
+
return Promise.resolve(app.modules['sms'].verify(username, cachePwd)).then((cachePwd) => {
|
|
981
|
+
if (!pwdVerified && !cachePwd) {
|
|
943
982
|
return done(null, false);
|
|
944
983
|
} else {
|
|
945
984
|
return done(null, user);
|
|
@@ -1007,16 +1046,28 @@ module.exports = (app) => ({
|
|
|
1007
1046
|
// permission control
|
|
1008
1047
|
app.use(async (req, res, next) => {
|
|
1009
1048
|
// permission control
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1049
|
+
let inWhiteList = false;
|
|
1050
|
+
const whiteList = ((m.config && m.config['whiteList']) || []).concat([`${app.config['baseUrl'] || ''}/login`]);
|
|
1051
|
+
for (let i = 0; i < whiteList.length; i += 1) {
|
|
1052
|
+
const wl = whiteList[i];
|
|
1053
|
+
|
|
1054
|
+
if (typeof wl === 'string' && wl.toLowerCase() === req.originalUrl.toLowerCase()) {
|
|
1055
|
+
inWhiteList = true;
|
|
1056
|
+
break;
|
|
1057
|
+
}
|
|
1016
1058
|
|
|
1017
|
-
|
|
1059
|
+
if (typeof wl === 'object' && new RegExp(wl).test(req.originalUrl)) {
|
|
1060
|
+
inWhiteList = true;
|
|
1061
|
+
break;
|
|
1018
1062
|
}
|
|
1063
|
+
}
|
|
1019
1064
|
|
|
1065
|
+
if (inWhiteList) {
|
|
1066
|
+
await m.hasPermission(req, m)
|
|
1067
|
+
return next();
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
if (!await m.hasPermission(req, m)) {
|
|
1020
1071
|
if (req.user && req.user.id) {
|
|
1021
1072
|
await res.endWithErr(400, 401);
|
|
1022
1073
|
}
|
|
@@ -1033,30 +1084,18 @@ module.exports = (app) => ({
|
|
|
1033
1084
|
if (token) {
|
|
1034
1085
|
res.cookie('token', token, { maxAge: app.config['cookieTimeout'] });
|
|
1035
1086
|
}
|
|
1036
|
-
|
|
1037
|
-
return next();
|
|
1038
|
-
});
|
|
1039
1087
|
|
|
1040
|
-
|
|
1041
|
-
app.use(async (req, res, next) => {
|
|
1088
|
+
// check for force reset pwd
|
|
1042
1089
|
const resetP = m.config && m.config['forceResetPwd'];
|
|
1043
1090
|
|
|
1044
|
-
if(resetP) {
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
const pastP = new Date() - updateAt;
|
|
1091
|
+
if(resetP && req.user && req.user.id) {
|
|
1092
|
+
const updateAt = req.user.PwdUpdatedAt || req.user.CreatedDate || req.user.LastUpdateDate;
|
|
1093
|
+
const pastP = new Date() - updateAt;
|
|
1048
1094
|
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
return next();
|
|
1053
|
-
}
|
|
1054
|
-
}
|
|
1055
|
-
else {
|
|
1056
|
-
await res.endWithErr(401);
|
|
1095
|
+
if(pastP > (resetP * 24 * 3600 * 1000)) {
|
|
1096
|
+
await res.makeError(403, 'RSTPWD');
|
|
1097
|
+
return next('route');
|
|
1057
1098
|
}
|
|
1058
|
-
|
|
1059
|
-
return;
|
|
1060
1099
|
}
|
|
1061
1100
|
|
|
1062
1101
|
return next();
|
|
@@ -1113,7 +1152,11 @@ module.exports = (app) => ({
|
|
|
1113
1152
|
let access_token = req.cookies.token || req.header('Authorization');
|
|
1114
1153
|
|
|
1115
1154
|
// call logout of the passport
|
|
1116
|
-
req.logout(() => {
|
|
1155
|
+
req.logout((err) => {
|
|
1156
|
+
if (err) {
|
|
1157
|
+
app.logger.error(err.message || err);
|
|
1158
|
+
}
|
|
1159
|
+
});
|
|
1117
1160
|
|
|
1118
1161
|
// clear the cached token
|
|
1119
1162
|
res.clearCookie('token');
|
|
@@ -1202,7 +1245,7 @@ module.exports = (app) => ({
|
|
|
1202
1245
|
return next('route');
|
|
1203
1246
|
}
|
|
1204
1247
|
const phone = crypto.encoder.desDecode(req.body.PhoneNumber, m.config.desKey);
|
|
1205
|
-
const result = await m.sms.verify(phone, req.body.code);
|
|
1248
|
+
const result = await m.sms.verify(phone, req.body.code, req.body.delete === false ? false : true);
|
|
1206
1249
|
// app.logger.debug(cache.exportJson());
|
|
1207
1250
|
|
|
1208
1251
|
if (!result) {
|
|
@@ -1263,16 +1306,52 @@ module.exports = (app) => ({
|
|
|
1263
1306
|
}
|
|
1264
1307
|
}
|
|
1265
1308
|
|
|
1266
|
-
const
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1309
|
+
const valid_phone = (d) => {
|
|
1310
|
+
return /^(0|86|17951)?(13[0-9]|14[0-9]|15[0-9]|16[0-9]|17[0-9]|18[0-9]|19[0-9])[0-9]{8}$/.test(d);
|
|
1311
|
+
};
|
|
1312
|
+
const valid_email = (d) => {
|
|
1313
|
+
// eslint-disable-next-line no-useless-escape
|
|
1314
|
+
return /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(d);
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
const userPhoneEmail = {};
|
|
1318
|
+
let isPhone = false;
|
|
1319
|
+
let isEmail = false;
|
|
1320
|
+
|
|
1321
|
+
if (valid_phone(phone)) {
|
|
1322
|
+
userPhoneEmail.PhoneNumber = phone;
|
|
1323
|
+
isPhone = true;
|
|
1324
|
+
} else if (valid_email(phone)) {
|
|
1325
|
+
isEmail = true;
|
|
1326
|
+
userPhoneEmail.UserName = phone;
|
|
1327
|
+
userPhoneEmail['Profile'] = {
|
|
1328
|
+
Email: phone
|
|
1329
|
+
};
|
|
1330
|
+
} else {
|
|
1331
|
+
userPhoneEmail.UserName = phone;
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
if (isPhone) {
|
|
1335
|
+
const existPhone = await res.app.models.account.countDocuments({ PhoneNumber: phone });
|
|
1336
|
+
if (existPhone) {
|
|
1337
|
+
res.makeError(404, 'The phone number was used already!', m);
|
|
1338
|
+
return next('route');
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
if (isEmail) {
|
|
1343
|
+
const existPhone = await res.app.models.account.countDocuments({ 'Profile.Email': phone });
|
|
1344
|
+
if (existPhone) {
|
|
1345
|
+
res.makeError(405, 'The email address was used already!', m);
|
|
1346
|
+
return next('route');
|
|
1347
|
+
}
|
|
1270
1348
|
}
|
|
1271
1349
|
|
|
1272
1350
|
// only create with specified fields
|
|
1273
1351
|
res.locals.body = {
|
|
1274
1352
|
Saved: true,
|
|
1275
|
-
PhoneNumber: phone,
|
|
1353
|
+
// PhoneNumber: phone,
|
|
1354
|
+
...userPhoneEmail,
|
|
1276
1355
|
Password: encryptPwd(password, m.config.pwdEncryptMethod || 'md5')
|
|
1277
1356
|
}
|
|
1278
1357
|
|
|
@@ -1323,18 +1402,31 @@ module.exports = (app) => ({
|
|
|
1323
1402
|
}
|
|
1324
1403
|
|
|
1325
1404
|
// only create with specified fields
|
|
1326
|
-
if (m.config.recoverNoSamePwd
|
|
1327
|
-
|
|
1328
|
-
|
|
1405
|
+
if (m.config.recoverNoSamePwd) {
|
|
1406
|
+
let oldPwd = req.user && req.user.Password;
|
|
1407
|
+
if (!oldPwd) {
|
|
1408
|
+
const theUser = await res.app.models.account.findOne({$or: [
|
|
1409
|
+
{ PhoneNumber: phone },
|
|
1410
|
+
{ 'Profile.Email': phone },
|
|
1411
|
+
]});
|
|
1412
|
+
|
|
1413
|
+
oldPwd = theUser && theUser.Password;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
if (oldPwd && verifyPassword(password, oldPwd, m.config.pwdEncryptMethod || 'md5')) {
|
|
1417
|
+
res.makeError(406, 'New password cannot be the same as the old one!', m);
|
|
1418
|
+
return next('route');
|
|
1419
|
+
}
|
|
1329
1420
|
}
|
|
1330
1421
|
|
|
1331
1422
|
res.locals.body = {
|
|
1332
1423
|
Password: encryptPwd(password, m.config.pwdEncryptMethod || 'md5'),
|
|
1333
1424
|
}
|
|
1334
1425
|
|
|
1335
|
-
res.locals.filter = {
|
|
1336
|
-
PhoneNumber: phone
|
|
1337
|
-
|
|
1426
|
+
res.locals.filter = {$or: [
|
|
1427
|
+
{ PhoneNumber: phone },
|
|
1428
|
+
{ 'Profile.Email': phone },
|
|
1429
|
+
]}
|
|
1338
1430
|
|
|
1339
1431
|
return next();
|
|
1340
1432
|
},
|
|
@@ -1442,6 +1534,35 @@ module.exports = (app) => ({
|
|
|
1442
1534
|
m.clearCachedPermission(app);
|
|
1443
1535
|
|
|
1444
1536
|
// TODO: remove service list which are in the white list
|
|
1537
|
+
},
|
|
1538
|
+
onAppReady: (app) => {
|
|
1539
|
+
let redisStore = new RedisStore({
|
|
1540
|
+
client: app.redis,
|
|
1541
|
+
prefix: app.config.prefix || 'xx-eis:',
|
|
1542
|
+
});
|
|
1543
|
+
|
|
1544
|
+
app.use(
|
|
1545
|
+
session({
|
|
1546
|
+
store: redisStore,
|
|
1547
|
+
resave: false, // required: force lightweight session keep alive (touch)
|
|
1548
|
+
saveUninitialized: false, // recommended: only save session when data exists
|
|
1549
|
+
secret: eis.session.secret || 'default eis session secret',
|
|
1550
|
+
}),
|
|
1551
|
+
);
|
|
1552
|
+
|
|
1553
|
+
app.use(passport.session());
|
|
1554
|
+
},
|
|
1555
|
+
},
|
|
1556
|
+
notify: (user, title, content, category) => {
|
|
1557
|
+
if (!user || !title) {
|
|
1558
|
+
return;
|
|
1445
1559
|
}
|
|
1446
|
-
|
|
1560
|
+
|
|
1561
|
+
app.models.system_notification.create({
|
|
1562
|
+
User: user,
|
|
1563
|
+
Title: title,
|
|
1564
|
+
Content: content,
|
|
1565
|
+
Category: category,
|
|
1566
|
+
});
|
|
1567
|
+
},
|
|
1447
1568
|
})
|