@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.
- package/README.md +7 -0
- package/app.js +36 -40
- package/backend/common/entity.js +55 -0
- package/backend/common/enum.js +247 -0
- package/backend/common/fss/index.js +18 -0
- package/backend/common/fss/routers/attachment.js +45 -0
- package/backend/common/fss/routers/download.js +43 -0
- package/backend/common/fss/routers/import_export.js +113 -0
- package/backend/common/fss/routers/resources.js +149 -0
- package/backend/common/fss/routers/upload.js +81 -0
- package/backend/common/fss/services/import_export.js +159 -0
- package/backend/common/fss/services/index.js +92 -0
- package/backend/common/fss/utils.js +39 -0
- package/backend/common/ginfo/config.js +5 -0
- package/backend/common/ginfo/index.js +62 -0
- package/backend/common/index_template.html +28 -0
- package/backend/common/logger/index.js +96 -0
- package/backend/common/mapping.js +98 -0
- package/backend/common/middleware/auth.js +97 -0
- package/backend/common/middleware/cors.js +13 -0
- package/backend/common/middleware/response.js +25 -0
- package/backend/common/page_engine.js +487 -0
- package/backend/common/schedule.js +45 -0
- package/backend/common/services/dataCombine.js +67 -0
- package/backend/common/services/dept.js +37 -0
- package/backend/common/services/dict.js +487 -0
- package/backend/common/services/email.js +49 -0
- package/backend/common/services/generalConfig.js +137 -0
- package/backend/common/services/login.js +18 -0
- package/backend/common/services/notice.js +260 -0
- package/backend/common/services/permission.js +500 -0
- package/backend/common/services/roles.js +57 -0
- package/backend/common/services/send-notice.js +86 -0
- package/backend/common/services/task.js +259 -0
- package/backend/common/services/user.js +673 -0
- package/backend/common/socket.js +18 -0
- package/backend/common/sse/index.js +81 -0
- package/backend/common/sse/router.js +30 -0
- package/backend/common/task.js +75 -0
- package/backend/common/wechat/index.js +9 -0
- package/backend/common/wechat/routers/auth.js +238 -0
- package/{modules/user/frontend → backend/common/wechat/routers}/index.html +14 -7
- package/backend/common/wechat/services/auth.js +209 -0
- package/backend/common/wechat/services/notice.js +171 -0
- package/backend/config/index.js +63 -0
- package/backend/config/path.js +3 -0
- package/backend/router.js +96 -0
- package/backend/routers/app.js +222 -0
- package/backend/routers/automate.js +276 -0
- package/backend/routers/dict.js +370 -0
- package/backend/routers/email.js +85 -0
- package/backend/routers/generalConfig.js +276 -0
- package/backend/routers/idm.js +245 -0
- package/backend/routers/module.js +357 -0
- package/backend/routers/notice.js +138 -0
- package/backend/routers/pages.js +46 -0
- package/backend/routers/permission.js +985 -0
- package/backend/routers/setting.js +184 -0
- package/backend/routers/team/index.js +22 -0
- package/backend/routers/team/routers/mapping.js +29 -0
- package/backend/routers/team/routers/member.js +72 -0
- package/backend/routers/team/routers/membermanage.js +289 -0
- package/backend/routers/team/routers/pages.js +47 -0
- package/backend/routers/team/routers/roles.js +92 -0
- package/backend/routers/team/routers/teaminfo.js +27 -0
- package/backend/routers/team/routers/usergroup.js +213 -0
- package/backend/routers/team/services/mapping.js +101 -0
- package/backend/routers/team/services/member.js +206 -0
- package/backend/routers/team/services/roles.js +71 -0
- package/backend/routers/team/services/teaminfo.js +20 -0
- package/backend/routers/team/services/usergroup.js +128 -0
- package/backend/routers/user.js +436 -0
- package/backend/services/automate.js +60 -0
- package/backend/services/config.js +14 -0
- package/backend/services/module.js +298 -0
- package/backend/services/permission.js +192 -0
- package/backend/services/services.js +115 -0
- package/backend/services/setting.js +190 -0
- package/backend/services/token.js +42 -0
- package/backend/space.js +52 -0
- package/backend/space_mapping.js +15 -0
- package/backend/utils/avatar.js +48 -0
- package/backend/utils/color_gen_helper.js +20 -0
- package/backend/utils/date.js +66 -0
- package/backend/utils/excel.js +446 -0
- package/backend/utils/fs/doc.md +64 -0
- package/backend/utils/fs/index.js +127 -0
- package/backend/utils/jwt.js +54 -0
- package/backend/utils/modules/sequence.js +93 -0
- package/backend/utils/object.js +31 -0
- package/backend/utils/page-query-helper/index.js +61 -0
- package/backend/utils/path.js +123 -0
- package/backend/utils/run.js +25 -0
- package/backend/utils/tokenize.js +82 -0
- package/backend/utils/typeof.js +5 -0
- package/backend/utils/util.js +153 -0
- package/backend/views/api/index.js +32 -0
- package/backend/views/api/index.xml +49 -0
- package/backend/views/dict/index.js +80 -0
- package/backend/views/dict/index.xml +52 -0
- package/backend/views/index.js +32 -0
- package/backend/views/members_manage/index.js +68 -0
- package/backend/views/members_manage/index.xml +68 -0
- package/backend/views/roles/index.js +17 -0
- package/backend/views/roles/index.xml +47 -0
- package/backend/views/usergroup/index.js +68 -0
- package/backend/views/usergroup/index.xml +65 -0
- package/dist/common-assets/css/index-05a08720.css +3 -0
- package/dist/common-assets/css/index-05a08720.css.gz +0 -0
- package/dist/common-assets/js/index-2e8c7128.js +762 -0
- package/dist/common-assets/js/index-2e8c7128.js.gz +0 -0
- package/dist/common-assets/js/react-cropper.es-19c27537.js +10 -0
- package/dist/common-assets/js/react-cropper.es-19c27537.js.gz +0 -0
- package/dist/common-assets/png/u9-2348c304.png +0 -0
- package/dist/common-assets/woff2/materialicons-83be7b2f.woff2 +0 -0
- package/dist/index.html +162 -0
- package/package.json +61 -5
- package/common/router.js +0 -42
- package/modules/user/backend/index.js +0 -19
- package/modules/user/backend/routers/user.js +0 -11
- package/modules/user/frontend/index.js +0 -1
- 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,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;
|