From d95d15598847c7f020aa056e7e6e0c02d2bbf732 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 1 Jul 2020 16:05:30 +0200 Subject: Use 3 tables to represent abuses --- server/lib/activitypub/process/process-flag.ts | 117 ++++++++++++++----------- server/lib/activitypub/send/send-flag.ts | 31 ++++--- server/lib/activitypub/url.ts | 10 +-- 3 files changed, 88 insertions(+), 70 deletions(-) (limited to 'server/lib/activitypub') diff --git a/server/lib/activitypub/process/process-flag.ts b/server/lib/activitypub/process/process-flag.ts index 1d7132a3a..6350cee12 100644 --- a/server/lib/activitypub/process/process-flag.ts +++ b/server/lib/activitypub/process/process-flag.ts @@ -1,24 +1,19 @@ -import { - ActivityCreate, - ActivityFlag, - VideoAbuseState, - videoAbusePredefinedReasonsMap -} from '../../../../shared' -import { VideoAbuseObject } from '../../../../shared/models/activitypub/objects' +import { createAccountAbuse, createVideoAbuse, createVideoCommentAbuse } from '@server/lib/moderation' +import { AccountModel } from '@server/models/account/account' +import { VideoModel } from '@server/models/video/video' +import { VideoCommentModel } from '@server/models/video/video-comment' +import { AbuseObject, abusePredefinedReasonsMap, AbuseState, ActivityCreate, ActivityFlag } from '../../../../shared' +import { getAPId } from '../../../helpers/activitypub' import { retryTransactionWrapper } from '../../../helpers/database-utils' import { logger } from '../../../helpers/logger' import { sequelizeTypescript } from '../../../initializers/database' -import { VideoAbuseModel } from '../../../models/video/video-abuse' -import { getOrCreateVideoAndAccountAndChannel } from '../videos' -import { Notifier } from '../../notifier' -import { getAPId } from '../../../helpers/activitypub' import { APProcessorOptions } from '../../../types/activitypub-processor.model' -import { MActorSignature, MVideoAbuseAccountVideo } from '../../../types/models' -import { AccountModel } from '@server/models/account/account' +import { MAccountDefault, MActorSignature, MCommentOwnerVideo } from '../../../types/models' async function processFlagActivity (options: APProcessorOptions) { const { activity, byActor } = options - return retryTransactionWrapper(processCreateVideoAbuse, activity, byActor) + + return retryTransactionWrapper(processCreateAbuse, activity, byActor) } // --------------------------------------------------------------------------- @@ -29,55 +24,79 @@ export { // --------------------------------------------------------------------------- -async function processCreateVideoAbuse (activity: ActivityCreate | ActivityFlag, byActor: MActorSignature) { - const flag = activity.type === 'Flag' ? activity : (activity.object as VideoAbuseObject) +async function processCreateAbuse (activity: ActivityCreate | ActivityFlag, byActor: MActorSignature) { + const flag = activity.type === 'Flag' ? activity : (activity.object as AbuseObject) const account = byActor.Account - if (!account) throw new Error('Cannot create video abuse with the non account actor ' + byActor.url) + if (!account) throw new Error('Cannot create abuse with the non account actor ' + byActor.url) + + const reporterAccount = await AccountModel.load(account.id) const objects = Array.isArray(flag.object) ? flag.object : [ flag.object ] + const tags = Array.isArray(flag.tag) ? flag.tag : [] + const predefinedReasons = tags.map(tag => abusePredefinedReasonsMap[tag.name]) + .filter(v => !isNaN(v)) + + const startAt = flag.startAt + const endAt = flag.endAt + for (const object of objects) { try { - logger.debug('Reporting remote abuse for video %s.', getAPId(object)) - - const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: object }) - const reporterAccount = await sequelizeTypescript.transaction(async t => AccountModel.load(account.id, t)) - const tags = Array.isArray(flag.tag) ? flag.tag : [] - const predefinedReasons = tags.map(tag => videoAbusePredefinedReasonsMap[tag.name]) - .filter(v => !isNaN(v)) - const startAt = flag.startAt - const endAt = flag.endAt - - const videoAbuseInstance = await sequelizeTypescript.transaction(async t => { - const videoAbuseData = { - reporterAccountId: account.id, - reason: flag.content, - videoId: video.id, - state: VideoAbuseState.PENDING, - predefinedReasons, - startAt, - endAt - } + const uri = getAPId(object) - const videoAbuseInstance: MVideoAbuseAccountVideo = await VideoAbuseModel.create(videoAbuseData, { transaction: t }) - videoAbuseInstance.Video = video - videoAbuseInstance.Account = reporterAccount + logger.debug('Reporting remote abuse for object %s.', uri) - logger.info('Remote abuse for video uuid %s created', flag.object) + await sequelizeTypescript.transaction(async t => { - return videoAbuseInstance - }) + const video = await VideoModel.loadByUrlAndPopulateAccount(uri) + let videoComment: MCommentOwnerVideo + let flaggedAccount: MAccountDefault + + if (!video) videoComment = await VideoCommentModel.loadByUrlAndPopulateAccountAndVideo(uri) + if (!videoComment) flaggedAccount = await AccountModel.loadByUrl(uri) + + if (!video && !videoComment && !flaggedAccount) { + logger.warn('Cannot flag unknown entity %s.', object) + return + } + + const baseAbuse = { + reporterAccountId: reporterAccount.id, + reason: flag.content, + state: AbuseState.PENDING, + predefinedReasons + } - const videoAbuseJSON = videoAbuseInstance.toFormattedJSON() + if (video) { + return createVideoAbuse({ + baseAbuse, + startAt, + endAt, + reporterAccount, + transaction: t, + videoInstance: video + }) + } + + if (videoComment) { + return createVideoCommentAbuse({ + baseAbuse, + reporterAccount, + transaction: t, + commentInstance: videoComment + }) + } - Notifier.Instance.notifyOnNewVideoAbuse({ - videoAbuse: videoAbuseJSON, - videoAbuseInstance, - reporter: reporterAccount.Actor.getIdentifier() + return await createAccountAbuse({ + baseAbuse, + reporterAccount, + transaction: t, + accountInstance: flaggedAccount + }) }) } catch (err) { - logger.debug('Cannot process report of %s. (Maybe not a video abuse).', getAPId(object), { err }) + logger.debug('Cannot process report of %s', getAPId(object), { err }) } } } diff --git a/server/lib/activitypub/send/send-flag.ts b/server/lib/activitypub/send/send-flag.ts index 3a1fe0812..821637ec8 100644 --- a/server/lib/activitypub/send/send-flag.ts +++ b/server/lib/activitypub/send/send-flag.ts @@ -1,32 +1,31 @@ -import { getVideoAbuseActivityPubUrl } from '../url' -import { unicastTo } from './utils' -import { logger } from '../../../helpers/logger' +import { Transaction } from 'sequelize' import { ActivityAudience, ActivityFlag } from '../../../../shared/models/activitypub' +import { logger } from '../../../helpers/logger' +import { MAbuseAP, MAccountLight, MActor } from '../../../types/models' import { audiencify, getAudience } from '../audience' -import { Transaction } from 'sequelize' -import { MActor, MVideoFullLight } from '../../../types/models' -import { MVideoAbuseVideo } from '../../../types/models/video' +import { getAbuseActivityPubUrl } from '../url' +import { unicastTo } from './utils' -function sendVideoAbuse (byActor: MActor, videoAbuse: MVideoAbuseVideo, video: MVideoFullLight, t: Transaction) { - if (!video.VideoChannel.Account.Actor.serverId) return // Local user +function sendAbuse (byActor: MActor, abuse: MAbuseAP, flaggedAccount: MAccountLight, t: Transaction) { + if (!flaggedAccount.Actor.serverId) return // Local user - const url = getVideoAbuseActivityPubUrl(videoAbuse) + const url = getAbuseActivityPubUrl(abuse) - logger.info('Creating job to send video abuse %s.', url) + logger.info('Creating job to send abuse %s.', url) // Custom audience, we only send the abuse to the origin instance - const audience = { to: [ video.VideoChannel.Account.Actor.url ], cc: [] } - const flagActivity = buildFlagActivity(url, byActor, videoAbuse, audience) + const audience = { to: [ flaggedAccount.Actor.url ], cc: [] } + const flagActivity = buildFlagActivity(url, byActor, abuse, audience) - t.afterCommit(() => unicastTo(flagActivity, byActor, video.VideoChannel.Account.Actor.getSharedInbox())) + t.afterCommit(() => unicastTo(flagActivity, byActor, flaggedAccount.Actor.getSharedInbox())) } -function buildFlagActivity (url: string, byActor: MActor, videoAbuse: MVideoAbuseVideo, audience: ActivityAudience): ActivityFlag { +function buildFlagActivity (url: string, byActor: MActor, abuse: MAbuseAP, audience: ActivityAudience): ActivityFlag { if (!audience) audience = getAudience(byActor) const activity = Object.assign( { id: url, actor: byActor.url }, - videoAbuse.toActivityPubObject() + abuse.toActivityPubObject() ) return audiencify(activity, audience) @@ -35,5 +34,5 @@ function buildFlagActivity (url: string, byActor: MActor, videoAbuse: MVideoAbus // --------------------------------------------------------------------------- export { - sendVideoAbuse + sendAbuse } diff --git a/server/lib/activitypub/url.ts b/server/lib/activitypub/url.ts index 7f98751a1..b54e038a4 100644 --- a/server/lib/activitypub/url.ts +++ b/server/lib/activitypub/url.ts @@ -5,10 +5,10 @@ import { MActorId, MActorUrl, MCommentId, - MVideoAbuseId, MVideoId, MVideoUrl, - MVideoUUID + MVideoUUID, + MAbuseId } from '../../types/models' import { MVideoPlaylist, MVideoPlaylistUUID } from '../../types/models/video/video-playlist' import { MVideoFileVideoUUID } from '../../types/models/video/video-file' @@ -48,8 +48,8 @@ function getAccountActivityPubUrl (accountName: string) { return WEBSERVER.URL + '/accounts/' + accountName } -function getVideoAbuseActivityPubUrl (videoAbuse: MVideoAbuseId) { - return WEBSERVER.URL + '/admin/video-abuses/' + videoAbuse.id +function getAbuseActivityPubUrl (abuse: MAbuseId) { + return WEBSERVER.URL + '/admin/abuses/' + abuse.id } function getVideoViewActivityPubUrl (byActor: MActorUrl, video: MVideoId) { @@ -118,7 +118,7 @@ export { getVideoCacheStreamingPlaylistActivityPubUrl, getVideoChannelActivityPubUrl, getAccountActivityPubUrl, - getVideoAbuseActivityPubUrl, + getAbuseActivityPubUrl, getActorFollowActivityPubUrl, getActorFollowAcceptActivityPubUrl, getVideoAnnounceActivityPubUrl, -- cgit v1.2.3