PeerTube/server/middlewares/validators/abuse.ts

256 lines
6.6 KiB
TypeScript
Raw Normal View History

2021-08-27 14:32:44 +02:00
import express from 'express'
2020-07-01 16:05:30 +02:00
import { body, param, query } from 'express-validator'
import {
2020-11-10 14:41:20 +01:00
areAbusePredefinedReasonsValid,
2020-07-07 10:57:04 +02:00
isAbuseFilterValid,
2020-07-24 15:05:51 +02:00
isAbuseMessageValid,
2020-07-01 16:05:30 +02:00
isAbuseModerationCommentValid,
isAbusePredefinedReasonValid,
isAbuseReasonValid,
isAbuseStateValid,
isAbuseTimestampCoherent,
isAbuseTimestampValid,
isAbuseVideoIsValid
} from '@server/helpers/custom-validators/abuses'
import { exists, isIdOrUUIDValid, isIdValid, toCompleteUUID, toIntOrNull } from '@server/helpers/custom-validators/misc'
2020-07-01 16:05:30 +02:00
import { logger } from '@server/helpers/logger'
2020-07-24 15:05:51 +02:00
import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
import { AbuseCreate, UserRight } from '@shared/models'
2021-07-16 10:42:24 +02:00
import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
import { areValidationErrors, doesAbuseExist, doesAccountIdExist, doesCommentIdExist, doesVideoExist } from './shared'
import { forceNumber } from '@shared/core-utils'
2020-07-01 16:05:30 +02:00
const abuseReportValidator = [
2020-07-07 10:57:04 +02:00
body('account.id')
.optional()
.custom(isIdValid),
2020-07-07 10:57:04 +02:00
body('video.id')
.optional()
.customSanitizer(toCompleteUUID)
.custom(isIdOrUUIDValid),
2020-07-07 10:57:04 +02:00
body('video.startAt')
2020-07-01 16:05:30 +02:00
.optional()
.customSanitizer(toIntOrNull)
.custom(isAbuseTimestampValid),
2020-07-07 10:57:04 +02:00
body('video.endAt')
2020-07-01 16:05:30 +02:00
.optional()
.customSanitizer(toIntOrNull)
.custom(isAbuseTimestampValid)
.bail()
.custom(isAbuseTimestampCoherent)
.withMessage('Should have a startAt timestamp beginning before endAt'),
2020-07-07 10:57:04 +02:00
body('comment.id')
.optional()
.custom(isIdValid),
2020-07-07 10:57:04 +02:00
body('reason')
.custom(isAbuseReasonValid),
2020-07-07 10:57:04 +02:00
body('predefinedReasons')
.optional()
.custom(areAbusePredefinedReasonsValid),
2020-07-07 10:57:04 +02:00
2020-07-01 16:05:30 +02:00
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
2020-07-07 10:57:04 +02:00
const body: AbuseCreate = req.body
if (body.video?.id && !await doesVideoExist(body.video.id, res)) return
if (body.account?.id && !await doesAccountIdExist(body.account.id, res)) return
if (body.comment?.id && !await doesCommentIdExist(body.comment.id, res)) return
if (!body.video?.id && !body.account?.id && !body.comment?.id) {
res.fail({ message: 'video id or account id or comment id is required.' })
2020-07-07 10:57:04 +02:00
return
}
2020-07-01 16:05:30 +02:00
return next()
}
]
const abuseGetValidator = [
param('id')
.custom(isIdValid),
2020-07-01 16:05:30 +02:00
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
2020-07-07 10:57:04 +02:00
if (!await doesAbuseExist(req.params.id, res)) return
2020-07-01 16:05:30 +02:00
return next()
}
]
const abuseUpdateValidator = [
param('id')
.custom(isIdValid),
2020-07-07 10:57:04 +02:00
2020-07-01 16:05:30 +02:00
body('state')
.optional()
.custom(isAbuseStateValid),
2020-07-01 16:05:30 +02:00
body('moderationComment')
.optional()
.custom(isAbuseModerationCommentValid),
2020-07-01 16:05:30 +02:00
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
2020-07-07 10:57:04 +02:00
if (!await doesAbuseExist(req.params.id, res)) return
2020-07-01 16:05:30 +02:00
return next()
}
]
2020-07-24 15:05:51 +02:00
const abuseListForAdminsValidator = [
2020-07-01 16:05:30 +02:00
query('id')
.optional()
.custom(isIdValid),
2020-07-07 10:57:04 +02:00
query('filter')
.optional()
.custom(isAbuseFilterValid),
2020-07-01 16:05:30 +02:00
query('predefinedReason')
.optional()
.custom(isAbusePredefinedReasonValid),
2020-07-01 16:05:30 +02:00
query('search')
.optional()
.custom(exists),
2020-07-01 16:05:30 +02:00
query('state')
.optional()
.custom(isAbuseStateValid),
2020-07-01 16:05:30 +02:00
query('videoIs')
.optional()
.custom(isAbuseVideoIsValid),
2020-07-01 16:05:30 +02:00
query('searchReporter')
.optional()
.custom(exists),
2020-07-01 16:05:30 +02:00
query('searchReportee')
.optional()
.custom(exists),
2020-07-01 16:05:30 +02:00
query('searchVideo')
.optional()
.custom(exists),
2020-07-01 16:05:30 +02:00
query('searchVideoChannel')
.optional()
.custom(exists),
2020-07-01 16:05:30 +02:00
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
return next()
}
]
2020-07-24 15:05:51 +02:00
const abuseListForUserValidator = [
query('id')
.optional()
.custom(isIdValid),
2020-07-24 15:05:51 +02:00
query('search')
.optional()
.custom(exists),
2020-07-24 15:05:51 +02:00
query('state')
.optional()
.custom(isAbuseStateValid),
2020-07-24 15:05:51 +02:00
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
return next()
}
]
const getAbuseValidator = [
param('id')
.custom(isIdValid),
2020-07-24 15:05:51 +02:00
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
if (!await doesAbuseExist(req.params.id, res)) return
const user = res.locals.oauth.token.user
const abuse = res.locals.abuse
if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuse.reporterAccountId !== user.Account.id) {
const message = `User ${user.username} does not have right to get abuse ${abuse.id}`
logger.warn(message)
return res.fail({
status: HttpStatusCode.FORBIDDEN_403,
message
})
2020-07-24 15:05:51 +02:00
}
return next()
}
]
const checkAbuseValidForMessagesValidator = [
(req: express.Request, res: express.Response, next: express.NextFunction) => {
const abuse = res.locals.abuse
if (abuse.ReporterAccount.isOwned() === false) {
return res.fail({ message: 'This abuse was created by a user of your instance.' })
}
return next()
}
]
2020-07-24 15:05:51 +02:00
const addAbuseMessageValidator = [
body('message')
.custom(isAbuseMessageValid),
2020-07-24 15:05:51 +02:00
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
return next()
}
]
const deleteAbuseMessageValidator = [
param('messageId')
.custom(isIdValid),
2020-07-24 15:05:51 +02:00
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
const user = res.locals.oauth.token.user
const abuse = res.locals.abuse
const messageId = forceNumber(req.params.messageId)
2020-07-24 15:05:51 +02:00
const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id)
if (!abuseMessage) {
return res.fail({
status: HttpStatusCode.NOT_FOUND_404,
message: 'Abuse message not found'
})
2020-07-24 15:05:51 +02:00
}
if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuseMessage.accountId !== user.Account.id) {
return res.fail({
status: HttpStatusCode.FORBIDDEN_403,
message: 'Cannot delete this abuse message'
})
2020-07-24 15:05:51 +02:00
}
res.locals.abuseMessage = abuseMessage
return next()
}
]
2020-07-01 16:05:30 +02:00
// ---------------------------------------------------------------------------
export {
2020-07-24 15:05:51 +02:00
abuseListForAdminsValidator,
2020-07-01 16:05:30 +02:00
abuseReportValidator,
abuseGetValidator,
2020-07-24 15:05:51 +02:00
addAbuseMessageValidator,
checkAbuseValidForMessagesValidator,
2020-07-01 16:05:30 +02:00
abuseUpdateValidator,
2020-07-24 15:05:51 +02:00
deleteAbuseMessageValidator,
abuseListForUserValidator,
2020-11-10 14:41:20 +01:00
getAbuseValidator
2020-07-01 16:05:30 +02:00
}