diff options
author | Chocobozzz <me@florianbigard.com> | 2020-07-24 15:05:51 +0200 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2020-07-31 11:35:19 +0200 |
commit | edbc9325462ddf4536775871ebc25e06f46612d1 (patch) | |
tree | 9671dd51303e75d48d4f4f9a1df7a1960e33780d /server/models/abuse/abuse.ts | |
parent | 20516920d2b72c8a18bc24b9740f7176aa962da2 (diff) | |
download | PeerTube-edbc9325462ddf4536775871ebc25e06f46612d1.tar.gz PeerTube-edbc9325462ddf4536775871ebc25e06f46612d1.tar.zst PeerTube-edbc9325462ddf4536775871ebc25e06f46612d1.zip |
Add server API to abuse messages
Diffstat (limited to 'server/models/abuse/abuse.ts')
-rw-r--r-- | server/models/abuse/abuse.ts | 182 |
1 files changed, 132 insertions, 50 deletions
diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts index bd96cf79c..7002502d5 100644 --- a/server/models/abuse/abuse.ts +++ b/server/models/abuse/abuse.ts | |||
@@ -18,7 +18,6 @@ import { | |||
18 | } from 'sequelize-typescript' | 18 | } from 'sequelize-typescript' |
19 | import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses' | 19 | import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses' |
20 | import { | 20 | import { |
21 | Abuse, | ||
22 | AbuseFilter, | 21 | AbuseFilter, |
23 | AbuseObject, | 22 | AbuseObject, |
24 | AbusePredefinedReasons, | 23 | AbusePredefinedReasons, |
@@ -26,11 +25,14 @@ import { | |||
26 | AbusePredefinedReasonsString, | 25 | AbusePredefinedReasonsString, |
27 | AbuseState, | 26 | AbuseState, |
28 | AbuseVideoIs, | 27 | AbuseVideoIs, |
29 | VideoAbuse, | 28 | AdminVideoAbuse, |
30 | VideoCommentAbuse | 29 | AdminAbuse, |
30 | AdminVideoCommentAbuse, | ||
31 | UserAbuse, | ||
32 | UserVideoAbuse | ||
31 | } from '@shared/models' | 33 | } from '@shared/models' |
32 | import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants' | 34 | import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants' |
33 | import { MAbuse, MAbuseAP, MAbuseFormattable, MUserAccountId } from '../../types/models' | 35 | import { MAbuse, MAbuseAdminFormattable, MAbuseAP, MUserAccountId, MAbuseUserFormattable } from '../../types/models' |
34 | import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' | 36 | import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' |
35 | import { getSort, throwIfNotValid } from '../utils' | 37 | import { getSort, throwIfNotValid } from '../utils' |
36 | import { ThumbnailModel } from '../video/thumbnail' | 38 | import { ThumbnailModel } from '../video/thumbnail' |
@@ -52,6 +54,16 @@ export enum ScopeNames { | |||
52 | attributes: { | 54 | attributes: { |
53 | include: [ | 55 | include: [ |
54 | [ | 56 | [ |
57 | literal( | ||
58 | '(' + | ||
59 | 'SELECT count(*) ' + | ||
60 | 'FROM "abuseMessage" ' + | ||
61 | 'WHERE "abuseId" = "AbuseModel"."id"' + | ||
62 | ')' | ||
63 | ), | ||
64 | 'countMessages' | ||
65 | ], | ||
66 | [ | ||
55 | // we don't care about this count for deleted videos, so there are not included | 67 | // we don't care about this count for deleted videos, so there are not included |
56 | literal( | 68 | literal( |
57 | '(' + | 69 | '(' + |
@@ -285,7 +297,7 @@ export class AbuseModel extends Model<AbuseModel> { | |||
285 | return AbuseModel.findOne(query) | 297 | return AbuseModel.findOne(query) |
286 | } | 298 | } |
287 | 299 | ||
288 | static async listForApi (parameters: { | 300 | static async listForAdminApi (parameters: { |
289 | start: number | 301 | start: number |
290 | count: number | 302 | count: number |
291 | sort: string | 303 | sort: string |
@@ -353,71 +365,98 @@ export class AbuseModel extends Model<AbuseModel> { | |||
353 | return { total, data } | 365 | return { total, data } |
354 | } | 366 | } |
355 | 367 | ||
356 | toFormattedJSON (this: MAbuseFormattable): Abuse { | 368 | static async listForUserApi (parameters: { |
357 | const predefinedReasons = AbuseModel.getPredefinedReasonsStrings(this.predefinedReasons) | 369 | user: MUserAccountId |
358 | 370 | ||
359 | const countReportsForVideo = this.get('countReportsForVideo') as number | 371 | start: number |
360 | const nthReportForVideo = this.get('nthReportForVideo') as number | 372 | count: number |
373 | sort: string | ||
361 | 374 | ||
362 | const countReportsForReporter = this.get('countReportsForReporter') as number | 375 | id?: number |
363 | const countReportsForReportee = this.get('countReportsForReportee') as number | 376 | search?: string |
377 | state?: AbuseState | ||
378 | }) { | ||
379 | const { | ||
380 | start, | ||
381 | count, | ||
382 | sort, | ||
383 | search, | ||
384 | user, | ||
385 | state, | ||
386 | id | ||
387 | } = parameters | ||
364 | 388 | ||
365 | let video: VideoAbuse = null | 389 | const queryOptions: BuildAbusesQueryOptions = { |
366 | let comment: VideoCommentAbuse = null | 390 | start, |
391 | count, | ||
392 | sort, | ||
393 | id, | ||
394 | search, | ||
395 | state, | ||
396 | reporterAccountId: user.Account.id | ||
397 | } | ||
398 | |||
399 | const [ total, data ] = await Promise.all([ | ||
400 | AbuseModel.internalCountForApi(queryOptions), | ||
401 | AbuseModel.internalListForApi(queryOptions) | ||
402 | ]) | ||
403 | |||
404 | return { total, data } | ||
405 | } | ||
367 | 406 | ||
368 | if (this.VideoAbuse) { | 407 | buildBaseVideoCommentAbuse (this: MAbuseUserFormattable) { |
369 | const abuseModel = this.VideoAbuse | 408 | if (!this.VideoCommentAbuse) return null |
370 | const entity = abuseModel.Video || abuseModel.deletedVideo | ||
371 | 409 | ||
372 | video = { | 410 | const abuseModel = this.VideoCommentAbuse |
373 | id: entity.id, | 411 | const entity = abuseModel.VideoComment |
374 | uuid: entity.uuid, | ||
375 | name: entity.name, | ||
376 | nsfw: entity.nsfw, | ||
377 | 412 | ||
378 | startAt: abuseModel.startAt, | 413 | return { |
379 | endAt: abuseModel.endAt, | 414 | id: entity.id, |
415 | threadId: entity.getThreadId(), | ||
380 | 416 | ||
381 | deleted: !abuseModel.Video, | 417 | text: entity.text ?? '', |
382 | blacklisted: abuseModel.Video?.isBlacklisted() || false, | ||
383 | thumbnailPath: abuseModel.Video?.getMiniatureStaticPath(), | ||
384 | 418 | ||
385 | channel: abuseModel.Video?.VideoChannel.toFormattedJSON() || abuseModel.deletedVideo?.channel, | 419 | deleted: entity.isDeleted(), |
386 | 420 | ||
387 | countReports: countReportsForVideo, | 421 | video: { |
388 | nthReport: nthReportForVideo | 422 | id: entity.Video.id, |
423 | name: entity.Video.name, | ||
424 | uuid: entity.Video.uuid | ||
389 | } | 425 | } |
390 | } | 426 | } |
427 | } | ||
391 | 428 | ||
392 | if (this.VideoCommentAbuse) { | 429 | buildBaseVideoAbuse (this: MAbuseUserFormattable): UserVideoAbuse { |
393 | const abuseModel = this.VideoCommentAbuse | 430 | if (!this.VideoAbuse) return null |
394 | const entity = abuseModel.VideoComment | ||
395 | 431 | ||
396 | comment = { | 432 | const abuseModel = this.VideoAbuse |
397 | id: entity.id, | 433 | const entity = abuseModel.Video || abuseModel.deletedVideo |
398 | threadId: entity.getThreadId(), | ||
399 | 434 | ||
400 | text: entity.text ?? '', | 435 | return { |
436 | id: entity.id, | ||
437 | uuid: entity.uuid, | ||
438 | name: entity.name, | ||
439 | nsfw: entity.nsfw, | ||
401 | 440 | ||
402 | deleted: entity.isDeleted(), | 441 | startAt: abuseModel.startAt, |
442 | endAt: abuseModel.endAt, | ||
403 | 443 | ||
404 | video: { | 444 | deleted: !abuseModel.Video, |
405 | id: entity.Video.id, | 445 | blacklisted: abuseModel.Video?.isBlacklisted() || false, |
406 | name: entity.Video.name, | 446 | thumbnailPath: abuseModel.Video?.getMiniatureStaticPath(), |
407 | uuid: entity.Video.uuid | 447 | |
408 | } | 448 | channel: abuseModel.Video?.VideoChannel.toFormattedJSON() || abuseModel.deletedVideo?.channel, |
409 | } | ||
410 | } | 449 | } |
450 | } | ||
451 | |||
452 | buildBaseAbuse (this: MAbuseUserFormattable, countMessages: number): UserAbuse { | ||
453 | const predefinedReasons = AbuseModel.getPredefinedReasonsStrings(this.predefinedReasons) | ||
411 | 454 | ||
412 | return { | 455 | return { |
413 | id: this.id, | 456 | id: this.id, |
414 | reason: this.reason, | 457 | reason: this.reason, |
415 | predefinedReasons, | 458 | predefinedReasons, |
416 | 459 | ||
417 | reporterAccount: this.ReporterAccount | ||
418 | ? this.ReporterAccount.toFormattedJSON() | ||
419 | : null, | ||
420 | |||
421 | flaggedAccount: this.FlaggedAccount | 460 | flaggedAccount: this.FlaggedAccount |
422 | ? this.FlaggedAccount.toFormattedJSON() | 461 | ? this.FlaggedAccount.toFormattedJSON() |
423 | : null, | 462 | : null, |
@@ -429,11 +468,41 @@ export class AbuseModel extends Model<AbuseModel> { | |||
429 | 468 | ||
430 | moderationComment: this.moderationComment, | 469 | moderationComment: this.moderationComment, |
431 | 470 | ||
471 | countMessages, | ||
472 | |||
473 | createdAt: this.createdAt, | ||
474 | updatedAt: this.updatedAt | ||
475 | } | ||
476 | } | ||
477 | |||
478 | toFormattedAdminJSON (this: MAbuseAdminFormattable): AdminAbuse { | ||
479 | const countReportsForVideo = this.get('countReportsForVideo') as number | ||
480 | const nthReportForVideo = this.get('nthReportForVideo') as number | ||
481 | |||
482 | const countReportsForReporter = this.get('countReportsForReporter') as number | ||
483 | const countReportsForReportee = this.get('countReportsForReportee') as number | ||
484 | |||
485 | const countMessages = this.get('countMessages') as number | ||
486 | |||
487 | const baseVideo = this.buildBaseVideoAbuse() | ||
488 | const video: AdminVideoAbuse = baseVideo | ||
489 | ? Object.assign(baseVideo, { | ||
490 | countReports: countReportsForVideo, | ||
491 | nthReport: nthReportForVideo | ||
492 | }) | ||
493 | : null | ||
494 | |||
495 | const comment: AdminVideoCommentAbuse = this.buildBaseVideoCommentAbuse() | ||
496 | |||
497 | const abuse = this.buildBaseAbuse(countMessages || 0) | ||
498 | |||
499 | return Object.assign(abuse, { | ||
432 | video, | 500 | video, |
433 | comment, | 501 | comment, |
434 | 502 | ||
435 | createdAt: this.createdAt, | 503 | reporterAccount: this.ReporterAccount |
436 | updatedAt: this.updatedAt, | 504 | ? this.ReporterAccount.toFormattedJSON() |
505 | : null, | ||
437 | 506 | ||
438 | countReportsForReporter: (countReportsForReporter || 0), | 507 | countReportsForReporter: (countReportsForReporter || 0), |
439 | countReportsForReportee: (countReportsForReportee || 0), | 508 | countReportsForReportee: (countReportsForReportee || 0), |
@@ -443,7 +512,20 @@ export class AbuseModel extends Model<AbuseModel> { | |||
443 | endAt: null, | 512 | endAt: null, |
444 | count: countReportsForVideo || 0, | 513 | count: countReportsForVideo || 0, |
445 | nth: nthReportForVideo || 0 | 514 | nth: nthReportForVideo || 0 |
446 | } | 515 | }) |
516 | } | ||
517 | |||
518 | toFormattedUserJSON (this: MAbuseUserFormattable): UserAbuse { | ||
519 | const countMessages = this.get('countMessages') as number | ||
520 | |||
521 | const video = this.buildBaseVideoAbuse() | ||
522 | const comment: AdminVideoCommentAbuse = this.buildBaseVideoCommentAbuse() | ||
523 | const abuse = this.buildBaseAbuse(countMessages || 0) | ||
524 | |||
525 | return Object.assign(abuse, { | ||
526 | video, | ||
527 | comment | ||
528 | }) | ||
447 | } | 529 | } |
448 | 530 | ||
449 | toActivityPubObject (this: MAbuseAP): AbuseObject { | 531 | toActivityPubObject (this: MAbuseAP): AbuseObject { |