aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/moderation.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2020-07-01 16:05:30 +0200
committerChocobozzz <chocobozzz@cpy.re>2020-07-10 14:02:41 +0200
commitd95d15598847c7f020aa056e7e6e0c02d2bbf732 (patch)
treea8a593f1269688caf9e5f99559996f346290fec5 /server/lib/moderation.ts
parent72493e44e9b455a04c4f093ed6c6ffa300b98d8b (diff)
downloadPeerTube-d95d15598847c7f020aa056e7e6e0c02d2bbf732.tar.gz
PeerTube-d95d15598847c7f020aa056e7e6e0c02d2bbf732.tar.zst
PeerTube-d95d15598847c7f020aa056e7e6e0c02d2bbf732.zip
Use 3 tables to represent abuses
Diffstat (limited to 'server/lib/moderation.ts')
-rw-r--r--server/lib/moderation.ts164
1 files changed, 154 insertions, 10 deletions
diff --git a/server/lib/moderation.ts b/server/lib/moderation.ts
index 60d1b4053..4fc9cd747 100644
--- a/server/lib/moderation.ts
+++ b/server/lib/moderation.ts
@@ -1,15 +1,33 @@
1import { VideoModel } from '../models/video/video' 1import { PathLike } from 'fs-extra'
2import { VideoCommentModel } from '../models/video/video-comment' 2import { Transaction } from 'sequelize/types'
3import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model' 3import { AbuseAuditView, auditLoggerFactory } from '@server/helpers/audit-logger'
4import { logger } from '@server/helpers/logger'
5import { AbuseModel } from '@server/models/abuse/abuse'
6import { VideoAbuseModel } from '@server/models/abuse/video-abuse'
7import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse'
8import { VideoFileModel } from '@server/models/video/video-file'
9import { FilteredModelAttributes } from '@server/types'
10import {
11 MAbuseFull,
12 MAccountDefault,
13 MAccountLight,
14 MCommentAbuseAccountVideo,
15 MCommentOwnerVideo,
16 MUser,
17 MVideoAbuseVideoFull,
18 MVideoAccountLightBlacklistAllFiles
19} from '@server/types/models'
20import { ActivityCreate } from '../../shared/models/activitypub'
21import { VideoTorrentObject } from '../../shared/models/activitypub/objects'
22import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object'
4import { VideoCreate, VideoImportCreate } from '../../shared/models/videos' 23import { VideoCreate, VideoImportCreate } from '../../shared/models/videos'
24import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model'
5import { UserModel } from '../models/account/user' 25import { UserModel } from '../models/account/user'
6import { VideoTorrentObject } from '../../shared/models/activitypub/objects'
7import { ActivityCreate } from '../../shared/models/activitypub'
8import { ActorModel } from '../models/activitypub/actor' 26import { ActorModel } from '../models/activitypub/actor'
9import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object' 27import { VideoModel } from '../models/video/video'
10import { VideoFileModel } from '@server/models/video/video-file' 28import { VideoCommentModel } from '../models/video/video-comment'
11import { PathLike } from 'fs-extra' 29import { sendAbuse } from './activitypub/send/send-flag'
12import { MUser } from '@server/types/models' 30import { Notifier } from './notifier'
13 31
14export type AcceptResult = { 32export type AcceptResult = {
15 accepted: boolean 33 accepted: boolean
@@ -73,6 +91,89 @@ function isPostImportVideoAccepted (object: {
73 return { accepted: true } 91 return { accepted: true }
74} 92}
75 93
94async function createVideoAbuse (options: {
95 baseAbuse: FilteredModelAttributes<AbuseModel>
96 videoInstance: MVideoAccountLightBlacklistAllFiles
97 startAt: number
98 endAt: number
99 transaction: Transaction
100 reporterAccount: MAccountDefault
101}) {
102 const { baseAbuse, videoInstance, startAt, endAt, transaction, reporterAccount } = options
103
104 const associateFun = async (abuseInstance: MAbuseFull) => {
105 const videoAbuseInstance: MVideoAbuseVideoFull = await VideoAbuseModel.create({
106 abuseId: abuseInstance.id,
107 videoId: videoInstance.id,
108 startAt: startAt,
109 endAt: endAt
110 }, { transaction })
111
112 videoAbuseInstance.Video = videoInstance
113 abuseInstance.VideoAbuse = videoAbuseInstance
114
115 return { isOwned: videoInstance.isOwned() }
116 }
117
118 return createAbuse({
119 base: baseAbuse,
120 reporterAccount,
121 flaggedAccount: videoInstance.VideoChannel.Account,
122 transaction,
123 associateFun
124 })
125}
126
127function createVideoCommentAbuse (options: {
128 baseAbuse: FilteredModelAttributes<AbuseModel>
129 commentInstance: MCommentOwnerVideo
130 transaction: Transaction
131 reporterAccount: MAccountDefault
132}) {
133 const { baseAbuse, commentInstance, transaction, reporterAccount } = options
134
135 const associateFun = async (abuseInstance: MAbuseFull) => {
136 const commentAbuseInstance: MCommentAbuseAccountVideo = await VideoCommentAbuseModel.create({
137 abuseId: abuseInstance.id,
138 videoCommentId: commentInstance.id
139 }, { transaction })
140
141 commentAbuseInstance.VideoComment = commentInstance
142 abuseInstance.VideoCommentAbuse = commentAbuseInstance
143
144 return { isOwned: commentInstance.isOwned() }
145 }
146
147 return createAbuse({
148 base: baseAbuse,
149 reporterAccount,
150 flaggedAccount: commentInstance.Account,
151 transaction,
152 associateFun
153 })
154}
155
156function createAccountAbuse (options: {
157 baseAbuse: FilteredModelAttributes<AbuseModel>
158 accountInstance: MAccountDefault
159 transaction: Transaction
160 reporterAccount: MAccountDefault
161}) {
162 const { baseAbuse, accountInstance, transaction, reporterAccount } = options
163
164 const associateFun = async () => {
165 return { isOwned: accountInstance.isOwned() }
166 }
167
168 return createAbuse({
169 base: baseAbuse,
170 reporterAccount,
171 flaggedAccount: accountInstance,
172 transaction,
173 associateFun
174 })
175}
176
76export { 177export {
77 isLocalVideoAccepted, 178 isLocalVideoAccepted,
78 isLocalVideoThreadAccepted, 179 isLocalVideoThreadAccepted,
@@ -80,5 +181,48 @@ export {
80 isRemoteVideoCommentAccepted, 181 isRemoteVideoCommentAccepted,
81 isLocalVideoCommentReplyAccepted, 182 isLocalVideoCommentReplyAccepted,
82 isPreImportVideoAccepted, 183 isPreImportVideoAccepted,
83 isPostImportVideoAccepted 184 isPostImportVideoAccepted,
185
186 createAbuse,
187 createVideoAbuse,
188 createVideoCommentAbuse,
189 createAccountAbuse
190}
191
192// ---------------------------------------------------------------------------
193
194async function createAbuse (options: {
195 base: FilteredModelAttributes<AbuseModel>
196 reporterAccount: MAccountDefault
197 flaggedAccount: MAccountLight
198 associateFun: (abuseInstance: MAbuseFull) => Promise<{ isOwned: boolean} >
199 transaction: Transaction
200}) {
201 const { base, reporterAccount, flaggedAccount, associateFun, transaction } = options
202 const auditLogger = auditLoggerFactory('abuse')
203
204 const abuseAttributes = Object.assign({}, base, { flaggedAccountId: flaggedAccount.id })
205 const abuseInstance: MAbuseFull = await AbuseModel.create(abuseAttributes, { transaction })
206
207 abuseInstance.ReporterAccount = reporterAccount
208 abuseInstance.FlaggedAccount = flaggedAccount
209
210 const { isOwned } = await associateFun(abuseInstance)
211
212 if (isOwned === false) {
213 await sendAbuse(reporterAccount.Actor, abuseInstance, abuseInstance.FlaggedAccount, transaction)
214 }
215
216 const abuseJSON = abuseInstance.toFormattedJSON()
217 auditLogger.create(reporterAccount.Actor.getIdentifier(), new AbuseAuditView(abuseJSON))
218
219 Notifier.Instance.notifyOnNewAbuse({
220 abuse: abuseJSON,
221 abuseInstance,
222 reporter: reporterAccount.Actor.getIdentifier()
223 })
224
225 logger.info('Abuse report %d created.', abuseInstance.id)
226
227 return abuseJSON
84} 228}