@gingkoo/base-server 0.0.1-alpha.0 → 0.0.1-alpha.2

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.
Files changed (122) hide show
  1. package/README.md +7 -0
  2. package/app.js +36 -40
  3. package/backend/common/entity.js +55 -0
  4. package/backend/common/enum.js +247 -0
  5. package/backend/common/fss/index.js +18 -0
  6. package/backend/common/fss/routers/attachment.js +45 -0
  7. package/backend/common/fss/routers/download.js +43 -0
  8. package/backend/common/fss/routers/import_export.js +113 -0
  9. package/backend/common/fss/routers/resources.js +149 -0
  10. package/backend/common/fss/routers/upload.js +81 -0
  11. package/backend/common/fss/services/import_export.js +159 -0
  12. package/backend/common/fss/services/index.js +92 -0
  13. package/backend/common/fss/utils.js +39 -0
  14. package/backend/common/ginfo/config.js +5 -0
  15. package/backend/common/ginfo/index.js +62 -0
  16. package/backend/common/index_template.html +28 -0
  17. package/backend/common/logger/index.js +96 -0
  18. package/backend/common/mapping.js +98 -0
  19. package/backend/common/middleware/auth.js +97 -0
  20. package/backend/common/middleware/cors.js +13 -0
  21. package/backend/common/middleware/response.js +25 -0
  22. package/backend/common/page_engine.js +487 -0
  23. package/backend/common/schedule.js +45 -0
  24. package/backend/common/services/dataCombine.js +67 -0
  25. package/backend/common/services/dept.js +37 -0
  26. package/backend/common/services/dict.js +487 -0
  27. package/backend/common/services/email.js +49 -0
  28. package/backend/common/services/generalConfig.js +137 -0
  29. package/backend/common/services/login.js +18 -0
  30. package/backend/common/services/notice.js +260 -0
  31. package/backend/common/services/permission.js +500 -0
  32. package/backend/common/services/roles.js +57 -0
  33. package/backend/common/services/send-notice.js +86 -0
  34. package/backend/common/services/task.js +259 -0
  35. package/backend/common/services/user.js +673 -0
  36. package/backend/common/socket.js +18 -0
  37. package/backend/common/sse/index.js +81 -0
  38. package/backend/common/sse/router.js +30 -0
  39. package/backend/common/task.js +75 -0
  40. package/backend/common/wechat/index.js +9 -0
  41. package/backend/common/wechat/routers/auth.js +238 -0
  42. package/{modules/user/frontend → backend/common/wechat/routers}/index.html +14 -7
  43. package/backend/common/wechat/services/auth.js +209 -0
  44. package/backend/common/wechat/services/notice.js +171 -0
  45. package/backend/config/index.js +63 -0
  46. package/backend/config/path.js +3 -0
  47. package/backend/router.js +96 -0
  48. package/backend/routers/app.js +222 -0
  49. package/backend/routers/automate.js +276 -0
  50. package/backend/routers/dict.js +370 -0
  51. package/backend/routers/email.js +85 -0
  52. package/backend/routers/generalConfig.js +276 -0
  53. package/backend/routers/idm.js +245 -0
  54. package/backend/routers/module.js +357 -0
  55. package/backend/routers/notice.js +138 -0
  56. package/backend/routers/pages.js +46 -0
  57. package/backend/routers/permission.js +985 -0
  58. package/backend/routers/setting.js +184 -0
  59. package/backend/routers/team/index.js +22 -0
  60. package/backend/routers/team/routers/mapping.js +29 -0
  61. package/backend/routers/team/routers/member.js +72 -0
  62. package/backend/routers/team/routers/membermanage.js +289 -0
  63. package/backend/routers/team/routers/pages.js +47 -0
  64. package/backend/routers/team/routers/roles.js +92 -0
  65. package/backend/routers/team/routers/teaminfo.js +27 -0
  66. package/backend/routers/team/routers/usergroup.js +213 -0
  67. package/backend/routers/team/services/mapping.js +101 -0
  68. package/backend/routers/team/services/member.js +206 -0
  69. package/backend/routers/team/services/roles.js +71 -0
  70. package/backend/routers/team/services/teaminfo.js +20 -0
  71. package/backend/routers/team/services/usergroup.js +128 -0
  72. package/backend/routers/user.js +436 -0
  73. package/backend/services/automate.js +60 -0
  74. package/backend/services/config.js +14 -0
  75. package/backend/services/module.js +298 -0
  76. package/backend/services/permission.js +192 -0
  77. package/backend/services/services.js +115 -0
  78. package/backend/services/setting.js +190 -0
  79. package/backend/services/token.js +42 -0
  80. package/backend/space.js +52 -0
  81. package/backend/space_mapping.js +15 -0
  82. package/backend/utils/avatar.js +48 -0
  83. package/backend/utils/color_gen_helper.js +20 -0
  84. package/backend/utils/date.js +66 -0
  85. package/backend/utils/excel.js +446 -0
  86. package/backend/utils/fs/doc.md +64 -0
  87. package/backend/utils/fs/index.js +127 -0
  88. package/backend/utils/jwt.js +54 -0
  89. package/backend/utils/modules/sequence.js +93 -0
  90. package/backend/utils/object.js +31 -0
  91. package/backend/utils/page-query-helper/index.js +61 -0
  92. package/backend/utils/path.js +123 -0
  93. package/backend/utils/run.js +25 -0
  94. package/backend/utils/tokenize.js +82 -0
  95. package/backend/utils/typeof.js +5 -0
  96. package/backend/utils/util.js +153 -0
  97. package/backend/views/api/index.js +32 -0
  98. package/backend/views/api/index.xml +49 -0
  99. package/backend/views/dict/index.js +80 -0
  100. package/backend/views/dict/index.xml +52 -0
  101. package/backend/views/index.js +32 -0
  102. package/backend/views/members_manage/index.js +68 -0
  103. package/backend/views/members_manage/index.xml +68 -0
  104. package/backend/views/roles/index.js +17 -0
  105. package/backend/views/roles/index.xml +47 -0
  106. package/backend/views/usergroup/index.js +68 -0
  107. package/backend/views/usergroup/index.xml +65 -0
  108. package/dist/common-assets/css/index-05a08720.css +3 -0
  109. package/dist/common-assets/css/index-05a08720.css.gz +0 -0
  110. package/dist/common-assets/js/index-2e8c7128.js +762 -0
  111. package/dist/common-assets/js/index-2e8c7128.js.gz +0 -0
  112. package/dist/common-assets/js/react-cropper.es-19c27537.js +10 -0
  113. package/dist/common-assets/js/react-cropper.es-19c27537.js.gz +0 -0
  114. package/dist/common-assets/png/u9-2348c304.png +0 -0
  115. package/dist/common-assets/woff2/materialicons-83be7b2f.woff2 +0 -0
  116. package/dist/index.html +162 -0
  117. package/package.json +61 -5
  118. package/common/router.js +0 -42
  119. package/modules/user/backend/index.js +0 -19
  120. package/modules/user/backend/routers/user.js +0 -11
  121. package/modules/user/frontend/index.js +0 -1
  122. package/serve.js +0 -9
