7c77e9a3945950a61bd57aca53b75f5f5db3f87d
[oweals/peertube.git] / server / middlewares / validators / users.ts
1 import * as express from 'express'
2 import 'express-validator'
3 import { body, param } from 'express-validator/check'
4 import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc'
5 import {
6   isAvatarFile, isUserAutoPlayVideoValid, isUserDisplayNSFWValid, isUserPasswordValid, isUserRoleValid, isUserUsernameValid,
7   isUserVideoQuotaValid
8 } from '../../helpers/custom-validators/users'
9 import { isVideoExist } from '../../helpers/custom-validators/videos'
10 import { logger } from '../../helpers/logger'
11 import { isSignupAllowed } from '../../helpers/utils'
12 import { CONSTRAINTS_FIELDS } from '../../initializers'
13 import { UserModel } from '../../models/account/user'
14 import { areValidationErrors } from './utils'
15
16 const usersAddValidator = [
17   body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'),
18   body('password').custom(isUserPasswordValid).withMessage('Should have a valid password'),
19   body('email').isEmail().withMessage('Should have a valid email'),
20   body('videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'),
21   body('role').custom(isUserRoleValid).withMessage('Should have a valid role'),
22
23   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
24     logger.debug('Checking usersAdd parameters', { parameters: req.body })
25
26     if (areValidationErrors(req, res)) return
27     if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return
28
29     return next()
30   }
31 ]
32
33 const usersRegisterValidator = [
34   body('username').custom(isUserUsernameValid).withMessage('Should have a valid username'),
35   body('password').custom(isUserPasswordValid).withMessage('Should have a valid password'),
36   body('email').isEmail().withMessage('Should have a valid email'),
37
38   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
39     logger.debug('Checking usersRegister parameters', { parameters: req.body })
40
41     if (areValidationErrors(req, res)) return
42     if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return
43
44     return next()
45   }
46 ]
47
48 const usersRemoveValidator = [
49   param('id').isInt().not().isEmpty().withMessage('Should have a valid id'),
50
51   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
52     logger.debug('Checking usersRemove parameters', { parameters: req.params })
53
54     if (areValidationErrors(req, res)) return
55     if (!await checkUserIdExist(req.params.id, res)) return
56
57     const user = res.locals.user
58     if (user.username === 'root') {
59       return res.status(400)
60                 .send({ error: 'Cannot remove the root user' })
61                 .end()
62     }
63
64     return next()
65   }
66 ]
67
68 const usersUpdateValidator = [
69   param('id').isInt().not().isEmpty().withMessage('Should have a valid id'),
70   body('email').optional().isEmail().withMessage('Should have a valid email attribute'),
71   body('videoQuota').optional().custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'),
72   body('role').optional().custom(isUserRoleValid).withMessage('Should have a valid role'),
73
74   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
75     logger.debug('Checking usersUpdate parameters', { parameters: req.body })
76
77     if (areValidationErrors(req, res)) return
78     if (!await checkUserIdExist(req.params.id, res)) return
79
80     return next()
81   }
82 ]
83
84 const usersUpdateMeValidator = [
85   body('password').optional().custom(isUserPasswordValid).withMessage('Should have a valid password'),
86   body('email').optional().isEmail().withMessage('Should have a valid email attribute'),
87   body('displayNSFW').optional().custom(isUserDisplayNSFWValid).withMessage('Should have a valid display Not Safe For Work attribute'),
88   body('autoPlayVideo').optional().custom(isUserAutoPlayVideoValid).withMessage('Should have a valid automatically plays video attribute'),
89
90   (req: express.Request, res: express.Response, next: express.NextFunction) => {
91     // TODO: Add old password verification
92     logger.debug('Checking usersUpdateMe parameters', { parameters: req.body })
93
94     if (areValidationErrors(req, res)) return
95
96     return next()
97   }
98 ]
99
100 const usersUpdateMyAvatarValidator = [
101   body('avatarfile').custom((value, { req }) => isAvatarFile(req.files)).withMessage(
102     'This file is not supported. Please, make sure it is of the following type : '
103     + CONSTRAINTS_FIELDS.ACTOR.AVATAR.EXTNAME.join(', ')
104   ),
105
106   (req: express.Request, res: express.Response, next: express.NextFunction) => {
107     logger.debug('Checking usersUpdateMyAvatarValidator parameters', { parameters: req.body })
108
109     if (areValidationErrors(req, res)) return
110
111     return next()
112   }
113 ]
114
115 const usersGetValidator = [
116   param('id').isInt().not().isEmpty().withMessage('Should have a valid id'),
117
118   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
119     logger.debug('Checking usersGet parameters', { parameters: req.body })
120
121     if (areValidationErrors(req, res)) return
122     if (!await checkUserIdExist(req.params.id, res)) return
123
124     return next()
125   }
126 ]
127
128 const usersVideoRatingValidator = [
129   param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'),
130
131   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
132     logger.debug('Checking usersVideoRating parameters', { parameters: req.params })
133
134     if (areValidationErrors(req, res)) return
135     if (!await isVideoExist(req.params.videoId, res)) return
136
137     return next()
138   }
139 ]
140
141 const ensureUserRegistrationAllowed = [
142   async (req: express.Request, res: express.Response, next: express.NextFunction) => {
143     const allowed = await isSignupAllowed()
144     if (allowed === false) {
145       return res.status(403)
146                 .send({ error: 'User registration is not enabled or user limit is reached.' })
147                 .end()
148     }
149
150     return next()
151   }
152 ]
153
154 // ---------------------------------------------------------------------------
155
156 export {
157   usersAddValidator,
158   usersRegisterValidator,
159   usersRemoveValidator,
160   usersUpdateValidator,
161   usersUpdateMeValidator,
162   usersVideoRatingValidator,
163   ensureUserRegistrationAllowed,
164   usersGetValidator,
165   usersUpdateMyAvatarValidator
166 }
167
168 // ---------------------------------------------------------------------------
169
170 async function checkUserIdExist (id: number, res: express.Response) {
171   const user = await UserModel.loadById(id)
172
173   if (!user) {
174     res.status(404)
175               .send({ error: 'User not found' })
176               .end()
177
178     return false
179   }
180
181   res.locals.user = user
182   return true
183 }
184
185 async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email: string, res: express.Response) {
186   const user = await UserModel.loadByUsernameOrEmail(username, email)
187
188   if (user) {
189     res.status(409)
190               .send({ error: 'User with this username of email already exists.' })
191               .end()
192     return false
193   }
194
195   return true
196 }