]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/lib/moderation.ts
Better 413 error handling in cli script
[github/Chocobozzz/PeerTube.git] / server / lib / moderation.ts
CommitLineData
f6d6e7f8 1import { VideoUploadFile } from 'express'
d95d1559
C
2import { PathLike } from 'fs-extra'
3import { Transaction } from 'sequelize/types'
4import { AbuseAuditView, auditLoggerFactory } from '@server/helpers/audit-logger'
f6d6e7f8 5import { afterCommitIfTransaction } from '@server/helpers/database-utils'
d95d1559
C
6import { logger } from '@server/helpers/logger'
7import { AbuseModel } from '@server/models/abuse/abuse'
8import { VideoAbuseModel } from '@server/models/abuse/video-abuse'
9import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse'
10import { VideoFileModel } from '@server/models/video/video-file'
11import { FilteredModelAttributes } from '@server/types'
12import {
13 MAbuseFull,
14 MAccountDefault,
15 MAccountLight,
16 MCommentAbuseAccountVideo,
17 MCommentOwnerVideo,
18 MUser,
19 MVideoAbuseVideoFull,
20 MVideoAccountLightBlacklistAllFiles
21} from '@server/types/models'
22import { ActivityCreate } from '../../shared/models/activitypub'
de6310b2 23import { VideoObject } from '../../shared/models/activitypub/objects'
d95d1559 24import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object'
3cabf353 25import { LiveVideoCreate, VideoCreate, VideoImportCreate } from '../../shared/models/videos'
12edc149 26import { VideoCommentCreate } from '../../shared/models/videos/comment'
7d9ba5c0 27import { ActorModel } from '../models/actor/actor'
2b02c520 28import { UserModel } from '../models/user/user'
d95d1559
C
29import { VideoModel } from '../models/video/video'
30import { VideoCommentModel } from '../models/video/video-comment'
31import { sendAbuse } from './activitypub/send/send-flag'
32import { Notifier } from './notifier'
b4055e1c
C
33
34export type AcceptResult = {
35 accepted: boolean
36 errorMessage?: string
37}
38
39// Can be filtered by plugins
40function isLocalVideoAccepted (object: {
a1587156 41 videoBody: VideoCreate
f6d6e7f8 42 videoFile: VideoUploadFile
b4055e1c
C
43 user: UserModel
44}): AcceptResult {
45 return { accepted: true }
46}
47
3cabf353
C
48function isLocalLiveVideoAccepted (object: {
49 liveVideoBody: LiveVideoCreate
50 user: UserModel
51}): AcceptResult {
52 return { accepted: true }
53}
54
b4055e1c 55function isLocalVideoThreadAccepted (_object: {
a1587156
C
56 commentBody: VideoCommentCreate
57 video: VideoModel
b4055e1c
C
58 user: UserModel
59}): AcceptResult {
60 return { accepted: true }
61}
62
63function isLocalVideoCommentReplyAccepted (_object: {
a1587156
C
64 commentBody: VideoCommentCreate
65 parentComment: VideoCommentModel
66 video: VideoModel
b4055e1c
C
67 user: UserModel
68}): AcceptResult {
69 return { accepted: true }
70}
71
72function isRemoteVideoAccepted (_object: {
a1587156 73 activity: ActivityCreate
de6310b2 74 videoAP: VideoObject
b4055e1c
C
75 byActor: ActorModel
76}): AcceptResult {
77 return { accepted: true }
78}
79
80function isRemoteVideoCommentAccepted (_object: {
a1587156
C
81 activity: ActivityCreate
82 commentAP: VideoCommentObject
b4055e1c
C
83 byActor: ActorModel
84}): AcceptResult {
85 return { accepted: true }
86}
87
2158ac90
RK
88function isPreImportVideoAccepted (object: {
89 videoImportBody: VideoImportCreate
90 user: MUser
91}): AcceptResult {
92 return { accepted: true }
93}
94
95function isPostImportVideoAccepted (object: {
96 videoFilePath: PathLike
97 videoFile: VideoFileModel
98 user: MUser
99}): AcceptResult {
100 return { accepted: true }
101}
102
d95d1559
C
103async function createVideoAbuse (options: {
104 baseAbuse: FilteredModelAttributes<AbuseModel>
105 videoInstance: MVideoAccountLightBlacklistAllFiles
106 startAt: number
107 endAt: number
108 transaction: Transaction
109 reporterAccount: MAccountDefault
9e847c17 110 skipNotification: boolean
d95d1559 111}) {
9e847c17 112 const { baseAbuse, videoInstance, startAt, endAt, transaction, reporterAccount, skipNotification } = options
d95d1559
C
113
114 const associateFun = async (abuseInstance: MAbuseFull) => {
115 const videoAbuseInstance: MVideoAbuseVideoFull = await VideoAbuseModel.create({
116 abuseId: abuseInstance.id,
117 videoId: videoInstance.id,
118 startAt: startAt,
119 endAt: endAt
120 }, { transaction })
121
122 videoAbuseInstance.Video = videoInstance
123 abuseInstance.VideoAbuse = videoAbuseInstance
124
125 return { isOwned: videoInstance.isOwned() }
126 }
127
128 return createAbuse({
129 base: baseAbuse,
130 reporterAccount,
131 flaggedAccount: videoInstance.VideoChannel.Account,
132 transaction,
9e847c17 133 skipNotification,
d95d1559
C
134 associateFun
135 })
136}
137
138function createVideoCommentAbuse (options: {
139 baseAbuse: FilteredModelAttributes<AbuseModel>
140 commentInstance: MCommentOwnerVideo
141 transaction: Transaction
142 reporterAccount: MAccountDefault
9e847c17 143 skipNotification: boolean
d95d1559 144}) {
9e847c17 145 const { baseAbuse, commentInstance, transaction, reporterAccount, skipNotification } = options
d95d1559
C
146
147 const associateFun = async (abuseInstance: MAbuseFull) => {
148 const commentAbuseInstance: MCommentAbuseAccountVideo = await VideoCommentAbuseModel.create({
149 abuseId: abuseInstance.id,
150 videoCommentId: commentInstance.id
151 }, { transaction })
152
153 commentAbuseInstance.VideoComment = commentInstance
154 abuseInstance.VideoCommentAbuse = commentAbuseInstance
155
156 return { isOwned: commentInstance.isOwned() }
157 }
158
159 return createAbuse({
160 base: baseAbuse,
161 reporterAccount,
162 flaggedAccount: commentInstance.Account,
163 transaction,
9e847c17 164 skipNotification,
d95d1559
C
165 associateFun
166 })
167}
168
169function createAccountAbuse (options: {
170 baseAbuse: FilteredModelAttributes<AbuseModel>
171 accountInstance: MAccountDefault
172 transaction: Transaction
173 reporterAccount: MAccountDefault
9e847c17 174 skipNotification: boolean
d95d1559 175}) {
9e847c17 176 const { baseAbuse, accountInstance, transaction, reporterAccount, skipNotification } = options
d95d1559 177
98ab5dc8
C
178 const associateFun = () => {
179 return Promise.resolve({ isOwned: accountInstance.isOwned() })
d95d1559
C
180 }
181
182 return createAbuse({
183 base: baseAbuse,
184 reporterAccount,
185 flaggedAccount: accountInstance,
186 transaction,
9e847c17 187 skipNotification,
d95d1559
C
188 associateFun
189 })
190}
191
b4055e1c 192export {
3cabf353
C
193 isLocalLiveVideoAccepted,
194
b4055e1c
C
195 isLocalVideoAccepted,
196 isLocalVideoThreadAccepted,
197 isRemoteVideoAccepted,
198 isRemoteVideoCommentAccepted,
2158ac90
RK
199 isLocalVideoCommentReplyAccepted,
200 isPreImportVideoAccepted,
d95d1559
C
201 isPostImportVideoAccepted,
202
203 createAbuse,
204 createVideoAbuse,
205 createVideoCommentAbuse,
206 createAccountAbuse
207}
208
209// ---------------------------------------------------------------------------
210
211async function createAbuse (options: {
212 base: FilteredModelAttributes<AbuseModel>
213 reporterAccount: MAccountDefault
214 flaggedAccount: MAccountLight
215 associateFun: (abuseInstance: MAbuseFull) => Promise<{ isOwned: boolean} >
9e847c17 216 skipNotification: boolean
d95d1559
C
217 transaction: Transaction
218}) {
9e847c17 219 const { base, reporterAccount, flaggedAccount, associateFun, transaction, skipNotification } = options
d95d1559
C
220 const auditLogger = auditLoggerFactory('abuse')
221
222 const abuseAttributes = Object.assign({}, base, { flaggedAccountId: flaggedAccount.id })
223 const abuseInstance: MAbuseFull = await AbuseModel.create(abuseAttributes, { transaction })
224
225 abuseInstance.ReporterAccount = reporterAccount
226 abuseInstance.FlaggedAccount = flaggedAccount
227
228 const { isOwned } = await associateFun(abuseInstance)
229
230 if (isOwned === false) {
eae0365b 231 sendAbuse(reporterAccount.Actor, abuseInstance, abuseInstance.FlaggedAccount, transaction)
d95d1559
C
232 }
233
edbc9325 234 const abuseJSON = abuseInstance.toFormattedAdminJSON()
d95d1559
C
235 auditLogger.create(reporterAccount.Actor.getIdentifier(), new AbuseAuditView(abuseJSON))
236
9e847c17
C
237 if (!skipNotification) {
238 afterCommitIfTransaction(transaction, () => {
239 Notifier.Instance.notifyOnNewAbuse({
240 abuse: abuseJSON,
241 abuseInstance,
242 reporter: reporterAccount.Actor.getIdentifier()
243 })
a2eba50b 244 })
9e847c17 245 }
d95d1559
C
246
247 logger.info('Abuse report %d created.', abuseInstance.id)
248
249 return abuseJSON
b4055e1c 250}