@@ -0,0 +1,171 @@
1
+ const httpclient = require('node-httpclient');
2
+ const nodemailer = require('nodemailer');
3
+ const config = require('../../../config/index');
4
+
5
+ const { logger } = require('../../logger');
6
+ const userServices = require('../../services/user');
7
+ const generalConfig = require('../../services/generalConfig');
8
+ const emailService = require('../../services/email');
9
+
10
+ const { getAccessToken } = require('./auth');
11
+ const wxConfig = require('../config');
12
+
13
+ const recallMessage = async (msgId, corpsecret = '') => {
14
+ const accessToken = await getAccessToken(corpsecret);
15
+ const url = `https://qyapi.weixin.qq.com/cgi-bin/message/recall?access_token=${accessToken}`;
16
+ let msg = {
17
+ msgid: msgId,
18
+ };
19
+
20
+ let resp = await httpclient.post(url, JSON.stringify(msg), 'application/json');
21
+ let json_data = resp.data;
22
+ logger.info(json_data);
23
+ };
24
+
25
+ /**
26
+ * 发送企业微信通知
27
+ * @param {string[]} toUsers 企业微信那边的用户id集合
28
+ * @param {'textcard'} msgType
29
+ * @param {object} message 消息对象
30
+ * @param {string} message.description 消息描述
31
+ * @param {string} message.title 消息标题
32
+ * @param {string} message.url 通知的跳转链接
33
+ */
34
+ const sendMessage = async (toUsers, msgType, message, agent_id = '', corpsecret = '') => {
35
+ const accessToken = await getAccessToken(corpsecret);
36
+ const url = `https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${accessToken}`;
37
+
38
+ let msg = {
39
+ touser: toUsers.join('|'),
40
+ msgtype: msgType,
41
+ agentid: agent_id || wxConfig['agentid'],
42
+ enable_id_trans: 0,
43
+ enable_duplicate_check: 1,
44
+ duplicate_check_interval: 20,
45
+ //"toparty": "PartyID1|PartyID2",
46
+ //"totag": "TagID1 | TagID2",
47
+ };
48
+
49
+ msg[msgType] = message;
50
+ logger.info(msg);
51
+
52
+ let resp = await httpclient.post(url, JSON.stringify(msg), 'application/json');
53
+ let json_data = resp.data;
54
+ logger.info(json_data);
55
+ if (json_data['errcode'] != 0) {
56
+ logger.info('error:{0}'.format(json_data['errmsg']));
57
+ return json_data['errcode'];
58
+ }
59
+
60
+ return json_data;
61
+ };
62
+
63
+ /**
64
+ * 发送企业微信通知
65
+ * @param {string} toUsers 用户邮箱
66
+ * @param {string} title 通知标题
67
+ * @param {string} content 消息描述
68
+ * @param {string} templateid 模版id
69
+ */
70
+ const sendEmail = async (toUsers, title, content, link, templateid) => {
71
+ let smtp = await generalConfig.getFromConfig({ GROUP_ID: 'E-mail' });
72
+ const { SMTP_PASSWORK, SMTP_SERVE, SMTP_USER, SMTP_SEND, SMTP_PORT, SMTP_TLS, EMAIL_TIME } = smtp;
73
+ if (!SMTP_PASSWORK || !SMTP_SERVE || !SMTP_USER) return;
74
+
75
+ // 创建一个SMTP传输对象
76
+ const transporter = nodemailer.createTransport({
77
+ host: SMTP_SERVE,
78
+ post: SMTP_PORT ? SMTP_PORT : 456,
79
+ secure: SMTP_TLS || true,
80
+ auth: {
81
+ user: SMTP_USER || 'service@gingkoo.com', // 发件人邮箱
82
+ pass: SMTP_PASSWORK || 'Jinqiu123', // 发件人邮箱的密码或授权码
83
+ },
84
+ });
85
+ let html = ``;
86
+ let obj = { title: title, content: content, link: link };
87
+ let email = await emailService.getTempateInfo({ TEMPLATE_ID: 'default' });
88
+ if (email[0]?.CONTENT) {
89
+ html = email[0]?.CONTENT;
90
+ html = html.replace(/{{(.*?)}}/g, (match, key) => {
91
+ return obj[key] || match;
92
+ });
93
+ }
94
+
95
+ //邮件的内容
96
+ const mailOptions = {
97
+ from: SMTP_SEND ? SMTP_SEND + `<${SMTP_USER}>` : SMTP_USER, // 发件人邮箱
98
+ to: toUsers, // 收件人邮箱
99
+ subject: title || '',
100
+ text: content || '',
101
+ html: html,
102
+ };
103
+ const timeoutValue = EMAIL_TIME - 0 ? EMAIL_TIME : 10000;
104
+ transporter.sendMail(mailOptions, (error, info) => {
105
+ if (error) {
106
+ console.log('发送邮件错误:', error);
107
+ } else {
108
+ // console.log('发送成功:', info);
109
+ }
110
+ });
111
+
112
+ let time = setTimeout(() => {
113
+ //发生邮件超时
114
+ transporter.close(); // 可以选择关闭传输器,如果需要的话
115
+ }, timeoutValue);
116
+ };
117
+
118
+ module.exports = {
119
+ sendMessage,
120
+ recallMessage,
121
+ sendEmail,
122
+ /**
123
+ * 企业微信通知
124
+ * @param {string[]} toUsers 通知的用户组
125
+ * @param {string} params.title 通知标题
126
+ * @param {string} params.content 通知内容
127
+ * @param {string} params.link 跳转地址
128
+ */
129
+ async notice(toUsers, params) {
130
+ // ① 将 teams的 userId 转成 ginfo userId
131
+ let verdorUsersMap = await userServices.userChannel(toUsers);
132
+ if (!verdorUsersMap) {
133
+ return;
134
+ }
135
+
136
+ let msg = {
137
+ title: params['title'],
138
+ description: params['content'],
139
+ url: config['site']['base_url'] + params['link'],
140
+ };
141
+
142
+ let qywxUsers = [];
143
+
144
+ Object.keys(verdorUsersMap).forEach((it) => {
145
+ if (verdorUsersMap[it]?.workwx) {
146
+ qywxUsers.push(verdorUsersMap[it].workwx);
147
+ }
148
+ });
149
+
150
+ sendMessage(qywxUsers, 'textcard', msg);
151
+ },
152
+
153
+ /***
154
+ * 企业邮件通知
155
+ * @param {string[]} toUsers 通知的用户组
156
+ * @param {string} title 通知标题
157
+ * @param {string} content 描述
158
+ */
159
+ async email(toUsers, props, templateid, info) {
160
+ let verdorUsersMap = await userServices.getEmail(toUsers);
161
+ let { title, content, link } = props;
162
+ let email = '';
163
+ verdorUsersMap.map((v, index) => {
164
+ if (v.EMAIL) {
165
+ email += v.EMAIL + ',';
166
+ }
167
+ });
168
+ if (!email) return;
169
+ sendEmail(email, title, content, link);
170
+ },
171
+ };
@@ -0,0 +1,63 @@
1
+ const path = require('path');
2
+ const _ = require('lodash');
3
+
4
+ function gConfig() {
5
+ let serverConfig = {};
6
+
7
+ try {
8
+ serverConfig = require(path.resolve('server.config.js'));
9
+ } catch (e) {
10
+ const chalk = require('chalk');
11
+
12
+ if (e.message.startsWith('Cannot find module')) {
13
+ console.log(chalk.red('⚠️ 项目根目录缺少 server.config.js 文件'));
14
+ }
15
+ }
16
+
17
+ // 必填属性,格式不对的属性,需要校验提示
18
+ return _.merge(
19
+ {
20
+ isProd: true, // 纯当前开发用, 通过 npm 包 使用该组件的时候 他应该永远是 true
21
+ orgid: 'GINGKOO',
22
+ allowedIPs: [], // 不校验登录的 ip
23
+ testUser: '', // 测试用户
24
+
25
+ ip: '0.0.0.0', // 服务 host
26
+ port: 8081, // 服务端口号
27
+ orgid: 'GINGKOO', // 组织 id
28
+
29
+ db: {},
30
+
31
+ app: {
32
+ home: path.resolve('app_home'), // 资源存放的磁盘位置 (绝对路径)
33
+ redirect_uri: '',
34
+ },
35
+
36
+ jwt: {
37
+ exp: 60 * 60 * 24 * 3, // 过期时间
38
+ auth_cert: '', // 加盐
39
+ },
40
+
41
+ proxy: {
42
+ targets: [], // 服务代理
43
+ },
44
+
45
+ scoket: {
46
+ files: [],
47
+ config: {},
48
+ },
49
+
50
+ logger: {
51
+ appenders: {},
52
+ categories: {},
53
+ },
54
+
55
+ site: {
56
+ title: '',
57
+ },
58
+ },
59
+ serverConfig,
60
+ );
61
+ }
62
+
63
+ module.exports = gConfig();
@@ -0,0 +1,3 @@
1
+ const config = require('./index')
2
+
3
+ exports.attachmentPath = config.app.home + '/storage/'
@@ -0,0 +1,96 @@
1
+ 'use strict';
2
+ const path = require('path');
3
+ const express = require('express');
4
+ const { createProxyMiddleware } = require('http-proxy-middleware');
5
+ const jwt = require('./utils/jwt');
6
+ const config = require('./config/index');
7
+ const mapping = require('./common/mapping');
8
+
9
+ const space = require('./space');
10
+ const wechat = require('./common/wechat');
11
+ const fss = require('./common/fss');
12
+
13
+ require('./space_mapping');
14
+
15
+ var router = express.Router();
16
+
17
+ // 后端
18
+ router.get('/(:module/)?mapping', async (req, res) => {
19
+ let { module } = req.params;
20
+ let { list = '', ...extra } = req.query;
21
+ res.sendOk({
22
+ dict: await mapping.getMapping(module, list.split('|'), extra),
23
+ });
24
+ });
25
+
26
+ router.use('/fss', fss);
27
+ router.use('/wechat', wechat);
28
+ router.use('/space', space);
29
+
30
+ // 前端
31
+ router.use('/static', express.static(path.join(__dirname, '../static')));
32
+
33
+ if (config.isProd) {
34
+ router.use('/', express.static(path.join(__dirname, '../dist')));
35
+ } else {
36
+ router.use(
37
+ '/',
38
+ createProxyMiddleware({
39
+ target: 'http://127.0.0.1:2000',
40
+ changeOrigin: false,
41
+ ws: true,
42
+ pathRewrite: {
43
+ '^/': '',
44
+ },
45
+ onProxyReq: function (proxyReq, req, res) {
46
+ if (req.body) {
47
+ let bodyData = JSON.stringify(req.body);
48
+ proxyReq.setHeader('Content-Type', 'application/json');
49
+ proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
50
+ proxyReq.write(bodyData);
51
+ }
52
+ },
53
+ }),
54
+ );
55
+ }
56
+
57
+ // 反向代理
58
+ if (Array.isArray(config?.proxy?.targets)) {
59
+ config.proxy.targets.forEach((element) => {
60
+ let pathRewrite = {};
61
+ if (element.rewrite) {
62
+ pathRewrite['^' + element.path] = element.rewrite || '';
63
+ }
64
+ router.use(
65
+ element.path,
66
+ createProxyMiddleware({
67
+ target: element.host,
68
+ changeOrigin: false,
69
+ ws: true,
70
+ pathRewrite: pathRewrite,
71
+ onProxyReq: function (proxyReq, req) {
72
+ if ('X-Token' in req.cookies) {
73
+ let tokenData = jwt.verifyToken(req.cookies['X-Token']);
74
+ if (tokenData) {
75
+ proxyReq.setHeader('X-Token', req.cookies['X-Token']);
76
+ tokenData?.data?.userid && proxyReq.setHeader('X-UserId', tokenData.data.userid);
77
+ // proxyReq.setHeader('X-OrgId', tokenData['orgid']);
78
+ } else {
79
+ proxyReq.removeHeader('X-UserId');
80
+ }
81
+ } else {
82
+ proxyReq.removeHeader('X-UserId');
83
+ }
84
+ if (req.body) {
85
+ let bodyData = JSON.stringify(req.body);
86
+ proxyReq.setHeader('Content-Type', 'application/json');
87
+ proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
88
+ proxyReq.write(bodyData);
89
+ }
90
+ },
91
+ }),
92
+ );
93
+ });
94
+ }
95
+
96
+ module.exports = router;
@@ -0,0 +1,222 @@
1
+ 'use strict';
2
+ var express = require('express');
3
+ const nodemailer = require('nodemailer');
4
+ const bcrypt = require('bcryptjs');
5
+ const config = require('../config');
6
+ const jwt = require('../utils/jwt');
7
+ const { checkLogin } = require('../common/middleware/auth');
8
+ const { join, readFileContent } = require('../utils/path');
9
+ const userService = require('../common/services/user');
10
+ const generalConfig = require('../common/services/generalConfig');
11
+ const emailService = require('../common/services/email');
12
+ const servicesServices = require('../services/services');
13
+ const setting = require('../services/setting');
14
+
15
+ var router = express.Router();
16
+
17
+ /**
18
+ * 用户名登陆
19
+ */
20
+ router.post('/login', async (req, res) => {
21
+ let { userId, password } = req.body;
22
+
23
+ if (!userId) {
24
+ res.sendErr('请输入用户名');
25
+ return;
26
+ }
27
+
28
+ let userinfo = await userService.getUserInfo(userId);
29
+ if (!userinfo?.USER_ID) {
30
+ res.sendErr('用户不存在');
31
+ return;
32
+ }
33
+
34
+ // 判断密码
35
+ if (userinfo.PASSWD) {
36
+ let flag = await bcrypt.compare(password, userinfo.PASSWD);
37
+ if (!flag) {
38
+ return res.sendErr('密码错误');
39
+ }
40
+ }
41
+
42
+ let token = jwt.generateToken({
43
+ userid: userinfo?.USER_ID,
44
+ });
45
+
46
+ let expires = new Date();
47
+ expires.setDate(expires.getDate() + 3);
48
+
49
+ res.cookie('X-Token', token, { expires });
50
+
51
+ res.sendOk({
52
+ token,
53
+ });
54
+ });
55
+
56
+ router.post('/verify', async (req, res) => {
57
+ let { token } = req.body;
58
+
59
+ let result = false;
60
+ var tokenResult = jwt.verifyToken(token);
61
+ if (tokenResult) {
62
+ let tokenData = tokenResult['data'];
63
+ if (tokenData && tokenData['userid']) {
64
+ req.headers['x-userid'] = tokenData['userid'];
65
+ let expires = new Date();
66
+ expires.setDate(expires.getDate() + 3);
67
+ if (tokenResult['exp'] + 30 * 60 > Math.floor(Date.now() / 1000)) {
68
+ result = true;
69
+ }
70
+ result = true;
71
+ }
72
+ return result;
73
+ }
74
+
75
+ res.sendOk(data);
76
+ });
77
+
78
+ router.put('/exit', async function (req, res) {
79
+ let { USER_ID } = req.body;
80
+ if (!USER_ID) return res.sendErr('缺少用户ID');
81
+
82
+ let exit = await userService.update({ MEMBER_STATUS: '3' }, { USER_ID });
83
+ if (!exit) return res.sendErr('退出登录失败');
84
+
85
+ return res.sendOk('已退出登录');
86
+ });
87
+
88
+ router.get('/allOrgs', checkLogin, async function (req, res) {
89
+ let userid = req.get('X-UserId');
90
+ let data = await servicesServices.getAllOrgs(userid);
91
+ if (!data) {
92
+ return res.sendErr('');
93
+ }
94
+ res.sendOk(data);
95
+ });
96
+
97
+ // 查看日志
98
+ router.get('/log/:file', async function (req, res) {
99
+ let { file } = req.params;
100
+ let logPath = join(config.app.home, 'logs', file);
101
+ let content = '文件不存在';
102
+ try {
103
+ content = readFileContent(logPath);
104
+ } catch (e) {}
105
+ res.sendOk(content);
106
+ });
107
+
108
+ // 获取安全设置登录数据
109
+ router.get('/safe-set', async function (req, res) {
110
+ let data = await setting.getAllSafeSetData();
111
+ if (!Array.isArray(data)) return res.sendErr('查询失败');
112
+
113
+ let result = data.reduce((prev, item) => {
114
+ if (Reflect.has(prev, item['CONFIG_TYPE'])) {
115
+ perv[item['CONFIG_TYPE']].item['CONFIG_NAME'] = item['CONFIG_VALUE'];
116
+ } else {
117
+ perv[item['CONFIG_TYPE']] = {
118
+ [item['CONFIG_NAME']]: item['CONFIG_VALUE'],
119
+ };
120
+ }
121
+ return prev;
122
+ }, {});
123
+
124
+ return res.sendOk(result);
125
+ });
126
+
127
+ // 判断用户邮件地址并发送验证码
128
+ router.get('/forget-password/sendEmailCode', async function (req, res) {
129
+ let { USER_ID, EMAIL } = req.query;
130
+ let userInfo = await userService.getUserInfo(USER_ID);
131
+ if (!userInfo) return res.sendErr('用户ID无效');
132
+ console.log('🚀 ~ userInfo:', userInfo);
133
+ if (userInfo.EMAIL !== EMAIL) return res.sendErr('邮件地址错误');
134
+
135
+ // 随机生成验证码,发送验证码,并返回前端
136
+ let code = Math.floor(Math.random() * (1000000 - 100000) + 100000);
137
+
138
+ let smtp = await generalConfig.getFromConfig({ GROUP_ID: 'E-mail' });
139
+ if (!smtp) return res.sendErr('查询失败');
140
+ const { SMTP_PASSWORK, SMTP_SERVE, SMTP_USER, SMTP_SEND, SMTP_PORT, SMTP_TLS } = smtp;
141
+ if (!SMTP_PASSWORK || !SMTP_SERVE || !SMTP_USER) return res.sendErr('系统缺少数据');
142
+
143
+ // 创建一个SMTP传输对象
144
+ const transporter = nodemailer.createTransport({
145
+ host: SMTP_SERVE,
146
+ post: SMTP_PORT ? SMTP_PORT : 456,
147
+ secure: SMTP_TLS || true,
148
+ auth: {
149
+ user: SMTP_USER || 'service@gingkoo.com', // 发件人邮箱
150
+ pass: SMTP_PASSWORK || 'Jinqiu123', // 发件人邮箱的密码或授权码
151
+ },
152
+ });
153
+
154
+ let html = ``;
155
+ let emails = await emailService.getTempateInfo({ TEMPLATE_ID: 'email_code' });
156
+ if (emails[0]?.CONTENT) {
157
+ html = emails[0]?.CONTENT;
158
+ html = html.replace('{{code}}', code);
159
+ }
160
+
161
+ //邮件的内容
162
+ const mailOptions = {
163
+ from: SMTP_SEND ? SMTP_SEND + `<${SMTP_USER}>` : SMTP_USER, // 发件人邮箱
164
+ to: EMAIL, // 收件人邮箱
165
+ subject: 'teams团队协同 账号安全中心-找回密码验证',
166
+ html: html,
167
+ };
168
+
169
+ transporter.sendMail(mailOptions, (error, info) => {
170
+ if (error) {
171
+ console.log('发送邮件错误:', error);
172
+ } else {
173
+ // console.log('发送成功:', info);
174
+ }
175
+ });
176
+
177
+ return res.sendOk({ code });
178
+ });
179
+
180
+ // 判断用户密保问题并修改密码
181
+ router.put('/forget-security/updatePwd', async function (req, res) {
182
+ let { SECURITY_PROBLEM, SECURITY_ANSWER, USER_ID, NEW_PWD, PASSWD_POWER } = req.body;
183
+ if (!NEW_PWD || !SECURITY_PROBLEM || !SECURITY_ANSWER) return res.sendErr('修改失败,参数无效');
184
+
185
+ let userInfo = userService.getUserInfo(USER_ID);
186
+ if (!userInfo) return res.sendErr('用户ID无效');
187
+
188
+ // 校验用户密保
189
+ let [error, userSecurity] = await userService.getUserSecurity({ USER_ID });
190
+ if (!userSecurity || !userSecurity.length || error)
191
+ return res.sendErr('修改失败,当前用户未设置密保,请通过其他方式修改密码');
192
+ let flag = userSecurity.some(
193
+ (security) =>
194
+ security['SECUR_KEY'] === SECURITY_PROBLEM && security['SECUR_VALUE'] === SECURITY_ANSWER,
195
+ );
196
+ if (!flag) return res.sendErr('修改失败,密保错误,请重新输入');
197
+
198
+ // 通过密保校验 修改密码
199
+ let newHash = await bcrypt.hash(NEW_PWD, 10);
200
+ if (!newHash || newHash?.length > 64) return res.sendErr('密码加密失败');
201
+ let updatePwd = await userService.operTeamMember(USER_ID, { PASSWD: newHash, PASSWD_POWER });
202
+ if (!updatePwd) return res.sendErr('修改密码失败');
203
+ return res.sendOk('修改成功');
204
+ });
205
+
206
+ // 修改密码
207
+ router.put('/forget-password/updatePwd', async function (req, res) {
208
+ let { USER_ID, NEW_PWD, PASSWD_POWER } = req.body;
209
+
210
+ let userInfo = userService.getUserInfo(USER_ID);
211
+ if (!userInfo) return res.sendErr('用户ID无效');
212
+
213
+ if (!NEW_PWD) return res.sendErr('修改失败,参数无效');
214
+
215
+ let newHash = await bcrypt.hash(NEW_PWD, 10);
216
+ if (!newHash || newHash?.length > 64) return res.sendErr('密码加密失败');
217
+ let updatePwd = await userService.operTeamMember(USER_ID, { PASSWD: newHash, PASSWD_POWER });
218
+ if (!updatePwd) return res.sendErr('修改密码失败');
219
+ return res.sendOk('修改成功');
220
+ });
221
+
222
+ module.exports = router;