2
1

abuse.ts 8.7 KB

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