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