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