@gingkoo/base-server 0.0.1-alpha.0 → 0.0.1-alpha.1
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 +32 -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/assets/css/index-cc834b52.css +3 -0
- package/dist/assets/css/index-cc834b52.css.gz +0 -0
- package/dist/assets/js/index-9eef7474.js +762 -0
- package/dist/assets/js/index-9eef7474.js.gz +0 -0
- package/dist/assets/js/react-cropper.es-d3337769.js +10 -0
- package/dist/assets/js/react-cropper.es-d3337769.js.gz +0 -0
- package/dist/assets/png/u9-2348c304.png +0 -0
- package/dist/assets/woff2/materialicons-83be7b2f.woff2 +0 -0
- package/dist/index.html +162 -0
- package/package.json +60 -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,20 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { sqlExecutor, updateSqlBuilder, queryBaseSqlBuilder } = require('@gingkoo/node-tools');
|
|
3
|
+
const entity = require('../../../common/entity');
|
|
4
|
+
|
|
5
|
+
const teaminfoService = {
|
|
6
|
+
async getTeamInfoList() {
|
|
7
|
+
const { sql, params } = await queryBaseSqlBuilder(entity.IDM_ORGS, { ORG_ID: global.orgid });
|
|
8
|
+
let result = await sqlExecutor(sql, params);
|
|
9
|
+
return result;
|
|
10
|
+
},
|
|
11
|
+
async modifyTeamInfo(param) {
|
|
12
|
+
const { sql, params } = await updateSqlBuilder(entity.IDM_ORGS, param, {
|
|
13
|
+
ORG_ID: global.orgid,
|
|
14
|
+
});
|
|
15
|
+
let result = await sqlExecutor(sql, params);
|
|
16
|
+
return result;
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
module.exports = teaminfoService;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const {
|
|
3
|
+
sqlExecutor,
|
|
4
|
+
pageQuery,
|
|
5
|
+
insertSqlBuilder,
|
|
6
|
+
updateSqlBuilder,
|
|
7
|
+
deleteSqlBuilder,
|
|
8
|
+
queryBaseSqlBuilder,
|
|
9
|
+
queryParamsBuilder,
|
|
10
|
+
} = require('@gingkoo/node-tools');
|
|
11
|
+
const entity = require('../../../common/entity');
|
|
12
|
+
|
|
13
|
+
const userGroupService = {
|
|
14
|
+
//查询组成员
|
|
15
|
+
async getGroupUsers(filter) {
|
|
16
|
+
let filters = filter || {};
|
|
17
|
+
filter.ORG_ID = global.orgid;
|
|
18
|
+
const { sql, params } = await queryBaseSqlBuilder(entity.IDM_GROUPS, filters);
|
|
19
|
+
let result = await sqlExecutor(sql, params);
|
|
20
|
+
return result;
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
// 新增成员组
|
|
24
|
+
async addUserGroup(filter) {
|
|
25
|
+
let filters = filter || {};
|
|
26
|
+
filter.ORG_ID = global.orgid;
|
|
27
|
+
const { sql, params } = await insertSqlBuilder(entity.IDM_GROUPS, filters);
|
|
28
|
+
let result = await sqlExecutor(sql, params);
|
|
29
|
+
|
|
30
|
+
return result;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// 删除组
|
|
34
|
+
async deleteGroup(filter) {
|
|
35
|
+
let filters = filter || {};
|
|
36
|
+
filters.ORG_ID = global.orgid;
|
|
37
|
+
const { sql, params } = await deleteSqlBuilder(entity.IDM_GROUPS, filter);
|
|
38
|
+
const result = await sqlExecutor(sql, params);
|
|
39
|
+
if (result.error) return null;
|
|
40
|
+
return result;
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
//修改组
|
|
44
|
+
async modifyGroup(body, filter) {
|
|
45
|
+
let filters = filter || {};
|
|
46
|
+
filters.ORG_ID = global.orgid;
|
|
47
|
+
const { sql, params } = await updateSqlBuilder(entity.IDM_GROUPS, body, filters);
|
|
48
|
+
let result = await sqlExecutor(sql, params);
|
|
49
|
+
if (result.error) return null;
|
|
50
|
+
return result;
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
//查询组成员
|
|
54
|
+
async getGroupUserList(filter, pageInfo) {
|
|
55
|
+
let pageSize = pageInfo.pageSize;
|
|
56
|
+
let pageIndex = pageInfo.pageIndex;
|
|
57
|
+
let sql = `SELECT * from ${entity.IDM_USERS} a WHERE USER_ID in(SELECT USER_ID FROM ${entity.IDM_GROUP_MEMBERS} WHERE ORG_ID ='${global.orgid}' AND a.STATUS = '00' AND a.USER_STATUS='normal' AND GROUP_ID = '${filter.GROUP_ID}') `;
|
|
58
|
+
let searchParam = {};
|
|
59
|
+
let props = {};
|
|
60
|
+
for (let v in filter) {
|
|
61
|
+
if (v !== 'GROUP_ID') {
|
|
62
|
+
searchParam[v] = filter[v];
|
|
63
|
+
props[v] = 'like';
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
if (Object.keys(filter).length > 1) {
|
|
67
|
+
const result = await queryParamsBuilder(searchParam, null, null, props);
|
|
68
|
+
sql += ' and ' + result.sql;
|
|
69
|
+
}
|
|
70
|
+
let results = await pageQuery(sql, [], pageSize, pageIndex);
|
|
71
|
+
if (!results) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
return results;
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
//查询用户组成员
|
|
78
|
+
async getGroupUser(GROUP_ID, USER_ID) {
|
|
79
|
+
let sql = `SELECT * FROM idm_group_members WHERE ORG_ID =? AND GROUP_ID=? AND USER_ID IN (?)`;
|
|
80
|
+
let result = await sqlExecutor(sql, [global.orgid, GROUP_ID, USER_ID]);
|
|
81
|
+
if (result.error) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return result.results;
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
// 新增用户组成员
|
|
89
|
+
async addGroupUser(filter) {
|
|
90
|
+
let filters = filter || {};
|
|
91
|
+
filters.ORG_ID = global.orgid;
|
|
92
|
+
const { sql, params } = await insertSqlBuilder(entity.IDM_GROUP_MEMBERS, filters);
|
|
93
|
+
const result = await sqlExecutor(sql, params);
|
|
94
|
+
if (result.error) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return result;
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
// 删除用户组成员
|
|
102
|
+
async delGroupUser(filter) {
|
|
103
|
+
let filters = filter || {};
|
|
104
|
+
filters.ORG_ID = global.orgid;
|
|
105
|
+
const { sql, params } = await deleteSqlBuilder(entity.IDM_GROUP_MEMBERS, filters);
|
|
106
|
+
let result = await sqlExecutor(sql, params);
|
|
107
|
+
if (result.error) return null;
|
|
108
|
+
return result;
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
// 修改用户组成员
|
|
112
|
+
async modifyGroupUser(filter) {
|
|
113
|
+
let body = {
|
|
114
|
+
REMARKS: filter.REMARKS || '',
|
|
115
|
+
USER_ROLE: filter.USER_ROLE || '',
|
|
116
|
+
};
|
|
117
|
+
let { sql, params } = await updateSqlBuilder(entity.IDM_GROUP_MEMBERS, body, {
|
|
118
|
+
GROUP_ID: filter.GROUP_ID,
|
|
119
|
+
USER_ID: filter.USER_ID,
|
|
120
|
+
ORG_ID: global.orgid,
|
|
121
|
+
});
|
|
122
|
+
const result = await sqlExecutor(sql, params);
|
|
123
|
+
if (result.error) return null;
|
|
124
|
+
return result;
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
module.exports = userGroupService;
|
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var express = require('express');
|
|
3
|
+
const bcrypt = require('bcryptjs');
|
|
4
|
+
const dayjs = require('dayjs');
|
|
5
|
+
const nodemailer = require('nodemailer');
|
|
6
|
+
|
|
7
|
+
var router = express.Router();
|
|
8
|
+
const servicesServices = require('../services/services');
|
|
9
|
+
const tokenService = require('../services/token');
|
|
10
|
+
|
|
11
|
+
const { fileExist } = require('../utils/path');
|
|
12
|
+
const { checkLogin } = require('../common/middleware/auth');
|
|
13
|
+
const userService = require('../common/services/user');
|
|
14
|
+
const generalConfig = require('../common/services/generalConfig');
|
|
15
|
+
const emailService = require('../common/services/email');
|
|
16
|
+
const taskService = require('../common/services/task');
|
|
17
|
+
const { sse, bgTaskEnum } = require('../common/sse');
|
|
18
|
+
|
|
19
|
+
router.get('/userInfo', checkLogin, async function (req, res) {
|
|
20
|
+
let userid = req.get('X-UserId');
|
|
21
|
+
let userinfo = await servicesServices.getUserInfo(userid);
|
|
22
|
+
if (!userinfo) {
|
|
23
|
+
return res.sendErr('未找到用户信息');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let [err, userSecuritys] = await userService.getUserSecurity({ USER_ID: userid });
|
|
27
|
+
if (Array.isArray(userSecuritys) && userSecuritys.length) {
|
|
28
|
+
userinfo.security = userSecuritys;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
res.sendOk(userinfo);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
router.put('/user/:userid', async function (req, res) {
|
|
35
|
+
let userid = req.params['userid'];
|
|
36
|
+
if (!userid) return res.sendErr('缺少用户ID');
|
|
37
|
+
if (!Object.values(req.body).length) return res.sendErr('缺少参数');
|
|
38
|
+
let userFields = [
|
|
39
|
+
'USER_NAME',
|
|
40
|
+
'EN_NAME',
|
|
41
|
+
'NIKE_NAME',
|
|
42
|
+
'GENDER',
|
|
43
|
+
'EMAIL',
|
|
44
|
+
'MOBILE',
|
|
45
|
+
'TEL',
|
|
46
|
+
'TITLE',
|
|
47
|
+
'DEPT_NO',
|
|
48
|
+
'AVATAR',
|
|
49
|
+
'ADDR',
|
|
50
|
+
'POSITION',
|
|
51
|
+
'EDUCATION',
|
|
52
|
+
'SCHOOL',
|
|
53
|
+
'ADMISSION_DATE',
|
|
54
|
+
'JOINED_DATE',
|
|
55
|
+
'BIRTHDAY',
|
|
56
|
+
'MAJOR',
|
|
57
|
+
'DEGREE',
|
|
58
|
+
'HOPPY',
|
|
59
|
+
'SOCIAL_ACCOUNTS',
|
|
60
|
+
'PER_INTRODUCTION',
|
|
61
|
+
'WORK_DATE',
|
|
62
|
+
'LANGUAGE',
|
|
63
|
+
'AREA',
|
|
64
|
+
'TIMEFORMAT',
|
|
65
|
+
'DATEFROMAT',
|
|
66
|
+
'WORK_STATUS',
|
|
67
|
+
'WORK_SIGN',
|
|
68
|
+
'WORK_SIGNICON',
|
|
69
|
+
'LEAVE_DATE',
|
|
70
|
+
'DUTY',
|
|
71
|
+
];
|
|
72
|
+
let userProps = {};
|
|
73
|
+
for (let k in req.body) {
|
|
74
|
+
if (userFields.indexOf(k) != -1) {
|
|
75
|
+
userProps[k] = req.body[k];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
let editAccount = await userService.operTeamMember(userid, userProps);
|
|
79
|
+
if (!editAccount) {
|
|
80
|
+
return res.sendOk('修改失败');
|
|
81
|
+
}
|
|
82
|
+
return res.sendOk('修改成功');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// 修改用户头像
|
|
86
|
+
router.post('/userAvatar/:userid', async function (req, res) {
|
|
87
|
+
let userid = req.params['userid'];
|
|
88
|
+
if (!userid) return res.sendOk('没有权限');
|
|
89
|
+
let { filepath } = req.body;
|
|
90
|
+
|
|
91
|
+
let editAccountAvatar = await userService.operTeamMember(userid, {
|
|
92
|
+
AVATAR: filepath,
|
|
93
|
+
});
|
|
94
|
+
if (!editAccountAvatar) return res.sendOk('修改失败');
|
|
95
|
+
res.sendOk({ value: '修改成功' });
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
router.get('/resources/:fileFolder/*', async function (req, res) {
|
|
99
|
+
let userid = req.get('X-UserId');
|
|
100
|
+
let filePath = resourcePath(
|
|
101
|
+
global.orgid,
|
|
102
|
+
userid,
|
|
103
|
+
req.params['fileFolder'],
|
|
104
|
+
req.path.split('/').slice(-1)[0],
|
|
105
|
+
);
|
|
106
|
+
if (!filePath) {
|
|
107
|
+
res.sendErr('resource not found');
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
filePath = decodeURIComponent(filePath);
|
|
111
|
+
let isExist = await fileExist(filePath);
|
|
112
|
+
if (isExist) {
|
|
113
|
+
var options = {
|
|
114
|
+
headers: {
|
|
115
|
+
'x-timestamp': Date.now(),
|
|
116
|
+
'x-sent': true,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
res.sendFile(filePath, options);
|
|
121
|
+
} else {
|
|
122
|
+
res.sendOk(404, 'resource not found');
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// 查询用户 token 列表
|
|
127
|
+
router.get('/token', async function (req, res) {
|
|
128
|
+
let userid = req.get('X-UserId');
|
|
129
|
+
let query = req.query;
|
|
130
|
+
|
|
131
|
+
let params = {};
|
|
132
|
+
tokenService.queryFields.forEach((field) => {
|
|
133
|
+
if (Reflect.has(query, field)) {
|
|
134
|
+
params[field] = query[field];
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
let [err, list] = await tokenService.getTokens({
|
|
139
|
+
USER_ID: userid,
|
|
140
|
+
...params,
|
|
141
|
+
});
|
|
142
|
+
if (err) {
|
|
143
|
+
return res.sendErr(err?.message);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
res.sendOk(
|
|
147
|
+
list.map((v) => {
|
|
148
|
+
let DATA_CRT_DATE = v.DATA_CRT_DATE || '';
|
|
149
|
+
let { TOKEN_CERT, ...rest } = v;
|
|
150
|
+
return {
|
|
151
|
+
...rest,
|
|
152
|
+
DATA_CRT_DATE: DATA_CRT_DATE
|
|
153
|
+
? DATA_CRT_DATE.slice(0, 4) +
|
|
154
|
+
'-' +
|
|
155
|
+
DATA_CRT_DATE.slice(4, 6) +
|
|
156
|
+
'-' +
|
|
157
|
+
DATA_CRT_DATE.slice(6)
|
|
158
|
+
: '',
|
|
159
|
+
};
|
|
160
|
+
}),
|
|
161
|
+
);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// 新增 token
|
|
165
|
+
router.post('/token', async function (req, res) {
|
|
166
|
+
let userid = req.get('X-UserId');
|
|
167
|
+
const body = req.body;
|
|
168
|
+
|
|
169
|
+
let params = {};
|
|
170
|
+
tokenService.createFields.forEach((field) => {
|
|
171
|
+
if (Reflect.has(body, field)) {
|
|
172
|
+
params[field] = body[field];
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
let [err] = await tokenService.createToken(userid, params);
|
|
177
|
+
if (err) {
|
|
178
|
+
return res.sendErr(err?.message);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
res.sendOk('添加成功');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// 查询用户 能生成 token 的应用列表
|
|
185
|
+
router.get('/token/apps', async function (req, res) {
|
|
186
|
+
// let userid = req.get('X-UserId');
|
|
187
|
+
|
|
188
|
+
// let [err, list] = await tokenService.tokenApps(userid);
|
|
189
|
+
// if (err) {
|
|
190
|
+
// return res.sendErr(err?.message);
|
|
191
|
+
// }
|
|
192
|
+
|
|
193
|
+
res.sendOk([]);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// 删除用户 token
|
|
197
|
+
router.delete('/token/:tokenId', async function (req, res) {
|
|
198
|
+
let userid = req.get('X-UserId');
|
|
199
|
+
let { tokenId } = req.params;
|
|
200
|
+
|
|
201
|
+
let [err] = await tokenService.update(
|
|
202
|
+
{
|
|
203
|
+
STATUS: '01',
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
USER_ID: userid,
|
|
207
|
+
TOKEN_ID: tokenId,
|
|
208
|
+
},
|
|
209
|
+
);
|
|
210
|
+
if (err) {
|
|
211
|
+
return res.sendErr(err?.message);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
res.sendOk();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// 获取用户的dict
|
|
218
|
+
router.get('/userinfo/dict', async function (req, res) {
|
|
219
|
+
let data = await servicesServices.getMappings();
|
|
220
|
+
return res.sendOk(data);
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// 修改密码
|
|
224
|
+
router.put('/update/passWord', async function (req, res) {
|
|
225
|
+
let userid = req.get('X-UserId');
|
|
226
|
+
let { oldPassWord, newPassWord, PASSWD_POWER } = req.body;
|
|
227
|
+
|
|
228
|
+
if (!newPassWord) return res.sendErr('缺少参数');
|
|
229
|
+
if (
|
|
230
|
+
typeof newPassWord !== 'string' ||
|
|
231
|
+
(typeof newPassWord === 'string' && newPassWord.length < 6)
|
|
232
|
+
)
|
|
233
|
+
return res.sendErr('密码参数不规范');
|
|
234
|
+
|
|
235
|
+
let userinfo = await servicesServices.getUserInfo(userid);
|
|
236
|
+
if (!userinfo) {
|
|
237
|
+
return res.sendErr('查询当前用户信息失败');
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (userinfo.PASSWD) {
|
|
241
|
+
// 判断旧密码是否正确
|
|
242
|
+
let flag = await bcrypt.compare(oldPassWord, userinfo.PASSWD);
|
|
243
|
+
if (!flag) return res.sendErr('原密码错误');
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// 新密码加密存放到数据库中
|
|
247
|
+
let newHash = await bcrypt.hash(newPassWord, 10);
|
|
248
|
+
|
|
249
|
+
if (!newHash || newHash?.length > 64) return res.sendErr('密码加密失败');
|
|
250
|
+
let updatePwd = await userService.operTeamMember(userid, { PASSWD: newHash, PASSWD_POWER });
|
|
251
|
+
if (!updatePwd) return res.sendErr('修改密码失败');
|
|
252
|
+
return res.sendOk('修改成功');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// 发送邮箱验证码
|
|
256
|
+
router.post('/sendEmailCode', async function (req, res) {
|
|
257
|
+
const email = req.body['EMAIL'];
|
|
258
|
+
if (!email) return res.sendErr('缺少邮件地址');
|
|
259
|
+
|
|
260
|
+
// 随机生成验证码,发送验证码,并返回前端
|
|
261
|
+
let code = Math.floor(Math.random() * (1000000 - 100000) + 100000);
|
|
262
|
+
|
|
263
|
+
let smtp = await generalConfig.getFromConfig({ GROUP_ID: 'E-mail' });
|
|
264
|
+
if (!smtp) return res.sendErr('查询失败');
|
|
265
|
+
const { SMTP_PASSWORK, SMTP_SERVE, SMTP_USER, SMTP_SEND, SMTP_PORT, SMTP_TLS } = smtp;
|
|
266
|
+
if (!SMTP_PASSWORK || !SMTP_SERVE || !SMTP_USER) return res.sendErr('系统缺少数据');
|
|
267
|
+
|
|
268
|
+
// 创建一个SMTP传输对象
|
|
269
|
+
const transporter = nodemailer.createTransport({
|
|
270
|
+
host: SMTP_SERVE,
|
|
271
|
+
post: SMTP_PORT ? SMTP_PORT : 456,
|
|
272
|
+
secure: SMTP_TLS || true,
|
|
273
|
+
auth: {
|
|
274
|
+
user: SMTP_USER || 'service@gingkoo.com', // 发件人邮箱
|
|
275
|
+
pass: SMTP_PASSWORK || 'Jinqiu123', // 发件人邮箱的密码或授权码
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
let html = ``;
|
|
280
|
+
let emails = await emailService.getTempateInfo({ TEMPLATE_ID: 'email_code' });
|
|
281
|
+
if (emails[0]?.CONTENT) {
|
|
282
|
+
html = emails[0]?.CONTENT;
|
|
283
|
+
html = html.replace('{{code}}', code);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
//邮件的内容
|
|
287
|
+
const mailOptions = {
|
|
288
|
+
from: SMTP_SEND ? SMTP_SEND + `<${SMTP_USER}>` : SMTP_USER, // 发件人邮箱
|
|
289
|
+
to: email, // 收件人邮箱
|
|
290
|
+
subject: 'teams团队协同 账号安全中心-绑定邮箱验证',
|
|
291
|
+
html: html,
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
transporter.sendMail(mailOptions, (error, info) => {
|
|
295
|
+
if (error) {
|
|
296
|
+
console.log('发送邮件错误:', error);
|
|
297
|
+
} else {
|
|
298
|
+
// console.log('发送成功:', info);
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
return res.sendOk({ code });
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// 设置密保SECURITY
|
|
306
|
+
router.put('/security', async function (req, res) {
|
|
307
|
+
const userid = req.get('X-UserId');
|
|
308
|
+
|
|
309
|
+
const { SECURITY_PROBLEM, SECURITY_ANSWER } = req.body;
|
|
310
|
+
if (!SECURITY_PROBLEM || !SECURITY_ANSWER) return res.sendErr('设置密保参数错误');
|
|
311
|
+
let props = {
|
|
312
|
+
SECUR_TYPE: 'question',
|
|
313
|
+
SECUR_KEY: SECURITY_PROBLEM,
|
|
314
|
+
SECUR_VALUE: SECURITY_ANSWER,
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
let result = false;
|
|
318
|
+
let [err1, userSecuritys] = await userService.getUserSecurity({ USER_ID: userid });
|
|
319
|
+
if (Array.isArray(userSecuritys) && userSecuritys.length) {
|
|
320
|
+
let [err2, update] = await userService.updateUserSecurity({ USER_ID: userid }, props);
|
|
321
|
+
result = update;
|
|
322
|
+
}
|
|
323
|
+
if (Array.isArray(userSecuritys) && !userSecuritys.length) {
|
|
324
|
+
let [err2, create] = await userService.addUserSecurity({ ...props, USER_ID: userid });
|
|
325
|
+
result = create;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (!result) return res.sendErr('操作失败');
|
|
329
|
+
|
|
330
|
+
return res.sendOk('操作成功');
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// 获取用户登录历史记录
|
|
334
|
+
router.get('/history', async function (req, res) {
|
|
335
|
+
const userId = req.get('X-UserId');
|
|
336
|
+
|
|
337
|
+
const token = req.cookies['X-Token'] || req.get('X-Token');
|
|
338
|
+
const ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress;
|
|
339
|
+
if (!token || !userId) return res.sendOk([]);
|
|
340
|
+
|
|
341
|
+
let { LOG_DEVICE_SYSTEM, LOG_BROWSER } = req.query;
|
|
342
|
+
if (LOG_DEVICE_SYSTEM && LOG_BROWSER) {
|
|
343
|
+
// 判断当前token是否登记过,如果登记过,则修改下最后登录时间,如果没有,则添加登录记录
|
|
344
|
+
let [err1, logs] = await userService.getUserHistory({
|
|
345
|
+
LOG_DEVICE_SYSTEM,
|
|
346
|
+
LOG_BROWSER,
|
|
347
|
+
USER_ID: userId,
|
|
348
|
+
});
|
|
349
|
+
if (Array.isArray(logs) && logs.length) {
|
|
350
|
+
// 存在记录
|
|
351
|
+
let [err] = await userService.updateUserHistory(
|
|
352
|
+
{ LOG_DEVICE_SYSTEM, LOG_BROWSER, USER_ID: userId },
|
|
353
|
+
{ LOG_LAST_USAGE: dayjs().format('YYYYMMDDHHmmss'), LOG_TOKEN: token, LOG_IP: ip },
|
|
354
|
+
);
|
|
355
|
+
} else {
|
|
356
|
+
let [err] = await userService.createUserHistory(
|
|
357
|
+
{
|
|
358
|
+
...req.body,
|
|
359
|
+
LOG_TOKEN: token,
|
|
360
|
+
LOG_IP: req.body['LOG_IP'] || ip,
|
|
361
|
+
},
|
|
362
|
+
userId,
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
let [error, list] = await userService.getUserHistory({ USER_ID: userId, LOG_STATUS: '1' }, 5);
|
|
368
|
+
if (error || !Array.isArray(list)) return res.sendErr(error);
|
|
369
|
+
|
|
370
|
+
return res.sendOk(list);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
// 查询导入导出后台任务列表
|
|
374
|
+
router.get('/export-import/log', async function (req, res) {
|
|
375
|
+
let TASK_SERVICE = req.query['TASK_SERVICE'];
|
|
376
|
+
const USER_ID = req.get('X-UserId');
|
|
377
|
+
if (!TASK_SERVICE) return res.sendErr('缺少类型参数');
|
|
378
|
+
|
|
379
|
+
let result = await taskService.selectTaskPaging(
|
|
380
|
+
{ TASK_SERVICE, USER_ID, ...req.query },
|
|
381
|
+
' order by DATA_CRT_TIME desc',
|
|
382
|
+
{ TASK_NAME: 'like' },
|
|
383
|
+
req.query,
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
if (!result) return res.sendErr('查询失败');
|
|
387
|
+
|
|
388
|
+
return res.sendOk(result);
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// 删除后台任务
|
|
392
|
+
router.delete('/export-import/log/:taskId', async function (req, res) {
|
|
393
|
+
const USER_ID = req.get('X-UserId');
|
|
394
|
+
let TASK_ID = req.params['taskId'];
|
|
395
|
+
|
|
396
|
+
let del = await taskService.deleteTask({ TASK_ID, USER_ID });
|
|
397
|
+
if (!del) return res.sendErr('删除失败');
|
|
398
|
+
return res.sendOk('删除成功');
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// 取消后台任务
|
|
402
|
+
router.put('/export-import/log/:taskId', async function (req, res) {
|
|
403
|
+
const USER_ID = req.get('X-UserId');
|
|
404
|
+
let TASK_ID = req.params['taskId'];
|
|
405
|
+
let tasks = await taskService.selectTask({ TASK_ID });
|
|
406
|
+
if (!tasks || !tasks[0] || tasks.length !== 1) return res.sendErr('查询失败');
|
|
407
|
+
|
|
408
|
+
let { TASK_SERVICE, FILE_DIR, FILE_NAME } = tasks[0];
|
|
409
|
+
|
|
410
|
+
// 修改后台任务的状态为取消状态
|
|
411
|
+
await taskService.updateTask({ TASK_ID, STATUS: 'Cancel' });
|
|
412
|
+
|
|
413
|
+
sse.overBgTaskStatus(
|
|
414
|
+
{
|
|
415
|
+
TASK_ID,
|
|
416
|
+
taskProgressStatus: bgTaskEnum.taskProgressStatus.taskError,
|
|
417
|
+
STATUS: 'Cancel',
|
|
418
|
+
DATA_UPD_TIME: dayjs().format('YYYYMMDDHHmmss'),
|
|
419
|
+
DATA_UPD_DATE: dayjs().format('YYYYMMDD'),
|
|
420
|
+
},
|
|
421
|
+
USER_ID,
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
sse.cancelBgTaskStatus(TASK_ID, USER_ID);
|
|
425
|
+
|
|
426
|
+
if (TASK_SERVICE === 'issueImport') {
|
|
427
|
+
// 取消导入后台任务 找到导入新创建的工作项然后删除
|
|
428
|
+
// 重新读取文件
|
|
429
|
+
} else if (TASK_SERVICE === 'issueExport') {
|
|
430
|
+
// 取消导出后台任务 可以删除服务器已经创建好的文件
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
res.sendOk();
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
module.exports = router;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
sqlExecutor,
|
|
5
|
+
insertSqlBuilder,
|
|
6
|
+
updateSqlBuilder,
|
|
7
|
+
queryParamsBuilder,
|
|
8
|
+
} = require('@gingkoo/node-tools');
|
|
9
|
+
const entity = require('../common/entity');
|
|
10
|
+
|
|
11
|
+
module.exports = {
|
|
12
|
+
// ---------------- 公共方法 ------------
|
|
13
|
+
// 批量更新mapping
|
|
14
|
+
async batchUpdate(table, setValue, filters) {
|
|
15
|
+
let { sql, params } = updateSqlBuilder(table, setValue, filters);
|
|
16
|
+
let { error, results } = await sqlExecutor(sql, params);
|
|
17
|
+
if (error) {
|
|
18
|
+
console.log(error);
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return results;
|
|
23
|
+
},
|
|
24
|
+
// 插入
|
|
25
|
+
async batchInsert(table, setValue) {
|
|
26
|
+
let { sql, params } = insertSqlBuilder(table, setValue);
|
|
27
|
+
let { error, results } = await sqlExecutor(sql, params);
|
|
28
|
+
if (error) {
|
|
29
|
+
console.log(error);
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return results;
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 获取自动化规则列表
|
|
38
|
+
*/
|
|
39
|
+
async getAutoMateList(filters) {
|
|
40
|
+
let sql = `select
|
|
41
|
+
DATA_ID, AUTO_NAME, AUTO_DESC, ISSUE_TYPE, PROJECT_ID, TRIGER_TYPE, AUTO_SCOPE, FIELDS, START_STATUS, END_STATUS, FLOW_CHART, LAST_REVISER, ENABLE, USER_ID, DATA_CRT_DATE, DATA_UPD_DATE
|
|
42
|
+
FROM ISSUE_AUTOMATION
|
|
43
|
+
where STATUS = '00'`;
|
|
44
|
+
let sqlParams = [];
|
|
45
|
+
if (Object.keys(filters).length > 0) {
|
|
46
|
+
let queryParam = queryParamsBuilder(filters, '', null, {
|
|
47
|
+
AUTO_NAME: 'like',
|
|
48
|
+
});
|
|
49
|
+
sql = sql + ' and ' + queryParam.sql;
|
|
50
|
+
sqlParams = queryParam.params;
|
|
51
|
+
}
|
|
52
|
+
sql += ' order by DATA_CRT_TIME DESC';
|
|
53
|
+
let { error, results } = await sqlExecutor(sql, sqlParams);
|
|
54
|
+
if (error) {
|
|
55
|
+
console.log(error);
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
return results;
|
|
59
|
+
},
|
|
60
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { sqlExecutor } = require('@gingkoo/node-tools');
|
|
3
|
+
const entity = require('../common/entity');
|
|
4
|
+
|
|
5
|
+
const configService = {
|
|
6
|
+
getTeamLogo: async function () {
|
|
7
|
+
let sql = `SELECT LOGO FROM ${entity.IDM_ORGS} WHERE ORG_ID =?`;
|
|
8
|
+
let result = await sqlExecutor(sql, [global.orgid]);
|
|
9
|
+
if (result.error || result.results.length == 0) return null;
|
|
10
|
+
return result.results[0].LOGO;
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
module.exports = configService;
|