@kne/fastify-account 1.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +1436 -0
  2. package/index.js +54 -0
  3. package/libs/controllers/account.js +189 -0
  4. package/libs/controllers/admin.js +153 -0
  5. package/libs/controllers/adminPermission.js +230 -0
  6. package/libs/controllers/adminRole.js +145 -0
  7. package/libs/controllers/adminTenant.js +461 -0
  8. package/libs/controllers/tenant.js +22 -0
  9. package/libs/controllers/user.js +12 -0
  10. package/libs/models/admin-role.js +19 -0
  11. package/libs/models/application.js +36 -0
  12. package/libs/models/login-log.js +15 -0
  13. package/libs/models/permission.js +53 -0
  14. package/libs/models/tenant-application.js +28 -0
  15. package/libs/models/tenant-org.js +30 -0
  16. package/libs/models/tenant-permission.js +28 -0
  17. package/libs/models/tenant-role-application.js +32 -0
  18. package/libs/models/tenant-role-permission.js +32 -0
  19. package/libs/models/tenant-role.js +27 -0
  20. package/libs/models/tenant-share-group-permission.js +22 -0
  21. package/libs/models/tenant-share-group.js +22 -0
  22. package/libs/models/tenant-source-user-share-group.js +22 -0
  23. package/libs/models/tenant-token.js +32 -0
  24. package/libs/models/tenant-user-org.js +22 -0
  25. package/libs/models/tenant-user-role.js +22 -0
  26. package/libs/models/tenant-user-share-group.js +22 -0
  27. package/libs/models/tenant-user.js +56 -0
  28. package/libs/models/tenant.js +38 -0
  29. package/libs/models/user-account.js +26 -0
  30. package/libs/models/user.js +50 -0
  31. package/libs/models/verification-code.js +26 -0
  32. package/libs/services/account.js +200 -0
  33. package/libs/services/admin.js +183 -0
  34. package/libs/services/permission.js +465 -0
  35. package/libs/services/tenant.js +576 -0
  36. package/libs/services/user.js +108 -0
  37. package/package.json +61 -0
