123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- import express, { VideoLegacyUploadFile } from 'express'
- import { PathLike } from 'fs-extra/esm'
- import { Transaction } from 'sequelize'
- import { AbuseAuditView, auditLoggerFactory } from '@server/helpers/audit-logger.js'
- import { afterCommitIfTransaction } from '@server/helpers/database-utils.js'
- import { logger } from '@server/helpers/logger.js'
- import { AbuseModel } from '@server/models/abuse/abuse.js'
- import { VideoAbuseModel } from '@server/models/abuse/video-abuse.js'
- import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse.js'
- import { VideoFileModel } from '@server/models/video/video-file.js'
- import { FilteredModelAttributes } from '@server/types/index.js'
- import {
- MAbuseFull,
- MAccountDefault,
- MAccountLight,
- MComment,
- MCommentAbuseAccountVideo,
- MCommentOwnerVideo,
- MUser,
- MUserDefault,
- MVideoAbuseVideoFull,
- MVideoAccountLightBlacklistAllFiles
- } from '@server/types/models/index.js'
- import { LiveVideoCreate, VideoCommentCreate, VideoCreate, VideoImportCreate } from '@peertube/peertube-models'
- import { UserModel } from '../models/user/user.js'
- import { VideoCommentModel } from '../models/video/video-comment.js'
- import { VideoModel } from '../models/video/video.js'
- import { sendAbuse } from './activitypub/send/send-flag.js'
- import { Notifier } from './notifier/index.js'
- export type AcceptResult = {
- accepted: boolean
- errorMessage?: string
- }
- // ---------------------------------------------------------------------------
- // Stub function that can be filtered by plugins
- function isLocalVideoFileAccepted (object: {
- videoBody: VideoCreate
- videoFile: VideoLegacyUploadFile
- user: MUserDefault
- }): AcceptResult {
- return { accepted: true }
- }
- // ---------------------------------------------------------------------------
- // Stub function that can be filtered by plugins
- function isLocalLiveVideoAccepted (object: {
- liveVideoBody: LiveVideoCreate
- user: UserModel
- }): AcceptResult {
- return { accepted: true }
- }
- // ---------------------------------------------------------------------------
- // Stub function that can be filtered by plugins
- function isLocalVideoThreadAccepted (_object: {
- req: express.Request
- commentBody: VideoCommentCreate
- video: VideoModel
- user: UserModel
- }): AcceptResult {
- return { accepted: true }
- }
- // Stub function that can be filtered by plugins
- function isLocalVideoCommentReplyAccepted (_object: {
- req: express.Request
- commentBody: VideoCommentCreate
- parentComment: VideoCommentModel
- video: VideoModel
- user: UserModel
- }): AcceptResult {
- return { accepted: true }
- }
- // ---------------------------------------------------------------------------
- // Stub function that can be filtered by plugins
- function isRemoteVideoCommentAccepted (_object: {
- comment: MComment
- }): AcceptResult {
- return { accepted: true }
- }
- // ---------------------------------------------------------------------------
- // Stub function that can be filtered by plugins
- function isPreImportVideoAccepted (object: {
- videoImportBody: VideoImportCreate
- user: MUser
- }): AcceptResult {
- return { accepted: true }
- }
- // Stub function that can be filtered by plugins
- function isPostImportVideoAccepted (object: {
- videoFilePath: PathLike
- videoFile: VideoFileModel
- user: MUser
- }): AcceptResult {
- return { accepted: true }
- }
- // ---------------------------------------------------------------------------
- async function createVideoAbuse (options: {
- baseAbuse: FilteredModelAttributes<AbuseModel>
- videoInstance: MVideoAccountLightBlacklistAllFiles
- startAt: number
- endAt: number
- transaction: Transaction
- reporterAccount: MAccountDefault
- skipNotification: boolean
- }) {
- const { baseAbuse, videoInstance, startAt, endAt, transaction, reporterAccount, skipNotification } = options
- const associateFun = async (abuseInstance: MAbuseFull) => {
- const videoAbuseInstance: MVideoAbuseVideoFull = await VideoAbuseModel.create({
- abuseId: abuseInstance.id,
- videoId: videoInstance.id,
- startAt,
- endAt
- }, { transaction })
- videoAbuseInstance.Video = videoInstance
- abuseInstance.VideoAbuse = videoAbuseInstance
- return { isOwned: videoInstance.isOwned() }
- }
- return createAbuse({
- base: baseAbuse,
- reporterAccount,
- flaggedAccount: videoInstance.VideoChannel.Account,
- transaction,
- skipNotification,
- associateFun
- })
- }
- function createVideoCommentAbuse (options: {
- baseAbuse: FilteredModelAttributes<AbuseModel>
- commentInstance: MCommentOwnerVideo
- transaction: Transaction
- reporterAccount: MAccountDefault
- skipNotification: boolean
- }) {
- const { baseAbuse, commentInstance, transaction, reporterAccount, skipNotification } = options
- const associateFun = async (abuseInstance: MAbuseFull) => {
- const commentAbuseInstance: MCommentAbuseAccountVideo = await VideoCommentAbuseModel.create({
- abuseId: abuseInstance.id,
- videoCommentId: commentInstance.id
- }, { transaction })
- commentAbuseInstance.VideoComment = commentInstance
- abuseInstance.VideoCommentAbuse = commentAbuseInstance
- return { isOwned: commentInstance.isOwned() }
- }
- return createAbuse({
- base: baseAbuse,
- reporterAccount,
- flaggedAccount: commentInstance.Account,
- transaction,
- skipNotification,
- associateFun
- })
- }
- function createAccountAbuse (options: {
- baseAbuse: FilteredModelAttributes<AbuseModel>
- accountInstance: MAccountDefault
- transaction: Transaction
- reporterAccount: MAccountDefault
- skipNotification: boolean
- }) {
- const { baseAbuse, accountInstance, transaction, reporterAccount, skipNotification } = options
- const associateFun = () => {
- return Promise.resolve({ isOwned: accountInstance.isOwned() })
- }
- return createAbuse({
- base: baseAbuse,
- reporterAccount,
- flaggedAccount: accountInstance,
- transaction,
- skipNotification,
- associateFun
- })
- }
- // ---------------------------------------------------------------------------
- export {
- isLocalLiveVideoAccepted,
- isLocalVideoFileAccepted,
- isLocalVideoThreadAccepted,
- isRemoteVideoCommentAccepted,
- isLocalVideoCommentReplyAccepted,
- isPreImportVideoAccepted,
- isPostImportVideoAccepted,
- createAbuse,
- createVideoAbuse,
- createVideoCommentAbuse,
- createAccountAbuse
- }
- // ---------------------------------------------------------------------------
- async function createAbuse (options: {
- base: FilteredModelAttributes<AbuseModel>
- reporterAccount: MAccountDefault
- flaggedAccount: MAccountLight
- associateFun: (abuseInstance: MAbuseFull) => Promise<{ isOwned: boolean }>
- skipNotification: boolean
- transaction: Transaction
- }) {
- const { base, reporterAccount, flaggedAccount, associateFun, transaction, skipNotification } = options
- const auditLogger = auditLoggerFactory('abuse')
- const abuseAttributes = Object.assign({}, base, { flaggedAccountId: flaggedAccount.id })
- const abuseInstance: MAbuseFull = await AbuseModel.create(abuseAttributes, { transaction })
- abuseInstance.ReporterAccount = reporterAccount
- abuseInstance.FlaggedAccount = flaggedAccount
- const { isOwned } = await associateFun(abuseInstance)
- if (isOwned === false) {
- sendAbuse(reporterAccount.Actor, abuseInstance, abuseInstance.FlaggedAccount, transaction)
- }
- const abuseJSON = abuseInstance.toFormattedAdminJSON()
- auditLogger.create(reporterAccount.Actor.getIdentifier(), new AbuseAuditView(abuseJSON))
- if (!skipNotification) {
- afterCommitIfTransaction(transaction, () => {
- Notifier.Instance.notifyOnNewAbuse({
- abuse: abuseJSON,
- abuseInstance,
- reporter: reporterAccount.Actor.getIdentifier()
- })
- })
- }
- logger.info('Abuse report %d created.', abuseInstance.id)
- return abuseJSON
- }
|