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