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