diff options
Diffstat (limited to 'server/models/abuse/abuse.ts')
-rw-r--r-- | server/models/abuse/abuse.ts | 130 |
1 files changed, 59 insertions, 71 deletions
diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts index 087c77bd3..9c17c4d51 100644 --- a/server/models/abuse/abuse.ts +++ b/server/models/abuse/abuse.ts | |||
@@ -31,15 +31,15 @@ import { | |||
31 | } from '@shared/models' | 31 | } from '@shared/models' |
32 | import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants' | 32 | import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants' |
33 | import { MAbuse, MAbuseAP, MAbuseFormattable, MUserAccountId } from '../../types/models' | 33 | import { MAbuse, MAbuseAP, MAbuseFormattable, MUserAccountId } from '../../types/models' |
34 | import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account' | 34 | import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' |
35 | import { buildBlockedAccountSQL, getSort, searchAttribute, throwIfNotValid } from '../utils' | 35 | import { buildBlockedAccountSQL, getSort, searchAttribute, throwIfNotValid } from '../utils' |
36 | import { ThumbnailModel } from '../video/thumbnail' | 36 | import { ThumbnailModel } from '../video/thumbnail' |
37 | import { VideoModel } from '../video/video' | 37 | import { VideoModel } from '../video/video' |
38 | import { VideoBlacklistModel } from '../video/video-blacklist' | 38 | import { VideoBlacklistModel } from '../video/video-blacklist' |
39 | import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from '../video/video-channel' | 39 | import { ScopeNames as VideoChannelScopeNames, SummaryOptions as ChannelSummaryOptions, VideoChannelModel } from '../video/video-channel' |
40 | import { VideoCommentModel } from '../video/video-comment' | ||
40 | import { VideoAbuseModel } from './video-abuse' | 41 | import { VideoAbuseModel } from './video-abuse' |
41 | import { VideoCommentAbuseModel } from './video-comment-abuse' | 42 | import { VideoCommentAbuseModel } from './video-comment-abuse' |
42 | import { VideoCommentModel } from '../video/video-comment' | ||
43 | 43 | ||
44 | export enum ScopeNames { | 44 | export enum ScopeNames { |
45 | FOR_API = 'FOR_API' | 45 | FOR_API = 'FOR_API' |
@@ -149,7 +149,7 @@ export enum ScopeNames { | |||
149 | '(' + | 149 | '(' + |
150 | 'SELECT count(*) ' + | 150 | 'SELECT count(*) ' + |
151 | 'FROM "videoAbuse" ' + | 151 | 'FROM "videoAbuse" ' + |
152 | 'WHERE "videoId" = "VideoAbuse"."videoId" ' + | 152 | 'WHERE "videoId" = "VideoAbuse"."videoId" AND "videoId" IS NOT NULL' + |
153 | ')' | 153 | ')' |
154 | ), | 154 | ), |
155 | 'countReportsForVideo' | 155 | 'countReportsForVideo' |
@@ -164,7 +164,7 @@ export enum ScopeNames { | |||
164 | 'row_number() OVER (PARTITION BY "videoId" ORDER BY "createdAt") AS nth ' + | 164 | 'row_number() OVER (PARTITION BY "videoId" ORDER BY "createdAt") AS nth ' + |
165 | 'FROM "videoAbuse" ' + | 165 | 'FROM "videoAbuse" ' + |
166 | ') t ' + | 166 | ') t ' + |
167 | 'WHERE t.id = "VideoAbuse".id' + | 167 | 'WHERE t.id = "VideoAbuse".id AND t.id IS NOT NULL' + |
168 | ')' | 168 | ')' |
169 | ), | 169 | ), |
170 | 'nthReportForVideo' | 170 | 'nthReportForVideo' |
@@ -172,51 +172,22 @@ export enum ScopeNames { | |||
172 | [ | 172 | [ |
173 | literal( | 173 | literal( |
174 | '(' + | 174 | '(' + |
175 | 'SELECT count("videoAbuse"."id") ' + | 175 | 'SELECT count("abuse"."id") ' + |
176 | 'FROM "videoAbuse" ' + | 176 | 'FROM "abuse" ' + |
177 | 'INNER JOIN "video" ON "video"."id" = "videoAbuse"."videoId" ' + | 177 | 'WHERE "abuse"."reporterAccountId" = "AbuseModel"."reporterAccountId"' + |
178 | 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + | ||
179 | 'INNER JOIN "account" ON "videoChannel"."accountId" = "account"."id" ' + | ||
180 | 'WHERE "account"."id" = "AbuseModel"."reporterAccountId" ' + | ||
181 | ')' | ||
182 | ), | ||
183 | 'countReportsForReporter__video' | ||
184 | ], | ||
185 | [ | ||
186 | literal( | ||
187 | '(' + | ||
188 | 'SELECT count(DISTINCT "videoAbuse"."id") ' + | ||
189 | 'FROM "videoAbuse" ' + | ||
190 | `WHERE CAST("deletedVideo"->'channel'->'ownerAccount'->>'id' AS INTEGER) = "AbuseModel"."reporterAccountId" ` + | ||
191 | ')' | ||
192 | ), | ||
193 | 'countReportsForReporter__deletedVideo' | ||
194 | ], | ||
195 | [ | ||
196 | literal( | ||
197 | '(' + | ||
198 | 'SELECT count(DISTINCT "videoAbuse"."id") ' + | ||
199 | 'FROM "videoAbuse" ' + | ||
200 | 'INNER JOIN "video" ON "video"."id" = "videoAbuse"."videoId" ' + | ||
201 | 'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' + | ||
202 | 'INNER JOIN "account" ON ' + | ||
203 | '"videoChannel"."accountId" = "VideoAbuse->Video->VideoChannel"."accountId" ' + | ||
204 | `OR "videoChannel"."accountId" = CAST("VideoAbuse"."deletedVideo"->'channel'->'ownerAccount'->>'id' AS INTEGER) ` + | ||
205 | ')' | 178 | ')' |
206 | ), | 179 | ), |
207 | 'countReportsForReportee__video' | 180 | 'countReportsForReporter' |
208 | ], | 181 | ], |
209 | [ | 182 | [ |
210 | literal( | 183 | literal( |
211 | '(' + | 184 | '(' + |
212 | 'SELECT count(DISTINCT "videoAbuse"."id") ' + | 185 | 'SELECT count("abuse"."id") ' + |
213 | 'FROM "videoAbuse" ' + | 186 | 'FROM "abuse" ' + |
214 | `WHERE CAST("deletedVideo"->'channel'->'ownerAccount'->>'id' AS INTEGER) = "VideoAbuse->Video->VideoChannel"."accountId" ` + | 187 | 'WHERE "abuse"."flaggedAccountId" = "AbuseModel"."flaggedAccountId"' + |
215 | `OR CAST("deletedVideo"->'channel'->'ownerAccount'->>'id' AS INTEGER) = ` + | ||
216 | `CAST("VideoAbuse"."deletedVideo"->'channel'->'ownerAccount'->>'id' AS INTEGER) ` + | ||
217 | ')' | 188 | ')' |
218 | ), | 189 | ), |
219 | 'countReportsForReportee__deletedVideo' | 190 | 'countReportsForReportee' |
220 | ] | 191 | ] |
221 | ] | 192 | ] |
222 | }, | 193 | }, |
@@ -224,13 +195,18 @@ export enum ScopeNames { | |||
224 | { | 195 | { |
225 | model: AccountModel.scope(AccountScopeNames.SUMMARY), | 196 | model: AccountModel.scope(AccountScopeNames.SUMMARY), |
226 | as: 'ReporterAccount', | 197 | as: 'ReporterAccount', |
227 | required: true, | 198 | required: !!options.searchReporter, |
228 | where: searchAttribute(options.searchReporter, 'name') | 199 | where: searchAttribute(options.searchReporter, 'name') |
229 | }, | 200 | }, |
230 | { | 201 | { |
231 | model: AccountModel.scope(AccountScopeNames.SUMMARY), | 202 | model: AccountModel.scope({ |
203 | method: [ | ||
204 | AccountScopeNames.SUMMARY, | ||
205 | { actorRequired: false } as AccountSummaryOptions | ||
206 | ] | ||
207 | }), | ||
232 | as: 'FlaggedAccount', | 208 | as: 'FlaggedAccount', |
233 | required: true, | 209 | required: !!options.searchReportee, |
234 | where: searchAttribute(options.searchReportee, 'name') | 210 | where: searchAttribute(options.searchReportee, 'name') |
235 | }, | 211 | }, |
236 | { | 212 | { |
@@ -243,35 +219,36 @@ export enum ScopeNames { | |||
243 | include: [ | 219 | include: [ |
244 | { | 220 | { |
245 | model: VideoModel.unscoped(), | 221 | model: VideoModel.unscoped(), |
246 | attributes: [ 'name', 'id', 'uuid' ], | 222 | attributes: [ 'name', 'id', 'uuid' ] |
247 | required: true | ||
248 | } | 223 | } |
249 | ] | 224 | ] |
250 | } | 225 | } |
251 | ] | 226 | ] |
252 | }, | 227 | }, |
253 | { | 228 | { |
254 | model: VideoAbuseModel, | 229 | model: VideoAbuseModel.unscoped(), |
255 | required: options.filter === 'video' || !!options.videoIs || videoRequired, | 230 | required: options.filter === 'video' || !!options.videoIs || videoRequired, |
256 | include: [ | 231 | include: [ |
257 | { | 232 | { |
258 | model: VideoModel, | 233 | attributes: [ 'id', 'uuid', 'name', 'nsfw' ], |
234 | model: VideoModel.unscoped(), | ||
259 | required: videoRequired, | 235 | required: videoRequired, |
260 | where: searchAttribute(options.searchVideo, 'name'), | 236 | where: searchAttribute(options.searchVideo, 'name'), |
261 | include: [ | 237 | include: [ |
262 | { | 238 | { |
239 | attributes: [ 'filename', 'fileUrl' ], | ||
263 | model: ThumbnailModel | 240 | model: ThumbnailModel |
264 | }, | 241 | }, |
265 | { | 242 | { |
266 | model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, { withAccount: false } as SummaryOptions ] }), | 243 | model: VideoChannelModel.scope({ |
244 | method: [ | ||
245 | VideoChannelScopeNames.SUMMARY, | ||
246 | { withAccount: false, actorRequired: false } as ChannelSummaryOptions | ||
247 | ] | ||
248 | }), | ||
249 | |||
267 | where: searchAttribute(options.searchVideoChannel, 'name'), | 250 | where: searchAttribute(options.searchVideoChannel, 'name'), |
268 | required: true, | 251 | required: !!options.searchVideoChannel |
269 | include: [ | ||
270 | { | ||
271 | model: AccountModel.scope(AccountScopeNames.SUMMARY), | ||
272 | required: true | ||
273 | } | ||
274 | ] | ||
275 | }, | 252 | }, |
276 | { | 253 | { |
277 | attributes: [ 'id', 'reason', 'unfederated' ], | 254 | attributes: [ 'id', 'reason', 'unfederated' ], |
@@ -304,19 +281,19 @@ export class AbuseModel extends Model<AbuseModel> { | |||
304 | 281 | ||
305 | @AllowNull(false) | 282 | @AllowNull(false) |
306 | @Default(null) | 283 | @Default(null) |
307 | @Is('VideoAbuseReason', value => throwIfNotValid(value, isAbuseReasonValid, 'reason')) | 284 | @Is('AbuseReason', value => throwIfNotValid(value, isAbuseReasonValid, 'reason')) |
308 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.ABUSES.REASON.max)) | 285 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.ABUSES.REASON.max)) |
309 | reason: string | 286 | reason: string |
310 | 287 | ||
311 | @AllowNull(false) | 288 | @AllowNull(false) |
312 | @Default(null) | 289 | @Default(null) |
313 | @Is('VideoAbuseState', value => throwIfNotValid(value, isAbuseStateValid, 'state')) | 290 | @Is('AbuseState', value => throwIfNotValid(value, isAbuseStateValid, 'state')) |
314 | @Column | 291 | @Column |
315 | state: AbuseState | 292 | state: AbuseState |
316 | 293 | ||
317 | @AllowNull(true) | 294 | @AllowNull(true) |
318 | @Default(null) | 295 | @Default(null) |
319 | @Is('VideoAbuseModerationComment', value => throwIfNotValid(value, isAbuseModerationCommentValid, 'moderationComment', true)) | 296 | @Is('AbuseModerationComment', value => throwIfNotValid(value, isAbuseModerationCommentValid, 'moderationComment', true)) |
320 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.ABUSES.MODERATION_COMMENT.max)) | 297 | @Column(DataType.STRING(CONSTRAINTS_FIELDS.ABUSES.MODERATION_COMMENT.max)) |
321 | moderationComment: string | 298 | moderationComment: string |
322 | 299 | ||
@@ -486,12 +463,12 @@ export class AbuseModel extends Model<AbuseModel> { | |||
486 | 463 | ||
487 | toFormattedJSON (this: MAbuseFormattable): Abuse { | 464 | toFormattedJSON (this: MAbuseFormattable): Abuse { |
488 | const predefinedReasons = AbuseModel.getPredefinedReasonsStrings(this.predefinedReasons) | 465 | const predefinedReasons = AbuseModel.getPredefinedReasonsStrings(this.predefinedReasons) |
466 | |||
489 | const countReportsForVideo = this.get('countReportsForVideo') as number | 467 | const countReportsForVideo = this.get('countReportsForVideo') as number |
490 | const nthReportForVideo = this.get('nthReportForVideo') as number | 468 | const nthReportForVideo = this.get('nthReportForVideo') as number |
491 | const countReportsForReporterVideo = this.get('countReportsForReporter__video') as number | 469 | |
492 | const countReportsForReporterDeletedVideo = this.get('countReportsForReporter__deletedVideo') as number | 470 | const countReportsForReporter = this.get('countReportsForReporter') as number |
493 | const countReportsForReporteeVideo = this.get('countReportsForReportee__video') as number | 471 | const countReportsForReportee = this.get('countReportsForReportee') as number |
494 | const countReportsForReporteeDeletedVideo = this.get('countReportsForReportee__deletedVideo') as number | ||
495 | 472 | ||
496 | let video: VideoAbuse | 473 | let video: VideoAbuse |
497 | let comment: VideoCommentAbuse | 474 | let comment: VideoCommentAbuse |
@@ -512,7 +489,11 @@ export class AbuseModel extends Model<AbuseModel> { | |||
512 | deleted: !abuseModel.Video, | 489 | deleted: !abuseModel.Video, |
513 | blacklisted: abuseModel.Video?.isBlacklisted() || false, | 490 | blacklisted: abuseModel.Video?.isBlacklisted() || false, |
514 | thumbnailPath: abuseModel.Video?.getMiniatureStaticPath(), | 491 | thumbnailPath: abuseModel.Video?.getMiniatureStaticPath(), |
515 | channel: abuseModel.Video?.VideoChannel.toFormattedJSON() || abuseModel.deletedVideo?.channel | 492 | |
493 | channel: abuseModel.Video?.VideoChannel.toFormattedJSON() || abuseModel.deletedVideo?.channel, | ||
494 | |||
495 | countReports: countReportsForVideo, | ||
496 | nthReport: nthReportForVideo | ||
516 | } | 497 | } |
517 | } | 498 | } |
518 | 499 | ||
@@ -539,7 +520,13 @@ export class AbuseModel extends Model<AbuseModel> { | |||
539 | reason: this.reason, | 520 | reason: this.reason, |
540 | predefinedReasons, | 521 | predefinedReasons, |
541 | 522 | ||
542 | reporterAccount: this.ReporterAccount.toFormattedJSON(), | 523 | reporterAccount: this.ReporterAccount |
524 | ? this.ReporterAccount.toFormattedJSON() | ||
525 | : null, | ||
526 | |||
527 | flaggedAccount: this.FlaggedAccount | ||
528 | ? this.FlaggedAccount.toFormattedJSON() | ||
529 | : null, | ||
543 | 530 | ||
544 | state: { | 531 | state: { |
545 | id: this.state, | 532 | id: this.state, |
@@ -553,14 +540,15 @@ export class AbuseModel extends Model<AbuseModel> { | |||
553 | 540 | ||
554 | createdAt: this.createdAt, | 541 | createdAt: this.createdAt, |
555 | updatedAt: this.updatedAt, | 542 | updatedAt: this.updatedAt, |
556 | count: countReportsForVideo || 0, | 543 | |
557 | nth: nthReportForVideo || 0, | 544 | countReportsForReporter: (countReportsForReporter || 0), |
558 | countReportsForReporter: (countReportsForReporterVideo || 0) + (countReportsForReporterDeletedVideo || 0), | 545 | countReportsForReportee: (countReportsForReportee || 0), |
559 | countReportsForReportee: (countReportsForReporteeVideo || 0) + (countReportsForReporteeDeletedVideo || 0), | ||
560 | 546 | ||
561 | // FIXME: deprecated in 2.3, remove this | 547 | // FIXME: deprecated in 2.3, remove this |
562 | startAt: null, | 548 | startAt: null, |
563 | endAt: null | 549 | endAt: null, |
550 | count: countReportsForVideo || 0, | ||
551 | nth: nthReportForVideo || 0 | ||
564 | } | 552 | } |
565 | } | 553 | } |
566 | 554 | ||