@kne/fastify-account 1.0.0-alpha.1 → 1.0.0-alpha.10
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 +101 -5
- package/index.js +13 -4
- package/libs/controllers/account.js +8 -7
- package/libs/controllers/admin.js +16 -15
- package/libs/controllers/adminPermission.js +42 -35
- package/libs/controllers/adminRole.js +13 -12
- package/libs/controllers/adminTenant.js +39 -36
- package/libs/controllers/tenant.js +16 -4
- package/libs/controllers/user.js +23 -1
- package/libs/models/admin-role.js +4 -8
- package/libs/models/application.js +16 -10
- package/libs/models/login-log.js +4 -8
- package/libs/models/permission.js +7 -9
- package/libs/models/tenant-application.js +8 -10
- package/libs/models/tenant-org.js +5 -9
- package/libs/models/tenant-permission.js +7 -9
- package/libs/models/tenant-role-application.js +14 -10
- package/libs/models/tenant-role-permission.js +10 -9
- package/libs/models/tenant-role.js +5 -9
- package/libs/models/tenant-share-group-permission.js +5 -9
- package/libs/models/tenant-share-group.js +5 -9
- package/libs/models/tenant-source-user-share-group.js +5 -9
- package/libs/models/tenant-token.js +7 -9
- package/libs/models/tenant-user-org.js +11 -10
- package/libs/models/tenant-user-role.js +11 -10
- package/libs/models/tenant-user-share-group.js +6 -10
- package/libs/models/tenant-user.js +35 -16
- package/libs/models/tenant.js +17 -9
- package/libs/models/user-account.js +17 -9
- package/libs/models/user.js +27 -17
- package/libs/models/verification-code.js +4 -8
- package/libs/services/account.js +34 -16
- package/libs/services/admin.js +17 -121
- package/libs/services/application.js +151 -0
- package/libs/services/permission.js +47 -145
- package/libs/services/tenant-invite.js +62 -0
- package/libs/services/tenant-org.js +97 -0
- package/libs/services/tenant-role.js +108 -0
- package/libs/services/tenant-user.js +555 -0
- package/libs/services/tenant.js +68 -512
- package/libs/services/user.js +69 -30
- package/package.json +3 -3
package/libs/services/account.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const fp = require('fastify-plugin');
|
|
2
2
|
const dayjs = require('dayjs');
|
|
3
3
|
const bcrypt = require('bcryptjs');
|
|
4
|
+
const crypto = require('crypto');
|
|
4
5
|
|
|
5
6
|
function generateRandom6DigitNumber() {
|
|
6
7
|
const randomNumber = Math.random() * 1000000;
|
|
@@ -12,9 +13,10 @@ function userNameIsEmail(username) {
|
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
module.exports = fp(async (fastify, options) => {
|
|
16
|
+
const { models, services } = fastify.account;
|
|
15
17
|
const login = async ({ username, password, ip }) => {
|
|
16
18
|
const isEmail = userNameIsEmail(username);
|
|
17
|
-
const user = await
|
|
19
|
+
const user = await models.user.findOne({
|
|
18
20
|
where: Object.assign(
|
|
19
21
|
{},
|
|
20
22
|
isEmail
|
|
@@ -38,16 +40,23 @@ module.exports = fp(async (fastify, options) => {
|
|
|
38
40
|
|
|
39
41
|
await passwordAuthentication({ accountId: user.userAccountId, password });
|
|
40
42
|
|
|
41
|
-
await
|
|
42
|
-
userId: user.
|
|
43
|
+
await models.loginLog.create({
|
|
44
|
+
userId: user.uuid,
|
|
43
45
|
ip
|
|
44
46
|
});
|
|
45
47
|
|
|
46
|
-
return
|
|
48
|
+
return {
|
|
49
|
+
token: fastify.jwt.sign({ payload: { id: user.uuid } }),
|
|
50
|
+
user: Object.assign({}, user.get({ plain: true }), { id: user.uuid })
|
|
51
|
+
};
|
|
47
52
|
};
|
|
48
53
|
|
|
49
54
|
const passwordAuthentication = async ({ accountId, password }) => {
|
|
50
|
-
const userAccount = await
|
|
55
|
+
const userAccount = await models.userAccount.findOne({
|
|
56
|
+
where: {
|
|
57
|
+
uuid: accountId
|
|
58
|
+
}
|
|
59
|
+
});
|
|
51
60
|
if (!userAccount) {
|
|
52
61
|
throw new Error('账号不存在');
|
|
53
62
|
}
|
|
@@ -68,23 +77,31 @@ module.exports = fp(async (fastify, options) => {
|
|
|
68
77
|
};
|
|
69
78
|
};
|
|
70
79
|
|
|
80
|
+
const md5 = value => {
|
|
81
|
+
const hash = crypto.createHash('md5');
|
|
82
|
+
hash.update(value);
|
|
83
|
+
return hash.digest('hex');
|
|
84
|
+
};
|
|
85
|
+
|
|
71
86
|
const resetPassword = async ({ userId, password }) => {
|
|
72
|
-
const userInfo = await
|
|
87
|
+
const userInfo = await models.user.findOne({
|
|
88
|
+
where: { uuid: userId }
|
|
89
|
+
});
|
|
73
90
|
if (!userInfo) {
|
|
74
91
|
throw new Error('用户不存在');
|
|
75
92
|
}
|
|
76
|
-
const account = await
|
|
93
|
+
const account = await models.userAccount.create(
|
|
77
94
|
Object.assign({}, await passwordEncryption(password), {
|
|
78
95
|
belongToUserId: userId
|
|
79
96
|
})
|
|
80
97
|
);
|
|
81
98
|
|
|
82
|
-
await userInfo.update({ userAccountId: account.
|
|
99
|
+
await userInfo.update({ userAccountId: account.uuid });
|
|
83
100
|
};
|
|
84
101
|
|
|
85
102
|
const register = async ({ avatar, nickname, gender, birthday, description, phone, email, code, password, status, invitationCode }) => {
|
|
86
103
|
const type = phone ? 0 : 1;
|
|
87
|
-
const verificationCode = await
|
|
104
|
+
const verificationCode = await models.verificationCode.findOne({
|
|
88
105
|
where: {
|
|
89
106
|
name: type === 0 ? phone : email,
|
|
90
107
|
type,
|
|
@@ -99,7 +116,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
99
116
|
verificationCode.status = 2;
|
|
100
117
|
await verificationCode.save();
|
|
101
118
|
|
|
102
|
-
return await
|
|
119
|
+
return await services.user.addUser({
|
|
103
120
|
avatar,
|
|
104
121
|
nickname,
|
|
105
122
|
gender,
|
|
@@ -117,7 +134,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
117
134
|
|
|
118
135
|
// 这里写发送逻辑
|
|
119
136
|
|
|
120
|
-
await
|
|
137
|
+
await models.verificationCode.update(
|
|
121
138
|
{
|
|
122
139
|
status: 2
|
|
123
140
|
},
|
|
@@ -130,7 +147,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
130
147
|
}
|
|
131
148
|
);
|
|
132
149
|
|
|
133
|
-
await
|
|
150
|
+
await models.verificationCode.create({
|
|
134
151
|
name: email,
|
|
135
152
|
type: 1,
|
|
136
153
|
code
|
|
@@ -140,7 +157,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
140
157
|
};
|
|
141
158
|
|
|
142
159
|
const verificationCodeValidate = async ({ name, type, code }) => {
|
|
143
|
-
const verificationCode = await
|
|
160
|
+
const verificationCode = await models.verificationCode.findOne({
|
|
144
161
|
where: {
|
|
145
162
|
name,
|
|
146
163
|
type,
|
|
@@ -165,7 +182,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
165
182
|
|
|
166
183
|
// 这里写发送逻辑
|
|
167
184
|
|
|
168
|
-
await
|
|
185
|
+
await models.verificationCode.update(
|
|
169
186
|
{
|
|
170
187
|
status: 2
|
|
171
188
|
},
|
|
@@ -178,7 +195,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
178
195
|
}
|
|
179
196
|
);
|
|
180
197
|
|
|
181
|
-
await
|
|
198
|
+
await models.verificationCode.create({
|
|
182
199
|
name: phone,
|
|
183
200
|
type: 0,
|
|
184
201
|
code
|
|
@@ -187,7 +204,8 @@ module.exports = fp(async (fastify, options) => {
|
|
|
187
204
|
return code;
|
|
188
205
|
};
|
|
189
206
|
|
|
190
|
-
|
|
207
|
+
services.account = {
|
|
208
|
+
md5,
|
|
191
209
|
login,
|
|
192
210
|
register,
|
|
193
211
|
sendEmailCode,
|
package/libs/services/admin.js
CHANGED
|
@@ -6,31 +6,30 @@ const ROLE = {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
module.exports = fp(async (fastify, options) => {
|
|
9
|
+
const { models, services } = fastify.account;
|
|
9
10
|
const initSuperAdmin = async user => {
|
|
10
|
-
if ((await
|
|
11
|
+
if ((await models.adminRole.count()) > 0) {
|
|
11
12
|
throw new Error('系统已经初始化完成,不能执行该操作');
|
|
12
13
|
}
|
|
13
|
-
await
|
|
14
|
+
await models.adminRole.create({
|
|
14
15
|
userId: user.id,
|
|
15
16
|
role: ROLE['SuperAdmin']
|
|
16
17
|
});
|
|
17
18
|
};
|
|
18
19
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
(await
|
|
20
|
+
const checkIsSuperAdmin = async user => {
|
|
21
|
+
return (
|
|
22
|
+
(await models.adminRole.count({
|
|
22
23
|
where: {
|
|
23
24
|
userId: user.id,
|
|
24
25
|
role: ROLE['SuperAdmin']
|
|
25
26
|
}
|
|
26
|
-
}))
|
|
27
|
-
)
|
|
28
|
-
throw new Error('不能执行该操作,需要超级管理员权限');
|
|
29
|
-
}
|
|
27
|
+
})) > 0
|
|
28
|
+
);
|
|
30
29
|
};
|
|
31
30
|
|
|
32
31
|
const addUser = async ({ avatar, nickname, phone, email, password, description }) => {
|
|
33
|
-
return await
|
|
32
|
+
return await services.user.addUser({
|
|
34
33
|
avatar,
|
|
35
34
|
nickname,
|
|
36
35
|
phone,
|
|
@@ -42,9 +41,9 @@ module.exports = fp(async (fastify, options) => {
|
|
|
42
41
|
};
|
|
43
42
|
|
|
44
43
|
const setSuperAdmin = async targetUser => {
|
|
45
|
-
const user = await
|
|
44
|
+
const user = await services.user.getUserInfo(targetUser);
|
|
46
45
|
if (
|
|
47
|
-
(await
|
|
46
|
+
(await models.adminRole.count({
|
|
48
47
|
where: {
|
|
49
48
|
userId: user.id,
|
|
50
49
|
role: ROLE['SuperAdmin']
|
|
@@ -54,130 +53,27 @@ module.exports = fp(async (fastify, options) => {
|
|
|
54
53
|
throw new Error('当前用户已经是超级管理员');
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
await
|
|
56
|
+
await models.adminRole.create({
|
|
58
57
|
userId: user.id,
|
|
59
58
|
role: ROLE['SuperAdmin']
|
|
60
59
|
});
|
|
61
60
|
};
|
|
62
61
|
|
|
63
|
-
const getAllUserList = async ({ filter, perPage, currentPage }) => {
|
|
64
|
-
const { count, rows } = await fastify.account.models.user.findAndCountAll({
|
|
65
|
-
include: [
|
|
66
|
-
{
|
|
67
|
-
attributes: ['role'],
|
|
68
|
-
model: fastify.account.models.adminRole
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
model: fastify.account.models.tenant
|
|
72
|
-
}
|
|
73
|
-
]
|
|
74
|
-
});
|
|
75
|
-
return {
|
|
76
|
-
pageData: rows,
|
|
77
|
-
totalCount: count
|
|
78
|
-
};
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const getAllTenantList = async ({ filter, perPage, currentPage }) => {
|
|
82
|
-
const queryFilter = {};
|
|
83
|
-
if (filter?.name) {
|
|
84
|
-
queryFilter.name = {
|
|
85
|
-
[fastify.sequelize.Sequelize.Op.like]: `%${filter.name}%`
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (filter?.serviceStartTime) {
|
|
90
|
-
queryFilter.serviceStartTime = {
|
|
91
|
-
[fastify.sequelize.Sequelize.Op.gt]: filter.serviceStartTime
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (filter?.serviceEndTime) {
|
|
96
|
-
queryFilter.serviceEndTime = {
|
|
97
|
-
[fastify.sequelize.Sequelize.Op.lt]: filter.serviceEndTime
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const { count, rows } = await fastify.account.models.tenant.findAndCountAll({
|
|
102
|
-
where: queryFilter,
|
|
103
|
-
offset: currentPage * (currentPage - 1),
|
|
104
|
-
limit: perPage
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const res = await fastify.account.models.tenantUser.findAll({
|
|
108
|
-
attributes: ['tenantId', fastify.sequelize.instance.fn('count', fastify.sequelize.instance.col('tenantId'))],
|
|
109
|
-
where: {
|
|
110
|
-
tenantId: {
|
|
111
|
-
[fastify.sequelize.Sequelize.Op.in]: rows.map(({ id }) => id)
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
group: 'tenantId'
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
return {
|
|
118
|
-
pageData: rows,
|
|
119
|
-
totalCount: count
|
|
120
|
-
};
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
const addTenant = async tenant => {
|
|
124
|
-
if (await fastify.account.models.tenant.count({ where: { name: tenant.name } })) {
|
|
125
|
-
throw new Error('租户名称不能重复');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const t = await fastify.sequelize.instance.transaction();
|
|
129
|
-
try {
|
|
130
|
-
const currentTenant = await fastify.account.models.tenant.create(tenant);
|
|
131
|
-
await fastify.account.models.tenantRole.create(
|
|
132
|
-
{
|
|
133
|
-
name: '系统默认角色',
|
|
134
|
-
tenantId: currentTenant.id,
|
|
135
|
-
description: '创建租户时自动生成,可以设置权限,不可更改删除,所有租户用户默认拥有该角色',
|
|
136
|
-
type: 1
|
|
137
|
-
},
|
|
138
|
-
{ transaction: t }
|
|
139
|
-
);
|
|
140
|
-
await fastify.account.models.tenantOrg.create(
|
|
141
|
-
{
|
|
142
|
-
name: '根组织',
|
|
143
|
-
tenantId: currentTenant.id
|
|
144
|
-
},
|
|
145
|
-
{ transaction: t }
|
|
146
|
-
);
|
|
147
|
-
await t.commit();
|
|
148
|
-
} catch (e) {
|
|
149
|
-
await t.rollback();
|
|
150
|
-
throw e;
|
|
151
|
-
}
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
const saveTenant = async tenant => {
|
|
155
|
-
const currentTenant = await fastify.account.models.tenant.findByPk(tenant.id);
|
|
156
|
-
if (!currentTenant) {
|
|
157
|
-
throw new Error('租户不存在,请刷新以后重试');
|
|
158
|
-
}
|
|
159
|
-
await currentTenant.update(tenant);
|
|
160
|
-
};
|
|
161
|
-
|
|
162
62
|
const generateTenantAdminVerifyCode = async () => {};
|
|
163
63
|
|
|
164
64
|
const verifyTenantAdmin = async () => {};
|
|
165
65
|
|
|
166
66
|
const resetUserPassword = async ({ userId, password }) => {
|
|
167
|
-
await
|
|
67
|
+
await services.account.resetPassword({ userId, password });
|
|
168
68
|
};
|
|
169
69
|
|
|
170
|
-
|
|
70
|
+
services.admin = {
|
|
171
71
|
initSuperAdmin,
|
|
172
72
|
setSuperAdmin,
|
|
173
|
-
|
|
174
|
-
getAllTenantList,
|
|
175
|
-
addTenant,
|
|
176
|
-
saveTenant,
|
|
177
|
-
superAdminAuthenticate,
|
|
73
|
+
checkIsSuperAdmin,
|
|
178
74
|
generateTenantAdminVerifyCode,
|
|
179
75
|
verifyTenantAdmin,
|
|
180
|
-
|
|
181
|
-
|
|
76
|
+
addUser,
|
|
77
|
+
resetUserPassword
|
|
182
78
|
};
|
|
183
79
|
});
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
const fp = require('fastify-plugin');
|
|
2
|
+
const isNil = require('lodash/isNil');
|
|
3
|
+
module.exports = fp(async (fastify, options) => {
|
|
4
|
+
const { models, services } = fastify.account;
|
|
5
|
+
|
|
6
|
+
const getApplicationInstance = async ({ id }) => {
|
|
7
|
+
if (!id) {
|
|
8
|
+
throw new Error('应用Id不能为空');
|
|
9
|
+
}
|
|
10
|
+
const application = await models.application.findOne({
|
|
11
|
+
where: {
|
|
12
|
+
uuid: id
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
if (!application) {
|
|
16
|
+
throw new Error('应用不存在');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return application;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const getApplication = async ({ id }) => {
|
|
23
|
+
const application = await getApplicationInstance({ id });
|
|
24
|
+
return Object.assign({}, application.get({ plain: true }), {
|
|
25
|
+
id: application.uuid
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const addApplication = async application => {
|
|
30
|
+
const currentApplication = await models.application.create(application);
|
|
31
|
+
return Object.assign({}, currentApplication.get({ plain: true }), {
|
|
32
|
+
id: currentApplication.uuid
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const saveApplication = async ({ id, ...others }) => {
|
|
37
|
+
const application = await getApplicationInstance({ id });
|
|
38
|
+
['name', 'code', 'avatar', 'url', 'description'].forEach(name => {
|
|
39
|
+
if (!isNil(others[name])) {
|
|
40
|
+
application[name] = others[name];
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
await application.save();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const deleteApplication = async ({ id }) => {
|
|
48
|
+
const application = await getApplicationInstance({ id });
|
|
49
|
+
if (
|
|
50
|
+
(await models.tenantApplication.count({
|
|
51
|
+
where: {
|
|
52
|
+
applicationId: application.uuid
|
|
53
|
+
}
|
|
54
|
+
})) > 0
|
|
55
|
+
) {
|
|
56
|
+
throw new Error('应用已经开放给其他租户使用,不能删除');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const permissionIdList = (
|
|
60
|
+
await models.permission.findAll({
|
|
61
|
+
where: { applicationId: application.uuid }
|
|
62
|
+
})
|
|
63
|
+
).map(({ id }) => id);
|
|
64
|
+
|
|
65
|
+
const t = await fastify.sequelize.instance.transaction();
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
await models.tenantPermission.destroy(
|
|
69
|
+
{
|
|
70
|
+
where: {
|
|
71
|
+
permissionId: {
|
|
72
|
+
[fastify.sequelize.Sequelize.Op.in]: permissionIdList
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
{ transaction: t }
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
await models.tenantRolePermission.destroy(
|
|
80
|
+
{
|
|
81
|
+
where: {
|
|
82
|
+
permissionId: {
|
|
83
|
+
[fastify.sequelize.Sequelize.Op.in]: permissionIdList
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
{ transaction: t }
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
await models.permission.destroy({
|
|
91
|
+
where: {
|
|
92
|
+
applicationId: application.uuid
|
|
93
|
+
},
|
|
94
|
+
transaction: t
|
|
95
|
+
});
|
|
96
|
+
await application.destroy({ transaction: t });
|
|
97
|
+
await t.commit();
|
|
98
|
+
} catch (e) {
|
|
99
|
+
await t.rollback();
|
|
100
|
+
throw e;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const getApplicationList = async ({ tenantId }) => {
|
|
105
|
+
const query = {};
|
|
106
|
+
if (tenantId) {
|
|
107
|
+
const tenant = await services.tenant.getTenant({ id: tenantId });
|
|
108
|
+
if (!tenant) {
|
|
109
|
+
throw new Error('租户不存在');
|
|
110
|
+
}
|
|
111
|
+
const tenantApplications = await models.tenantApplication.findAll({
|
|
112
|
+
where: { tenantId }
|
|
113
|
+
});
|
|
114
|
+
query.uuid = {
|
|
115
|
+
[fastify.sequelize.Sequelize.Op.in]: tenantApplications.map(({ applicationId }) => applicationId)
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const list = await models.application.findAll({
|
|
119
|
+
where: query
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
return list.map(item => {
|
|
123
|
+
return Object.assign({}, item.get({ plain: true }), {
|
|
124
|
+
id: item.uuid
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const getApplicationListByIds = async ({ ids }) => {
|
|
130
|
+
const applications = await models.application.findAll({
|
|
131
|
+
where: {
|
|
132
|
+
uuid: {
|
|
133
|
+
[fastify.sequelize.Sequelize.Op.in]: ids
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
return applications.map(item => {
|
|
139
|
+
return Object.assign({}, item.get({ plain: true }), { id: item.uuid });
|
|
140
|
+
});
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
services.application = {
|
|
144
|
+
addApplication,
|
|
145
|
+
getApplication,
|
|
146
|
+
saveApplication,
|
|
147
|
+
deleteApplication,
|
|
148
|
+
getApplicationList,
|
|
149
|
+
getApplicationListByIds
|
|
150
|
+
};
|
|
151
|
+
});
|