aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/middlewares/validators/users.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/middlewares/validators/users.ts')
-rw-r--r--server/middlewares/validators/users.ts151
1 files changed, 4 insertions, 147 deletions
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index 64bd9ca70..f7033f44a 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -1,8 +1,7 @@
1import express from 'express' 1import express from 'express'
2import { body, param, query } from 'express-validator' 2import { body, param, query } from 'express-validator'
3import { Hooks } from '@server/lib/plugins/hooks'
4import { forceNumber } from '@shared/core-utils' 3import { forceNumber } from '@shared/core-utils'
5import { HttpStatusCode, UserRegister, UserRight, UserRole } from '@shared/models' 4import { HttpStatusCode, UserRight, UserRole } from '@shared/models'
6import { exists, isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc' 5import { exists, isBooleanValid, isIdValid, toBooleanOrNull, toIntOrNull } from '../../helpers/custom-validators/misc'
7import { isThemeNameValid } from '../../helpers/custom-validators/plugins' 6import { isThemeNameValid } from '../../helpers/custom-validators/plugins'
8import { 7import {
@@ -24,17 +23,16 @@ import {
24 isUserVideoQuotaValid, 23 isUserVideoQuotaValid,
25 isUserVideosHistoryEnabledValid 24 isUserVideosHistoryEnabledValid
26} from '../../helpers/custom-validators/users' 25} from '../../helpers/custom-validators/users'
27import { isVideoChannelDisplayNameValid, isVideoChannelUsernameValid } from '../../helpers/custom-validators/video-channels' 26import { isVideoChannelUsernameValid } from '../../helpers/custom-validators/video-channels'
28import { logger } from '../../helpers/logger' 27import { logger } from '../../helpers/logger'
29import { isThemeRegistered } from '../../lib/plugins/theme-utils' 28import { isThemeRegistered } from '../../lib/plugins/theme-utils'
30import { Redis } from '../../lib/redis' 29import { Redis } from '../../lib/redis'
31import { isSignupAllowed, isSignupAllowedForCurrentIP } from '../../lib/signup'
32import { ActorModel } from '../../models/actor/actor' 30import { ActorModel } from '../../models/actor/actor'
33import { 31import {
34 areValidationErrors, 32 areValidationErrors,
35 checkUserEmailExist, 33 checkUserEmailExist,
36 checkUserIdExist, 34 checkUserIdExist,
37 checkUserNameOrEmailDoesNotAlreadyExist, 35 checkUserNameOrEmailDoNotAlreadyExist,
38 doesVideoChannelIdExist, 36 doesVideoChannelIdExist,
39 doesVideoExist, 37 doesVideoExist,
40 isValidVideoIdParam 38 isValidVideoIdParam
@@ -81,7 +79,7 @@ const usersAddValidator = [
81 79
82 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 80 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
83 if (areValidationErrors(req, res, { omitBodyLog: true })) return 81 if (areValidationErrors(req, res, { omitBodyLog: true })) return
84 if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return 82 if (!await checkUserNameOrEmailDoNotAlreadyExist(req.body.username, req.body.email, res)) return
85 83
86 const authUser = res.locals.oauth.token.User 84 const authUser = res.locals.oauth.token.User
87 if (authUser.role !== UserRole.ADMINISTRATOR && req.body.role !== UserRole.USER) { 85 if (authUser.role !== UserRole.ADMINISTRATOR && req.body.role !== UserRole.USER) {
@@ -109,51 +107,6 @@ const usersAddValidator = [
109 } 107 }
110] 108]
111 109
112const usersRegisterValidator = [
113 body('username')
114 .custom(isUserUsernameValid),
115 body('password')
116 .custom(isUserPasswordValid),
117 body('email')
118 .isEmail(),
119 body('displayName')
120 .optional()
121 .custom(isUserDisplayNameValid),
122
123 body('channel.name')
124 .optional()
125 .custom(isVideoChannelUsernameValid),
126 body('channel.displayName')
127 .optional()
128 .custom(isVideoChannelDisplayNameValid),
129
130 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
131 if (areValidationErrors(req, res, { omitBodyLog: true })) return
132 if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return
133
134 const body: UserRegister = req.body
135 if (body.channel) {
136 if (!body.channel.name || !body.channel.displayName) {
137 return res.fail({ message: 'Channel is optional but if you specify it, channel.name and channel.displayName are required.' })
138 }
139
140 if (body.channel.name === body.username) {
141 return res.fail({ message: 'Channel name cannot be the same as user username.' })
142 }
143
144 const existing = await ActorModel.loadLocalByName(body.channel.name)
145 if (existing) {
146 return res.fail({
147 status: HttpStatusCode.CONFLICT_409,
148 message: `Channel with name ${body.channel.name} already exists.`
149 })
150 }
151 }
152
153 return next()
154 }
155]
156
157const usersRemoveValidator = [ 110const usersRemoveValidator = [
158 param('id') 111 param('id')
159 .custom(isIdValid), 112 .custom(isIdValid),
@@ -365,45 +318,6 @@ const usersVideosValidator = [
365 } 318 }
366] 319]
367 320
368const ensureUserRegistrationAllowed = [
369 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
370 const allowedParams = {
371 body: req.body,
372 ip: req.ip
373 }
374
375 const allowedResult = await Hooks.wrapPromiseFun(
376 isSignupAllowed,
377 allowedParams,
378 'filter:api.user.signup.allowed.result'
379 )
380
381 if (allowedResult.allowed === false) {
382 return res.fail({
383 status: HttpStatusCode.FORBIDDEN_403,
384 message: allowedResult.errorMessage || 'User registration is not enabled or user limit is reached.'
385 })
386 }
387
388 return next()
389 }
390]
391
392const ensureUserRegistrationAllowedForIP = [
393 (req: express.Request, res: express.Response, next: express.NextFunction) => {
394 const allowed = isSignupAllowedForCurrentIP(req.ip)
395
396 if (allowed === false) {
397 return res.fail({
398 status: HttpStatusCode.FORBIDDEN_403,
399 message: 'You are not on a network authorized for registration.'
400 })
401 }
402
403 return next()
404 }
405]
406
407const usersAskResetPasswordValidator = [ 321const usersAskResetPasswordValidator = [
408 body('email') 322 body('email')
409 .isEmail(), 323 .isEmail(),
@@ -455,58 +369,6 @@ const usersResetPasswordValidator = [
455 } 369 }
456] 370]
457 371
458const usersAskSendVerifyEmailValidator = [
459 body('email').isEmail().not().isEmpty().withMessage('Should have a valid email'),
460
461 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
462 if (areValidationErrors(req, res)) return
463
464 const exists = await checkUserEmailExist(req.body.email, res, false)
465 if (!exists) {
466 logger.debug('User with email %s does not exist (asking verify email).', req.body.email)
467 // Do not leak our emails
468 return res.status(HttpStatusCode.NO_CONTENT_204).end()
469 }
470
471 if (res.locals.user.pluginAuth) {
472 return res.fail({
473 status: HttpStatusCode.CONFLICT_409,
474 message: 'Cannot ask verification email of a user that uses a plugin authentication.'
475 })
476 }
477
478 return next()
479 }
480]
481
482const usersVerifyEmailValidator = [
483 param('id')
484 .isInt().not().isEmpty().withMessage('Should have a valid id'),
485
486 body('verificationString')
487 .not().isEmpty().withMessage('Should have a valid verification string'),
488 body('isPendingEmail')
489 .optional()
490 .customSanitizer(toBooleanOrNull),
491
492 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
493 if (areValidationErrors(req, res)) return
494 if (!await checkUserIdExist(req.params.id, res)) return
495
496 const user = res.locals.user
497 const redisVerificationString = await Redis.Instance.getVerifyEmailLink(user.id)
498
499 if (redisVerificationString !== req.body.verificationString) {
500 return res.fail({
501 status: HttpStatusCode.FORBIDDEN_403,
502 message: 'Invalid verification string.'
503 })
504 }
505
506 return next()
507 }
508]
509
510const usersCheckCurrentPasswordFactory = (targetUserIdGetter: (req: express.Request) => number | string) => { 372const usersCheckCurrentPasswordFactory = (targetUserIdGetter: (req: express.Request) => number | string) => {
511 return [ 373 return [
512 body('currentPassword').optional().custom(exists), 374 body('currentPassword').optional().custom(exists),
@@ -603,21 +465,16 @@ export {
603 usersListValidator, 465 usersListValidator,
604 usersAddValidator, 466 usersAddValidator,
605 deleteMeValidator, 467 deleteMeValidator,
606 usersRegisterValidator,
607 usersBlockingValidator, 468 usersBlockingValidator,
608 usersRemoveValidator, 469 usersRemoveValidator,
609 usersUpdateValidator, 470 usersUpdateValidator,
610 usersUpdateMeValidator, 471 usersUpdateMeValidator,
611 usersVideoRatingValidator, 472 usersVideoRatingValidator,
612 usersCheckCurrentPasswordFactory, 473 usersCheckCurrentPasswordFactory,
613 ensureUserRegistrationAllowed,
614 ensureUserRegistrationAllowedForIP,
615 usersGetValidator, 474 usersGetValidator,
616 usersVideosValidator, 475 usersVideosValidator,
617 usersAskResetPasswordValidator, 476 usersAskResetPasswordValidator,
618 usersResetPasswordValidator, 477 usersResetPasswordValidator,
619 usersAskSendVerifyEmailValidator,
620 usersVerifyEmailValidator,
621 userAutocompleteValidator, 478 userAutocompleteValidator,
622 ensureAuthUserOwnsAccountValidator, 479 ensureAuthUserOwnsAccountValidator,
623 ensureCanModerateUser, 480 ensureCanModerateUser,