]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/middlewares/validators/abuse.ts
replace numbers with typed http status codes (#3409)
[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 areAbusePredefinedReasonsValid,
5 isAbuseFilterValid,
6 isAbuseMessageValid,
7 isAbuseModerationCommentValid,
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, 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 import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
23
24 const abuseReportValidator = [
25 body('account.id')
26 .optional()
27 .custom(isIdValid)
28 .withMessage('Should have a valid accountId'),
29
30 body('video.id')
31 .optional()
32 .custom(isIdOrUUIDValid)
33 .withMessage('Should have a valid videoId'),
34 body('video.startAt')
35 .optional()
36 .customSanitizer(toIntOrNull)
37 .custom(isAbuseTimestampValid)
38 .withMessage('Should have valid starting time value'),
39 body('video.endAt')
40 .optional()
41 .customSanitizer(toIntOrNull)
42 .custom(isAbuseTimestampValid)
43 .withMessage('Should have valid ending time value')
44 .bail()
45 .custom(isAbuseTimestampCoherent)
46 .withMessage('Should have a startAt timestamp beginning before endAt'),
47
48 body('comment.id')
49 .optional()
50 .custom(isIdValid)
51 .withMessage('Should have a valid commentId'),
52
53 body('reason')
54 .custom(isAbuseReasonValid)
55 .withMessage('Should have a valid reason'),
56
57 body('predefinedReasons')
58 .optional()
59 .custom(areAbusePredefinedReasonsValid)
60 .withMessage('Should have a valid list of predefined reasons'),
61
62 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
63 logger.debug('Checking abuseReport parameters', { parameters: req.body })
64
65 if (areValidationErrors(req, res)) return
66
67 const body: AbuseCreate = req.body
68
69 if (body.video?.id && !await doesVideoExist(body.video.id, res)) return
70 if (body.account?.id && !await doesAccountIdExist(body.account.id, res)) return
71 if (body.comment?.id && !await doesCommentIdExist(body.comment.id, res)) return
72
73 if (!body.video?.id && !body.account?.id && !body.comment?.id) {
74 res.status(HttpStatusCode.BAD_REQUEST_400)
75 .json({ error: 'video id or account id or comment id is required.' })
76
77 return
78 }
79
80 return next()
81 }
82 ]
83
84 const abuseGetValidator = [
85 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
86
87 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
88 logger.debug('Checking abuseGetValidator parameters', { parameters: req.body })
89
90 if (areValidationErrors(req, res)) return
91 if (!await doesAbuseExist(req.params.id, res)) return
92
93 return next()
94 }
95 ]
96
97 const abuseUpdateValidator = [
98 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
99
100 body('state')
101 .optional()
102 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
103 body('moderationComment')
104 .optional()
105 .custom(isAbuseModerationCommentValid).withMessage('Should have a valid moderation comment'),
106
107 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
108 logger.debug('Checking abuseUpdateValidator parameters', { parameters: req.body })
109
110 if (areValidationErrors(req, res)) return
111 if (!await doesAbuseExist(req.params.id, res)) return
112
113 return next()
114 }
115 ]
116
117 const abuseListForAdminsValidator = [
118 query('id')
119 .optional()
120 .custom(isIdValid).withMessage('Should have a valid id'),
121 query('filter')
122 .optional()
123 .custom(isAbuseFilterValid)
124 .withMessage('Should have a valid filter'),
125 query('predefinedReason')
126 .optional()
127 .custom(isAbusePredefinedReasonValid)
128 .withMessage('Should have a valid predefinedReason'),
129 query('search')
130 .optional()
131 .custom(exists).withMessage('Should have a valid search'),
132 query('state')
133 .optional()
134 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
135 query('videoIs')
136 .optional()
137 .custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'),
138 query('searchReporter')
139 .optional()
140 .custom(exists).withMessage('Should have a valid reporter search'),
141 query('searchReportee')
142 .optional()
143 .custom(exists).withMessage('Should have a valid reportee search'),
144 query('searchVideo')
145 .optional()
146 .custom(exists).withMessage('Should have a valid video search'),
147 query('searchVideoChannel')
148 .optional()
149 .custom(exists).withMessage('Should have a valid video channel search'),
150
151 (req: express.Request, res: express.Response, next: express.NextFunction) => {
152 logger.debug('Checking abuseListForAdminsValidator parameters', { parameters: req.body })
153
154 if (areValidationErrors(req, res)) return
155
156 return next()
157 }
158 ]
159
160 const abuseListForUserValidator = [
161 query('id')
162 .optional()
163 .custom(isIdValid).withMessage('Should have a valid id'),
164
165 query('search')
166 .optional()
167 .custom(exists).withMessage('Should have a valid search'),
168
169 query('state')
170 .optional()
171 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
172
173 (req: express.Request, res: express.Response, next: express.NextFunction) => {
174 logger.debug('Checking abuseListForUserValidator parameters', { parameters: req.body })
175
176 if (areValidationErrors(req, res)) return
177
178 return next()
179 }
180 ]
181
182 const getAbuseValidator = [
183 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
184
185 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
186 logger.debug('Checking getAbuseValidator parameters', { parameters: req.body })
187
188 if (areValidationErrors(req, res)) return
189 if (!await doesAbuseExist(req.params.id, res)) return
190
191 const user = res.locals.oauth.token.user
192 const abuse = res.locals.abuse
193
194 if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuse.reporterAccountId !== user.Account.id) {
195 const message = `User ${user.username} does not have right to get abuse ${abuse.id}`
196 logger.warn(message)
197
198 return res.status(HttpStatusCode.FORBIDDEN_403)
199 .json({ error: message })
200 }
201
202 return next()
203 }
204 ]
205
206 const checkAbuseValidForMessagesValidator = [
207 (req: express.Request, res: express.Response, next: express.NextFunction) => {
208 logger.debug('Checking checkAbuseValidForMessagesValidator parameters', { parameters: req.body })
209
210 const abuse = res.locals.abuse
211 if (abuse.ReporterAccount.isOwned() === false) {
212 return res.status(HttpStatusCode.BAD_REQUEST_400)
213 .json({
214 error: 'This abuse was created by a user of your instance.'
215 })
216 }
217
218 return next()
219 }
220 ]
221
222 const addAbuseMessageValidator = [
223 body('message').custom(isAbuseMessageValid).not().isEmpty().withMessage('Should have a valid abuse message'),
224
225 (req: express.Request, res: express.Response, next: express.NextFunction) => {
226 logger.debug('Checking addAbuseMessageValidator parameters', { parameters: req.body })
227
228 if (areValidationErrors(req, res)) return
229
230 return next()
231 }
232 ]
233
234 const deleteAbuseMessageValidator = [
235 param('messageId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid message id'),
236
237 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
238 logger.debug('Checking deleteAbuseMessageValidator parameters', { parameters: req.body })
239
240 if (areValidationErrors(req, res)) return
241
242 const user = res.locals.oauth.token.user
243 const abuse = res.locals.abuse
244
245 const messageId = parseInt(req.params.messageId + '', 10)
246 const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id)
247
248 if (!abuseMessage) {
249 return res.status(HttpStatusCode.NOT_FOUND_404)
250 .json({ error: 'Abuse message not found' })
251 }
252
253 if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuseMessage.accountId !== user.Account.id) {
254 return res.status(HttpStatusCode.FORBIDDEN_403)
255 .json({ error: 'Cannot delete this abuse message' })
256 }
257
258 res.locals.abuseMessage = abuseMessage
259
260 return next()
261 }
262 ]
263
264 // ---------------------------------------------------------------------------
265
266 export {
267 abuseListForAdminsValidator,
268 abuseReportValidator,
269 abuseGetValidator,
270 addAbuseMessageValidator,
271 checkAbuseValidForMessagesValidator,
272 abuseUpdateValidator,
273 deleteAbuseMessageValidator,
274 abuseListForUserValidator,
275 getAbuseValidator
276 }