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