]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/middlewares/validators/abuse.ts
cb0bc658a12f4bda3cb79ea61b20588ac4b23b29
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / abuse.ts
1 import * as express from 'express'
2 import { body, param, query } from 'express-validator'
3 import {
4 isAbuseFilterValid,
5 isAbuseMessageValid,
6 isAbuseModerationCommentValid,
7 areAbusePredefinedReasonsValid,
8 isAbusePredefinedReasonValid,
9 isAbuseReasonValid,
10 isAbuseStateValid,
11 isAbuseTimestampCoherent,
12 isAbuseTimestampValid,
13 isAbuseVideoIsValid
14 } from '@server/helpers/custom-validators/abuses'
15 import { exists, isIdOrUUIDValid, isIdValid, toIntOrNull } from '@server/helpers/custom-validators/misc'
16 import { doesCommentIdExist } from '@server/helpers/custom-validators/video-comments'
17 import { logger } from '@server/helpers/logger'
18 import { doesAbuseExist, doesAccountIdExist, doesVideoAbuseExist, doesVideoExist } from '@server/helpers/middlewares'
19 import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
20 import { AbuseCreate, UserRight } from '@shared/models'
21 import { areValidationErrors } from './utils'
22
23 const abuseReportValidator = [
24 body('account.id')
25 .optional()
26 .custom(isIdValid)
27 .withMessage('Should have a valid accountId'),
28
29 body('video.id')
30 .optional()
31 .custom(isIdOrUUIDValid)
32 .withMessage('Should have a valid videoId'),
33 body('video.startAt')
34 .optional()
35 .customSanitizer(toIntOrNull)
36 .custom(isAbuseTimestampValid)
37 .withMessage('Should have valid starting time value'),
38 body('video.endAt')
39 .optional()
40 .customSanitizer(toIntOrNull)
41 .custom(isAbuseTimestampValid)
42 .withMessage('Should have valid ending time value')
43 .bail()
44 .custom(isAbuseTimestampCoherent)
45 .withMessage('Should have a startAt timestamp beginning before endAt'),
46
47 body('comment.id')
48 .optional()
49 .custom(isIdValid)
50 .withMessage('Should have a valid commentId'),
51
52 body('reason')
53 .custom(isAbuseReasonValid)
54 .withMessage('Should have a valid reason'),
55
56 body('predefinedReasons')
57 .optional()
58 .custom(areAbusePredefinedReasonsValid)
59 .withMessage('Should have a valid list of predefined reasons'),
60
61 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
62 logger.debug('Checking abuseReport parameters', { parameters: req.body })
63
64 if (areValidationErrors(req, res)) return
65
66 const body: AbuseCreate = req.body
67
68 if (body.video?.id && !await doesVideoExist(body.video.id, res)) return
69 if (body.account?.id && !await doesAccountIdExist(body.account.id, res)) return
70 if (body.comment?.id && !await doesCommentIdExist(body.comment.id, res)) return
71
72 if (!body.video?.id && !body.account?.id && !body.comment?.id) {
73 res.status(400)
74 .json({ error: 'video id or account id or comment id is required.' })
75
76 return
77 }
78
79 return next()
80 }
81 ]
82
83 const abuseGetValidator = [
84 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
85
86 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
87 logger.debug('Checking abuseGetValidator parameters', { parameters: req.body })
88
89 if (areValidationErrors(req, res)) return
90 if (!await doesAbuseExist(req.params.id, res)) return
91
92 return next()
93 }
94 ]
95
96 const abuseUpdateValidator = [
97 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
98
99 body('state')
100 .optional()
101 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
102 body('moderationComment')
103 .optional()
104 .custom(isAbuseModerationCommentValid).withMessage('Should have a valid moderation comment'),
105
106 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
107 logger.debug('Checking abuseUpdateValidator parameters', { parameters: req.body })
108
109 if (areValidationErrors(req, res)) return
110 if (!await doesAbuseExist(req.params.id, res)) return
111
112 return next()
113 }
114 ]
115
116 const abuseListForAdminsValidator = [
117 query('id')
118 .optional()
119 .custom(isIdValid).withMessage('Should have a valid id'),
120 query('filter')
121 .optional()
122 .custom(isAbuseFilterValid)
123 .withMessage('Should have a valid filter'),
124 query('predefinedReason')
125 .optional()
126 .custom(isAbusePredefinedReasonValid)
127 .withMessage('Should have a valid predefinedReason'),
128 query('search')
129 .optional()
130 .custom(exists).withMessage('Should have a valid search'),
131 query('state')
132 .optional()
133 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
134 query('videoIs')
135 .optional()
136 .custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'),
137 query('searchReporter')
138 .optional()
139 .custom(exists).withMessage('Should have a valid reporter search'),
140 query('searchReportee')
141 .optional()
142 .custom(exists).withMessage('Should have a valid reportee search'),
143 query('searchVideo')
144 .optional()
145 .custom(exists).withMessage('Should have a valid video search'),
146 query('searchVideoChannel')
147 .optional()
148 .custom(exists).withMessage('Should have a valid video channel search'),
149
150 (req: express.Request, res: express.Response, next: express.NextFunction) => {
151 logger.debug('Checking abuseListForAdminsValidator parameters', { parameters: req.body })
152
153 if (areValidationErrors(req, res)) return
154
155 return next()
156 }
157 ]
158
159 const abuseListForUserValidator = [
160 query('id')
161 .optional()
162 .custom(isIdValid).withMessage('Should have a valid id'),
163
164 query('search')
165 .optional()
166 .custom(exists).withMessage('Should have a valid search'),
167
168 query('state')
169 .optional()
170 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
171
172 (req: express.Request, res: express.Response, next: express.NextFunction) => {
173 logger.debug('Checking abuseListForUserValidator parameters', { parameters: req.body })
174
175 if (areValidationErrors(req, res)) return
176
177 return next()
178 }
179 ]
180
181 const getAbuseValidator = [
182 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
183
184 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
185 logger.debug('Checking getAbuseValidator parameters', { parameters: req.body })
186
187 if (areValidationErrors(req, res)) return
188 if (!await doesAbuseExist(req.params.id, res)) return
189
190 const user = res.locals.oauth.token.user
191 const abuse = res.locals.abuse
192
193 if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuse.reporterAccountId !== user.Account.id) {
194 const message = `User ${user.username} does not have right to get abuse ${abuse.id}`
195 logger.warn(message)
196
197 return res.status(403).json({ error: message })
198 }
199
200 return next()
201 }
202 ]
203
204 const addAbuseMessageValidator = [
205 body('message').custom(isAbuseMessageValid).not().isEmpty().withMessage('Should have a valid abuse message'),
206
207 (req: express.Request, res: express.Response, next: express.NextFunction) => {
208 logger.debug('Checking addAbuseMessageValidator parameters', { parameters: req.body })
209
210 if (areValidationErrors(req, res)) return
211
212 return next()
213 }
214 ]
215
216 const deleteAbuseMessageValidator = [
217 param('messageId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid message id'),
218
219 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
220 logger.debug('Checking deleteAbuseMessageValidator parameters', { parameters: req.body })
221
222 if (areValidationErrors(req, res)) return
223
224 const user = res.locals.oauth.token.user
225 const abuse = res.locals.abuse
226
227 const messageId = parseInt(req.params.messageId + '', 10)
228 const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id)
229
230 if (!abuseMessage) {
231 return res.status(404).json({ error: 'Abuse message not found' })
232 }
233
234 if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuseMessage.accountId !== user.Account.id) {
235 return res.status(403).json({ error: 'Cannot delete this abuse message' })
236 }
237
238 res.locals.abuseMessage = abuseMessage
239
240 return next()
241 }
242 ]
243
244 // FIXME: deprecated in 2.3. Remove these validators
245
246 const videoAbuseReportValidator = [
247 param('videoId')
248 .custom(isIdOrUUIDValid)
249 .not()
250 .isEmpty()
251 .withMessage('Should have a valid videoId'),
252 body('reason')
253 .custom(isAbuseReasonValid)
254 .withMessage('Should have a valid reason'),
255 body('predefinedReasons')
256 .optional()
257 .custom(areAbusePredefinedReasonsValid)
258 .withMessage('Should have a valid list of predefined reasons'),
259 body('startAt')
260 .optional()
261 .customSanitizer(toIntOrNull)
262 .custom(isAbuseTimestampValid)
263 .withMessage('Should have valid starting time value'),
264 body('endAt')
265 .optional()
266 .customSanitizer(toIntOrNull)
267 .custom(isAbuseTimestampValid)
268 .withMessage('Should have valid ending time value'),
269
270 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
271 logger.debug('Checking videoAbuseReport parameters', { parameters: req.body })
272
273 if (areValidationErrors(req, res)) return
274 if (!await doesVideoExist(req.params.videoId, res)) return
275
276 return next()
277 }
278 ]
279
280 const videoAbuseGetValidator = [
281 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
282 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
283
284 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
285 logger.debug('Checking videoAbuseGetValidator parameters', { parameters: req.body })
286
287 if (areValidationErrors(req, res)) return
288 if (!await doesVideoAbuseExist(req.params.id, req.params.videoId, res)) return
289
290 return next()
291 }
292 ]
293
294 const videoAbuseUpdateValidator = [
295 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
296 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
297 body('state')
298 .optional()
299 .custom(isAbuseStateValid).withMessage('Should have a valid video abuse state'),
300 body('moderationComment')
301 .optional()
302 .custom(isAbuseModerationCommentValid).withMessage('Should have a valid video moderation comment'),
303
304 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
305 logger.debug('Checking videoAbuseUpdateValidator parameters', { parameters: req.body })
306
307 if (areValidationErrors(req, res)) return
308 if (!await doesVideoAbuseExist(req.params.id, req.params.videoId, res)) return
309
310 return next()
311 }
312 ]
313
314 const videoAbuseListValidator = [
315 query('id')
316 .optional()
317 .custom(isIdValid).withMessage('Should have a valid id'),
318 query('predefinedReason')
319 .optional()
320 .custom(isAbusePredefinedReasonValid)
321 .withMessage('Should have a valid predefinedReason'),
322 query('search')
323 .optional()
324 .custom(exists).withMessage('Should have a valid search'),
325 query('state')
326 .optional()
327 .custom(isAbuseStateValid).withMessage('Should have a valid video abuse state'),
328 query('videoIs')
329 .optional()
330 .custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'),
331 query('searchReporter')
332 .optional()
333 .custom(exists).withMessage('Should have a valid reporter search'),
334 query('searchReportee')
335 .optional()
336 .custom(exists).withMessage('Should have a valid reportee search'),
337 query('searchVideo')
338 .optional()
339 .custom(exists).withMessage('Should have a valid video search'),
340 query('searchVideoChannel')
341 .optional()
342 .custom(exists).withMessage('Should have a valid video channel search'),
343
344 (req: express.Request, res: express.Response, next: express.NextFunction) => {
345 logger.debug('Checking videoAbuseListValidator parameters', { parameters: req.body })
346
347 if (areValidationErrors(req, res)) return
348
349 return next()
350 }
351 ]
352
353 // ---------------------------------------------------------------------------
354
355 export {
356 abuseListForAdminsValidator,
357 abuseReportValidator,
358 abuseGetValidator,
359 addAbuseMessageValidator,
360 abuseUpdateValidator,
361 deleteAbuseMessageValidator,
362 abuseListForUserValidator,
363 getAbuseValidator,
364 videoAbuseReportValidator,
365 videoAbuseGetValidator,
366 videoAbuseUpdateValidator,
367 videoAbuseListValidator
368 }