]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/middlewares/validators/abuse.ts
Add server API to abuse messages
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / abuse.ts
CommitLineData
d95d1559
C
1import * as express from 'express'
2import { body, param, query } from 'express-validator'
3import {
57f6896f 4 isAbuseFilterValid,
edbc9325 5 isAbuseMessageValid,
d95d1559 6 isAbuseModerationCommentValid,
edbc9325 7 areAbusePredefinedReasonsValid,
d95d1559
C
8 isAbusePredefinedReasonValid,
9 isAbuseReasonValid,
10 isAbuseStateValid,
11 isAbuseTimestampCoherent,
12 isAbuseTimestampValid,
13 isAbuseVideoIsValid
14} from '@server/helpers/custom-validators/abuses'
15import { exists, isIdOrUUIDValid, isIdValid, toIntOrNull } from '@server/helpers/custom-validators/misc'
57f6896f 16import { doesCommentIdExist } from '@server/helpers/custom-validators/video-comments'
d95d1559 17import { logger } from '@server/helpers/logger'
57f6896f 18import { doesAbuseExist, doesAccountIdExist, doesVideoAbuseExist, doesVideoExist } from '@server/helpers/middlewares'
edbc9325
C
19import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
20import { AbuseCreate, UserRight } from '@shared/models'
d95d1559
C
21import { areValidationErrors } from './utils'
22
23const abuseReportValidator = [
57f6896f
C
24 body('account.id')
25 .optional()
26 .custom(isIdValid)
27 .withMessage('Should have a valid accountId'),
28
29 body('video.id')
30 .optional()
d95d1559 31 .custom(isIdOrUUIDValid)
d95d1559 32 .withMessage('Should have a valid videoId'),
57f6896f 33 body('video.startAt')
d95d1559
C
34 .optional()
35 .customSanitizer(toIntOrNull)
36 .custom(isAbuseTimestampValid)
37 .withMessage('Should have valid starting time value'),
57f6896f 38 body('video.endAt')
d95d1559
C
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
57f6896f
C
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()
edbc9325 58 .custom(areAbusePredefinedReasonsValid)
57f6896f
C
59 .withMessage('Should have a valid list of predefined reasons'),
60
d95d1559
C
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
d95d1559 65
57f6896f
C
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 }
d95d1559
C
78
79 return next()
80 }
81]
82
83const abuseGetValidator = [
d95d1559
C
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
57f6896f 90 if (!await doesAbuseExist(req.params.id, res)) return
d95d1559
C
91
92 return next()
93 }
94]
95
96const abuseUpdateValidator = [
d95d1559 97 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
57f6896f 98
d95d1559
C
99 body('state')
100 .optional()
57f6896f 101 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
d95d1559
C
102 body('moderationComment')
103 .optional()
57f6896f 104 .custom(isAbuseModerationCommentValid).withMessage('Should have a valid moderation comment'),
d95d1559
C
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
57f6896f 110 if (!await doesAbuseExist(req.params.id, res)) return
d95d1559
C
111
112 return next()
113 }
114]
115
edbc9325 116const abuseListForAdminsValidator = [
d95d1559
C
117 query('id')
118 .optional()
119 .custom(isIdValid).withMessage('Should have a valid id'),
57f6896f
C
120 query('filter')
121 .optional()
122 .custom(isAbuseFilterValid)
123 .withMessage('Should have a valid filter'),
d95d1559
C
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()
310b5219 133 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
d95d1559
C
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) => {
edbc9325 151 logger.debug('Checking abuseListForAdminsValidator parameters', { parameters: req.body })
d95d1559
C
152
153 if (areValidationErrors(req, res)) return
154
155 return next()
156 }
157]
158
edbc9325
C
159const 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
181const 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
204const 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
216const 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
d95d1559
C
244// FIXME: deprecated in 2.3. Remove these validators
245
246const 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()
edbc9325 257 .custom(areAbusePredefinedReasonsValid)
d95d1559
C
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)
57f6896f 268 .withMessage('Should have valid ending time value'),
d95d1559
C
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
280const 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
294const 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
314const 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
355export {
edbc9325 356 abuseListForAdminsValidator,
d95d1559
C
357 abuseReportValidator,
358 abuseGetValidator,
edbc9325 359 addAbuseMessageValidator,
d95d1559 360 abuseUpdateValidator,
edbc9325
C
361 deleteAbuseMessageValidator,
362 abuseListForUserValidator,
363 getAbuseValidator,
d95d1559
C
364 videoAbuseReportValidator,
365 videoAbuseGetValidator,
366 videoAbuseUpdateValidator,
367 videoAbuseListValidator
368}