]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/middlewares/validators/users.ts
Fix tests
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / users.ts
CommitLineData
41fb13c3 1import express from 'express'
76314386 2import { body, param, query } from 'express-validator'
b49f22d8
C
3import { Hooks } from '@server/lib/plugins/hooks'
4import { MUserDefault } from '@server/types/models'
a37e9e74 5import { HttpStatusCode, UserRegister, UserRight, UserRole } from '@shared/models'
978c87e7 6import { isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
b49f22d8 7import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
b60e5f38 8import {
1eddc9a7 9 isUserAdminFlagsValid,
c1e5bd23 10 isUserAutoPlayNextVideoValid,
1a12adcd
C
11 isUserAutoPlayVideoValid,
12 isUserBlockedReasonValid,
4bbfc6c6
C
13 isUserDescriptionValid,
14 isUserDisplayNameValid,
8f581725 15 isUserNoModal,
0883b324 16 isUserNSFWPolicyValid,
a9bfa85d 17 isUserP2PEnabledValid,
ecb4e35f 18 isUserPasswordValid,
45f1bd72 19 isUserPasswordValidOrEmpty,
ecb4e35f 20 isUserRoleValid,
3e753302
C
21 isUserUsernameValid,
22 isUserVideoLanguages,
1a12adcd 23 isUserVideoQuotaDailyValid,
dae86118
C
24 isUserVideoQuotaValid,
25 isUserVideosHistoryEnabledValid
3fd3ab2d 26} from '../../helpers/custom-validators/users'
27db7840 27import { isVideoChannelDisplayNameValid, isVideoChannelUsernameValid } from '../../helpers/custom-validators/video-channels'
da854ddd 28import { logger } from '../../helpers/logger'
b49f22d8 29import { isThemeRegistered } from '../../lib/plugins/theme-utils'
ecb4e35f 30import { Redis } from '../../lib/redis'
10363c74 31import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../lib/signup'
7d9ba5c0 32import { ActorModel } from '../../models/actor/actor'
10363c74 33import { UserModel } from '../../models/user/user'
978c87e7 34import { areValidationErrors, doesVideoChannelIdExist, doesVideoExist, isValidVideoIdParam } from './shared'
9bd26629 35
8491293b
RK
36const usersListValidator = [
37 query('blocked')
38 .optional()
f1273314 39 .customSanitizer(toBooleanOrNull)
396f6f01 40 .isBoolean().withMessage('Should be a valid blocked boolena'),
8491293b 41
ea7337cf 42 (req: express.Request, res: express.Response, next: express.NextFunction) => {
8491293b
RK
43 if (areValidationErrors(req, res)) return
44
45 return next()
46 }
47]
48
b60e5f38 49const usersAddValidator = [
396f6f01
C
50 body('username')
51 .custom(isUserUsernameValid)
52 .withMessage('Should have a valid username (lowercase alphanumeric characters)'),
53 body('password')
54 .custom(isUserPasswordValidOrEmpty),
55 body('email')
56 .isEmail(),
27db7840 57
396f6f01
C
58 body('channelName')
59 .optional()
60 .custom(isVideoChannelUsernameValid),
27db7840 61
396f6f01
C
62 body('videoQuota')
63 .custom(isUserVideoQuotaValid),
64 body('videoQuotaDaily')
65 .custom(isUserVideoQuotaDailyValid),
27db7840 66
dea16773
C
67 body('role')
68 .customSanitizer(toIntOrNull)
396f6f01
C
69 .custom(isUserRoleValid),
70
71 body('adminFlags')
72 .optional()
73 .custom(isUserAdminFlagsValid),
9bd26629 74
a2431b7d 75 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a85d5303 76 if (areValidationErrors(req, res, { omitBodyLog: true })) return
a2431b7d
C
77 if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return
78
a95a4cc8
C
79 const authUser = res.locals.oauth.token.User
80 if (authUser.role !== UserRole.ADMINISTRATOR && req.body.role !== UserRole.USER) {
76148b27
RK
81 return res.fail({
82 status: HttpStatusCode.FORBIDDEN_403,
83 message: 'You can only create users (and not administrators or moderators)'
84 })
a95a4cc8
C
85 }
86
766d13b4 87 if (req.body.channelName) {
88 if (req.body.channelName === req.body.username) {
76148b27 89 return res.fail({ message: 'Channel name cannot be the same as user username.' })
766d13b4 90 }
4e68fc86 91
766d13b4 92 const existing = await ActorModel.loadLocalByName(req.body.channelName)
93 if (existing) {
76148b27
RK
94 return res.fail({
95 status: HttpStatusCode.CONFLICT_409,
96 message: `Channel with name ${req.body.channelName} already exists.`
97 })
766d13b4 98 }
4e68fc86 99 }
100
a2431b7d 101 return next()
b60e5f38
C
102 }
103]
6fcd19ba 104
b60e5f38 105const usersRegisterValidator = [
396f6f01
C
106 body('username')
107 .custom(isUserUsernameValid),
108 body('password')
109 .custom(isUserPasswordValid),
110 body('email')
111 .isEmail(),
1f20622f
C
112 body('displayName')
113 .optional()
396f6f01 114 .custom(isUserDisplayNameValid),
1f20622f
C
115
116 body('channel.name')
117 .optional()
396f6f01 118 .custom(isVideoChannelUsernameValid),
1f20622f
C
119 body('channel.displayName')
120 .optional()
396f6f01 121 .custom(isVideoChannelDisplayNameValid),
77a5501f 122
a2431b7d 123 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a85d5303 124 if (areValidationErrors(req, res, { omitBodyLog: true })) return
a2431b7d
C
125 if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return
126
e590b4a5
C
127 const body: UserRegister = req.body
128 if (body.channel) {
129 if (!body.channel.name || !body.channel.displayName) {
76148b27 130 return res.fail({ message: 'Channel is optional but if you specify it, channel.name and channel.displayName are required.' })
e590b4a5
C
131 }
132
1d5342ab 133 if (body.channel.name === body.username) {
76148b27 134 return res.fail({ message: 'Channel name cannot be the same as user username.' })
1d5342ab
C
135 }
136
e590b4a5
C
137 const existing = await ActorModel.loadLocalByName(body.channel.name)
138 if (existing) {
76148b27
RK
139 return res.fail({
140 status: HttpStatusCode.CONFLICT_409,
141 message: `Channel with name ${body.channel.name} already exists.`
142 })
e590b4a5
C
143 }
144 }
145
a2431b7d 146 return next()
b60e5f38
C
147 }
148]
9bd26629 149
b60e5f38 150const usersRemoveValidator = [
396f6f01
C
151 param('id')
152 .custom(isIdValid),
9bd26629 153
a2431b7d 154 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a2431b7d
C
155 if (areValidationErrors(req, res)) return
156 if (!await checkUserIdExist(req.params.id, res)) return
157
158 const user = res.locals.user
159 if (user.username === 'root') {
76148b27 160 return res.fail({ message: 'Cannot remove the root user' })
a2431b7d
C
161 }
162
163 return next()
b60e5f38
C
164 }
165]
8094a898 166
e6921918 167const usersBlockingValidator = [
396f6f01
C
168 param('id')
169 .custom(isIdValid),
170 body('reason')
171 .optional()
172 .custom(isUserBlockedReasonValid),
e6921918
C
173
174 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
e6921918
C
175 if (areValidationErrors(req, res)) return
176 if (!await checkUserIdExist(req.params.id, res)) return
177
178 const user = res.locals.user
179 if (user.username === 'root') {
76148b27 180 return res.fail({ message: 'Cannot block the root user' })
e6921918
C
181 }
182
183 return next()
184 }
185]
186
92b9d60c 187const deleteMeValidator = [
a1587156 188 (req: express.Request, res: express.Response, next: express.NextFunction) => {
dae86118 189 const user = res.locals.oauth.token.User
92b9d60c 190 if (user.username === 'root') {
76148b27 191 return res.fail({ message: 'You cannot delete your root account.' })
92b9d60c
C
192 }
193
194 return next()
195 }
196]
197
b60e5f38 198const usersUpdateValidator = [
396f6f01
C
199 param('id').custom(isIdValid),
200
201 body('password')
202 .optional()
203 .custom(isUserPasswordValid),
204 body('email')
205 .optional()
206 .isEmail(),
207 body('emailVerified')
208 .optional()
209 .isBoolean(),
210 body('videoQuota')
211 .optional()
212 .custom(isUserVideoQuotaValid),
213 body('videoQuotaDaily')
214 .optional()
215 .custom(isUserVideoQuotaDailyValid),
216 body('pluginAuth')
217 .optional()
218 .exists(),
dea16773
C
219 body('role')
220 .optional()
221 .customSanitizer(toIntOrNull)
396f6f01
C
222 .custom(isUserRoleValid),
223 body('adminFlags')
224 .optional()
225 .custom(isUserAdminFlagsValid),
8094a898 226
a2431b7d 227 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a85d5303 228 if (areValidationErrors(req, res, { omitBodyLog: true })) return
a2431b7d
C
229 if (!await checkUserIdExist(req.params.id, res)) return
230
f8b8c36b
C
231 const user = res.locals.user
232 if (user.username === 'root' && req.body.role !== undefined && user.role !== req.body.role) {
76148b27 233 return res.fail({ message: 'Cannot change root role.' })
f8b8c36b
C
234 }
235
a2431b7d 236 return next()
b60e5f38
C
237 }
238]
9bd26629 239
b60e5f38 240const usersUpdateMeValidator = [
d1ab89de
C
241 body('displayName')
242 .optional()
396f6f01 243 .custom(isUserDisplayNameValid),
d1ab89de
C
244 body('description')
245 .optional()
396f6f01 246 .custom(isUserDescriptionValid),
d1ab89de
C
247 body('currentPassword')
248 .optional()
396f6f01 249 .custom(isUserPasswordValid),
d1ab89de
C
250 body('password')
251 .optional()
396f6f01 252 .custom(isUserPasswordValid),
d1ab89de
C
253 body('email')
254 .optional()
396f6f01 255 .isEmail(),
d1ab89de
C
256 body('nsfwPolicy')
257 .optional()
396f6f01 258 .custom(isUserNSFWPolicyValid),
d1ab89de
C
259 body('autoPlayVideo')
260 .optional()
396f6f01 261 .custom(isUserAutoPlayVideoValid),
a9bfa85d
C
262 body('p2pEnabled')
263 .optional()
264 .custom(isUserP2PEnabledValid).withMessage('Should have a valid p2p enabled boolean'),
3caf77d3
C
265 body('videoLanguages')
266 .optional()
396f6f01 267 .custom(isUserVideoLanguages),
1a12adcd
C
268 body('videosHistoryEnabled')
269 .optional()
396f6f01 270 .custom(isUserVideosHistoryEnabledValid).withMessage('Should have a valid videos history enabled boolean'),
7cd4d2ba
C
271 body('theme')
272 .optional()
396f6f01 273 .custom(v => isThemeNameValid(v) && isThemeRegistered(v)),
8f581725 274
43d0ea7f
C
275 body('noInstanceConfigWarningModal')
276 .optional()
8f581725 277 .custom(v => isUserNoModal(v)).withMessage('Should have a valid noInstanceConfigWarningModal boolean'),
43d0ea7f
C
278 body('noWelcomeModal')
279 .optional()
8f581725
C
280 .custom(v => isUserNoModal(v)).withMessage('Should have a valid noWelcomeModal boolean'),
281 body('noAccountSetupWarningModal')
282 .optional()
283 .custom(v => isUserNoModal(v)).withMessage('Should have a valid noAccountSetupWarningModal boolean'),
284
c1e5bd23
C
285 body('autoPlayNextVideo')
286 .optional()
287 .custom(v => isUserAutoPlayNextVideoValid(v)).withMessage('Should have a valid autoPlayNextVideo boolean'),
9bd26629 288
a890d1e0 289 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
9a7fd960
C
290 const user = res.locals.oauth.token.User
291
0ba5f5ba 292 if (req.body.password || req.body.email) {
9a7fd960 293 if (user.pluginAuth !== null) {
76148b27 294 return res.fail({ message: 'You cannot update your email or password that is associated with an external auth system.' })
9a7fd960
C
295 }
296
a890d1e0 297 if (!req.body.currentPassword) {
76148b27 298 return res.fail({ message: 'currentPassword parameter is missing.' })
a890d1e0
C
299 }
300
a890d1e0 301 if (await user.isPasswordMatch(req.body.currentPassword) !== true) {
76148b27
RK
302 return res.fail({
303 status: HttpStatusCode.UNAUTHORIZED_401,
304 message: 'currentPassword is invalid.'
305 })
a890d1e0
C
306 }
307 }
308
a85d5303 309 if (areValidationErrors(req, res, { omitBodyLog: true })) return
a2431b7d
C
310
311 return next()
b60e5f38
C
312 }
313]
8094a898 314
b60e5f38 315const usersGetValidator = [
396f6f01
C
316 param('id')
317 .custom(isIdValid),
318 query('withStats')
319 .optional()
320 .isBoolean().withMessage('Should have a valid withStats boolean'),
d38b8281 321
a2431b7d 322 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a2431b7d 323 if (areValidationErrors(req, res)) return
76314386 324 if (!await checkUserIdExist(req.params.id, res, req.query.withStats)) return
a2431b7d
C
325
326 return next()
b60e5f38
C
327 }
328]
d38b8281 329
b60e5f38 330const usersVideoRatingValidator = [
d4a8e7a6 331 isValidVideoIdParam('videoId'),
0a6658fd 332
a2431b7d 333 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
a2431b7d 334 if (areValidationErrors(req, res)) return
0f6acda1 335 if (!await doesVideoExist(req.params.videoId, res, 'id')) return
a2431b7d
C
336
337 return next()
b60e5f38
C
338 }
339]
340
978c87e7
C
341const usersVideosValidator = [
342 query('isLive')
343 .optional()
344 .customSanitizer(toBooleanOrNull)
396f6f01 345 .custom(isBooleanValid).withMessage('Should have a valid isLive boolean'),
978c87e7
C
346
347 query('channelId')
348 .optional()
349 .customSanitizer(toIntOrNull)
396f6f01 350 .custom(isIdValid),
978c87e7
C
351
352 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
978c87e7
C
353 if (areValidationErrors(req, res)) return
354
355 if (req.query.channelId && !await doesVideoChannelIdExist(req.query.channelId, res)) return
356
357 return next()
358 }
359]
360
b60e5f38 361const ensureUserRegistrationAllowed = [
a2431b7d 362 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
4ce7eb71 363 const allowedParams = {
ba7b7e57
RK
364 body: req.body,
365 ip: req.ip
4ce7eb71
C
366 }
367
368 const allowedResult = await Hooks.wrapPromiseFun(
369 isSignupAllowed,
370 allowedParams,
371 'filter:api.user.signup.allowed.result'
372 )
373
374 if (allowedResult.allowed === false) {
76148b27
RK
375 return res.fail({
376 status: HttpStatusCode.FORBIDDEN_403,
377 message: allowedResult.errorMessage || 'User registration is not enabled or user limit is reached.'
378 })
a2431b7d
C
379 }
380
381 return next()
b60e5f38
C
382 }
383]
291e8d3e 384
ff2c1fe8 385const ensureUserRegistrationAllowedForIP = [
a1587156 386 (req: express.Request, res: express.Response, next: express.NextFunction) => {
ff2c1fe8
RK
387 const allowed = isSignupAllowedForCurrentIP(req.ip)
388
389 if (allowed === false) {
76148b27
RK
390 return res.fail({
391 status: HttpStatusCode.FORBIDDEN_403,
392 message: 'You are not on a network authorized for registration.'
393 })
ff2c1fe8
RK
394 }
395
396 return next()
397 }
398]
399
ecb4e35f 400const usersAskResetPasswordValidator = [
396f6f01
C
401 body('email')
402 .isEmail(),
ecb4e35f
C
403
404 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
ecb4e35f 405 if (areValidationErrors(req, res)) return
b426edd4 406
ecb4e35f
C
407 const exists = await checkUserEmailExist(req.body.email, res, false)
408 if (!exists) {
409 logger.debug('User with email %s does not exist (asking reset password).', req.body.email)
410 // Do not leak our emails
2d53be02 411 return res.status(HttpStatusCode.NO_CONTENT_204).end()
ecb4e35f
C
412 }
413
c5f3ff39
C
414 if (res.locals.user.pluginAuth) {
415 return res.fail({
416 status: HttpStatusCode.CONFLICT_409,
417 message: 'Cannot recover password of a user that uses a plugin authentication.'
418 })
419 }
420
ecb4e35f
C
421 return next()
422 }
423]
424
425const usersResetPasswordValidator = [
396f6f01
C
426 param('id')
427 .custom(isIdValid),
428 body('verificationString')
429 .not().isEmpty(),
430 body('password')
431 .custom(isUserPasswordValid),
ecb4e35f
C
432
433 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
ecb4e35f
C
434 if (areValidationErrors(req, res)) return
435 if (!await checkUserIdExist(req.params.id, res)) return
436
dae86118 437 const user = res.locals.user
ecb4e35f
C
438 const redisVerificationString = await Redis.Instance.getResetPasswordLink(user.id)
439
440 if (redisVerificationString !== req.body.verificationString) {
76148b27
RK
441 return res.fail({
442 status: HttpStatusCode.FORBIDDEN_403,
443 message: 'Invalid verification string.'
444 })
ecb4e35f
C
445 }
446
447 return next()
448 }
449]
450
d9eaee39
JM
451const usersAskSendVerifyEmailValidator = [
452 body('email').isEmail().not().isEmpty().withMessage('Should have a valid email'),
453
454 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
d9eaee39 455 if (areValidationErrors(req, res)) return
a85d5303 456
d9eaee39
JM
457 const exists = await checkUserEmailExist(req.body.email, res, false)
458 if (!exists) {
459 logger.debug('User with email %s does not exist (asking verify email).', req.body.email)
460 // Do not leak our emails
2d53be02 461 return res.status(HttpStatusCode.NO_CONTENT_204).end()
d9eaee39
JM
462 }
463
c5f3ff39
C
464 if (res.locals.user.pluginAuth) {
465 return res.fail({
466 status: HttpStatusCode.CONFLICT_409,
467 message: 'Cannot ask verification email of a user that uses a plugin authentication.'
468 })
469 }
470
d9eaee39
JM
471 return next()
472 }
473]
474
475const usersVerifyEmailValidator = [
d1ab89de
C
476 param('id')
477 .isInt().not().isEmpty().withMessage('Should have a valid id'),
478
479 body('verificationString')
480 .not().isEmpty().withMessage('Should have a valid verification string'),
481 body('isPendingEmail')
482 .optional()
2b65c4e5 483 .customSanitizer(toBooleanOrNull),
d9eaee39
JM
484
485 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
d9eaee39
JM
486 if (areValidationErrors(req, res)) return
487 if (!await checkUserIdExist(req.params.id, res)) return
488
dae86118 489 const user = res.locals.user
d9eaee39
JM
490 const redisVerificationString = await Redis.Instance.getVerifyEmailLink(user.id)
491
492 if (redisVerificationString !== req.body.verificationString) {
76148b27
RK
493 return res.fail({
494 status: HttpStatusCode.FORBIDDEN_403,
495 message: 'Invalid verification string.'
496 })
d9eaee39
JM
497 }
498
499 return next()
500 }
501]
502
74d63469 503const userAutocompleteValidator = [
a85d5303
C
504 param('search')
505 .isString()
506 .not().isEmpty()
74d63469
GR
507]
508
c100a614 509const ensureAuthUserOwnsAccountValidator = [
a1587156 510 (req: express.Request, res: express.Response, next: express.NextFunction) => {
c100a614
YB
511 const user = res.locals.oauth.token.User
512
513 if (res.locals.account.id !== user.Account.id) {
76148b27
RK
514 return res.fail({
515 status: HttpStatusCode.FORBIDDEN_403,
7a4fd56c 516 message: 'Only owner of this account can access this resource.'
4beda9e1
C
517 })
518 }
519
520 return next()
521 }
522]
523
d4d9bbc6 524const ensureCanManageChannelOrAccount = [
4beda9e1 525 (req: express.Request, res: express.Response, next: express.NextFunction) => {
a37e9e74 526 const user = res.locals.oauth.token.user
d4d9bbc6
C
527 const account = res.locals.videoChannel?.Account ?? res.locals.account
528 const isUserOwner = account.userId === user.id
a37e9e74 529
530 if (!isUserOwner && user.hasRight(UserRight.MANAGE_ANY_VIDEO_CHANNEL) === false) {
d4d9bbc6 531 const message = `User ${user.username} does not have right this channel or account.`
4beda9e1 532
4beda9e1
C
533 return res.fail({
534 status: HttpStatusCode.FORBIDDEN_403,
a37e9e74 535 message
76148b27 536 })
c100a614
YB
537 }
538
539 return next()
540 }
541]
542
d4d9bbc6 543const ensureCanModerateUser = [
a95a4cc8
C
544 (req: express.Request, res: express.Response, next: express.NextFunction) => {
545 const authUser = res.locals.oauth.token.User
546 const onUser = res.locals.user
547
548 if (authUser.role === UserRole.ADMINISTRATOR) return next()
549 if (authUser.role === UserRole.MODERATOR && onUser.role === UserRole.USER) return next()
550
76148b27
RK
551 return res.fail({
552 status: HttpStatusCode.FORBIDDEN_403,
d4d9bbc6 553 message: 'A moderator can only manage users.'
76148b27 554 })
a95a4cc8
C
555 }
556]
557
9bd26629
C
558// ---------------------------------------------------------------------------
559
65fcc311 560export {
8491293b 561 usersListValidator,
65fcc311 562 usersAddValidator,
92b9d60c 563 deleteMeValidator,
77a5501f 564 usersRegisterValidator,
e6921918 565 usersBlockingValidator,
65fcc311
C
566 usersRemoveValidator,
567 usersUpdateValidator,
8094a898 568 usersUpdateMeValidator,
291e8d3e 569 usersVideoRatingValidator,
8094a898 570 ensureUserRegistrationAllowed,
ff2c1fe8 571 ensureUserRegistrationAllowedForIP,
c5911fd3 572 usersGetValidator,
978c87e7 573 usersVideosValidator,
ecb4e35f 574 usersAskResetPasswordValidator,
d9eaee39
JM
575 usersResetPasswordValidator,
576 usersAskSendVerifyEmailValidator,
74d63469 577 usersVerifyEmailValidator,
c100a614 578 userAutocompleteValidator,
a95a4cc8 579 ensureAuthUserOwnsAccountValidator,
d4d9bbc6
C
580 ensureCanModerateUser,
581 ensureCanManageChannelOrAccount
8094a898
C
582}
583
584// ---------------------------------------------------------------------------
585
76314386 586function checkUserIdExist (idArg: number | string, res: express.Response, withStats = false) {
d5d9b6d7 587 const id = parseInt(idArg + '', 10)
fb719404 588 return checkUserExist(() => UserModel.loadByIdWithChannels(id, withStats), res)
ecb4e35f 589}
a2431b7d 590
ecb4e35f
C
591function checkUserEmailExist (email: string, res: express.Response, abortResponse = true) {
592 return checkUserExist(() => UserModel.loadByEmail(email), res, abortResponse)
65fcc311 593}
77a5501f 594
a2431b7d 595async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email: string, res: express.Response) {
3fd3ab2d 596 const user = await UserModel.loadByUsernameOrEmail(username, email)
a2431b7d
C
597
598 if (user) {
76148b27
RK
599 res.fail({
600 status: HttpStatusCode.CONFLICT_409,
601 message: 'User with this username or email already exists.'
602 })
a2431b7d
C
603 return false
604 }
605
2ef6a063
C
606 const actor = await ActorModel.loadLocalByName(username)
607 if (actor) {
76148b27
RK
608 res.fail({
609 status: HttpStatusCode.CONFLICT_409,
610 message: 'Another actor (account/channel) with this name on this instance already exists or has already existed.'
611 })
2ef6a063
C
612 return false
613 }
614
a2431b7d 615 return true
77a5501f 616}
ecb4e35f 617
b49f22d8 618async function checkUserExist (finder: () => Promise<MUserDefault>, res: express.Response, abortResponse = true) {
ecb4e35f
C
619 const user = await finder()
620
621 if (!user) {
622 if (abortResponse === true) {
76148b27
RK
623 res.fail({
624 status: HttpStatusCode.NOT_FOUND_404,
625 message: 'User not found'
626 })
ecb4e35f
C
627 }
628
629 return false
630 }
631
632 res.locals.user = user
ecb4e35f
C
633 return true
634}