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