@kne/fastify-account 1.0.0-alpha.14 → 1.0.0-alpha.15

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/index.js CHANGED
@@ -2,7 +2,8 @@ const fp = require('fastify-plugin');
2
2
  const packageJson = require('./package.json');
3
3
  const path = require('path');
4
4
  const merge = require('lodash/merge');
5
- const { Unauthorized } = require('http-errors');
5
+ const get = require('lodash/get');
6
+ const { Unauthorized, Forbidden } = require('http-errors');
6
7
 
7
8
  module.exports = fp(
8
9
  async function (fastify, options) {
@@ -13,7 +14,8 @@ module.exports = fp(
13
14
  dbTableNamePrefix: 't_account_',
14
15
  isTest: false,
15
16
  jwt: {
16
- secret: 'super-secret'
17
+ secret: 'super-secret',
18
+ expires: null
17
19
  },
18
20
  defaultPassword: 'Aa000000!'
19
21
  },
@@ -39,7 +41,9 @@ module.exports = fp(
39
41
  user: async request => {
40
42
  const info = await request.jwtVerify();
41
43
  //这里判断失效时间
42
- //info.iat
44
+ if (options.jwt.expires && Date.now() - info.iat * 1000 > options.jwt.expires) {
45
+ throw Unauthorized('身份认证超时');
46
+ }
43
47
  request.authenticatePayload = info.payload;
44
48
  request.userInfo = await fastify.account.services.user.getUser(request.authenticatePayload);
45
49
  },
@@ -50,6 +54,15 @@ module.exports = fp(
50
54
  if (!(await fastify.account.services.admin.checkIsSuperAdmin(request.userInfo))) {
51
55
  throw Unauthorized('不能执行该操作,需要超级管理员权限');
52
56
  }
57
+ },
58
+ createPermission: permission => async request => {
59
+ const permissions = get(request.tenantInfo, 'tenantUser.permissions');
60
+ if (!permissions) {
61
+ throw Forbidden('未获取到权限信息');
62
+ }
63
+ if (!(permission && permissions.indexOf(permission) > -1)) {
64
+ throw Forbidden('用户没有权限执行该操作');
65
+ }
53
66
  }
54
67
  }
55
68
  ]
@@ -88,6 +88,8 @@ module.exports = fp(async (fastify, options) => {
88
88
  {
89
89
  onRequest: [authenticate.user, authenticate.admin],
90
90
  schema: {
91
+ tags: ['管理后台'],
92
+ summary: '添加用户',
91
93
  body: {}
92
94
  }
93
95
  },
@@ -103,6 +105,8 @@ module.exports = fp(async (fastify, options) => {
103
105
  {
104
106
  onRequest: [authenticate.user, authenticate.admin],
105
107
  schema: {
108
+ tags: ['管理后台'],
109
+ summary: '获取用户列表',
106
110
  query: {
107
111
  perPage: { type: 'number' },
108
112
  currentPage: { type: 'number' }
@@ -130,6 +134,8 @@ module.exports = fp(async (fastify, options) => {
130
134
  {
131
135
  onRequest: [authenticate.user, authenticate.admin],
132
136
  schema: {
137
+ tags: ['管理后台'],
138
+ summary: '重置用户账号密码',
133
139
  body: {
134
140
  type: 'object',
135
141
  required: ['userId', 'password'],
@@ -151,6 +157,8 @@ module.exports = fp(async (fastify, options) => {
151
157
  {
152
158
  onRequest: [authenticate.user, authenticate.admin],
153
159
  schema: {
160
+ tags: ['管理后台'],
161
+ summary: '修改用户信息',
154
162
  body: {
155
163
  type: 'object',
156
164
  required: ['id'],
@@ -177,6 +185,8 @@ module.exports = fp(async (fastify, options) => {
177
185
  {
178
186
  onRequest: [authenticate.user, authenticate.admin],
179
187
  schema: {
188
+ tags: ['管理后台'],
189
+ summary: '关闭用户',
180
190
  body: {
181
191
  type: 'object',
182
192
  required: ['id'],
@@ -198,6 +208,8 @@ module.exports = fp(async (fastify, options) => {
198
208
  {
199
209
  onRequest: [authenticate.user, authenticate.admin],
200
210
  schema: {
211
+ tags: ['管理后台'],
212
+ summary: '将用户设置为正常',
201
213
  body: {
202
214
  type: 'object',
203
215
  required: ['id'],
@@ -33,6 +33,8 @@ module.exports = fp(async (fastify, options) => {
33
33
  {
34
34
  onRequest: [authenticate.user, authenticate.admin],
35
35
  schema: {
36
+ tags: ['管理后台-权限'],
37
+ summary: '修改应用',
36
38
  body: {
37
39
  type: 'object',
38
40
  required: ['id', 'name', 'code'],
@@ -58,6 +60,8 @@ module.exports = fp(async (fastify, options) => {
58
60
  {
59
61
  onRequest: [authenticate.user, authenticate.admin],
60
62
  schema: {
63
+ tags: ['管理后台-权限'],
64
+ summary: '删除应用',
61
65
  body: {
62
66
  type: 'object',
63
67
  required: ['id'],
@@ -79,6 +83,8 @@ module.exports = fp(async (fastify, options) => {
79
83
  {
80
84
  onRequest: [authenticate.user, authenticate.admin],
81
85
  schema: {
86
+ tags: ['管理后台-权限'],
87
+ summary: '获取应用列表',
82
88
  query: {
83
89
  type: 'object',
84
90
  properties: {
@@ -98,6 +104,8 @@ module.exports = fp(async (fastify, options) => {
98
104
  {
99
105
  onRequest: [authenticate.user, authenticate.admin],
100
106
  schema: {
107
+ tags: ['管理后台-权限'],
108
+ summary: '添加应用权限',
101
109
  body: {
102
110
  type: 'object',
103
111
  required: ['applicationId', 'name', 'code'],
@@ -125,6 +133,8 @@ module.exports = fp(async (fastify, options) => {
125
133
  {
126
134
  onRequest: [authenticate.user, authenticate.admin],
127
135
  schema: {
136
+ tags: ['管理后台-权限'],
137
+ summary: '获取应用权限列表',
128
138
  query: {
129
139
  type: 'object',
130
140
  required: ['applicationId'],
@@ -132,6 +142,35 @@ module.exports = fp(async (fastify, options) => {
132
142
  applicationId: { type: 'string' },
133
143
  tenantId: { type: 'string' }
134
144
  }
145
+ },
146
+ response: {
147
+ 200: {
148
+ content: {
149
+ 'application/json': {
150
+ schema: {
151
+ type: 'array',
152
+ items: {
153
+ type: 'object',
154
+ properties: {
155
+ id: { type: 'number' },
156
+ code: { type: 'string' },
157
+ name: { type: 'string' },
158
+ isModule: { type: 'number' },
159
+ isMust: { type: 'number' },
160
+ type: { type: 'number' },
161
+ pid: { type: 'number' },
162
+ paths: { type: 'array', items: { type: 'number' } },
163
+ description: { type: 'string' },
164
+ status: { type: 'number' },
165
+ createdAt: { type: 'string' },
166
+ updatedAt: { type: 'string' },
167
+ deletedAt: { type: 'string' }
168
+ }
169
+ }
170
+ }
171
+ }
172
+ }
173
+ }
135
174
  }
136
175
  }
137
176
  },
@@ -141,11 +180,83 @@ module.exports = fp(async (fastify, options) => {
141
180
  }
142
181
  );
143
182
 
183
+ fastify.post(`${options.prefix}/admin/parsePermissionList`, {}, async request => {
184
+ const file = await request.file();
185
+ if (!file) {
186
+ throw new Error('不能获取到上传文件');
187
+ }
188
+
189
+ return await services.permission.parsePermissionListJSON({ file });
190
+ });
191
+
192
+ fastify.post(
193
+ `${options.prefix}/admin/exportPermissionList`,
194
+ {
195
+ onRequest: [authenticate.user, authenticate.admin],
196
+ schema: {
197
+ tags: ['管理后台-权限'],
198
+ summary: '导出应用权限列表',
199
+ body: {
200
+ type: 'object',
201
+ required: ['applicationIds'],
202
+ properties: {
203
+ applicationIds: { type: 'array', items: { type: 'string' } },
204
+ tenantId: { type: 'string' }
205
+ }
206
+ },
207
+ response: {
208
+ 200: {
209
+ content: {
210
+ 'application/json': {
211
+ schema: {
212
+ type: 'array',
213
+ items: {
214
+ type: 'object',
215
+ properties: {
216
+ code: { type: 'string' },
217
+ name: { type: 'string' },
218
+ url: { type: 'string' },
219
+ description: { type: 'string' },
220
+ status: { type: 'number' },
221
+ permissions: {
222
+ type: 'array',
223
+ items: {
224
+ type: 'object',
225
+ properties: {
226
+ id: { type: 'number' },
227
+ code: { type: 'string' },
228
+ name: { type: 'string' },
229
+ isModule: { type: 'number' },
230
+ isMust: { type: 'number' },
231
+ type: { type: 'number' },
232
+ pid: { type: 'number' },
233
+ description: { type: 'string' },
234
+ status: { type: 'number' }
235
+ }
236
+ }
237
+ }
238
+ }
239
+ }
240
+ }
241
+ }
242
+ }
243
+ }
244
+ }
245
+ }
246
+ },
247
+ async request => {
248
+ const { applicationIds, tenantId } = request.body;
249
+ return await services.permission.exportPermissionList({ applicationIds, tenantId });
250
+ }
251
+ );
252
+
144
253
  fastify.post(
145
254
  `${options.prefix}/admin/deletePermission`,
146
255
  {
147
256
  onRequest: [authenticate.user, authenticate.admin],
148
257
  schema: {
258
+ tags: ['管理后台-权限'],
259
+ summary: '删除应用权限',
149
260
  body: {
150
261
  type: 'object',
151
262
  required: ['id'],
@@ -169,6 +280,8 @@ module.exports = fp(async (fastify, options) => {
169
280
  {
170
281
  onRequest: [authenticate.user, authenticate.admin],
171
282
  schema: {
283
+ tags: ['管理后台-权限'],
284
+ summary: '修改应用权限',
172
285
  body: {
173
286
  type: 'object',
174
287
  required: ['id'],
@@ -188,11 +301,35 @@ module.exports = fp(async (fastify, options) => {
188
301
  }
189
302
  );
190
303
 
304
+ fastify.get(
305
+ `${options.prefix}/admin/getTenantPermissionList`,
306
+ {
307
+ onRequest: [authenticate.user, authenticate.admin],
308
+ schema: {
309
+ tags: ['管理后台-权限'],
310
+ summary: '获取租户应用权限配置',
311
+ query: {
312
+ type: 'object',
313
+ required: ['tenantId'],
314
+ properties: {
315
+ tenantId: { type: 'string' }
316
+ }
317
+ }
318
+ }
319
+ },
320
+ async request => {
321
+ const { tenantId } = request.query;
322
+ return await services.permission.getTenantPermissionList({ tenantId });
323
+ }
324
+ );
325
+
191
326
  fastify.post(
192
327
  `${options.prefix}/admin/saveTenantPermissionList`,
193
328
  {
194
329
  onRequest: [authenticate.user, authenticate.admin],
195
330
  schema: {
331
+ tags: ['管理后台-权限'],
332
+ summary: '修改租户应用权限配置',
196
333
  body: {
197
334
  type: 'object',
198
335
  required: ['tenantId', 'applications', 'permissions'],
@@ -216,24 +353,4 @@ module.exports = fp(async (fastify, options) => {
216
353
  return {};
217
354
  }
218
355
  );
219
-
220
- fastify.get(
221
- `${options.prefix}/admin/getTenantPermissionList`,
222
- {
223
- onRequest: [authenticate.user, authenticate.admin],
224
- schema: {
225
- query: {
226
- type: 'object',
227
- required: ['tenantId'],
228
- properties: {
229
- tenantId: { type: 'string' }
230
- }
231
- }
232
- }
233
- },
234
- async request => {
235
- const { tenantId } = request.query;
236
- return await services.permission.getTenantPermissionList({ tenantId });
237
- }
238
- );
239
356
  });
@@ -26,6 +26,21 @@ module.exports = fp(async (fastify, options) => {
26
26
  });
27
27
  };
28
28
 
29
+ const getApplicationByCode = async ({ code }) => {
30
+ const application = await models.application.findOne({
31
+ where: {
32
+ code
33
+ }
34
+ });
35
+ if (application) {
36
+ await getApplicationInstance({ id: application.uuid });
37
+ return Object.assign({}, application.get({ plain: true }), {
38
+ id: application.uuid
39
+ });
40
+ }
41
+ return null;
42
+ };
43
+
29
44
  const addApplication = async application => {
30
45
  const currentApplication = await models.application.create(application);
31
46
  return Object.assign({}, currentApplication.get({ plain: true }), {
@@ -143,6 +158,7 @@ module.exports = fp(async (fastify, options) => {
143
158
  services.application = {
144
159
  addApplication,
145
160
  getApplication,
161
+ getApplicationByCode,
146
162
  saveApplication,
147
163
  deleteApplication,
148
164
  getApplicationList,
@@ -1,8 +1,12 @@
1
1
  const fp = require('fastify-plugin');
2
2
  const isNil = require('lodash/isNil');
3
+ const get = require('lodash/get');
4
+ const groupBy = require('lodash/groupBy');
5
+
6
+ const uniq = require('lodash/uniq');
3
7
  module.exports = fp(async (fastify, options) => {
4
8
  const { models, services } = fastify.account;
5
-
9
+ const { Op } = fastify.sequelize.Sequelize;
6
10
  const addPermission = async ({ applicationId, pid, code, name, type, isModule, isMust, description }) => {
7
11
  if (!(await services.application.getApplication({ id: applicationId }))) {
8
12
  throw new Error('应用不存在');
@@ -47,10 +51,10 @@ module.exports = fp(async (fastify, options) => {
47
51
  const tenantPermissions = await models.tenantPermission.findAll({
48
52
  where: { tenantId }
49
53
  });
50
- query[fastify.sequelize.Sequelize.Op.or] = [
54
+ query[Op.or] = [
51
55
  {
52
56
  id: {
53
- [fastify.sequelize.Sequelize.Op.in]: tenantPermissions.map(({ permissionId }) => permissionId)
57
+ [Op.in]: tenantPermissions.map(({ permissionId }) => permissionId)
54
58
  }
55
59
  },
56
60
  { isMust: 1 }
@@ -64,6 +68,57 @@ module.exports = fp(async (fastify, options) => {
64
68
  });
65
69
  };
66
70
 
71
+ const parsePermissionListJSON = async ({ file }) => {
72
+ const data = JSON.parse(await file.toBuffer());
73
+ await Promise.all(
74
+ data.map(async application => {
75
+ const { permissions, ...other } = application;
76
+ const app = await services.application.getApplicationByCode({ code: application.code });
77
+
78
+ if (!app) {
79
+ const newApplication = await services.application.addApplication(other);
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);
105
+ }
106
+ return app;
107
+ })
108
+ );
109
+ return data;
110
+ };
111
+
112
+ const exportPermissionList = async ({ applicationIds, tenantId }) => {
113
+ return await Promise.all(
114
+ (applicationIds || []).map(async applicationId => {
115
+ let application = await services.application.getApplication({ id: applicationId });
116
+ application.permissions = await services.permission.getPermissionList({ applicationId, tenantId });
117
+ return application;
118
+ })
119
+ );
120
+ };
121
+
67
122
  const deletePermission = async ({ id }) => {
68
123
  const currentPermission = await models.permission.findByPk(id);
69
124
 
@@ -90,7 +145,7 @@ module.exports = fp(async (fastify, options) => {
90
145
  await models.tenantPermission.destroy({
91
146
  where: {
92
147
  permissionId: {
93
- [fastify.sequelize.Sequelize.Op.in]: permissionIdList
148
+ [Op.in]: permissionIdList
94
149
  }
95
150
  },
96
151
  transaction: t
@@ -98,7 +153,7 @@ module.exports = fp(async (fastify, options) => {
98
153
  await models.tenantRolePermission.destroy({
99
154
  where: {
100
155
  permissionId: {
101
- [fastify.sequelize.Sequelize.Op.in]: permissionIdList
156
+ [Op.in]: permissionIdList
102
157
  }
103
158
  },
104
159
  transaction: t
@@ -106,7 +161,7 @@ module.exports = fp(async (fastify, options) => {
106
161
  await models.permission.destroy({
107
162
  where: {
108
163
  id: {
109
- [fastify.sequelize.Sequelize.Op.in]: permissionIdList
164
+ [Op.in]: permissionIdList
110
165
  }
111
166
  },
112
167
  transaction: t
@@ -159,7 +214,7 @@ module.exports = fp(async (fastify, options) => {
159
214
  await models.tenantRoleApplication.destroy({
160
215
  where: {
161
216
  applicationId: {
162
- [fastify.sequelize.Sequelize.Op.in]: needDeleteApplications
217
+ [Op.in]: needDeleteApplications
163
218
  },
164
219
  tenantId
165
220
  },
@@ -169,7 +224,7 @@ module.exports = fp(async (fastify, options) => {
169
224
  await models.tenantRolePermission.destroy({
170
225
  where: {
171
226
  permissionId: {
172
- [fastify.sequelize.Sequelize.Op.in]: needDeletePermissions
227
+ [Op.in]: needDeletePermissions
173
228
  },
174
229
  tenantId
175
230
  },
@@ -179,7 +234,7 @@ module.exports = fp(async (fastify, options) => {
179
234
  await models.tenantApplication.destroy({
180
235
  where: {
181
236
  applicationId: {
182
- [fastify.sequelize.Sequelize.Op.in]: needDeleteApplications
237
+ [Op.in]: needDeleteApplications
183
238
  },
184
239
  tenantId
185
240
  },
@@ -189,7 +244,7 @@ module.exports = fp(async (fastify, options) => {
189
244
  await models.tenantPermission.destroy({
190
245
  where: {
191
246
  permissionId: {
192
- [fastify.sequelize.Sequelize.Op.in]: needDeletePermissions
247
+ [Op.in]: needDeletePermissions
193
248
  },
194
249
  tenantId
195
250
  },
@@ -239,15 +294,20 @@ module.exports = fp(async (fastify, options) => {
239
294
  where: { tenantId }
240
295
  });
241
296
 
297
+ const mustPermissions = await models.permission.findAll({
298
+ attributes: ['id'],
299
+ where: { isMust: 1 }
300
+ });
301
+
242
302
  const tenantApplicationIds = tenantApplications.map(({ applicationId }) => applicationId);
243
- const tenantPermissionIds = tenantPermissions.map(({ permissionId }) => permissionId);
303
+ const tenantPermissionIds = uniq([...mustPermissions.map(({ id }) => id), ...tenantPermissions.map(({ permissionId }) => permissionId)]);
244
304
 
245
305
  const currentApplications = await models.tenantRoleApplication.findAll({
246
306
  where: {
247
307
  roleId: role.id,
248
308
  tenantId,
249
309
  applicationId: {
250
- [fastify.sequelize.Sequelize.Op.in]: tenantApplicationIds
310
+ [Op.in]: tenantApplicationIds
251
311
  }
252
312
  }
253
313
  });
@@ -256,7 +316,7 @@ module.exports = fp(async (fastify, options) => {
256
316
  where: {
257
317
  roleId: role.id,
258
318
  tenantId,
259
- permissionId: { [fastify.sequelize.Sequelize.Op.in]: tenantPermissionIds }
319
+ permissionId: { [Op.in]: tenantPermissionIds }
260
320
  }
261
321
  });
262
322
 
@@ -276,7 +336,7 @@ module.exports = fp(async (fastify, options) => {
276
336
  (await models.tenantRoleApplication.destroy({
277
337
  where: {
278
338
  applicationId: {
279
- [fastify.sequelize.Sequelize.Op.in]: needDeleteApplications
339
+ [Op.in]: needDeleteApplications
280
340
  },
281
341
  tenantId
282
342
  },
@@ -287,7 +347,7 @@ module.exports = fp(async (fastify, options) => {
287
347
  (await models.tenantRolePermission.destroy({
288
348
  where: {
289
349
  permissionId: {
290
- [fastify.sequelize.Sequelize.Op.in]: needDeletePermissions
350
+ [Op.in]: needDeletePermissions
291
351
  },
292
352
  tenantId
293
353
  },
@@ -357,6 +417,7 @@ module.exports = fp(async (fastify, options) => {
357
417
  services.permission = {
358
418
  addPermission,
359
419
  getPermissionList,
420
+ exportPermissionList,
360
421
  deletePermission,
361
422
  savePermission,
362
423
  saveTenantPermissionList,
@@ -83,16 +83,9 @@ module.exports = fp(async (fastify, options) => {
83
83
  return await models.permission.findAll({
84
84
  attributes: ['id', 'code', 'name', 'isModule', 'pid', 'applicationId', 'paths'],
85
85
  where: {
86
- [Op.or]: [
87
- {
88
- id: {
89
- [Op.in]: tenantRolePermission.map(({ permissionId }) => permissionId)
90
- }
91
- },
92
- {
93
- isMust: true
94
- }
95
- ]
86
+ id: {
87
+ [Op.in]: tenantRolePermission.map(({ permissionId }) => permissionId)
88
+ }
96
89
  }
97
90
  });
98
91
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kne/fastify-account",
3
- "version": "1.0.0-alpha.14",
3
+ "version": "1.0.0-alpha.15",
4
4
  "description": "fastify的用户管理账号等实现",
5
5
  "main": "index.js",
6
6
  "scripts": {