1 import express from 'express'
2 import { body, param, query } from 'express-validator'
4 areAbusePredefinedReasonsValid,
7 isAbuseModerationCommentValid,
8 isAbusePredefinedReasonValid,
11 isAbuseTimestampCoherent,
12 isAbuseTimestampValid,
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'
22 const abuseReportValidator = [
26 .withMessage('Should have a valid accountId'),
30 .customSanitizer(toCompleteUUID)
31 .custom(isIdOrUUIDValid)
32 .withMessage('Should have a valid videoId'),
35 .customSanitizer(toIntOrNull)
36 .custom(isAbuseTimestampValid)
37 .withMessage('Should have valid starting time value'),
40 .customSanitizer(toIntOrNull)
41 .custom(isAbuseTimestampValid)
42 .withMessage('Should have valid ending time value')
44 .custom(isAbuseTimestampCoherent)
45 .withMessage('Should have a startAt timestamp beginning before endAt'),
50 .withMessage('Should have a valid commentId'),
53 .custom(isAbuseReasonValid)
54 .withMessage('Should have a valid reason'),
56 body('predefinedReasons')
58 .custom(areAbusePredefinedReasonsValid)
59 .withMessage('Should have a valid list of predefined reasons'),
61 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
62 logger.debug('Checking abuseReport parameters', { parameters: req.body })
64 if (areValidationErrors(req, res)) return
66 const body: AbuseCreate = req.body
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
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.' })
81 const abuseGetValidator = [
82 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
84 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
85 logger.debug('Checking abuseGetValidator parameters', { parameters: req.body })
87 if (areValidationErrors(req, res)) return
88 if (!await doesAbuseExist(req.params.id, res)) return
94 const abuseUpdateValidator = [
95 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
99 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
100 body('moderationComment')
102 .custom(isAbuseModerationCommentValid).withMessage('Should have a valid moderation comment'),
104 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
105 logger.debug('Checking abuseUpdateValidator parameters', { parameters: req.body })
107 if (areValidationErrors(req, res)) return
108 if (!await doesAbuseExist(req.params.id, res)) return
114 const abuseListForAdminsValidator = [
117 .custom(isIdValid).withMessage('Should have a valid id'),
120 .custom(isAbuseFilterValid)
121 .withMessage('Should have a valid filter'),
122 query('predefinedReason')
124 .custom(isAbusePredefinedReasonValid)
125 .withMessage('Should have a valid predefinedReason'),
128 .custom(exists).withMessage('Should have a valid search'),
131 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
134 .custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'),
135 query('searchReporter')
137 .custom(exists).withMessage('Should have a valid reporter search'),
138 query('searchReportee')
140 .custom(exists).withMessage('Should have a valid reportee search'),
143 .custom(exists).withMessage('Should have a valid video search'),
144 query('searchVideoChannel')
146 .custom(exists).withMessage('Should have a valid video channel search'),
148 (req: express.Request, res: express.Response, next: express.NextFunction) => {
149 logger.debug('Checking abuseListForAdminsValidator parameters', { parameters: req.body })
151 if (areValidationErrors(req, res)) return
157 const abuseListForUserValidator = [
160 .custom(isIdValid).withMessage('Should have a valid id'),
164 .custom(exists).withMessage('Should have a valid search'),
168 .custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
170 (req: express.Request, res: express.Response, next: express.NextFunction) => {
171 logger.debug('Checking abuseListForUserValidator parameters', { parameters: req.body })
173 if (areValidationErrors(req, res)) return
179 const getAbuseValidator = [
180 param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
182 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
183 logger.debug('Checking getAbuseValidator parameters', { parameters: req.body })
185 if (areValidationErrors(req, res)) return
186 if (!await doesAbuseExist(req.params.id, res)) return
188 const user = res.locals.oauth.token.user
189 const abuse = res.locals.abuse
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}`
196 status: HttpStatusCode.FORBIDDEN_403,
205 const checkAbuseValidForMessagesValidator = [
206 (req: express.Request, res: express.Response, next: express.NextFunction) => {
207 logger.debug('Checking checkAbuseValidForMessagesValidator parameters', { parameters: req.body })
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.' })
218 const addAbuseMessageValidator = [
219 body('message').custom(isAbuseMessageValid).not().isEmpty().withMessage('Should have a valid abuse message'),
221 (req: express.Request, res: express.Response, next: express.NextFunction) => {
222 logger.debug('Checking addAbuseMessageValidator parameters', { parameters: req.body })
224 if (areValidationErrors(req, res)) return
230 const deleteAbuseMessageValidator = [
231 param('messageId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid message id'),
233 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
234 logger.debug('Checking deleteAbuseMessageValidator parameters', { parameters: req.body })
236 if (areValidationErrors(req, res)) return
238 const user = res.locals.oauth.token.user
239 const abuse = res.locals.abuse
241 const messageId = parseInt(req.params.messageId + '', 10)
242 const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id)
246 status: HttpStatusCode.NOT_FOUND_404,
247 message: 'Abuse message not found'
251 if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuseMessage.accountId !== user.Account.id) {
253 status: HttpStatusCode.FORBIDDEN_403,
254 message: 'Cannot delete this abuse message'
258 res.locals.abuseMessage = abuseMessage
264 // ---------------------------------------------------------------------------
267 abuseListForAdminsValidator,
268 abuseReportValidator,
270 addAbuseMessageValidator,
271 checkAbuseValidForMessagesValidator,
272 abuseUpdateValidator,
273 deleteAbuseMessageValidator,
274 abuseListForUserValidator,