@kne/fastify-account 1.0.0-alpha.17 → 1.0.0-alpha.19
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 +1171 -335
- package/index.js +29 -3
- package/libs/controllers/account.js +12 -26
- package/libs/controllers/adminPermission.js +23 -0
- package/libs/controllers/adminTenant.js +27 -259
- package/libs/controllers/adminTenantOrg.js +71 -0
- package/libs/controllers/adminTenantUser.js +168 -0
- package/libs/controllers/tenant.js +0 -46
- package/libs/controllers/tenantOrg.js +65 -0
- package/libs/controllers/tenantRole.js +219 -0
- package/libs/controllers/tenantUser.js +169 -0
- package/libs/models/company-info.js +25 -0
- package/libs/models/login-log.js +7 -1
- package/libs/models/request-log.js +39 -0
- package/libs/services/account.js +34 -42
- package/libs/services/application.js +4 -1
- package/libs/services/permission.js +69 -34
- package/libs/services/request-log.js +19 -0
- package/libs/services/tenant-org.js +20 -7
- package/libs/services/tenant-role.js +10 -2
- package/libs/services/tenant-user.js +16 -4
- package/libs/services/user.js +34 -1
- package/package.json +1 -1
- /package/libs/controllers/{adminRole.js → adminTenantRole.js} +0 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module.exports = ({ DataTypes }) => {
|
|
2
|
+
return {
|
|
3
|
+
model: {
|
|
4
|
+
userId: {
|
|
5
|
+
type: DataTypes.UUID,
|
|
6
|
+
allowNull: false
|
|
7
|
+
},
|
|
8
|
+
tenantId: {
|
|
9
|
+
type: DataTypes.UUID
|
|
10
|
+
},
|
|
11
|
+
type: {
|
|
12
|
+
type: DataTypes.STRING,
|
|
13
|
+
comment: 'user,tenant,admin'
|
|
14
|
+
},
|
|
15
|
+
applicationId: {
|
|
16
|
+
type: DataTypes.UUID
|
|
17
|
+
},
|
|
18
|
+
action: {
|
|
19
|
+
type: DataTypes.STRING
|
|
20
|
+
},
|
|
21
|
+
summary: {
|
|
22
|
+
type: DataTypes.TEXT
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
options: {
|
|
26
|
+
indexes: [
|
|
27
|
+
{
|
|
28
|
+
fields: ['user_id', 'type']
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
fields: ['tenant_id', 'type']
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
fields: ['action', 'type']
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
};
|
package/libs/services/account.js
CHANGED
|
@@ -14,7 +14,7 @@ function userNameIsEmail(username) {
|
|
|
14
14
|
|
|
15
15
|
module.exports = fp(async (fastify, options) => {
|
|
16
16
|
const { models, services } = fastify.account;
|
|
17
|
-
const login = async ({ username, password, ip }) => {
|
|
17
|
+
const login = async ({ username, password, ip, appName }) => {
|
|
18
18
|
const isEmail = userNameIsEmail(username);
|
|
19
19
|
const user = await models.user.findOne({
|
|
20
20
|
where: Object.assign(
|
|
@@ -40,9 +40,13 @@ module.exports = fp(async (fastify, options) => {
|
|
|
40
40
|
|
|
41
41
|
await passwordAuthentication({ accountId: user.userAccountId, password });
|
|
42
42
|
|
|
43
|
+
const application = appName && (await services.application.getApplicationByCode({ code: appName }));
|
|
44
|
+
|
|
43
45
|
await models.loginLog.create({
|
|
44
46
|
userId: user.uuid,
|
|
45
|
-
ip
|
|
47
|
+
ip,
|
|
48
|
+
currentTenantId: user.currentTenantId,
|
|
49
|
+
applicationId: application?.id
|
|
46
50
|
});
|
|
47
51
|
|
|
48
52
|
return {
|
|
@@ -51,22 +55,25 @@ module.exports = fp(async (fastify, options) => {
|
|
|
51
55
|
};
|
|
52
56
|
};
|
|
53
57
|
|
|
58
|
+
const resetPassword = async ({ password, userId }) => {
|
|
59
|
+
const userInfo = await services.user.getUserInstance({ id: userId });
|
|
60
|
+
const account = await models.userAccount.create(
|
|
61
|
+
Object.assign({}, await passwordEncryption(password), {
|
|
62
|
+
belongToUserId: userInfo.uuid
|
|
63
|
+
})
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
await userInfo.update({ userAccountId: account.uuid });
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const resetPasswordByToken = async ({ password, token }) => {
|
|
70
|
+
const { name } = await verificationJWTCodeValidate({ token });
|
|
71
|
+
const user = await services.user.getUserInstanceByName({ name, status: [0, 1] });
|
|
72
|
+
await resetPassword({ password, userId: user.uuid });
|
|
73
|
+
};
|
|
74
|
+
|
|
54
75
|
const modifyPassword = async ({ email, phone, oldPwd, newPwd }) => {
|
|
55
|
-
const user = await
|
|
56
|
-
where: Object.assign(
|
|
57
|
-
{},
|
|
58
|
-
email
|
|
59
|
-
? {
|
|
60
|
-
email
|
|
61
|
-
}
|
|
62
|
-
: {
|
|
63
|
-
phone
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
status: 1
|
|
67
|
-
}
|
|
68
|
-
)
|
|
69
|
-
});
|
|
76
|
+
const user = await services.user.getUserInstanceByName({ name: email || phone, status: 1 });
|
|
70
77
|
if (!user) {
|
|
71
78
|
throw new Error('新用户密码只能初始化一次');
|
|
72
79
|
}
|
|
@@ -111,30 +118,9 @@ module.exports = fp(async (fastify, options) => {
|
|
|
111
118
|
return hash.digest('hex');
|
|
112
119
|
};
|
|
113
120
|
|
|
114
|
-
const resetPassword = async ({ password, token }) => {
|
|
115
|
-
const { name } = await verificationJWTCodeValidate({ token });
|
|
116
|
-
|
|
117
|
-
const isEmail = userNameIsEmail(name);
|
|
118
|
-
|
|
119
|
-
const userInfo = await models.user.findOne({
|
|
120
|
-
where: isEmail ? { email: name } : { phone: name }
|
|
121
|
-
});
|
|
122
|
-
if (!userInfo) {
|
|
123
|
-
throw new Error('用户不存在');
|
|
124
|
-
}
|
|
125
|
-
const account = await models.userAccount.create(
|
|
126
|
-
Object.assign({}, await passwordEncryption(password), {
|
|
127
|
-
belongToUserId: userInfo.uuid
|
|
128
|
-
})
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
await userInfo.update({ userAccountId: account.uuid });
|
|
132
|
-
};
|
|
133
|
-
|
|
134
121
|
const register = async ({ avatar, nickname, gender, birthday, description, phone, email, code, password, status, invitationCode }) => {
|
|
135
122
|
const type = phone ? 0 : 1;
|
|
136
|
-
|
|
137
|
-
if (!(await verificationCodeValidate({ name: type === 0 ? phone : email, type, code }))) {
|
|
123
|
+
if (!(await verificationCodeValidate({ name: type === 0 ? phone : email, type: 0, code }))) {
|
|
138
124
|
throw new Error('验证码不正确或者已经过期');
|
|
139
125
|
}
|
|
140
126
|
|
|
@@ -173,9 +159,12 @@ module.exports = fp(async (fastify, options) => {
|
|
|
173
159
|
return code;
|
|
174
160
|
};
|
|
175
161
|
|
|
176
|
-
const sendVerificationCode = async ({ name, type
|
|
162
|
+
const sendVerificationCode = async ({ name, type }) => {
|
|
163
|
+
// messageType: 0:短信验证码,1:邮件验证码 type: 0:注册,2:登录,4:验证租户管理员,5:忘记密码
|
|
177
164
|
const code = await generateVerificationCode({ name, type });
|
|
165
|
+
const isEmail = userNameIsEmail(name);
|
|
178
166
|
// 这里写发送逻辑
|
|
167
|
+
await options.sendMessage({ name, type, messageType: isEmail ? 1 : 0, props: { code } });
|
|
179
168
|
return code;
|
|
180
169
|
};
|
|
181
170
|
|
|
@@ -200,10 +189,12 @@ module.exports = fp(async (fastify, options) => {
|
|
|
200
189
|
return isPass;
|
|
201
190
|
};
|
|
202
191
|
|
|
203
|
-
const sendJWTVerificationCode = async ({ name, type
|
|
192
|
+
const sendJWTVerificationCode = async ({ name, type }) => {
|
|
204
193
|
const code = await generateVerificationCode({ name, type });
|
|
205
194
|
const token = fastify.jwt.sign({ name, type, code });
|
|
195
|
+
const isEmail = userNameIsEmail(name);
|
|
206
196
|
// 这里写发送逻辑
|
|
197
|
+
await options.sendMessage({ name, type, messageType: isEmail ? 1 : 0, props: { token } });
|
|
207
198
|
return token;
|
|
208
199
|
};
|
|
209
200
|
|
|
@@ -227,6 +218,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
227
218
|
verificationJWTCodeValidate,
|
|
228
219
|
passwordEncryption,
|
|
229
220
|
passwordAuthentication,
|
|
230
|
-
resetPassword
|
|
221
|
+
resetPassword,
|
|
222
|
+
resetPasswordByToken
|
|
231
223
|
};
|
|
232
224
|
});
|
|
@@ -116,7 +116,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
116
116
|
}
|
|
117
117
|
};
|
|
118
118
|
|
|
119
|
-
const getApplicationList = async ({ tenantId }) => {
|
|
119
|
+
const getApplicationList = async ({ tenantId, appName }) => {
|
|
120
120
|
const query = {};
|
|
121
121
|
if (tenantId) {
|
|
122
122
|
const tenant = await services.tenant.getTenant({ id: tenantId });
|
|
@@ -130,6 +130,9 @@ module.exports = fp(async (fastify, options) => {
|
|
|
130
130
|
[fastify.sequelize.Sequelize.Op.in]: tenantApplications.map(({ applicationId }) => applicationId)
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
|
+
if (appName) {
|
|
134
|
+
query['code'] = appName;
|
|
135
|
+
}
|
|
133
136
|
const list = await models.application.findAll({
|
|
134
137
|
where: query
|
|
135
138
|
});
|
|
@@ -68,52 +68,75 @@ module.exports = fp(async (fastify, options) => {
|
|
|
68
68
|
});
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
const importPermissionsToApplication = async ({ applicationId, permissions }) => {
|
|
72
|
+
const permissionsPidMapping = groupBy(permissions, 'pid');
|
|
73
|
+
const pidMapping = {};
|
|
74
|
+
for (let pid of await Promise.all(Object.keys(permissionsPidMapping).sort())) {
|
|
75
|
+
const targetPid = pid === '0' ? 0 : pidMapping[pid];
|
|
76
|
+
await Promise.all(
|
|
77
|
+
permissionsPidMapping[pid].map(async item => {
|
|
78
|
+
const originPermission = await models.permission.findOne({
|
|
79
|
+
where: {
|
|
80
|
+
pid: targetPid,
|
|
81
|
+
code: item.code,
|
|
82
|
+
applicationId
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
if (originPermission) {
|
|
86
|
+
pidMapping[item.id] = originPermission.id;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const newPermission = await services.permission.addPermission({
|
|
90
|
+
applicationId,
|
|
91
|
+
pid: targetPid,
|
|
92
|
+
code: item.code,
|
|
93
|
+
name: item.name,
|
|
94
|
+
type: item.type,
|
|
95
|
+
isModule: item.isModule,
|
|
96
|
+
isMust: item.isMust,
|
|
97
|
+
description: item.description
|
|
98
|
+
});
|
|
99
|
+
pidMapping[item.id] = newPermission.id;
|
|
100
|
+
})
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
71
105
|
const parsePermissionListJSON = async ({ file }) => {
|
|
72
106
|
const data = JSON.parse(await file.toBuffer());
|
|
73
107
|
await Promise.all(
|
|
74
108
|
data.map(async application => {
|
|
75
109
|
const { permissions, ...other } = application;
|
|
76
|
-
|
|
77
|
-
|
|
110
|
+
let app = await services.application.getApplicationByCode({ code: application.code });
|
|
78
111
|
if (!app) {
|
|
79
|
-
|
|
80
|
-
const permissionsPidMapping = groupBy(permissions, 'pid');
|
|
81
|
-
const addPermissions = async (pid, applicationId) =>
|
|
82
|
-
await Promise.all(
|
|
83
|
-
(get(permissionsPidMapping, pid) || []).map(async ({ id, ...permissionProps }) => {
|
|
84
|
-
const permission = await services.permission.addPermission(Object.assign({}, permissionProps, { applicationId, pid }));
|
|
85
|
-
await addPermissions(permission.id, applicationId);
|
|
86
|
-
})
|
|
87
|
-
);
|
|
88
|
-
await addPermissions(0, newApplication.uuid);
|
|
89
|
-
} else {
|
|
90
|
-
const permissionsPidMapping = groupBy(permissions, 'pid');
|
|
91
|
-
const addPermissions = async (pid, applicationId, importPid) => {
|
|
92
|
-
await Promise.all(
|
|
93
|
-
(get(permissionsPidMapping, importPid || pid) || []).map(async ({ id, ...permissionProps }) => {
|
|
94
|
-
const current = await models.permission.findOne({ where: { code: permissionProps.code, pid } });
|
|
95
|
-
if (current) {
|
|
96
|
-
await addPermissions(current.id, applicationId, id);
|
|
97
|
-
} else {
|
|
98
|
-
const permission = await services.permission.addPermission(Object.assign({}, permissionProps, { applicationId, pid }));
|
|
99
|
-
await addPermissions(permission.id, applicationId);
|
|
100
|
-
}
|
|
101
|
-
})
|
|
102
|
-
);
|
|
103
|
-
};
|
|
104
|
-
await addPermissions(0, app.uuid);
|
|
112
|
+
app = await services.application.addApplication(other);
|
|
105
113
|
}
|
|
114
|
+
await services.permission.importPermissionsToApplication({ applicationId: app.uuid, permissions });
|
|
106
115
|
return app;
|
|
107
116
|
})
|
|
108
117
|
);
|
|
109
118
|
return data;
|
|
110
119
|
};
|
|
111
120
|
|
|
112
|
-
const
|
|
121
|
+
const copyPermissions = async ({ applicationId, originApplicationId }) => {
|
|
122
|
+
if (applicationId === originApplicationId) {
|
|
123
|
+
throw new Error('复制对象不能和自己相同');
|
|
124
|
+
}
|
|
125
|
+
await services.application.getApplication({ id: originApplicationId });
|
|
126
|
+
await services.application.getApplication({ id: applicationId });
|
|
127
|
+
const permissions = await models.permission.findAll({
|
|
128
|
+
where: { applicationId: originApplicationId }
|
|
129
|
+
});
|
|
130
|
+
await services.permission.importPermissionsToApplication({ applicationId, permissions });
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const exportPermissionList = async ({ applicationIds }) => {
|
|
113
134
|
return await Promise.all(
|
|
114
135
|
(applicationIds || []).map(async applicationId => {
|
|
115
136
|
let application = await services.application.getApplication({ id: applicationId });
|
|
116
|
-
application.permissions = await
|
|
137
|
+
application.permissions = await models.permission.findAll({
|
|
138
|
+
where: { applicationId }
|
|
139
|
+
});
|
|
117
140
|
return application;
|
|
118
141
|
})
|
|
119
142
|
);
|
|
@@ -274,13 +297,17 @@ module.exports = fp(async (fastify, options) => {
|
|
|
274
297
|
}
|
|
275
298
|
};
|
|
276
299
|
|
|
277
|
-
const saveRolePermissionList = async ({ roleId, applications, permissions }) => {
|
|
300
|
+
const saveRolePermissionList = async ({ roleId, tenantId, applications, permissions }) => {
|
|
278
301
|
const role = await models.tenantRole.findByPk(roleId);
|
|
279
302
|
if (!role) {
|
|
280
303
|
throw new Error('角色不存在');
|
|
281
304
|
}
|
|
282
305
|
|
|
283
|
-
|
|
306
|
+
if (tenantId && role.tenantId !== tenantId) {
|
|
307
|
+
throw new Error('数据已过期,请刷新页面后重试');
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
tenantId = role.tenantId;
|
|
284
311
|
|
|
285
312
|
await services.tenant.getTenant({ id: tenantId });
|
|
286
313
|
|
|
@@ -399,11 +426,16 @@ module.exports = fp(async (fastify, options) => {
|
|
|
399
426
|
return { applications, permissions };
|
|
400
427
|
};
|
|
401
428
|
|
|
402
|
-
const getRolePermissionList = async ({ roleId }) => {
|
|
429
|
+
const getRolePermissionList = async ({ roleId, tenantId }) => {
|
|
403
430
|
const role = await models.tenantRole.findByPk(roleId);
|
|
404
431
|
if (!role) {
|
|
405
432
|
throw new Error('角色不存在');
|
|
406
433
|
}
|
|
434
|
+
|
|
435
|
+
if (tenantId && role.tenantId !== tenantId) {
|
|
436
|
+
throw new Error('数据已过期,请刷新页面后重试');
|
|
437
|
+
}
|
|
438
|
+
|
|
407
439
|
const applications = await models.tenantRoleApplication.findAll({
|
|
408
440
|
where: { roleId: role.id, tenantId: role.tenantId }
|
|
409
441
|
});
|
|
@@ -423,6 +455,9 @@ module.exports = fp(async (fastify, options) => {
|
|
|
423
455
|
saveTenantPermissionList,
|
|
424
456
|
saveRolePermissionList,
|
|
425
457
|
getTenantPermissionList,
|
|
426
|
-
getRolePermissionList
|
|
458
|
+
getRolePermissionList,
|
|
459
|
+
parsePermissionListJSON,
|
|
460
|
+
copyPermissions,
|
|
461
|
+
importPermissionsToApplication
|
|
427
462
|
};
|
|
428
463
|
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const fp = require('fastify-plugin');
|
|
2
|
+
module.exports = fp(async (fastify, options) => {
|
|
3
|
+
const { models, services } = fastify.account;
|
|
4
|
+
|
|
5
|
+
const addRequestLog = async ({ userInfo, type, tenantId, appName, action, summary }) => {
|
|
6
|
+
const application = appName && (await services.application.getApplicationByCode({ code: appName }));
|
|
7
|
+
await models.requestLog.create({
|
|
8
|
+
userId: userInfo.id,
|
|
9
|
+
tenantId,
|
|
10
|
+
applicationId: application?.id,
|
|
11
|
+
type,
|
|
12
|
+
action,
|
|
13
|
+
summary
|
|
14
|
+
});
|
|
15
|
+
return {};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
services.requestLog = { addRequestLog };
|
|
19
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const fp = require('fastify-plugin');
|
|
2
2
|
module.exports = fp(async (fastify, options) => {
|
|
3
3
|
const { models, services } = fastify.account;
|
|
4
|
-
|
|
4
|
+
const { Op } = fastify.sequelize.Sequelize;
|
|
5
5
|
const getTenantOrgInstance = async ({ id }) => {
|
|
6
6
|
const tenantOrg = await models.tenantOrg.findByPk(id, {
|
|
7
7
|
where: {
|
|
@@ -37,21 +37,30 @@ module.exports = fp(async (fastify, options) => {
|
|
|
37
37
|
});
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
-
const saveTenantOrg = async ({ id, ...otherInfo }) => {
|
|
40
|
+
const saveTenantOrg = async ({ id, tenantId, ...otherInfo }) => {
|
|
41
41
|
const tenantOrg = await getTenantOrgInstance({ id });
|
|
42
|
+
if (tenantId && tenantOrg.tenantId !== tenantId) {
|
|
43
|
+
throw new Error('数据已过期,请刷新页面后重试');
|
|
44
|
+
}
|
|
42
45
|
if (
|
|
43
46
|
await models.tenantOrg.count({
|
|
44
47
|
where: {
|
|
45
48
|
name: otherInfo.name,
|
|
46
49
|
pid: otherInfo.pid,
|
|
47
|
-
|
|
50
|
+
[Op.not]: {
|
|
51
|
+
id
|
|
52
|
+
}
|
|
48
53
|
}
|
|
49
54
|
})
|
|
50
55
|
) {
|
|
51
56
|
throw new Error('组织名称在同一父组织下有重复');
|
|
52
57
|
}
|
|
53
58
|
|
|
54
|
-
|
|
59
|
+
if (otherInfo.pid === tenantOrg.id) {
|
|
60
|
+
throw new Error('不能用自己作为自己的父节点');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
['name', 'enName', 'pid'].forEach(name => {
|
|
55
64
|
if (otherInfo[name]) {
|
|
56
65
|
tenantOrg[name] = otherInfo[name];
|
|
57
66
|
}
|
|
@@ -63,11 +72,15 @@ module.exports = fp(async (fastify, options) => {
|
|
|
63
72
|
const deleteTenantOrg = async ({ id, tenantId }) => {
|
|
64
73
|
const tenantOrg = await getTenantOrgInstance({ id });
|
|
65
74
|
|
|
66
|
-
|
|
67
|
-
|
|
75
|
+
if (tenantId && tenantOrg.tenantId !== tenantId) {
|
|
76
|
+
throw new Error('数据已过期,请刷新页面后重试');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const count = await models.tenantOrg.count({
|
|
80
|
+
where: { tenantId: tenantOrg.tenantId, pid: id }
|
|
68
81
|
});
|
|
69
82
|
|
|
70
|
-
if (
|
|
83
|
+
if (count > 0) {
|
|
71
84
|
throw new Error('组织下有用户或子组织无法删除');
|
|
72
85
|
}
|
|
73
86
|
|
|
@@ -42,9 +42,13 @@ module.exports = fp(async (fastify, options) => {
|
|
|
42
42
|
});
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
const saveTenantRole = async ({ id, ...otherInfo }) => {
|
|
45
|
+
const saveTenantRole = async ({ id, tenantId, ...otherInfo }) => {
|
|
46
46
|
const tenantRole = await getTenantRoleInstance({ id });
|
|
47
47
|
|
|
48
|
+
if (tenantId && tenantRole.tenantId !== tenantId) {
|
|
49
|
+
throw new Error('数据已过期,请刷新页面后重试');
|
|
50
|
+
}
|
|
51
|
+
|
|
48
52
|
['name', 'description'].forEach(name => {
|
|
49
53
|
if (otherInfo[name]) {
|
|
50
54
|
tenantRole[name] = otherInfo[name];
|
|
@@ -54,9 +58,13 @@ module.exports = fp(async (fastify, options) => {
|
|
|
54
58
|
await tenantRole.save();
|
|
55
59
|
};
|
|
56
60
|
|
|
57
|
-
const removeTenantRole = async ({ id }) => {
|
|
61
|
+
const removeTenantRole = async ({ id, tenantId }) => {
|
|
58
62
|
const tenantRole = await getTenantRoleInstance({ id });
|
|
59
63
|
|
|
64
|
+
if (tenantId && tenantRole.tenantId !== tenantId) {
|
|
65
|
+
throw new Error('数据已过期,请刷新页面后重试');
|
|
66
|
+
}
|
|
67
|
+
|
|
60
68
|
await services.tenantUser.checkTenantRoleUsed({ tenantRoleId: tenantRole.id });
|
|
61
69
|
|
|
62
70
|
if (tenantRole.type === 1) {
|
|
@@ -92,7 +92,8 @@ module.exports = fp(async (fastify, options) => {
|
|
|
92
92
|
const user = await services.user.getUser(authenticatePayload);
|
|
93
93
|
const tenantUserList = await models.tenantUser.findAll({
|
|
94
94
|
where: {
|
|
95
|
-
userId: user.id
|
|
95
|
+
userId: user.id,
|
|
96
|
+
status: 0
|
|
96
97
|
}
|
|
97
98
|
});
|
|
98
99
|
|
|
@@ -137,12 +138,19 @@ module.exports = fp(async (fastify, options) => {
|
|
|
137
138
|
return currentTenantUser;
|
|
138
139
|
};
|
|
139
140
|
|
|
140
|
-
const getTenantUserByUserId = async user => {
|
|
141
|
+
const getTenantUserByUserId = async ({ userInfo: user, appName }) => {
|
|
141
142
|
if (!user.currentTenantId) {
|
|
142
143
|
throw new Unauthorized('没有找到当前绑定租户');
|
|
143
144
|
}
|
|
145
|
+
|
|
144
146
|
const tenant = await services.tenant.getTenant({ id: user.currentTenantId });
|
|
145
147
|
|
|
148
|
+
const tenantApplications = await services.application.getApplicationList({ tenantId: tenant.id, appName });
|
|
149
|
+
|
|
150
|
+
if (appName && !tenantApplications.some(item => item.code === appName)) {
|
|
151
|
+
throw Unauthorized('当前租户没有开通该应用权限');
|
|
152
|
+
}
|
|
153
|
+
|
|
146
154
|
const tenantUser = await models.tenantUser.findOne({
|
|
147
155
|
attributes: ['uuid', 'avatar', 'name', 'description', 'phone', 'email'],
|
|
148
156
|
include: [
|
|
@@ -181,11 +189,15 @@ module.exports = fp(async (fastify, options) => {
|
|
|
181
189
|
const tenantRoleIds = tenantUser.tenantRoles.map(({ id }) => id);
|
|
182
190
|
tenantRoleIds.push(defaultTenant.id);
|
|
183
191
|
|
|
184
|
-
const { userPermissionList } = await getTenantUserPermissionList({ tenantRoleIds });
|
|
192
|
+
const { userPermissionList, applications: roleApplications } = await getTenantUserPermissionList({ tenantRoleIds });
|
|
185
193
|
if (!tenantUser) {
|
|
186
194
|
throw new Error('当前租户用户不存在或者已经被关闭');
|
|
187
195
|
}
|
|
188
196
|
|
|
197
|
+
if (appName && !roleApplications.some(item => item.code === appName)) {
|
|
198
|
+
throw Unauthorized('当前用户没有开通该应用权限');
|
|
199
|
+
}
|
|
200
|
+
|
|
189
201
|
const outputTenantUser = Object.assign({}, tenantUser.get({ plain: true }), { id: tenantUser.uuid });
|
|
190
202
|
outputTenantUser.tenantOrgs = outputTenantUser?.tenantOrgs.map(({ id, name }) => ({ id, name }));
|
|
191
203
|
outputTenantUser.tenantRoles = outputTenantUser?.tenantRoles.map(({ id, name }) => ({ id, name }));
|
|
@@ -194,7 +206,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
194
206
|
tenantUser: Object.assign({}, outputTenantUser, {
|
|
195
207
|
permissions: userPermissionList
|
|
196
208
|
}),
|
|
197
|
-
user
|
|
209
|
+
userInfo: user
|
|
198
210
|
};
|
|
199
211
|
};
|
|
200
212
|
|
package/libs/services/user.js
CHANGED
|
@@ -2,6 +2,12 @@ const fp = require('fastify-plugin');
|
|
|
2
2
|
const { Unauthorized } = require('http-errors');
|
|
3
3
|
const get = require('lodash/get');
|
|
4
4
|
const pick = require('lodash/pick');
|
|
5
|
+
const isNil = require('lodash/isNil');
|
|
6
|
+
|
|
7
|
+
function userNameIsEmail(username) {
|
|
8
|
+
return /^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/.test(username);
|
|
9
|
+
}
|
|
10
|
+
|
|
5
11
|
module.exports = fp(async (fastify, options) => {
|
|
6
12
|
const { models, services } = fastify.account;
|
|
7
13
|
|
|
@@ -19,6 +25,27 @@ module.exports = fp(async (fastify, options) => {
|
|
|
19
25
|
return user;
|
|
20
26
|
};
|
|
21
27
|
|
|
28
|
+
const getUserInstanceByName = async ({ name, status }) => {
|
|
29
|
+
const isEmail = userNameIsEmail(name);
|
|
30
|
+
const query = {};
|
|
31
|
+
if (!isNil(status)) {
|
|
32
|
+
query['status'] = Array.isArray(status)
|
|
33
|
+
? {
|
|
34
|
+
[fastify.sequelize.Sequelize.Op.or]: status
|
|
35
|
+
}
|
|
36
|
+
: status;
|
|
37
|
+
}
|
|
38
|
+
const user = await models.user.findOne({
|
|
39
|
+
where: Object.assign({}, isEmail ? { email: name } : { phone: name }, query)
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (!user) {
|
|
43
|
+
throw new Error('用户不存在');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return user;
|
|
47
|
+
};
|
|
48
|
+
|
|
22
49
|
const getUser = async authenticatePayload => {
|
|
23
50
|
if (!(authenticatePayload && authenticatePayload.id)) {
|
|
24
51
|
throw new Unauthorized();
|
|
@@ -127,7 +154,12 @@ module.exports = fp(async (fastify, options) => {
|
|
|
127
154
|
});
|
|
128
155
|
return {
|
|
129
156
|
pageData: rows.map(item => {
|
|
130
|
-
return Object.assign({}, item.get({ pain: true }), {
|
|
157
|
+
return Object.assign({}, item.get({ pain: true }), {
|
|
158
|
+
id: item.uuid,
|
|
159
|
+
tenants: item.tenants.map(({ uuid, name }) => {
|
|
160
|
+
return { id: uuid, name };
|
|
161
|
+
})
|
|
162
|
+
});
|
|
131
163
|
}),
|
|
132
164
|
totalCount: count
|
|
133
165
|
};
|
|
@@ -136,6 +168,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
136
168
|
services.user = {
|
|
137
169
|
getUser,
|
|
138
170
|
getUserInstance,
|
|
171
|
+
getUserInstanceByName,
|
|
139
172
|
saveUser,
|
|
140
173
|
accountIsExists,
|
|
141
174
|
addUser,
|
package/package.json
CHANGED
|
File without changes
|