@kne/fastify-account 1.0.0-alpha.12 → 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
  ]
@@ -5,6 +5,8 @@ module.exports = fp(async (fastify, options) => {
5
5
  `${options.prefix}/sendEmailCode`,
6
6
  {
7
7
  schema: {
8
+ tags: ['账号'],
9
+ summary: '发送邮箱验证码',
8
10
  body: {
9
11
  type: 'object',
10
12
  required: ['email'],
@@ -39,12 +41,28 @@ module.exports = fp(async (fastify, options) => {
39
41
  `${options.prefix}/sendSMSCode`,
40
42
  {
41
43
  schema: {
44
+ tags: ['账号'],
45
+ summary: '发送短信验证码',
42
46
  body: {
43
47
  type: 'object',
44
48
  required: ['phone'],
45
49
  properties: {
46
50
  phone: { type: 'string', description: '电话' }
47
51
  }
52
+ },
53
+ response: {
54
+ 200: {
55
+ content: {
56
+ 'application/json': {
57
+ schema: {
58
+ type: 'object',
59
+ properties: {
60
+ code: { type: 'string', description: '验证码' }
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
48
66
  }
49
67
  }
50
68
  },
@@ -59,6 +77,8 @@ module.exports = fp(async (fastify, options) => {
59
77
  `${options.prefix}/validateCode`,
60
78
  {
61
79
  schema: {
80
+ tags: ['账号'],
81
+ summary: '验证码验证',
62
82
  body: {
63
83
  type: 'object',
64
84
  required: ['name', 'type', 'code'],
@@ -67,6 +87,15 @@ module.exports = fp(async (fastify, options) => {
67
87
  type: { type: 'number', description: '0:手机注册,1:邮箱注册,2:手机登录,3:邮箱登录,4:验证租户管理员' },
68
88
  code: { type: 'string', description: '接受到的验证码' }
69
89
  }
90
+ },
91
+ response: {
92
+ 200: {
93
+ content: {
94
+ 'application/json': {
95
+ schema: {}
96
+ }
97
+ }
98
+ }
70
99
  }
71
100
  }
72
101
  },
@@ -88,23 +117,39 @@ module.exports = fp(async (fastify, options) => {
88
117
  `${options.prefix}/accountIsExists`,
89
118
  {
90
119
  schema: {
120
+ tags: ['账号'],
121
+ summary: '账号是否已存在',
91
122
  body: {
92
123
  oneOf: [
93
124
  {
94
125
  type: 'object',
95
126
  required: ['phone'],
96
127
  properties: {
97
- phone: { type: 'string' }
128
+ phone: { type: 'string', description: '电话' }
98
129
  }
99
130
  },
100
131
  {
101
132
  type: 'object',
102
133
  required: ['email'],
103
134
  properties: {
104
- email: { type: 'string' }
135
+ email: { type: 'string', description: '邮箱' }
105
136
  }
106
137
  }
107
138
  ]
139
+ },
140
+ response: {
141
+ 200: {
142
+ content: {
143
+ 'application/json': {
144
+ schema: {
145
+ type: 'object',
146
+ properties: {
147
+ isExists: { type: 'boolean', description: 'true已存在,false不存在' }
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
108
153
  }
109
154
  }
110
155
  },
@@ -118,39 +163,50 @@ module.exports = fp(async (fastify, options) => {
118
163
  `${options.prefix}/register`,
119
164
  {
120
165
  schema: {
166
+ tags: ['账号'],
167
+ summary: '注册账号',
121
168
  body: {
122
169
  oneOf: [
123
170
  {
124
171
  type: 'object',
125
172
  required: ['phone', 'password', 'code'],
126
173
  properties: {
127
- avatar: { type: 'string' },
128
- phone: { type: 'string' },
129
- code: { type: 'string' },
130
- password: { type: 'string' },
131
- invitationCode: { type: 'string' },
132
- nickname: { type: 'string' },
133
- gender: { type: 'string' },
134
- birthday: { type: 'string', format: 'date' },
135
- description: { type: 'string' }
174
+ avatar: { type: 'string', description: '头像图片id' },
175
+ phone: { type: 'string', description: '电话' },
176
+ code: { type: 'string', description: '验证码' },
177
+ password: { type: 'string', description: '密码(需要md5加密)' },
178
+ invitationCode: { type: 'string', description: '邀请码,用来默认加入租户' },
179
+ nickname: { type: 'string', description: '昵称' },
180
+ gender: { type: 'string', description: '性别' },
181
+ birthday: { type: 'string', format: 'date', description: '出生日期' },
182
+ description: { type: 'string', description: '个人简介' }
136
183
  }
137
184
  },
138
185
  {
139
186
  type: 'object',
140
187
  required: ['email', 'password', 'code'],
141
188
  properties: {
142
- avatar: { type: 'string' },
143
- email: { type: 'string' },
144
- code: { type: 'string' },
145
- password: { type: 'string' },
146
- invitationCode: { type: 'string' },
147
- nickname: { type: 'string' },
148
- gender: { type: 'string' },
149
- birthday: { type: 'string', format: 'date' },
150
- description: { type: 'string' }
189
+ avatar: { type: 'string', description: '头像图片id' },
190
+ email: { type: 'string', description: '邮箱' },
191
+ code: { type: 'string', description: '验证码' },
192
+ password: { type: 'string', description: '密码(需要md5加密)' },
193
+ invitationCode: { type: 'string', description: '邀请码,用来默认加入租户' },
194
+ nickname: { type: 'string', description: '昵称' },
195
+ gender: { type: 'string', description: '性别' },
196
+ birthday: { type: 'string', format: 'date', description: '出生日期' },
197
+ description: { type: 'string', description: '个人简介' }
151
198
  }
152
199
  }
153
200
  ]
201
+ },
202
+ response: {
203
+ 200: {
204
+ content: {
205
+ 'application/json': {
206
+ schema: {}
207
+ }
208
+ }
209
+ }
154
210
  }
155
211
  }
156
212
  },
@@ -164,12 +220,29 @@ module.exports = fp(async (fastify, options) => {
164
220
  `${options.prefix}/login`,
165
221
  {
166
222
  schema: {
223
+ tags: ['账号'],
224
+ summary: '登录',
167
225
  body: {
168
226
  type: 'object',
169
227
  required: ['username', 'password'],
170
228
  properties: {
171
- username: { type: 'string' },
172
- password: { type: 'string' }
229
+ username: { type: 'string', description: '用户名' },
230
+ password: { type: 'string', description: '密码' }
231
+ }
232
+ },
233
+ response: {
234
+ 200: {
235
+ content: {
236
+ 'application/json': {
237
+ schema: {
238
+ type: 'object',
239
+ properties: {
240
+ token: { type: 'string', description: '用户token' },
241
+ currentTenantId: { type: 'string', description: '当前租户id' }
242
+ }
243
+ }
244
+ }
245
+ }
173
246
  }
174
247
  }
175
248
  }
@@ -2,11 +2,15 @@ const fp = require('fastify-plugin');
2
2
 
3
3
  module.exports = fp(async (fastify, options) => {
4
4
  const { authenticate, services } = fastify.account;
5
- // 用于系统初始化时,设置第一个用户,只能使用一次,其他用户由该用户创建
6
5
  fastify.post(
7
6
  `${options.prefix}/initSuperAdmin`,
8
7
  {
9
- onRequest: [authenticate.user]
8
+ onRequest: [authenticate.user],
9
+ schema: {
10
+ tags: ['管理后台'],
11
+ summary: '初始化用户为管理员',
12
+ description: '用于系统初始化时,设置第一个用户,只能使用一次,其他用户由该用户创建'
13
+ }
10
14
  },
11
15
  async request => {
12
16
  await services.admin.initSuperAdmin(request.userInfo);
@@ -17,7 +21,38 @@ module.exports = fp(async (fastify, options) => {
17
21
  fastify.get(
18
22
  `${options.prefix}/admin/getSuperAdminInfo`,
19
23
  {
20
- onRequest: [authenticate.user, authenticate.admin]
24
+ onRequest: [authenticate.user, authenticate.admin],
25
+ schema: {
26
+ tags: ['管理后台'],
27
+ summary: '获取管理员信息',
28
+ response: {
29
+ 200: {
30
+ content: {
31
+ 'application/json': {
32
+ schema: {
33
+ type: 'object',
34
+ properties: {
35
+ userInfo: {
36
+ type: 'object',
37
+ properties: {
38
+ id: { type: 'string', description: '用户id' },
39
+ nickname: { type: 'string', description: '用户昵称' },
40
+ email: { type: 'string', description: '邮箱' },
41
+ phone: { type: 'string', description: '电话' },
42
+ gender: { type: 'string', description: '性别' },
43
+ birthday: { type: 'string', format: 'date', description: '出生日期' },
44
+ description: { type: 'string', description: '个人简介' },
45
+ currentTenantId: { type: 'string', description: '当前租户ID' },
46
+ status: { type: 'number', description: '状态' }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
21
56
  },
22
57
  async request => {
23
58
  return { userInfo: request.userInfo };
@@ -29,12 +64,14 @@ module.exports = fp(async (fastify, options) => {
29
64
  {
30
65
  onRequest: [authenticate.user, authenticate.admin],
31
66
  schema: {
67
+ tags: ['管理后台'],
68
+ summary: '设置用户为超级管理员',
32
69
  body: {
33
70
  type: 'object',
34
71
  required: ['status', 'userId'],
35
72
  properties: {
36
- status: { type: 'boolean' },
37
- userId: { type: 'string' }
73
+ status: { type: 'boolean', description: 'true:将用户设置为超级管理员,false:取消用户超级管理员' },
74
+ userId: { type: 'string', description: '用户ID' }
38
75
  }
39
76
  }
40
77
  }
@@ -51,6 +88,8 @@ module.exports = fp(async (fastify, options) => {
51
88
  {
52
89
  onRequest: [authenticate.user, authenticate.admin],
53
90
  schema: {
91
+ tags: ['管理后台'],
92
+ summary: '添加用户',
54
93
  body: {}
55
94
  }
56
95
  },
@@ -66,7 +105,12 @@ module.exports = fp(async (fastify, options) => {
66
105
  {
67
106
  onRequest: [authenticate.user, authenticate.admin],
68
107
  schema: {
69
- query: {}
108
+ tags: ['管理后台'],
109
+ summary: '获取用户列表',
110
+ query: {
111
+ perPage: { type: 'number' },
112
+ currentPage: { type: 'number' }
113
+ }
70
114
  }
71
115
  },
72
116
  async request => {
@@ -90,6 +134,8 @@ module.exports = fp(async (fastify, options) => {
90
134
  {
91
135
  onRequest: [authenticate.user, authenticate.admin],
92
136
  schema: {
137
+ tags: ['管理后台'],
138
+ summary: '重置用户账号密码',
93
139
  body: {
94
140
  type: 'object',
95
141
  required: ['userId', 'password'],
@@ -111,6 +157,8 @@ module.exports = fp(async (fastify, options) => {
111
157
  {
112
158
  onRequest: [authenticate.user, authenticate.admin],
113
159
  schema: {
160
+ tags: ['管理后台'],
161
+ summary: '修改用户信息',
114
162
  body: {
115
163
  type: 'object',
116
164
  required: ['id'],
@@ -137,6 +185,8 @@ module.exports = fp(async (fastify, options) => {
137
185
  {
138
186
  onRequest: [authenticate.user, authenticate.admin],
139
187
  schema: {
188
+ tags: ['管理后台'],
189
+ summary: '关闭用户',
140
190
  body: {
141
191
  type: 'object',
142
192
  required: ['id'],
@@ -158,6 +208,8 @@ module.exports = fp(async (fastify, options) => {
158
208
  {
159
209
  onRequest: [authenticate.user, authenticate.admin],
160
210
  schema: {
211
+ tags: ['管理后台'],
212
+ summary: '将用户设置为正常',
161
213
  body: {
162
214
  type: 'object',
163
215
  required: ['id'],
@@ -7,6 +7,8 @@ module.exports = fp(async (fastify, options) => {
7
7
  {
8
8
  onRequest: [authenticate.user, authenticate.admin],
9
9
  schema: {
10
+ tags: ['管理后台-权限'],
11
+ summary: '添加应用',
10
12
  body: {
11
13
  type: 'object',
12
14
  required: ['name', 'code'],
@@ -31,6 +33,8 @@ module.exports = fp(async (fastify, options) => {
31
33
  {
32
34
  onRequest: [authenticate.user, authenticate.admin],
33
35
  schema: {
36
+ tags: ['管理后台-权限'],
37
+ summary: '修改应用',
34
38
  body: {
35
39
  type: 'object',
36
40
  required: ['id', 'name', 'code'],
@@ -56,6 +60,8 @@ module.exports = fp(async (fastify, options) => {
56
60
  {
57
61
  onRequest: [authenticate.user, authenticate.admin],
58
62
  schema: {
63
+ tags: ['管理后台-权限'],
64
+ summary: '删除应用',
59
65
  body: {
60
66
  type: 'object',
61
67
  required: ['id'],
@@ -77,6 +83,8 @@ module.exports = fp(async (fastify, options) => {
77
83
  {
78
84
  onRequest: [authenticate.user, authenticate.admin],
79
85
  schema: {
86
+ tags: ['管理后台-权限'],
87
+ summary: '获取应用列表',
80
88
  query: {
81
89
  type: 'object',
82
90
  properties: {
@@ -96,6 +104,8 @@ module.exports = fp(async (fastify, options) => {
96
104
  {
97
105
  onRequest: [authenticate.user, authenticate.admin],
98
106
  schema: {
107
+ tags: ['管理后台-权限'],
108
+ summary: '添加应用权限',
99
109
  body: {
100
110
  type: 'object',
101
111
  required: ['applicationId', 'name', 'code'],
@@ -123,6 +133,8 @@ module.exports = fp(async (fastify, options) => {
123
133
  {
124
134
  onRequest: [authenticate.user, authenticate.admin],
125
135
  schema: {
136
+ tags: ['管理后台-权限'],
137
+ summary: '获取应用权限列表',
126
138
  query: {
127
139
  type: 'object',
128
140
  required: ['applicationId'],
@@ -130,6 +142,35 @@ module.exports = fp(async (fastify, options) => {
130
142
  applicationId: { type: 'string' },
131
143
  tenantId: { type: 'string' }
132
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
+ }
133
174
  }
134
175
  }
135
176
  },
@@ -139,11 +180,83 @@ module.exports = fp(async (fastify, options) => {
139
180
  }
140
181
  );
141
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
+
142
253
  fastify.post(
143
254
  `${options.prefix}/admin/deletePermission`,
144
255
  {
145
256
  onRequest: [authenticate.user, authenticate.admin],
146
257
  schema: {
258
+ tags: ['管理后台-权限'],
259
+ summary: '删除应用权限',
147
260
  body: {
148
261
  type: 'object',
149
262
  required: ['id'],
@@ -167,6 +280,8 @@ module.exports = fp(async (fastify, options) => {
167
280
  {
168
281
  onRequest: [authenticate.user, authenticate.admin],
169
282
  schema: {
283
+ tags: ['管理后台-权限'],
284
+ summary: '修改应用权限',
170
285
  body: {
171
286
  type: 'object',
172
287
  required: ['id'],
@@ -186,11 +301,35 @@ module.exports = fp(async (fastify, options) => {
186
301
  }
187
302
  );
188
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
+
189
326
  fastify.post(
190
327
  `${options.prefix}/admin/saveTenantPermissionList`,
191
328
  {
192
329
  onRequest: [authenticate.user, authenticate.admin],
193
330
  schema: {
331
+ tags: ['管理后台-权限'],
332
+ summary: '修改租户应用权限配置',
194
333
  body: {
195
334
  type: 'object',
196
335
  required: ['tenantId', 'applications', 'permissions'],
@@ -214,24 +353,4 @@ module.exports = fp(async (fastify, options) => {
214
353
  return {};
215
354
  }
216
355
  );
217
-
218
- fastify.get(
219
- `${options.prefix}/admin/getTenantPermissionList`,
220
- {
221
- onRequest: [authenticate.user, authenticate.admin],
222
- schema: {
223
- query: {
224
- type: 'object',
225
- required: ['tenantId'],
226
- properties: {
227
- tenantId: { type: 'string' }
228
- }
229
- }
230
- }
231
- },
232
- async request => {
233
- const { tenantId } = request.query;
234
- return await services.permission.getTenantPermissionList({ tenantId });
235
- }
236
- );
237
356
  });
@@ -12,6 +12,8 @@ module.exports = fp(async (fastify, options) => {
12
12
  required: ['tenantId'],
13
13
  properties: {
14
14
  tenantId: { type: 'string' },
15
+ perPage: { type: 'number' },
16
+ currentPage: { type: 'number' },
15
17
  filter: {
16
18
  type: 'object',
17
19
  properties: {
@@ -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,