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 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.isWx = true;
858
- done(null, user);
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.cache.get(username)).then((cachePwd) => {
942
- if (!pwdVerified && cachePwd !== password) {
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
- if (!await m.hasPermission(req, m)) {
1011
- const whiteList = ((m.config && m.config['whiteList']) || []).concat([`${app.config['baseUrl'] || ''}/login`]);
1012
- for (let i = 0; i < whiteList.length; i += 1) {
1013
- const wl = whiteList[i];
1014
-
1015
- if (typeof wl === 'string' && wl.toLowerCase() === req.originalUrl.toLowerCase()) return next();
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
- if (typeof wl === 'object' && new RegExp(wl).test(req.originalUrl)) return next();
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
- // check for force reset pwd
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
- if (req.user && req.user.id) {
1046
- const updateAt = req.user.PwdUpdatedAt || req.user.CreatedDate || req.user.LastUpdateDate;
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
- if(pastP > (resetP * 24 * 3600 * 1000)) {
1050
- await res.endWithErr(403, 'RSTPWD');
1051
- } else {
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 existPhone = await res.app.models.account.countDocuments({ PhoneNumber: phone });
1267
- if (existPhone) {
1268
- res.makeError(404, 'The phone number was used already!', m);
1269
- return next('route');
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 && verifyPassword(password, req.user.Password, m.config.pwdEncryptMethod || 'md5')) {
1327
- res.makeError(406, 'New password cannot be the same as the old one!', m);
1328
- return next('route');
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
  })