@@ -0,0 +1,576 @@
1
+ const fp = require('fastify-plugin');
2
+ const isNil = require('lodash/isNil');
3
+ module.exports = fp(async (fastify, options) => {
4
+ const getUserTenant = async authenticatePayload => {
5
+ const user = await fastify.account.services.user.getUserInfo(authenticatePayload);
6
+ const tenantUserList = await fastify.account.models.tenantUser.findAll({
7
+ where: {
8
+ userId: user.id
9
+ }
10
+ });
11
+
12
+ const tenantList =
13
+ tenantUserList.length > 0
14
+ ? await fastify.account.models.tenant.findAll({
15
+ where: {
16
+ id: {
17
+ [fastify.sequelize.Sequelize.Op.in]: tenantUserList.map(({ tenantId }) => tenantId)
18
+ },
19
+ status: 0
20
+ }
21
+ })
22
+ : [];
23
+
24
+ const currentTenantUser = user.currentTenantId && tenantUserList.find(({ tenantId }) => tenantId === user.currentTenantId);
25
+ const currentTenant = currentTenantUser && tenantList.find(({ id }) => id === currentTenantUser.tenantId);
26
+
27
+ return {
28
+ currentTenant,
29
+ currentTenantUser,
30
+ tenantList,
31
+ tenantUserList,
32
+ userInfo: user
33
+ };
34
+ };
35
+
36
+ const getTenantInfo = async ({ id }) => {
37
+ const tenant = await fastify.account.models.tenant.findByPk(id);
38
+ if (!tenant) {
39
+ throw new Error('租户不存在');
40
+ }
41
+ return tenant;
42
+ };
43
+
44
+ const getRoleList = async ({ tenantId, currentPage, perPage, filter }) => {
45
+ const queryFilter = {};
46
+ if (!isNil(filter?.type)) {
47
+ queryFilter.type = filter.type;
48
+ }
49
+ const { count, rows } = await fastify.account.models.tenantRole.findAndCountAll({
50
+ where: Object.assign({}, queryFilter, { tenantId }),
51
+ offset: currentPage * (currentPage - 1),
52
+ limit: perPage
53
+ });
54
+
55
+ return { pageData: rows, totalCount: count };
56
+ };
57
+
58
+ const addRole = async ({ tenantId, name, description }) => {
59
+ if (!(await fastify.account.models.tenant.findByPk(tenantId))) {
60
+ throw new Error('租户不存在');
61
+ }
62
+
63
+ return await fastify.account.models.tenantRole.create({
64
+ tenantId,
65
+ name,
66
+ description
67
+ });
68
+ };
69
+
70
+ const saveRole = async ({ id, ...otherInfo }) => {
71
+ const tenantRole = await fastify.account.models.tenantRole.findByPk(id, {
72
+ where: {
73
+ type: 0
74
+ }
75
+ });
76
+
77
+ if (!tenantRole) {
78
+ throw new Error('角色不存在');
79
+ }
80
+
81
+ ['name', 'description'].forEach(name => {
82
+ if (otherInfo[name]) {
83
+ tenantRole[name] = otherInfo[name];
84
+ }
85
+ });
86
+
87
+ await tenantRole.save();
88
+ };
89
+
90
+ const removeRole = async ({ id }) => {
91
+ const tenantRole = await fastify.account.models.tenantRole.findByPk(id, {
92
+ where: {
93
+ type: 0
94
+ }
95
+ });
96
+
97
+ if (!tenantRole) {
98
+ throw new Error('角色不存在');
99
+ }
100
+
101
+ if (
102
+ (await fastify.account.models.tenantUserRole.count({
103
+ where: {
104
+ tenantRoleId: tenantRole.id
105
+ }
106
+ })) > 0
107
+ ) {
108
+ throw new Error('该角色已经被使用,请在租户用户种处理掉所有使用该角色的租户用户后重试');
109
+ }
110
+
111
+ if (tenantRole.type === 1) {
112
+ throw new Error('该角色为系统默认角色,不能删除');
113
+ }
114
+
115
+ await tenantRole.destroy();
116
+ };
117
+
118
+ const tenantUserAuthenticate = async user => {
119
+ if (!user.currentTenantId) {
120
+ throw new Error('没有找到当前绑定租户');
121
+ }
122
+ const tenant = await fastify.account.models.tenant.findByPk(user.currentTenantId, {
123
+ where: {
124
+ status: 0
125
+ }
126
+ });
127
+ if (!tenant) {
128
+ throw new Error('当前绑定租户不存在或者已经被关闭');
129
+ }
130
+
131
+ const tenantUser = await fastify.account.models.tenantUser.findOne({
132
+ where: {
133
+ tenantId: tenant.id,
134
+ userId: user.id,
135
+ status: 0
136
+ }
137
+ });
138
+
139
+ if (!tenantUser) {
140
+ throw new Error('当前租户用户不存在或者已经被关闭');
141
+ }
142
+
143
+ return {
144
+ tenant,
145
+ tenantUser
146
+ };
147
+ };
148
+
149
+ const closeTenant = async ({ tenantId }) => {
150
+ const tenant = await getTenantInfo({ id: tenantId });
151
+ tenant.status = 12;
152
+ await tenant.save();
153
+ };
154
+
155
+ const openTenant = async ({ tenantId }) => {
156
+ const tenant = await getTenantInfo({ id: tenantId });
157
+ tenant.status = 0;
158
+ await tenant.save();
159
+ };
160
+
161
+ const addTenantOrg = async org => {
162
+ if (await fastify.account.models.tenantOrg.count({ where: { name: org.name } })) {
163
+ throw new Error('组织名称不能重复');
164
+ }
165
+
166
+ return await fastify.account.models.tenantOrg.create({
167
+ name: org.name,
168
+ enName: org.enName,
169
+ tenantId: org.tenantId,
170
+ pid: org.pid
171
+ });
172
+ };
173
+
174
+ const saveTenantOrg = async ({ id, ...otherInfo }) => {
175
+ const tenantOrg = await fastify.account.models.tenantOrg.findByPk(id, {
176
+ where: {
177
+ type: 0
178
+ }
179
+ });
180
+
181
+ if (!tenantOrg) {
182
+ throw new Error('该组织不存在');
183
+ }
184
+ if (
185
+ await fastify.account.models.tenantOrg.count({
186
+ where: {
187
+ name: otherInfo.name,
188
+ pid: otherInfo.pid,
189
+ tenantId: otherInfo.tenantId
190
+ }
191
+ })
192
+ ) {
193
+ throw new Error('组织名称在同一父组织下有重复');
194
+ }
195
+
196
+ ['name', 'enName', 'tenantId', 'pid'].forEach(name => {
197
+ if (otherInfo[name]) {
198
+ tenantOrg[name] = otherInfo[name];
199
+ }
200
+ });
201
+
202
+ await tenantOrg.save();
203
+ };
204
+
205
+ const deleteTenantOrg = async ({ id, tenantId }) => {
206
+ const tenantOrg = await fastify.account.models.tenantOrg.findByPk(id, {
207
+ where: {
208
+ type: 0
209
+ }
210
+ });
211
+
212
+ if (!tenantOrg) {
213
+ throw new Error('该组织不存在');
214
+ }
215
+
216
+ const { rows } = await fastify.account.models.tenantOrg.findAndCountAll({
217
+ where: { tenantId, pid: id }
218
+ });
219
+
220
+ if (rows?.length) {
221
+ throw new Error('组织下有用户或子组织无法删除');
222
+ }
223
+
224
+ await tenantOrg.destroy();
225
+ };
226
+
227
+ const getTenantOrgList = async ({ tenantId }) => {
228
+ const { count, rows } = await fastify.account.models.tenantOrg.findAndCountAll({
229
+ where: { tenantId }
230
+ });
231
+
232
+ return { pageData: rows, totalCount: count };
233
+ };
234
+
235
+ const getTenantUserList = async ({ tenantId }) => {
236
+ if (!(await fastify.account.models.tenant.findByPk(tenantId))) {
237
+ throw new Error('租户不存在');
238
+ }
239
+ const { count, rows } = await fastify.account.models.tenantUser.findAndCountAll({
240
+ include: [fastify.account.models.tenantRole, fastify.account.models.tenantOrg, fastify.account.models.user],
241
+ where: { tenantId }
242
+ });
243
+
244
+ return { pageData: rows, totalCount: count };
245
+ };
246
+
247
+ const saveTenantUserInfoValidate = async ({ tenantId, roleIds, orgIds, userId }) => {
248
+ await getTenantInfo({ id: tenantId });
249
+ if (
250
+ roleIds.length > 0 &&
251
+ (await fastify.account.models.tenantRole.count({
252
+ where: {
253
+ id: {
254
+ [fastify.sequelize.Sequelize.Op.in]: roleIds
255
+ }
256
+ }
257
+ })) < roleIds.length
258
+ ) {
259
+ throw new Error('包含租户不存在的角色');
260
+ }
261
+ if (orgIds.length === 0) {
262
+ const tenantOrg = await fastify.account.models.tenantOrg.findOne({
263
+ where: {
264
+ pid: 0,
265
+ tenantId
266
+ }
267
+ });
268
+ if (!tenantOrg) {
269
+ throw new Error('租户根节点不存在');
270
+ }
271
+ orgIds = [tenantOrg.id];
272
+ }
273
+
274
+ if (
275
+ (await fastify.account.models.tenantOrg.count({
276
+ where: {
277
+ tenantId,
278
+ id: {
279
+ [fastify.sequelize.Sequelize.Op.in]: orgIds
280
+ }
281
+ }
282
+ })) < orgIds.length
283
+ ) {
284
+ throw new Error('包含租户不存在组织');
285
+ }
286
+
287
+ if (!(await fastify.account.models.user.findByPk(userId))) {
288
+ throw new Error('用户不存在,应该先创建用户再创建租户用户');
289
+ }
290
+ };
291
+
292
+ const addTenantUser = async ({ tenantId, roleIds, orgIds, userId, ...tenantUser }) => {
293
+ const tenant = await getTenantInfo({ id: tenantId });
294
+
295
+ const currentAccountNumber = await fastify.account.models.tenantUser.count({
296
+ where: { tenantId }
297
+ });
298
+
299
+ if (currentAccountNumber >= tenant.accountNumber) {
300
+ throw new Error('租户用户数量已达上限');
301
+ }
302
+
303
+ await saveTenantUserInfoValidate({ tenantId, roleIds, orgIds, userId });
304
+
305
+ const t = await fastify.sequelize.instance.transaction();
306
+
307
+ if (
308
+ (await fastify.account.models.tenantUser.count({
309
+ where: {
310
+ userId,
311
+ tenantId
312
+ }
313
+ })) > 0
314
+ ) {
315
+ throw new Error('该用户已经属于该租户,不能重复添加');
316
+ }
317
+
318
+ try {
319
+ const currentTenantUser = await fastify.account.models.tenantUser.create(
320
+ {
321
+ name: tenantUser.name,
322
+ avatar: tenantUser.avatar,
323
+ phone: tenantUser.phone,
324
+ email: tenantUser.email,
325
+ description: tenantUser.description,
326
+ tenantId,
327
+ userId
328
+ },
329
+ { transaction: t }
330
+ );
331
+ roleIds.length > 0 &&
332
+ (await fastify.account.models.tenantUserRole.bulkCreate(
333
+ roleIds.map(roleId => {
334
+ return {
335
+ tenantRoleId: roleId,
336
+ tenantId,
337
+ tenantUserId: currentTenantUser.id
338
+ };
339
+ }),
340
+ { transaction: t }
341
+ ));
342
+
343
+ await fastify.account.models.tenantUserOrg.bulkCreate(
344
+ orgIds.map(orgId => {
345
+ return {
346
+ tenantOrgId: orgId,
347
+ tenantId,
348
+ tenantUserId: currentTenantUser.id
349
+ };
350
+ }),
351
+ { transaction: t }
352
+ );
353
+
354
+ await t.commit();
355
+ } catch (e) {
356
+ await t.rollback();
357
+ throw e;
358
+ }
359
+ };
360
+
361
+ const saveTenantUser = async ({ id, tenantId, roleIds, orgIds, userId, ...tenantUser }) => {
362
+ const currentTenantUser = await fastify.account.models.tenantUser.findByPk(id);
363
+ if (!currentTenantUser) {
364
+ throw new Error('租户用户不存在');
365
+ }
366
+ if (tenantId !== currentTenantUser.tenantId) {
367
+ throw new Error('租户Id和当前租户用户的租户Id不一致');
368
+ }
369
+ await saveTenantUserInfoValidate({ tenantId, roleIds, orgIds, userId: currentTenantUser.userId });
370
+
371
+ const tenantRoleIds = (
372
+ await fastify.account.models.tenantUserRole.findAll({
373
+ attributes: ['tenantRoleId'],
374
+ where: {
375
+ tenantId,
376
+ tenantUserId: currentTenantUser.id
377
+ }
378
+ })
379
+ ).map(({ tenantRoleId }) => tenantRoleId);
380
+
381
+ const tenantOrgIds = (
382
+ await fastify.account.models.tenantUserOrg.findAll({
383
+ attributes: ['tenantOrgId'],
384
+ where: {
385
+ tenantId,
386
+ tenantUserId: currentTenantUser.id
387
+ }
388
+ })
389
+ ).map(({ tenantOrgId }) => tenantOrgId);
390
+
391
+ const t = await fastify.sequelize.instance.transaction();
392
+
393
+ try {
394
+ ['name', 'avatar', 'phone', 'email', 'description'].forEach(name => {
395
+ if (!isNil(tenantUser[name])) {
396
+ currentTenantUser[name] = tenantUser[name];
397
+ }
398
+ });
399
+ await currentTenantUser.save({ transaction: t });
400
+ // 修改角色
401
+ const needDeleteTenantRole = tenantRoleIds.filter(targetId => roleIds.indexOf(targetId) === -1);
402
+ const needAddTenantRole = roleIds.filter(targetId => tenantRoleIds.indexOf(targetId) === -1);
403
+ await fastify.account.models.tenantUserRole.destroy({
404
+ where: {
405
+ tenantId,
406
+ tenantUserId: currentTenantUser.id,
407
+ tenantRoleId: {
408
+ [fastify.sequelize.Sequelize.Op.in]: needDeleteTenantRole
409
+ }
410
+ },
411
+ transaction: t
412
+ });
413
+ await fastify.account.models.tenantUserRole.bulkCreate(
414
+ needAddTenantRole.map(tenantRoleId => {
415
+ return { tenantId, tenantUserId: currentTenantUser.id, tenantRoleId };
416
+ }),
417
+ { transaction: t }
418
+ );
419
+ //修改组织
420
+ const needDeleteTenantOrg = tenantOrgIds.filter(targetId => orgIds.indexOf(targetId) === -1);
421
+ const needAddTenantOrg = orgIds.filter(targetId => tenantOrgIds.indexOf(targetId) === -1);
422
+ await fastify.account.models.tenantUserOrg.destroy({
423
+ where: {
424
+ tenantId,
425
+ tenantUserId: currentTenantUser.id,
426
+ tenantOrgId: {
427
+ [fastify.sequelize.Sequelize.Op.in]: needDeleteTenantOrg
428
+ }
429
+ },
430
+ transaction: t
431
+ });
432
+ await fastify.account.models.tenantUserOrg.bulkCreate(
433
+ needAddTenantOrg.map(tenantOrgId => {
434
+ return { tenantId, tenantUserId: currentTenantUser.id, tenantOrgId };
435
+ }),
436
+ { transaction: t }
437
+ );
438
+ await t.commit();
439
+ } catch (e) {
440
+ await t.rollback();
441
+ throw e;
442
+ }
443
+ };
444
+
445
+ const deleteTenantUser = async ({ tenantId, tenantUserId }) => {
446
+ await getTenantInfo({ id: tenantId });
447
+ const tenantUser = await fastify.account.models.tenantUser.findByPk(tenantUserId);
448
+ if (!tenantUser) {
449
+ throw new Error('租户用户不存在');
450
+ }
451
+
452
+ const t = await fastify.sequelize.instance.transaction();
453
+
454
+ try {
455
+ await fastify.account.models.tenantUserOrg.destroy({
456
+ where: {
457
+ tenantId,
458
+ tenantUserId: tenantUser.id
459
+ },
460
+ transaction: t
461
+ });
462
+ await fastify.account.models.tenantUserRole.destroy({
463
+ where: {
464
+ tenantId,
465
+ tenantUserId: tenantUser.id
466
+ },
467
+ transaction: t
468
+ });
469
+ await tenantUser.destroy({ transaction: t });
470
+ await t.commit();
471
+ } catch (e) {
472
+ await t.rollback();
473
+ throw e;
474
+ }
475
+ };
476
+
477
+ const closeTenantUser = async ({ tenantId, tenantUserId }) => {
478
+ await getTenantInfo({ id: tenantId });
479
+ const tenantUser = await fastify.account.models.tenantUser.findByPk(tenantUserId);
480
+ if (!tenantUser) {
481
+ throw new Error('租户用户不存在');
482
+ }
483
+ tenantUser.status = 12;
484
+
485
+ await tenantUser.save();
486
+ };
487
+
488
+ const openTenantUser = async ({ tenantId, tenantUserId }) => {
489
+ await getTenantInfo({ id: tenantId });
490
+ const tenantUser = await fastify.account.models.tenantUser.findByPk(tenantUserId);
491
+ if (!tenantUser) {
492
+ throw new Error('租户用户不存在');
493
+ }
494
+ tenantUser.status = 0;
495
+
496
+ await tenantUser.save();
497
+ };
498
+
499
+ const getInviteList = async ({ tenantId, filter, currentPage, perPage }) => {
500
+ const queryFilter = {};
501
+ const { count, rows } = await fastify.account.models.tenantToken.findAndCountAll({
502
+ where: Object.assign({}, queryFilter, { tenantId, type: 10 }),
503
+ offset: currentPage * (currentPage - 1),
504
+ limit: perPage
505
+ });
506
+ return { pageData: rows, totalCount: count };
507
+ };
508
+
509
+ const generateTenantToken = async ({ type, tenantId, info, tenantUserId }) => {
510
+ await getTenantInfo({ id: tenantId });
511
+ const token = fastify.jwt.sign({ tenantId });
512
+ return await fastify.account.models.tenantToken.create({
513
+ token,
514
+ tenantId,
515
+ info,
516
+ tenantUserId,
517
+ type
518
+ });
519
+ };
520
+
521
+ const decodeTenantToken = async ({ type, tenantId, token }) => {
522
+ if (
523
+ (await fastify.account.models.tenantToken.count({
524
+ where: {
525
+ type,
526
+ tenantId,
527
+ token
528
+ }
529
+ })) === 0
530
+ ) {
531
+ throw new Error('token已过期');
532
+ }
533
+
534
+ return fastify.jwt.decode(token);
535
+ };
536
+
537
+ const addInviteToken = async ({ info, tenantId, tenantUserId }) => {
538
+ return await generateTenantToken({ info, tenantId, tenantUserId, type: 10 });
539
+ };
540
+
541
+ const deleteInviteToken = async ({ id }) => {
542
+ const token = await fastify.account.models.tenantToken.findByPk(id);
543
+ if (!token) {
544
+ throw new Error('数据不存在');
545
+ }
546
+
547
+ await token.destroy();
548
+ };
549
+
550
+ fastify.account.services.tenant = {
551
+ getUserTenant,
552
+ closeTenant,
553
+ openTenant,
554
+ tenantUserAuthenticate,
555
+ getTenantInfo,
556
+ getRoleList,
557
+ addRole,
558
+ saveRole,
559
+ removeRole,
560
+ addTenantOrg,
561
+ deleteTenantOrg,
562
+ saveTenantOrg,
563
+ getTenantOrgList,
564
+ getTenantUserList,
565
+ addTenantUser,
566
+ saveTenantUser,
567
+ deleteTenantUser,
568
+ closeTenantUser,
569
+ openTenantUser,
570
+ getInviteList,
571
+ generateTenantToken,
572
+ decodeTenantToken,
573
+ addInviteToken,
574
+ deleteInviteToken
575
+ };
576
+ });
@@ -0,0 +1,108 @@
1
+ const fp = require('fastify-plugin');
2
+ const { Unauthorized } = require('http-errors');
3
+ const get = require('lodash/get');
4
+ module.exports = fp(async (fastify, options) => {
5
+ const getUserInfo = async authenticatePayload => {
6
+ if (!(authenticatePayload && authenticatePayload.id)) {
7
+ throw new Unauthorized();
8
+ }
9
+ const user = await fastify.account.models.user.findByPk(authenticatePayload.id);
10
+ if (!user) {
11
+ throw new Unauthorized();
12
+ }
13
+ const userInfo = user.get({ plain: true });
14
+ delete userInfo['userAccountId'];
15
+
16
+ return userInfo;
17
+ };
18
+
19
+ const accountIsExists = async ({ email, phone }, currentUser) => {
20
+ const query = [];
21
+ if (email && email !== get(currentUser, 'email')) {
22
+ query.push({ email });
23
+ }
24
+ if (phone && phone !== get(currentUser, 'phone')) {
25
+ query.push({ phone });
26
+ }
27
+
28
+ return (
29
+ (await fastify.account.models.user.count({
30
+ where: {
31
+ [fastify.sequelize.Sequelize.Op.or]: query
32
+ }
33
+ })) > 0
34
+ );
35
+ };
36
+
37
+ const addUser = async ({ avatar, nickname, gender, birthday, description, phone, email, password, status }) => {
38
+ if ((await accountIsExists({ phone, email })) > 0) {
39
+ throw new Error('手机号或者邮箱都不能重复');
40
+ }
41
+ if (!password) {
42
+ throw new Error('密码不能为空');
43
+ }
44
+ const account = await fastify.account.models.userAccount.create(await fastify.account.services.account.passwordEncryption(password));
45
+ const user = await fastify.account.models.user.create({
46
+ avatar,
47
+ nickname,
48
+ gender,
49
+ birthday,
50
+ description,
51
+ phone,
52
+ email,
53
+ status,
54
+ userAccountId: account.id
55
+ });
56
+ await account.update({ belongToUserId: user.id });
57
+ return user;
58
+ };
59
+
60
+ const saveUser = async ({ id, ...otherInfo }) => {
61
+ const user = await fastify.account.models.user.findByPk(id);
62
+
63
+ if (!user) {
64
+ throw new Error('用户不存在');
65
+ }
66
+
67
+ if ((await accountIsExists({ phone: otherInfo.phone, email: otherInfo.email }, user)) > 0) {
68
+ throw new Error('手机号或者邮箱都不能重复');
69
+ }
70
+
71
+ ['nickname', 'avatar', 'phone', 'email', 'description'].forEach(fieldName => {
72
+ if (otherInfo[fieldName]) {
73
+ user[fieldName] = otherInfo[fieldName];
74
+ }
75
+ });
76
+
77
+ await user.save();
78
+ };
79
+
80
+ const closeUser = async ({ id }) => {
81
+ const user = await fastify.account.models.user.findByPk(id);
82
+
83
+ if (!user) {
84
+ throw new Error('用户不存在');
85
+ }
86
+ user.status = 12;
87
+ await user.save();
88
+ };
89
+
90
+ const openUser = async ({ id }) => {
91
+ const user = await fastify.account.models.user.findByPk(id);
92
+
93
+ if (!user) {
94
+ throw new Error('用户不存在');
95
+ }
96
+ user.status = 0;
97
+ await user.save();
98
+ };
99
+
100
+ fastify.account.services.user = {
101
+ getUserInfo,
102
+ saveUser,
103
+ accountIsExists,
104
+ addUser,
105
+ closeUser,
106
+ openUser
107
+ };
108
+ });