@kne/fastify-account 1.0.0-alpha.2 → 1.0.0-alpha.20
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 +2506 -803
- package/index.js +61 -8
- package/libs/controllers/account.js +221 -37
- package/libs/controllers/admin.js +92 -17
- package/libs/controllers/adminPermission.js +188 -38
- package/libs/controllers/adminTenant.js +44 -257
- package/libs/controllers/adminTenantCompany.js +53 -0
- package/libs/controllers/adminTenantOrg.js +71 -0
- package/libs/controllers/{adminRole.js → adminTenantRole.js} +15 -12
- package/libs/controllers/adminTenantUser.js +169 -0
- package/libs/controllers/requestLog.js +77 -0
- package/libs/controllers/tenant.js +4 -14
- package/libs/controllers/tenantCompany.js +54 -0
- package/libs/controllers/tenantOrg.js +65 -0
- package/libs/controllers/tenantRole.js +219 -0
- package/libs/controllers/tenantUser.js +169 -0
- package/libs/controllers/user.js +4 -3
- package/libs/models/admin-role.js +4 -8
- package/libs/models/application.js +16 -10
- package/libs/models/company-info.js +25 -0
- package/libs/models/login-log.js +11 -9
- package/libs/models/permission.js +7 -9
- package/libs/models/request-log.js +43 -0
- 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 +13 -13
- package/libs/models/tenant-role-permission.js +9 -14
- 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 +8 -10
- package/libs/services/account.js +95 -71
- package/libs/services/admin.js +38 -122
- package/libs/services/application.js +170 -0
- package/libs/services/permission.js +161 -163
- package/libs/services/request-log.js +37 -0
- package/libs/services/tenant-company.js +54 -0
- package/libs/services/tenant-invite.js +62 -0
- package/libs/services/tenant-org.js +118 -0
- package/libs/services/tenant-role.js +109 -0
- package/libs/services/tenant-user.js +578 -0
- package/libs/services/tenant.js +69 -670
- package/libs/services/user.js +109 -33
- package/package.json +3 -3
package/index.js
CHANGED
|
@@ -2,6 +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 get = require('lodash/get');
|
|
6
|
+
const { Unauthorized, Forbidden } = require('http-errors');
|
|
5
7
|
|
|
6
8
|
module.exports = fp(
|
|
7
9
|
async function (fastify, options) {
|
|
@@ -9,21 +11,27 @@ module.exports = fp(
|
|
|
9
11
|
options = merge(
|
|
10
12
|
{
|
|
11
13
|
prefix: `/api/v${packageJson.version.split('.')[0]}/account`, //如果为true,发送邮件和短信将不调用,验证码随response返回
|
|
14
|
+
dbTableNamePrefix: 't_account_',
|
|
12
15
|
isTest: false,
|
|
13
16
|
jwt: {
|
|
14
|
-
secret: 'super-secret'
|
|
17
|
+
secret: 'super-secret',
|
|
18
|
+
expires: null
|
|
15
19
|
},
|
|
16
|
-
|
|
20
|
+
sendMessage: async () => {}
|
|
17
21
|
},
|
|
18
22
|
options
|
|
19
23
|
);
|
|
20
|
-
fastify.register(require('fastify-ip'));
|
|
21
24
|
fastify.register(require('@fastify/jwt'), options.jwt);
|
|
22
25
|
fastify.register(require('@kne/fastify-namespace'), {
|
|
23
26
|
options,
|
|
24
27
|
name: 'account',
|
|
25
28
|
modules: [
|
|
26
|
-
[
|
|
29
|
+
[
|
|
30
|
+
'models',
|
|
31
|
+
await fastify.sequelize.addModels(path.resolve(__dirname, './libs/models'), {
|
|
32
|
+
prefix: options.dbTableNamePrefix
|
|
33
|
+
})
|
|
34
|
+
],
|
|
27
35
|
['services', path.resolve(__dirname, './libs/services')],
|
|
28
36
|
['controllers', path.resolve(__dirname, './libs/controllers')],
|
|
29
37
|
[
|
|
@@ -32,15 +40,60 @@ module.exports = fp(
|
|
|
32
40
|
user: async request => {
|
|
33
41
|
const info = await request.jwtVerify();
|
|
34
42
|
//这里判断失效时间
|
|
35
|
-
|
|
43
|
+
if (options.jwt.expires && Date.now() - info.iat * 1000 > options.jwt.expires) {
|
|
44
|
+
throw Unauthorized('身份认证超时');
|
|
45
|
+
}
|
|
36
46
|
request.authenticatePayload = info.payload;
|
|
37
|
-
request.userInfo = await fastify.account.services.user.
|
|
47
|
+
request.userInfo = await fastify.account.services.user.getUser(request.authenticatePayload);
|
|
48
|
+
request.appName = request.headers['x-app-name'];
|
|
49
|
+
await fastify.account.services.requestLog.addRequestLog({
|
|
50
|
+
userInfo: request.userInfo,
|
|
51
|
+
tenantId: request.userInfo.currentTenantId,
|
|
52
|
+
appName: request.appName,
|
|
53
|
+
type: 'user',
|
|
54
|
+
action: `${request.routerPath}:${request.method}`,
|
|
55
|
+
summary: request.routeSchema?.summary
|
|
56
|
+
});
|
|
38
57
|
},
|
|
39
58
|
tenant: async request => {
|
|
40
|
-
request.
|
|
59
|
+
request.appName = request.headers['x-app-name'];
|
|
60
|
+
request.tenantInfo = await fastify.account.services.tenantUser.getTenantUserByUserId({
|
|
61
|
+
userInfo: request.userInfo,
|
|
62
|
+
appName: request.appName
|
|
63
|
+
});
|
|
64
|
+
request.tenantInfo.companyInfo = await fastify.account.services.tenantCompany.getTenantCompanyInfo({
|
|
65
|
+
tenantId: request.tenantInfo.tenant.id
|
|
66
|
+
});
|
|
67
|
+
await fastify.account.services.requestLog.addRequestLog({
|
|
68
|
+
userInfo: request.userInfo,
|
|
69
|
+
tenantId: request.tenantInfo.tenant.id,
|
|
70
|
+
appName: request.appName,
|
|
71
|
+
type: 'tenant',
|
|
72
|
+
action: `${request.routerPath}:${request.method}`,
|
|
73
|
+
summary: request.routeSchema?.summary
|
|
74
|
+
});
|
|
41
75
|
},
|
|
42
76
|
admin: async request => {
|
|
43
|
-
|
|
77
|
+
if (!(await fastify.account.services.admin.checkIsSuperAdmin(request.userInfo))) {
|
|
78
|
+
throw Unauthorized('不能执行该操作,需要超级管理员权限');
|
|
79
|
+
}
|
|
80
|
+
request.appName = request.headers['x-app-name'];
|
|
81
|
+
await fastify.account.services.requestLog.addRequestLog({
|
|
82
|
+
userInfo: request.userInfo,
|
|
83
|
+
appName: request.appName,
|
|
84
|
+
type: 'admin',
|
|
85
|
+
action: `${request.routerPath}:${request.method}`,
|
|
86
|
+
summary: request.routeSchema?.summary
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
createPermission: permission => async request => {
|
|
90
|
+
const permissions = get(request.tenantInfo, 'tenantUser.permissions');
|
|
91
|
+
if (!permissions) {
|
|
92
|
+
throw Forbidden('未获取到权限信息');
|
|
93
|
+
}
|
|
94
|
+
if (!(permission && permissions.indexOf(permission) > -1)) {
|
|
95
|
+
throw Forbidden('用户没有权限执行该操作');
|
|
96
|
+
}
|
|
44
97
|
}
|
|
45
98
|
}
|
|
46
99
|
]
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
const fp = require('fastify-plugin');
|
|
2
2
|
module.exports = fp(async (fastify, options) => {
|
|
3
|
+
const { services } = fastify.account;
|
|
3
4
|
fastify.post(
|
|
4
5
|
`${options.prefix}/sendEmailCode`,
|
|
5
6
|
{
|
|
6
7
|
schema: {
|
|
8
|
+
tags: ['账号'],
|
|
9
|
+
summary: '发送登录邮箱验证码',
|
|
7
10
|
body: {
|
|
8
11
|
type: 'object',
|
|
9
12
|
required: ['email'],
|
|
@@ -18,14 +21,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
18
21
|
schema: {
|
|
19
22
|
type: 'object',
|
|
20
23
|
properties: {
|
|
21
|
-
code: { type: '
|
|
22
|
-
data: {
|
|
23
|
-
type: 'object',
|
|
24
|
-
properties: {
|
|
25
|
-
code: { type: 'string', description: '验证码' }
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
msg: { type: 'string' }
|
|
24
|
+
code: { type: 'string', description: '验证码' }
|
|
29
25
|
}
|
|
30
26
|
}
|
|
31
27
|
}
|
|
@@ -36,7 +32,7 @@ module.exports = fp(async (fastify, options) => {
|
|
|
36
32
|
},
|
|
37
33
|
async request => {
|
|
38
34
|
const { email } = request.body;
|
|
39
|
-
const code = await
|
|
35
|
+
const code = await services.account.sendVerificationCode({ name: email, type: 0 });
|
|
40
36
|
return options.isTest ? { code } : {};
|
|
41
37
|
}
|
|
42
38
|
);
|
|
@@ -45,18 +41,34 @@ module.exports = fp(async (fastify, options) => {
|
|
|
45
41
|
`${options.prefix}/sendSMSCode`,
|
|
46
42
|
{
|
|
47
43
|
schema: {
|
|
44
|
+
tags: ['账号'],
|
|
45
|
+
summary: '发送登录短信验证码',
|
|
48
46
|
body: {
|
|
49
47
|
type: 'object',
|
|
50
48
|
required: ['phone'],
|
|
51
49
|
properties: {
|
|
52
50
|
phone: { type: 'string', description: '电话' }
|
|
53
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
|
+
}
|
|
54
66
|
}
|
|
55
67
|
}
|
|
56
68
|
},
|
|
57
69
|
async request => {
|
|
58
70
|
const { phone } = request.body;
|
|
59
|
-
const code = await
|
|
71
|
+
const code = await services.account.sendVerificationCode({ name: phone, type: 0 });
|
|
60
72
|
return options.isTest ? { code } : {};
|
|
61
73
|
}
|
|
62
74
|
);
|
|
@@ -65,20 +77,31 @@ module.exports = fp(async (fastify, options) => {
|
|
|
65
77
|
`${options.prefix}/validateCode`,
|
|
66
78
|
{
|
|
67
79
|
schema: {
|
|
80
|
+
tags: ['账号'],
|
|
81
|
+
summary: '验证码验证',
|
|
68
82
|
body: {
|
|
69
83
|
type: 'object',
|
|
70
84
|
required: ['name', 'type', 'code'],
|
|
71
85
|
properties: {
|
|
72
86
|
name: { type: 'string', description: '被验证的账号,手机或邮箱' },
|
|
73
|
-
type: { type: 'number', description: '0
|
|
87
|
+
type: { type: 'number', description: '0:注册,2:登录,4:验证租户管理员,5:忘记密码' },
|
|
74
88
|
code: { type: 'string', description: '接受到的验证码' }
|
|
75
89
|
}
|
|
90
|
+
},
|
|
91
|
+
response: {
|
|
92
|
+
200: {
|
|
93
|
+
content: {
|
|
94
|
+
'application/json': {
|
|
95
|
+
schema: {}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
76
99
|
}
|
|
77
100
|
}
|
|
78
101
|
},
|
|
79
102
|
async request => {
|
|
80
103
|
const { name, type, code } = request.body;
|
|
81
|
-
const isPass = await
|
|
104
|
+
const isPass = await services.account.verificationCodeValidate({
|
|
82
105
|
name,
|
|
83
106
|
type,
|
|
84
107
|
code
|
|
@@ -94,29 +117,45 @@ module.exports = fp(async (fastify, options) => {
|
|
|
94
117
|
`${options.prefix}/accountIsExists`,
|
|
95
118
|
{
|
|
96
119
|
schema: {
|
|
120
|
+
tags: ['账号'],
|
|
121
|
+
summary: '账号是否已存在',
|
|
97
122
|
body: {
|
|
98
123
|
oneOf: [
|
|
99
124
|
{
|
|
100
125
|
type: 'object',
|
|
101
126
|
required: ['phone'],
|
|
102
127
|
properties: {
|
|
103
|
-
phone: { type: 'string' }
|
|
128
|
+
phone: { type: 'string', description: '电话' }
|
|
104
129
|
}
|
|
105
130
|
},
|
|
106
131
|
{
|
|
107
132
|
type: 'object',
|
|
108
133
|
required: ['email'],
|
|
109
134
|
properties: {
|
|
110
|
-
email: { type: 'string' }
|
|
135
|
+
email: { type: 'string', description: '邮箱' }
|
|
111
136
|
}
|
|
112
137
|
}
|
|
113
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
|
+
}
|
|
114
153
|
}
|
|
115
154
|
}
|
|
116
155
|
},
|
|
117
156
|
async request => {
|
|
118
157
|
const { phone, email } = request.body;
|
|
119
|
-
return { isExists: await
|
|
158
|
+
return { isExists: await services.user.accountIsExists({ phone, email }) };
|
|
120
159
|
}
|
|
121
160
|
);
|
|
122
161
|
|
|
@@ -124,45 +163,56 @@ module.exports = fp(async (fastify, options) => {
|
|
|
124
163
|
`${options.prefix}/register`,
|
|
125
164
|
{
|
|
126
165
|
schema: {
|
|
166
|
+
tags: ['账号'],
|
|
167
|
+
summary: '注册账号',
|
|
127
168
|
body: {
|
|
128
169
|
oneOf: [
|
|
129
170
|
{
|
|
130
171
|
type: 'object',
|
|
131
172
|
required: ['phone', 'password', 'code'],
|
|
132
173
|
properties: {
|
|
133
|
-
avatar: { type: 'string' },
|
|
134
|
-
phone: { type: 'string' },
|
|
135
|
-
code: { type: 'string' },
|
|
136
|
-
password: { type: 'string' },
|
|
137
|
-
invitationCode: { type: 'string' },
|
|
138
|
-
nickname: { type: 'string' },
|
|
139
|
-
gender: { type: 'string' },
|
|
140
|
-
birthday: { type: 'string', format: 'date' },
|
|
141
|
-
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: '个人简介' }
|
|
142
183
|
}
|
|
143
184
|
},
|
|
144
185
|
{
|
|
145
186
|
type: 'object',
|
|
146
187
|
required: ['email', 'password', 'code'],
|
|
147
188
|
properties: {
|
|
148
|
-
avatar: { type: 'string' },
|
|
149
|
-
email: { type: 'string' },
|
|
150
|
-
code: { type: 'string' },
|
|
151
|
-
password: { type: 'string' },
|
|
152
|
-
invitationCode: { type: 'string' },
|
|
153
|
-
nickname: { type: 'string' },
|
|
154
|
-
gender: { type: 'string' },
|
|
155
|
-
birthday: { type: 'string', format: 'date' },
|
|
156
|
-
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: '个人简介' }
|
|
157
198
|
}
|
|
158
199
|
}
|
|
159
200
|
]
|
|
201
|
+
},
|
|
202
|
+
response: {
|
|
203
|
+
200: {
|
|
204
|
+
content: {
|
|
205
|
+
'application/json': {
|
|
206
|
+
schema: {}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
160
210
|
}
|
|
161
211
|
}
|
|
162
212
|
},
|
|
163
213
|
async request => {
|
|
164
214
|
const account = request.body;
|
|
165
|
-
return await
|
|
215
|
+
return await services.account.register(account);
|
|
166
216
|
}
|
|
167
217
|
);
|
|
168
218
|
|
|
@@ -170,20 +220,154 @@ module.exports = fp(async (fastify, options) => {
|
|
|
170
220
|
`${options.prefix}/login`,
|
|
171
221
|
{
|
|
172
222
|
schema: {
|
|
223
|
+
tags: ['账号'],
|
|
224
|
+
summary: '登录',
|
|
173
225
|
body: {
|
|
174
226
|
type: 'object',
|
|
175
227
|
required: ['username', 'password'],
|
|
176
228
|
properties: {
|
|
177
|
-
username: { type: 'string' },
|
|
178
|
-
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
|
+
}
|
|
179
246
|
}
|
|
180
247
|
}
|
|
181
248
|
}
|
|
182
249
|
},
|
|
183
250
|
async request => {
|
|
184
251
|
const { username, password } = request.body;
|
|
185
|
-
const
|
|
252
|
+
const appName = request.headers['x-app-name'];
|
|
253
|
+
const { token, user } = await services.account.login({ username, password, ip: request.ip, appName });
|
|
186
254
|
return { token, currentTenantId: user.currentTenantId };
|
|
187
255
|
}
|
|
188
256
|
);
|
|
257
|
+
|
|
258
|
+
fastify.post(
|
|
259
|
+
`${options.prefix}/modifyPassword`,
|
|
260
|
+
{
|
|
261
|
+
schema: {
|
|
262
|
+
tags: ['账号'],
|
|
263
|
+
summary: '新用户重置新密码',
|
|
264
|
+
body: {
|
|
265
|
+
oneOf: [
|
|
266
|
+
{
|
|
267
|
+
type: 'object',
|
|
268
|
+
required: ['email', 'newPwd', 'oldPwd'],
|
|
269
|
+
properties: {
|
|
270
|
+
email: { type: 'string', description: '邮箱' },
|
|
271
|
+
newPwd: { type: 'string', description: '新密码' },
|
|
272
|
+
oldPwd: { type: 'string', description: '原密码' }
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
type: 'object',
|
|
277
|
+
required: ['phone', 'newPwd', 'oldPwd'],
|
|
278
|
+
properties: {
|
|
279
|
+
phone: { type: 'string', description: '手机号' },
|
|
280
|
+
newPwd: { type: 'string', description: '新密码' },
|
|
281
|
+
oldPwd: { type: 'string', description: '原密码' }
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
},
|
|
288
|
+
async request => {
|
|
289
|
+
await services.account.modifyPassword(request.body);
|
|
290
|
+
return {};
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
fastify.post(
|
|
295
|
+
`${options.prefix}/resetPassword`,
|
|
296
|
+
{
|
|
297
|
+
schema: {
|
|
298
|
+
tags: ['账号'],
|
|
299
|
+
summary: '用户重置密码',
|
|
300
|
+
body: {
|
|
301
|
+
type: 'object',
|
|
302
|
+
required: ['newPwd', 'token'],
|
|
303
|
+
properties: {
|
|
304
|
+
newPwd: { type: 'string', description: '新密码' },
|
|
305
|
+
token: { type: 'string', description: '验证token' }
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
},
|
|
310
|
+
async request => {
|
|
311
|
+
await services.account.resetPasswordByToken({
|
|
312
|
+
password: request.body.newPwd,
|
|
313
|
+
token: request.body.token
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
return {};
|
|
317
|
+
}
|
|
318
|
+
);
|
|
319
|
+
|
|
320
|
+
fastify.post(
|
|
321
|
+
`${options.prefix}/forgetPwd`,
|
|
322
|
+
{
|
|
323
|
+
schema: {
|
|
324
|
+
tags: ['账号'],
|
|
325
|
+
summary: '忘记密码',
|
|
326
|
+
body: {
|
|
327
|
+
oneOf: [
|
|
328
|
+
{
|
|
329
|
+
type: 'object',
|
|
330
|
+
required: ['email'],
|
|
331
|
+
properties: {
|
|
332
|
+
email: { type: 'string', description: '邮箱' }
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
type: 'object',
|
|
337
|
+
required: ['phone'],
|
|
338
|
+
properties: {
|
|
339
|
+
phone: { type: 'string', description: '手机号' }
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
async request => {
|
|
347
|
+
const name = request.body.email || request.body.phone;
|
|
348
|
+
const token = await services.account.sendJWTVerificationCode({ name, type: 5 });
|
|
349
|
+
return options.isTest ? { token } : {};
|
|
350
|
+
}
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
fastify.post(
|
|
354
|
+
`${options.prefix}/parseResetToken`,
|
|
355
|
+
{
|
|
356
|
+
schema: {
|
|
357
|
+
tags: ['账号'],
|
|
358
|
+
summary: '通过token获取name',
|
|
359
|
+
body: {
|
|
360
|
+
type: 'object',
|
|
361
|
+
required: ['token'],
|
|
362
|
+
properties: {
|
|
363
|
+
token: { type: 'string' }
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
async request => {
|
|
369
|
+
const { name } = await services.account.verificationJWTCodeValidate(request.body);
|
|
370
|
+
return { name };
|
|
371
|
+
}
|
|
372
|
+
);
|
|
189
373
|
});
|