]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/middlewares/validators/abuse.ts
Support short uuid for GET video/playlist
[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, 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/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 .customSanitizer(toCompleteUUID)
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.fail({ message: 'video id or account id or comment id is required.' })
74 return
75 }
76
77 return next()
78 }
79 ]
80
81 const abuseGetValidator = [
82 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
83
84 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
85 logger.debug('Checking abuseGetValidator parameters', { parameters: req.body })
86
87 if (areValidationErrors(req, res)) return
88 if (!await doesAbuseExist(req.params.id, res)) return
89
90 return next()
91 }
92 ]
93
94 const abuseUpdateValidator = [
95 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
96
97 body('state')
98 .optional()
99 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
100 body('moderationComment')
101 .optional()
102 .custom(isAbuseModerationCommentValid).withMessage('Should have a valid moderation comment'),
103
104 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
105 logger.debug('Checking abuseUpdateValidator parameters', { parameters: req.body })
106
107 if (areValidationErrors(req, res)) return
108 if (!await doesAbuseExist(req.params.id, res)) return
109
110 return next()
111 }
112 ]
113
114 const abuseListForAdminsValidator = [
115 query('id')
116 .optional()
117 .custom(isIdValid).withMessage('Should have a valid id'),
118 query('filter')
119 .optional()
120 .custom(isAbuseFilterValid)
121 .withMessage('Should have a valid filter'),
122 query('predefinedReason')
123 .optional()
124 .custom(isAbusePredefinedReasonValid)
125 .withMessage('Should have a valid predefinedReason'),
126 query('search')
127 .optional()
128 .custom(exists).withMessage('Should have a valid search'),
129 query('state')
130 .optional()
131 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
132 query('videoIs')
133 .optional()
134 .custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'),
135 query('searchReporter')
136 .optional()
137 .custom(exists).withMessage('Should have a valid reporter search'),
138 query('searchReportee')
139 .optional()
140 .custom(exists).withMessage('Should have a valid reportee search'),
141 query('searchVideo')
142 .optional()
143 .custom(exists).withMessage('Should have a valid video search'),
144 query('searchVideoChannel')
145 .optional()
146 .custom(exists).withMessage('Should have a valid video channel search'),
147
148 (req: express.Request, res: express.Response, next: express.NextFunction) => {
149 logger.debug('Checking abuseListForAdminsValidator parameters', { parameters: req.body })
150
151 if (areValidationErrors(req, res)) return
152
153 return next()
154 }
155 ]
156
157 const abuseListForUserValidator = [
158 query('id')
159 .optional()
160 .custom(isIdValid).withMessage('Should have a valid id'),
161
162 query('search')
163 .optional()
164 .custom(exists).withMessage('Should have a valid search'),
165
166 query('state')
167 .optional()
168 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
169
170 (req: express.Request, res: express.Response, next: express.NextFunction) => {
171 logger.debug('Checking abuseListForUserValidator parameters', { parameters: req.body })
172
173 if (areValidationErrors(req, res)) return
174
175 return next()
176 }
177 ]
178
179 const getAbuseValidator = [
180 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
181
182 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
183 logger.debug('Checking getAbuseValidator parameters', { parameters: req.body })
184
185 if (areValidationErrors(req, res)) return
186 if (!await doesAbuseExist(req.params.id, res)) return
187
188 const user = res.locals.oauth.token.user
189 const abuse = res.locals.abuse
190
191 if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuse.reporterAccountId !== user.Account.id) {
192 const message = `User ${user.username} does not have right to get abuse ${abuse.id}`
193 logger.warn(message)
194
195 return res.fail({
196 status: HttpStatusCode.FORBIDDEN_403,
197 message
198 })
199 }
200
201 return next()
202 }
203 ]
204
205 const checkAbuseValidForMessagesValidator = [
206 (req: express.Request, res: express.Response, next: express.NextFunction) => {
207 logger.debug('Checking checkAbuseValidForMessagesValidator parameters', { parameters: req.body })
208
209 const abuse = res.locals.abuse
210 if (abuse.ReporterAccount.isOwned() === false) {
211 return res.fail({ message: 'This abuse was created by a user of your instance.' })
212 }
213
214 return next()
215 }
216 ]
217
218 const addAbuseMessageValidator = [
219 body('message').custom(isAbuseMessageValid).not().isEmpty().withMessage('Should have a valid abuse message'),
220
221 (req: express.Request, res: express.Response, next: express.NextFunction) => {
222 logger.debug('Checking addAbuseMessageValidator parameters', { parameters: req.body })
223
224 if (areValidationErrors(req, res)) return
225
226 return next()
227 }
228 ]
229
230 const deleteAbuseMessageValidator = [
231 param('messageId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid message id'),
232
233 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
234 logger.debug('Checking deleteAbuseMessageValidator parameters', { parameters: req.body })
235
236 if (areValidationErrors(req, res)) return
237
238 const user = res.locals.oauth.token.user
239 const abuse = res.locals.abuse
240
241 const messageId = parseInt(req.params.messageId + '', 10)
242 const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id)
243
244 if (!abuseMessage) {
245 return res.fail({
246 status: HttpStatusCode.NOT_FOUND_404,
247 message: 'Abuse message not found'
248 })
249 }
250
251 if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuseMessage.accountId !== user.Account.id) {
252 return res.fail({
253 status: HttpStatusCode.FORBIDDEN_403,
254 message: 'Cannot delete this abuse message'
255 })
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 }