Add new abuses tests

This commit is contained in:
Chocobozzz 2020-07-08 15:51:46 +02:00 committed by Chocobozzz
parent 811cef146c
commit 310b5219b3
29 changed files with 869 additions and 386 deletions

View File

@ -138,8 +138,8 @@
<tr>
<td colspan="6">
<div class="no-results">
<ng-container *ngIf="search" i18n>No video abuses found matching current filters.</ng-container>
<ng-container *ngIf="!search" i18n>No video abuses found.</ng-container>
<ng-container *ngIf="search" i18n>No abuses found matching current filters.</ng-container>
<ng-container *ngIf="!search" i18n>No abuses found.</ng-container>
</div>
</td>
</tr>

View File

@ -118,7 +118,7 @@ export class UserNotification implements UserNotificationServer {
this.commentUrl = [ this.buildVideoUrl(this.comment.video), { threadId: this.comment.threadId } ]
break
case UserNotificationType.NEW_VIDEO_ABUSE_FOR_MODERATORS:
case UserNotificationType.NEW_ABUSE_FOR_MODERATORS:
this.abuseUrl = '/admin/moderation/abuses/list'
if (this.abuse.video) this.videoUrl = this.buildVideoUrl(this.abuse.video)

View File

@ -42,7 +42,7 @@
</div>
</ng-container>
<ng-container *ngSwitchCase="UserNotificationType.NEW_VIDEO_ABUSE_FOR_MODERATORS">
<ng-container *ngSwitchCase="UserNotificationType.NEW_ABUSE_FOR_MODERATORS">
<my-global-icon iconName="flag" aria-hidden="true"></my-global-icon>
<div class="message" i18n>

View File

@ -140,7 +140,6 @@ export class VideoReportComponent extends FormReactive implements OnInit {
const { hasStart, startAt, hasEnd, endAt } = this.form.get('timestamp').value
this.abuseService.reportVideo({
accountId: this.video.account.id,
reason,
predefinedReasons,
video: {

View File

@ -100,7 +100,7 @@ async function updateAbuse (req: express.Request, res: express.Response) {
return abuse.save({ transaction: t })
})
// Do not send the delete to other instances, we updated OUR copy of this video abuse
// Do not send the delete to other instances, we updated OUR copy of this abuse
return res.type('json').status(204).end()
}
@ -112,7 +112,7 @@ async function deleteAbuse (req: express.Request, res: express.Response) {
return abuse.destroy({ transaction: t })
})
// Do not send the delete to other instances, we delete OUR copy of this video abuse
// Do not send the delete to other instances, we delete OUR copy of this abuse
return res.type('json').status(204).end()
}

View File

@ -50,7 +50,5 @@ async function removeUserHistory (req: express.Request, res: express.Response) {
return UserVideoHistoryModel.removeUserHistoryBefore(user, beforeDate, t)
})
// Do not send the delete to other instances, we delete OUR copy of this video abuse
return res.type('json').status(204).end()
}

View File

@ -3,10 +3,10 @@ import { AbuseFilter, abusePredefinedReasonsMap, AbusePredefinedReasonsString, A
import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants'
import { exists, isArray } from './misc'
const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.ABUSES
const ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.ABUSES
function isAbuseReasonValid (value: string) {
return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
return exists(value) && validator.isLength(value, ABUSES_CONSTRAINTS_FIELDS.REASON)
}
function isAbusePredefinedReasonValid (value: AbusePredefinedReasonsString) {
@ -32,7 +32,7 @@ function isAbuseTimestampCoherent (endAt: number, { req }) {
}
function isAbuseModerationCommentValid (value: string) {
return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.MODERATION_COMMENT)
return exists(value) && validator.isLength(value, ABUSES_CONSTRAINTS_FIELDS.MODERATION_COMMENT)
}
function isAbuseStateValid (value: string) {

View File

@ -68,7 +68,7 @@ async function doesVideoCommentExist (idArg: number | string, video: MVideoId, r
async function doesCommentIdExist (idArg: number | string, res: express.Response) {
const id = parseInt(idArg + '', 10)
const videoComment = await VideoCommentModel.loadById(id)
const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id)
if (!videoComment) {
res.status(404)
@ -77,7 +77,7 @@ async function doesCommentIdExist (idArg: number | string, res: express.Response
return false
}
res.locals.videoComment = videoComment
res.locals.videoCommentFull = videoComment
return true
}

View File

@ -30,7 +30,7 @@ async function doesAbuseExist (abuseId: number | string, res: Response) {
if (!abuse) {
res.status(404)
.json({ error: 'Video abuse not found' })
.json({ error: 'Abuse not found' })
return false
}

View File

@ -43,12 +43,10 @@ async function up (utils: {
await utils.sequelize.query(`
CREATE TABLE IF NOT EXISTS "commentAbuse" (
"id" serial,
"deletedComment" jsonb DEFAULT NULL,
"abuseId" integer NOT NULL REFERENCES "abuse" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
"videoCommentId" integer REFERENCES "videoComment" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
"createdAt" timestamp WITH time zone NOT NULL,
"updatedAt" timestamp WITH time zone NOT NULL,
"commentId" integer REFERENCES "videoComment" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
PRIMARY KEY ("id")
);
`)

View File

@ -325,6 +325,7 @@ class Emailer {
subject: `New comment abuse report from ${reporter}`,
locals: {
commentUrl,
videoName: comment.Video.name,
isLocal: comment.isOwned(),
commentCreatedAt: new Date(comment.createdAt).toLocaleString(),
reason: abuse.reason,

View File

@ -7,7 +7,8 @@ block title
block content
p
| #[a(href=WEBSERVER.URL) #{WEBSERVER.HOST}] received an abuse report for the #{isLocal ? '' : 'remote '}comment "
a(href=commentUrl) of #{flaggedAccount}
a(href=commentUrl) on video #{videoName}
| of #{flaggedAccount}
| created on #{commentCreatedAt}
p The reporter, #{reporter}, cited the following reason(s):

View File

@ -371,7 +371,7 @@ class Notifier {
async function notificationCreator (user: MUserWithNotificationSetting) {
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
type: UserNotificationType.NEW_VIDEO_ABUSE_FOR_MODERATORS,
type: UserNotificationType.NEW_ABUSE_FOR_MODERATORS,
userId: user.id,
abuseId: abuse.id
})

View File

@ -128,7 +128,7 @@ const abuseListValidator = [
.custom(exists).withMessage('Should have a valid search'),
query('state')
.optional()
.custom(isAbuseStateValid).withMessage('Should have a valid video abuse state'),
.custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
query('videoIs')
.optional()
.custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'),

View File

@ -362,8 +362,8 @@ export class AbuseModel extends Model<AbuseModel> {
const countReportsForReporter = this.get('countReportsForReporter') as number
const countReportsForReportee = this.get('countReportsForReportee') as number
let video: VideoAbuse
let comment: VideoCommentAbuse
let video: VideoAbuse = null
let comment: VideoCommentAbuse = null
if (this.VideoAbuse) {
const abuseModel = this.VideoAbuse
@ -391,13 +391,13 @@ export class AbuseModel extends Model<AbuseModel> {
if (this.VideoCommentAbuse) {
const abuseModel = this.VideoCommentAbuse
const entity = abuseModel.VideoComment || abuseModel.deletedComment
const entity = abuseModel.VideoComment
comment = {
id: entity.id,
text: entity.text,
text: entity.text ?? '',
deleted: !abuseModel.VideoComment,
deleted: entity.isDeleted(),
video: {
id: entity.Video.id,

View File

@ -1,5 +1,4 @@
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { VideoComment } from '@shared/models'
import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
import { VideoCommentModel } from '../video/video-comment'
import { AbuseModel } from './abuse'
@ -22,11 +21,6 @@ export class VideoCommentAbuseModel extends Model<VideoCommentAbuseModel> {
@UpdatedAt
updatedAt: Date
@AllowNull(true)
@Default(null)
@Column(DataType.JSONB)
deletedComment: VideoComment & { Video: { name: string, id: number, uuid: string }}
@ForeignKey(() => AbuseModel)
@Column
abuseId: number

View File

@ -109,7 +109,7 @@ function buildAccountInclude (required: boolean, withActor = false) {
required: true,
include: [
{
attributes: [ 'uuid' ],
attributes: [ 'id', 'name', 'uuid' ],
model: VideoModel.unscoped(),
required: true
}
@ -492,6 +492,8 @@ export class UserNotificationModel extends Model<UserNotificationModel> {
threadId: abuse.VideoCommentAbuse.VideoComment.getThreadId(),
video: {
id: abuse.VideoCommentAbuse.VideoComment.Video.id,
name: abuse.VideoCommentAbuse.VideoComment.Video.name,
uuid: abuse.VideoCommentAbuse.VideoComment.Video.uuid
}
} : undefined

View File

@ -3,7 +3,6 @@ import { uniq } from 'lodash'
import { FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction } from 'sequelize'
import {
AllowNull,
BeforeDestroy,
BelongsTo,
Column,
CreatedAt,
@ -16,7 +15,6 @@ import {
Table,
UpdatedAt
} from 'sequelize-typescript'
import { logger } from '@server/helpers/logger'
import { getServerActor } from '@server/models/application/application'
import { MAccount, MAccountId, MUserAccountId } from '@server/types/models'
import { VideoPrivacy } from '@shared/models'
@ -242,51 +240,13 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
@HasMany(() => VideoCommentAbuseModel, {
foreignKey: {
name: 'commentId',
name: 'videoCommentId',
allowNull: true
},
onDelete: 'set null'
})
CommentAbuses: VideoCommentAbuseModel[]
@BeforeDestroy
static async saveEssentialDataToAbuses (instance: VideoCommentModel, options) {
const tasks: Promise<any>[] = []
if (!Array.isArray(instance.CommentAbuses)) {
instance.CommentAbuses = await instance.$get('CommentAbuses')
if (instance.CommentAbuses.length === 0) return undefined
}
if (!instance.Video) {
instance.Video = await instance.$get('Video')
}
logger.info('Saving video comment %s for abuse.', instance.url)
const details = Object.assign(instance.toFormattedJSON(), {
Video: {
id: instance.Video.id,
name: instance.Video.name,
uuid: instance.Video.uuid
}
})
for (const abuse of instance.CommentAbuses) {
abuse.deletedComment = details
tasks.push(abuse.save({ transaction: options.transaction }))
}
Promise.all(tasks)
.catch(err => {
logger.error('Some errors when saving details of comment %s in its abuses before destroy hook.', instance.url, { err })
})
return undefined
}
static loadById (id: number, t?: Transaction): Bluebird<MComment> {
const query: FindOptions = {
where: {

View File

@ -21,9 +21,7 @@ import {
checkBadStartPagination
} from '../../../../shared/extra-utils/requests/check-api-params'
// FIXME: deprecated in 2.3. Remove this controller
describe('Test video abuses API validators', function () {
describe('Test abuses API validators', function () {
const basePath = '/api/v1/abuses/'
let server: ServerInfo

View File

@ -2,21 +2,30 @@
import 'mocha'
import * as chai from 'chai'
import { Abuse, AbusePredefinedReasonsString, AbuseState } from '@shared/models'
import { Abuse, AbuseFilter, AbusePredefinedReasonsString, AbuseState, VideoComment, Account } from '@shared/models'
import {
addVideoCommentThread,
cleanupTests,
createUser,
deleteVideoAbuse,
deleteAbuse,
deleteVideoComment,
flushAndRunMultipleServers,
getVideoAbusesList,
getAbusesList,
getVideoCommentThreads,
getVideoIdFromUUID,
getVideosList,
immutableAssign,
removeVideo,
reportVideoAbuse,
reportAbuse,
ServerInfo,
setAccessTokensToServers,
updateVideoAbuse,
updateAbuse,
uploadVideo,
userLogin
uploadVideoAndGetId,
userLogin,
getAccount,
removeUser,
generateUserAccessToken
} from '../../../../shared/extra-utils/index'
import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
@ -31,6 +40,7 @@ const expect = chai.expect
describe('Test abuses', function () {
let servers: ServerInfo[] = []
let abuseServer1: Abuse
let abuseServer2: Abuse
before(async function () {
@ -44,6 +54,12 @@ describe('Test abuses', function () {
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
})
describe('Video abuses', function () {
before(async function () {
this.timeout(50000)
// Upload some videos on each servers
const video1Attributes = {
@ -70,8 +86,8 @@ describe('Test abuses', function () {
servers[1].video = videos.find(video => video.name === 'my super name for server 2')
})
it('Should not have video abuses', async function () {
const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
it('Should not have abuses', async function () {
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(0)
expect(res.body.data).to.be.an('array')
@ -82,14 +98,14 @@ describe('Test abuses', function () {
this.timeout(15000)
const reason = 'my super bad reason'
await reportVideoAbuse(servers[0].url, servers[0].accessToken, servers[0].video.id, reason)
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, videoId: servers[0].video.id, reason })
// We wait requests propagation, even if the server 1 is not supposed to make a request to server 2
await waitJobs(servers)
})
it('Should have 1 video abuses on server 1 and 0 on server 2', async function () {
const res1 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const res1 = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res1.body.total).to.equal(1)
expect(res1.body.data).to.be.an('array')
@ -97,16 +113,25 @@ describe('Test abuses', function () {
const abuse: Abuse = res1.body.data[0]
expect(abuse.reason).to.equal('my super bad reason')
expect(abuse.reporterAccount.name).to.equal('root')
expect(abuse.reporterAccount.host).to.equal('localhost:' + servers[0].port)
expect(abuse.reporterAccount.host).to.equal(servers[0].host)
expect(abuse.video.id).to.equal(servers[0].video.id)
expect(abuse.video.channel).to.exist
expect(abuse.count).to.equal(1)
expect(abuse.nth).to.equal(1)
expect(abuse.comment).to.be.null
expect(abuse.flaggedAccount.name).to.equal('root')
expect(abuse.flaggedAccount.host).to.equal(servers[0].host)
expect(abuse.video.countReports).to.equal(1)
expect(abuse.video.nthReport).to.equal(1)
expect(abuse.countReportsForReporter).to.equal(1)
expect(abuse.countReportsForReportee).to.equal(1)
const res2 = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
const res2 = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken })
expect(res2.body.total).to.equal(0)
expect(res2.body.data).to.be.an('array')
expect(res2.body.data.length).to.equal(0)
@ -116,86 +141,88 @@ describe('Test abuses', function () {
this.timeout(10000)
const reason = 'my super bad reason 2'
await reportVideoAbuse(servers[0].url, servers[0].accessToken, servers[1].video.id, reason)
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, videoId: servers[1].video.id, reason })
// We wait requests propagation
await waitJobs(servers)
})
it('Should have 2 video abuses on server 1 and 1 on server 2', async function () {
const res1 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const res1 = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res1.body.total).to.equal(2)
expect(res1.body.data).to.be.an('array')
expect(res1.body.data.length).to.equal(2)
const abuse1: Abuse = res1.body.data[0]
expect(abuse1.reason).to.equal('my super bad reason')
expect(abuse1.reporterAccount.name).to.equal('root')
expect(abuse1.reporterAccount.host).to.equal('localhost:' + servers[0].port)
expect(abuse1.reporterAccount.host).to.equal(servers[0].host)
expect(abuse1.video.id).to.equal(servers[0].video.id)
expect(abuse1.video.countReports).to.equal(1)
expect(abuse1.video.nthReport).to.equal(1)
expect(abuse1.comment).to.be.null
expect(abuse1.flaggedAccount.name).to.equal('root')
expect(abuse1.flaggedAccount.host).to.equal(servers[0].host)
expect(abuse1.state.id).to.equal(AbuseState.PENDING)
expect(abuse1.state.label).to.equal('Pending')
expect(abuse1.moderationComment).to.be.null
expect(abuse1.count).to.equal(1)
expect(abuse1.nth).to.equal(1)
const abuse2: Abuse = res1.body.data[1]
expect(abuse2.reason).to.equal('my super bad reason 2')
expect(abuse2.reporterAccount.name).to.equal('root')
expect(abuse2.reporterAccount.host).to.equal('localhost:' + servers[0].port)
expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
expect(abuse2.video.id).to.equal(servers[1].video.id)
expect(abuse2.comment).to.be.null
expect(abuse2.flaggedAccount.name).to.equal('root')
expect(abuse2.flaggedAccount.host).to.equal(servers[1].host)
expect(abuse2.state.id).to.equal(AbuseState.PENDING)
expect(abuse2.state.label).to.equal('Pending')
expect(abuse2.moderationComment).to.be.null
const res2 = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
const res2 = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken })
expect(res2.body.total).to.equal(1)
expect(res2.body.data).to.be.an('array')
expect(res2.body.data.length).to.equal(1)
abuseServer2 = res2.body.data[0]
expect(abuseServer2.reason).to.equal('my super bad reason 2')
expect(abuseServer2.reporterAccount.name).to.equal('root')
expect(abuseServer2.reporterAccount.host).to.equal('localhost:' + servers[0].port)
expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
expect(abuse2.flaggedAccount.name).to.equal('root')
expect(abuse2.flaggedAccount.host).to.equal(servers[1].host)
expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
expect(abuseServer2.state.label).to.equal('Pending')
expect(abuseServer2.moderationComment).to.be.null
})
it('Should update the state of a video abuse', async function () {
const body = { state: AbuseState.REJECTED }
await updateVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id, body)
const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
expect(res.body.data[0].state.id).to.equal(AbuseState.REJECTED)
})
it('Should add a moderation comment', async function () {
const body = { state: AbuseState.ACCEPTED, moderationComment: 'It is valid' }
await updateVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id, body)
const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
expect(res.body.data[0].state.id).to.equal(AbuseState.ACCEPTED)
expect(res.body.data[0].moderationComment).to.equal('It is valid')
})
it('Should hide video abuses from blocked accounts', async function () {
this.timeout(10000)
{
await reportVideoAbuse(servers[1].url, servers[1].accessToken, servers[0].video.uuid, 'will mute this')
const videoId = await getVideoIdFromUUID(servers[1].url, servers[0].video.uuid)
await reportAbuse({ url: servers[1].url, token: servers[1].accessToken, videoId, reason: 'will mute this' })
await waitJobs(servers)
const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(3)
}
const accountToBlock = 'root@localhost:' + servers[1].port
const accountToBlock = 'root@' + servers[1].host
{
await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(2)
const abuse = res.body.data.find(a => a.reason === 'will mute this')
@ -205,7 +232,7 @@ describe('Test abuses', function () {
{
await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(3)
}
})
@ -216,7 +243,7 @@ describe('Test abuses', function () {
{
await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, servers[1].host)
const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(2)
const abuse = res.body.data.find(a => a.reason === 'will mute this')
@ -226,7 +253,7 @@ describe('Test abuses', function () {
{
await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, serverToBlock)
const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(3)
}
})
@ -238,12 +265,12 @@ describe('Test abuses', function () {
await waitJobs(servers)
const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken })
expect(res.body.total).to.equal(2, "wrong number of videos returned")
expect(res.body.data.length).to.equal(2, "wrong number of videos returned")
expect(res.body.data[0].id).to.equal(abuseServer2.id, "wrong origin server id for first video")
expect(res.body.data).to.have.lengthOf(2, "wrong number of videos returned")
const abuse: Abuse = res.body.data[0]
expect(abuse.id).to.equal(abuseServer2.id, "wrong origin server id for first video")
expect(abuse.video.id).to.equal(abuseServer2.video.id, "wrong video id")
expect(abuse.video.channel).to.exist
expect(abuse.video.deleted).to.be.true
@ -270,24 +297,24 @@ describe('Test abuses', function () {
// resume with the test
const reason3 = 'my super bad reason 3'
await reportVideoAbuse(servers[0].url, servers[0].accessToken, video3.id, reason3)
const reason4 = 'my super bad reason 4'
await reportVideoAbuse(servers[0].url, userAccessToken, servers[0].video.id, reason4)
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, videoId: video3.id, reason: reason3 })
const res2 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const reason4 = 'my super bad reason 4'
await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId: servers[0].video.id, reason: reason4 })
{
for (const abuse of res2.body.data as Abuse[]) {
if (abuse.video.id === video3.id) {
expect(abuse.count).to.equal(1, "wrong reports count for video 3")
expect(abuse.nth).to.equal(1, "wrong report position in report list for video 3")
expect(abuse.countReportsForReportee).to.equal(1, "wrong reports count for reporter on video 3 abuse")
expect(abuse.countReportsForReporter).to.equal(3, "wrong reports count for reportee on video 3 abuse")
}
if (abuse.video.id === servers[0].video.id) {
expect(abuse.countReportsForReportee).to.equal(3, "wrong reports count for reporter on video 1 abuse")
}
}
const res2 = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const abuses = res2.body.data as Abuse[]
const abuseVideo3 = res2.body.data.find(a => a.video.id === video3.id)
expect(abuseVideo3).to.not.be.undefined
expect(abuseVideo3.video.countReports).to.equal(1, "wrong reports count for video 3")
expect(abuseVideo3.video.nthReport).to.equal(1, "wrong report position in report list for video 3")
expect(abuseVideo3.countReportsForReportee).to.equal(1, "wrong reports count for reporter on video 3 abuse")
expect(abuseVideo3.countReportsForReporter).to.equal(3, "wrong reports count for reportee on video 3 abuse")
const abuseServer1 = abuses.find(a => a.video.id === servers[0].video.id)
expect(abuseServer1.countReportsForReportee).to.equal(3, "wrong reports count for reporter on video 1 abuse")
}
})
@ -296,17 +323,17 @@ describe('Test abuses', function () {
const reason5 = 'my super bad reason 5'
const predefinedReasons5: AbusePredefinedReasonsString[] = [ 'violentOrRepulsive', 'captions' ]
const createdAbuse = (await reportVideoAbuse(
servers[0].url,
servers[0].accessToken,
servers[0].video.id,
reason5,
predefinedReasons5,
1,
5
)).body.abuse
const createdAbuse = (await reportAbuse({
url: servers[0].url,
token: servers[0].accessToken,
videoId: servers[0].video.id,
reason: reason5,
predefinedReasons: predefinedReasons5,
startAt: 1,
endAt: 5
})).body.abuse
const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
{
const abuse = (res.body.data as Abuse[]).find(a => a.id === createdAbuse.id)
@ -320,25 +347,27 @@ describe('Test abuses', function () {
it('Should delete the video abuse', async function () {
this.timeout(10000)
await deleteVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id)
await deleteAbuse(servers[1].url, servers[1].accessToken, abuseServer2.id)
await waitJobs(servers)
{
const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken })
expect(res.body.total).to.equal(1)
expect(res.body.data.length).to.equal(1)
expect(res.body.data[0].id).to.not.equal(abuseServer2.id)
}
{
const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(6)
}
})
it('Should list and filter video abuses', async function () {
async function list (query: Omit<Parameters<typeof getVideoAbusesList>[0], 'url' | 'token'>) {
this.timeout(10000)
async function list (query: Omit<Parameters<typeof getAbusesList>[0], 'url' | 'token'>) {
const options = {
url: servers[0].url,
token: servers[0].accessToken
@ -346,7 +375,7 @@ describe('Test abuses', function () {
Object.assign(options, query)
const res = await getVideoAbusesList(options)
const res = await getAbusesList(options)
return res.body.data as Abuse[]
}
@ -377,6 +406,370 @@ describe('Test abuses', function () {
expect(await list({ predefinedReason: 'violentOrRepulsive' })).to.have.lengthOf(1)
expect(await list({ predefinedReason: 'serverRules' })).to.have.lengthOf(0)
})
})
describe('Comment abuses', function () {
async function getComment (url: string, videoIdArg: number | string) {
const videoId = typeof videoIdArg === 'string'
? await getVideoIdFromUUID(url, videoIdArg)
: videoIdArg
const res = await getVideoCommentThreads(url, videoId, 0, 5)
return res.body.data[0] as VideoComment
}
before(async function () {
this.timeout(50000)
servers[0].video = await uploadVideoAndGetId({ server: servers[0], videoName: 'server 1' })
servers[1].video = await uploadVideoAndGetId({ server: servers[1], videoName: 'server 2' })
await addVideoCommentThread(servers[0].url, servers[0].accessToken, servers[0].video.id, 'comment server 1')
await addVideoCommentThread(servers[1].url, servers[1].accessToken, servers[1].video.id, 'comment server 2')
await waitJobs(servers)
})
it('Should report abuse on a comment', async function () {
this.timeout(15000)
const comment = await getComment(servers[0].url, servers[0].video.id)
const reason = 'it is a bad comment'
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, commentId: comment.id, reason })
await waitJobs(servers)
})
it('Should have 1 comment abuse on server 1 and 0 on server 2', async function () {
{
const comment = await getComment(servers[0].url, servers[0].video.id)
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment' })
expect(res.body.total).to.equal(1)
expect(res.body.data).to.have.lengthOf(1)
const abuse: Abuse = res.body.data[0]
expect(abuse.reason).to.equal('it is a bad comment')
expect(abuse.reporterAccount.name).to.equal('root')
expect(abuse.reporterAccount.host).to.equal(servers[0].host)
expect(abuse.video).to.be.null
expect(abuse.comment.deleted).to.be.false
expect(abuse.comment.id).to.equal(comment.id)
expect(abuse.comment.text).to.equal(comment.text)
expect(abuse.comment.video.name).to.equal('server 1')
expect(abuse.comment.video.id).to.equal(servers[0].video.id)
expect(abuse.comment.video.uuid).to.equal(servers[0].video.uuid)
expect(abuse.countReportsForReporter).to.equal(5)
expect(abuse.countReportsForReportee).to.equal(5)
}
{
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
expect(res.body.total).to.equal(0)
expect(res.body.data.length).to.equal(0)
}
})
it('Should report abuse on a remote comment', async function () {
this.timeout(10000)
const comment = await getComment(servers[0].url, servers[1].video.uuid)
const reason = 'it is a really bad comment'
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, commentId: comment.id, reason })
await waitJobs(servers)
})
it('Should have 2 comment abuses on server 1 and 1 on server 2', async function () {
const commentServer2 = await getComment(servers[0].url, servers[1].video.id)
const res1 = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment' })
expect(res1.body.total).to.equal(2)
expect(res1.body.data.length).to.equal(2)
const abuse: Abuse = res1.body.data[0]
expect(abuse.reason).to.equal('it is a bad comment')
expect(abuse.countReportsForReporter).to.equal(6)
expect(abuse.countReportsForReportee).to.equal(5)
const abuse2: Abuse = res1.body.data[1]
expect(abuse2.reason).to.equal('it is a really bad comment')
expect(abuse2.reporterAccount.name).to.equal('root')
expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
expect(abuse2.video).to.be.null
expect(abuse2.comment.deleted).to.be.false
expect(abuse2.comment.id).to.equal(commentServer2.id)
expect(abuse2.comment.text).to.equal(commentServer2.text)
expect(abuse2.comment.video.name).to.equal('server 2')
expect(abuse2.comment.video.uuid).to.equal(servers[1].video.uuid)
expect(abuse2.state.id).to.equal(AbuseState.PENDING)
expect(abuse2.state.label).to.equal('Pending')
expect(abuse2.moderationComment).to.be.null
expect(abuse2.countReportsForReporter).to.equal(6)
expect(abuse2.countReportsForReportee).to.equal(2)
const res2 = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
expect(res2.body.total).to.equal(1)
expect(res2.body.data.length).to.equal(1)
abuseServer2 = res2.body.data[0]
expect(abuseServer2.reason).to.equal('it is a really bad comment')
expect(abuseServer2.reporterAccount.name).to.equal('root')
expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
expect(abuseServer2.state.label).to.equal('Pending')
expect(abuseServer2.moderationComment).to.be.null
expect(abuseServer2.countReportsForReporter).to.equal(1)
expect(abuseServer2.countReportsForReportee).to.equal(1)
})
it('Should keep the comment abuse when deleting the comment', async function () {
this.timeout(10000)
const commentServer2 = await getComment(servers[0].url, servers[1].video.id)
await deleteVideoComment(servers[0].url, servers[0].accessToken, servers[1].video.uuid, commentServer2.id)
await waitJobs(servers)
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment' })
expect(res.body.total).to.equal(2)
expect(res.body.data).to.have.lengthOf(2)
const abuse = (res.body.data as Abuse[]).find(a => a.comment?.id === commentServer2.id)
expect(abuse).to.not.be.undefined
expect(abuse.comment.text).to.be.empty
expect(abuse.comment.video.name).to.equal('server 2')
expect(abuse.comment.deleted).to.be.true
})
it('Should delete the comment abuse', async function () {
this.timeout(10000)
await deleteAbuse(servers[1].url, servers[1].accessToken, abuseServer2.id)
await waitJobs(servers)
{
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
expect(res.body.total).to.equal(0)
expect(res.body.data.length).to.equal(0)
}
{
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment' })
expect(res.body.total).to.equal(2)
}
})
it('Should list and filter video abuses', async function () {
{
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment', searchReportee: 'foo' })
expect(res.body.total).to.equal(0)
}
{
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment', searchReportee: 'ot' })
expect(res.body.total).to.equal(2)
}
{
const baseParams = { url: servers[0].url, token: servers[0].accessToken, filter: 'comment' as AbuseFilter, start: 1, count: 1 }
const res1 = await getAbusesList(immutableAssign(baseParams, { sort: 'createdAt' }))
expect(res1.body.data).to.have.lengthOf(1)
expect(res1.body.data[0].comment.text).to.be.empty
const res2 = await getAbusesList(immutableAssign(baseParams, { sort: '-createdAt' }))
expect(res2.body.data).to.have.lengthOf(1)
expect(res2.body.data[0].comment.text).to.equal('comment server 1')
}
})
})
describe('Account abuses', function () {
async function getAccountFromServer (url: string, name: string, server: ServerInfo) {
const res = await getAccount(url, name + '@' + server.host)
return res.body as Account
}
before(async function () {
this.timeout(50000)
await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: 'user_1', password: 'donald' })
const token = await generateUserAccessToken(servers[1], 'user_2')
await uploadVideo(servers[1].url, token, { name: 'super video' })
await waitJobs(servers)
})
it('Should report abuse on an account', async function () {
this.timeout(15000)
const account = await getAccountFromServer(servers[0].url, 'user_1', servers[0])
const reason = 'it is a bad account'
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, accountId: account.id, reason })
await waitJobs(servers)
})
it('Should have 1 account abuse on server 1 and 0 on server 2', async function () {
{
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'account' })
expect(res.body.total).to.equal(1)
expect(res.body.data).to.have.lengthOf(1)
const abuse: Abuse = res.body.data[0]
expect(abuse.reason).to.equal('it is a bad account')
expect(abuse.reporterAccount.name).to.equal('root')
expect(abuse.reporterAccount.host).to.equal(servers[0].host)
expect(abuse.video).to.be.null
expect(abuse.comment).to.be.null
expect(abuse.flaggedAccount.name).to.equal('user_1')
expect(abuse.flaggedAccount.host).to.equal(servers[0].host)
}
{
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
expect(res.body.total).to.equal(0)
expect(res.body.data.length).to.equal(0)
}
})
it('Should report abuse on a remote account', async function () {
this.timeout(10000)
const account = await getAccountFromServer(servers[0].url, 'user_2', servers[1])
const reason = 'it is a really bad account'
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, accountId: account.id, reason })
await waitJobs(servers)
})
it('Should have 2 comment abuses on server 1 and 1 on server 2', async function () {
const res1 = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'account' })
expect(res1.body.total).to.equal(2)
expect(res1.body.data.length).to.equal(2)
const abuse: Abuse = res1.body.data[0]
expect(abuse.reason).to.equal('it is a bad account')
const abuse2: Abuse = res1.body.data[1]
expect(abuse2.reason).to.equal('it is a really bad account')
expect(abuse2.reporterAccount.name).to.equal('root')
expect(abuse2.reporterAccount.host).to.equal(servers[0].host)
expect(abuse2.video).to.be.null
expect(abuse2.comment).to.be.null
expect(abuse2.state.id).to.equal(AbuseState.PENDING)
expect(abuse2.state.label).to.equal('Pending')
expect(abuse2.moderationComment).to.be.null
const res2 = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'account' })
expect(res2.body.total).to.equal(1)
expect(res2.body.data.length).to.equal(1)
abuseServer2 = res2.body.data[0]
expect(abuseServer2.reason).to.equal('it is a really bad account')
expect(abuseServer2.reporterAccount.name).to.equal('root')
expect(abuseServer2.reporterAccount.host).to.equal(servers[0].host)
expect(abuseServer2.state.id).to.equal(AbuseState.PENDING)
expect(abuseServer2.state.label).to.equal('Pending')
expect(abuseServer2.moderationComment).to.be.null
})
it('Should keep the account abuse when deleting the account', async function () {
this.timeout(10000)
const account = await getAccountFromServer(servers[1].url, 'user_2', servers[1])
await removeUser(servers[1].url, account.userId, servers[1].accessToken)
await waitJobs(servers)
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'account' })
expect(res.body.total).to.equal(2)
expect(res.body.data).to.have.lengthOf(2)
const abuse = (res.body.data as Abuse[]).find(a => a.reason === 'it is a really bad account')
expect(abuse).to.not.be.undefined
})
it('Should delete the account abuse', async function () {
this.timeout(10000)
await deleteAbuse(servers[1].url, servers[1].accessToken, abuseServer2.id)
await waitJobs(servers)
{
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'account' })
expect(res.body.total).to.equal(0)
expect(res.body.data.length).to.equal(0)
}
{
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'account' })
expect(res.body.total).to.equal(2)
abuseServer1 = res.body.data[0]
}
})
})
describe('Common actions on abuses', function () {
it('Should update the state of an abuse', async function () {
const body = { state: AbuseState.REJECTED }
await updateAbuse(servers[0].url, servers[0].accessToken, abuseServer1.id, body)
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, id: abuseServer1.id })
expect(res.body.data[0].state.id).to.equal(AbuseState.REJECTED)
})
it('Should add a moderation comment', async function () {
const body = { state: AbuseState.ACCEPTED, moderationComment: 'It is valid' }
await updateAbuse(servers[0].url, servers[0].accessToken, abuseServer1.id, body)
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, id: abuseServer1.id })
expect(res.body.data[0].state.id).to.equal(AbuseState.ACCEPTED)
expect(res.body.data[0].moderationComment).to.equal('It is valid')
})
})
after(async function () {
await cleanupTests(servers)

View File

@ -3,10 +3,16 @@
import 'mocha'
import { v4 as uuidv4 } from 'uuid'
import {
addVideoCommentThread,
addVideoToBlacklist,
cleanupTests,
createUser,
follow,
generateUserAccessToken,
getAccount,
getCustomConfig,
getVideoCommentThreads,
getVideoIdFromUUID,
immutableAssign,
MockInstancesIndex,
registerUser,
@ -23,7 +29,9 @@ import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
import {
checkAutoInstanceFollowing,
CheckerBaseParams,
checkNewAccountAbuseForModerators,
checkNewBlacklistOnMyVideo,
checkNewCommentAbuseForModerators,
checkNewInstanceFollower,
checkNewVideoAbuseForModerators,
checkNewVideoFromSubscription,
@ -91,11 +99,74 @@ describe('Test moderation notifications', function () {
await waitJobs(servers)
await reportAbuse({ url: servers[1].url, token: servers[1].accessToken, videoId: video.id, reason: 'super reason' })
const videoId = await getVideoIdFromUUID(servers[1].url, video.uuid)
await reportAbuse({ url: servers[1].url, token: servers[1].accessToken, videoId, reason: 'super reason' })
await waitJobs(servers)
await checkNewVideoAbuseForModerators(baseParams, video.uuid, name, 'presence')
})
it('Should send a notification to moderators on local comment abuse', async function () {
this.timeout(10000)
const name = 'video for abuse ' + uuidv4()
const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
const video = resVideo.body.video
const resComment = await addVideoCommentThread(servers[0].url, userAccessToken, video.id, 'comment abuse ' + uuidv4())
const comment = resComment.body.comment
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, commentId: comment.id, reason: 'super reason' })
await waitJobs(servers)
await checkNewCommentAbuseForModerators(baseParams, video.uuid, name, 'presence')
})
it('Should send a notification to moderators on remote comment abuse', async function () {
this.timeout(10000)
const name = 'video for abuse ' + uuidv4()
const resVideo = await uploadVideo(servers[0].url, userAccessToken, { name })
const video = resVideo.body.video
await addVideoCommentThread(servers[0].url, userAccessToken, video.id, 'comment abuse ' + uuidv4())
await waitJobs(servers)
const resComments = await getVideoCommentThreads(servers[1].url, video.uuid, 0, 5)
const commentId = resComments.body.data[0].id
await reportAbuse({ url: servers[1].url, token: servers[1].accessToken, commentId, reason: 'super reason' })
await waitJobs(servers)
await checkNewCommentAbuseForModerators(baseParams, video.uuid, name, 'presence')
})
it('Should send a notification to moderators on local account abuse', async function () {
this.timeout(10000)
const username = 'user' + new Date().getTime()
const resUser = await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username, password: 'donald' })
const accountId = resUser.body.user.account.id
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, accountId, reason: 'super reason' })
await waitJobs(servers)
await checkNewAccountAbuseForModerators(baseParams, username, 'presence')
})
it('Should send a notification to moderators on remote account abuse', async function () {
this.timeout(10000)
const username = 'user' + new Date().getTime()
const tmpToken = await generateUserAccessToken(servers[0], username)
await uploadVideo(servers[0].url, tmpToken, { name: 'super video' })
await waitJobs(servers)
const resAccount = await getAccount(servers[1].url, username + '@' + servers[0].host)
await reportAbuse({ url: servers[1].url, token: servers[1].accessToken, accountId: resAccount.body.id, reason: 'super reason' })
await waitJobs(servers)
await checkNewAccountAbuseForModerators(baseParams, username, 'presence')
})
})
describe('Video blacklist on my video', function () {

View File

@ -180,7 +180,7 @@ describe('Test emails', function () {
})
})
describe('When creating a video abuse', function () {
describe('When creating an abuse', function () {
it('Should send the notification email', async function () {
this.timeout(10000)

View File

@ -53,7 +53,7 @@ export module UserNotificationIncludes {
Pick<VideoCommentAbuseModel, 'id'> &
PickWith<VideoCommentAbuseModel, 'VideoComment',
Pick<VideoCommentModel, 'id' | 'originCommentId' | 'getThreadId'> &
PickWith<VideoCommentModel, 'Video', Pick<VideoModel, 'uuid'>>>
PickWith<VideoCommentModel, 'Video', Pick<VideoModel, 'id' | 'name' | 'uuid'>>>
export type AbuseInclude =
Pick<AbuseModel, 'id'> &

View File

@ -91,7 +91,6 @@ declare module 'express' {
accountVideoRate?: MAccountVideoRateAccountVideo
videoComment?: MComment
videoCommentFull?: MCommentOwnerVideoReply
videoCommentThread?: MComment

View File

@ -57,10 +57,15 @@ function reportAbuse (options: {
function getAbusesList (options: {
url: string
token: string
start?: number
count?: number
sort?: string
id?: number
predefinedReason?: AbusePredefinedReasonsString
search?: string
filter?: AbuseFilter,
filter?: AbuseFilter
state?: AbuseState
videoIs?: AbuseVideoIs
searchReporter?: string
@ -71,6 +76,9 @@ function getAbusesList (options: {
const {
url,
token,
start,
count,
sort,
id,
predefinedReason,
search,
@ -85,13 +93,15 @@ function getAbusesList (options: {
const path = '/api/v1/abuses'
const query = {
sort: 'createdAt',
id,
predefinedReason,
search,
state,
filter,
videoIs,
start,
count,
sort: sort || 'createdAt',
searchReporter,
searchReportee,
searchVideo,

View File

@ -37,8 +37,8 @@ interface ServerInfo {
video?: {
id: number
uuid: string
name: string
account: {
name?: string
account?: {
name: string
}
}

View File

@ -139,13 +139,17 @@ async function checkNotification (
}
function checkVideo (video: any, videoName?: string, videoUUID?: string) {
if (videoName) {
expect(video.name).to.be.a('string')
expect(video.name).to.not.be.empty
if (videoName) expect(video.name).to.equal(videoName)
expect(video.name).to.equal(videoName)
}
if (videoUUID) {
expect(video.uuid).to.be.a('string')
expect(video.uuid).to.not.be.empty
if (videoUUID) expect(video.uuid).to.equal(videoUUID)
expect(video.uuid).to.equal(videoUUID)
}
expect(video.id).to.be.a('number')
}
@ -436,7 +440,7 @@ async function checkNewCommentOnMyVideo (base: CheckerBaseParams, uuid: string,
}
async function checkNewVideoAbuseForModerators (base: CheckerBaseParams, videoUUID: string, videoName: string, type: CheckerType) {
const notificationType = UserNotificationType.NEW_VIDEO_ABUSE_FOR_MODERATORS
const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
function notificationChecker (notification: UserNotification, type: CheckerType) {
if (type === 'presence') {
@ -460,6 +464,56 @@ async function checkNewVideoAbuseForModerators (base: CheckerBaseParams, videoUU
await checkNotification(base, notificationChecker, emailNotificationFinder, type)
}
async function checkNewCommentAbuseForModerators (base: CheckerBaseParams, videoUUID: string, videoName: string, type: CheckerType) {
const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
function notificationChecker (notification: UserNotification, type: CheckerType) {
if (type === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
expect(notification.abuse.id).to.be.a('number')
checkVideo(notification.abuse.comment.video, videoName, videoUUID)
} else {
expect(notification).to.satisfy((n: UserNotification) => {
return n === undefined || n.abuse === undefined || n.abuse.comment.video.uuid !== videoUUID
})
}
}
function emailNotificationFinder (email: object) {
const text = email['text']
return text.indexOf(videoUUID) !== -1 && text.indexOf('abuse') !== -1
}
await checkNotification(base, notificationChecker, emailNotificationFinder, type)
}
async function checkNewAccountAbuseForModerators (base: CheckerBaseParams, displayName: string, type: CheckerType) {
const notificationType = UserNotificationType.NEW_ABUSE_FOR_MODERATORS
function notificationChecker (notification: UserNotification, type: CheckerType) {
if (type === 'presence') {
expect(notification).to.not.be.undefined
expect(notification.type).to.equal(notificationType)
expect(notification.abuse.id).to.be.a('number')
expect(notification.abuse.account.displayName).to.equal(displayName)
} else {
expect(notification).to.satisfy((n: UserNotification) => {
return n === undefined || n.abuse === undefined || n.abuse.account.displayName !== displayName
})
}
}
function emailNotificationFinder (email: object) {
const text = email['text']
return text.indexOf(displayName) !== -1 && text.indexOf('abuse') !== -1
}
await checkNotification(base, notificationChecker, emailNotificationFinder, type)
}
async function checkVideoAutoBlacklistForModerators (base: CheckerBaseParams, videoUUID: string, videoName: string, type: CheckerType) {
const notificationType = UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
@ -541,6 +595,9 @@ async function prepareNotificationsTest (serversCount = 3) {
smtp: {
hostname: 'localhost',
port
},
signup: {
limit: 20
}
}
const servers = await flushAndRunMultipleServers(serversCount, overrideConfig)
@ -623,5 +680,7 @@ export {
markAsReadNotifications,
getLastNotification,
checkNewInstanceFollower,
prepareNotificationsTest
prepareNotificationsTest,
checkNewCommentAbuseForModerators,
checkNewAccountAbuseForModerators
}

View File

@ -3,7 +3,7 @@ import { FollowState } from '../actors'
export enum UserNotificationType {
NEW_VIDEO_FROM_SUBSCRIPTION = 1,
NEW_COMMENT_ON_MY_VIDEO = 2,
NEW_VIDEO_ABUSE_FOR_MODERATORS = 3,
NEW_ABUSE_FOR_MODERATORS = 3,
BLACKLIST_ON_MY_VIDEO = 4,
UNBLACKLIST_ON_MY_VIDEO = 5,

View File

@ -106,9 +106,9 @@ tags:
Managing plugins installed from a local path or from NPM, or search for new ones.
externalDocs:
url: https://docs.joinpeertube.org/#/api-plugins
- name: Video Abuses
- name: Abuses
description: |
Video abuses deal with reports of local or remote videos alike.
Abuses deal with reports of local or remote videos/comments/accounts alike.
- name: Video
description: |
Operations dealing with listing, uploading, fetching or modifying videos.
@ -166,7 +166,7 @@ x-tagGroups:
- Search
- name: Moderation
tags:
- Video Abuses
- Abuses
- Video Blocks
- Account Blocks
- Server Blocks
@ -1474,13 +1474,13 @@ paths:
/videos/abuse:
get:
deprecated: true
summary: List video abuses
summary: List abuses
security:
- OAuth2:
- admin
- moderator
tags:
- Video Abuses
- Abuses
parameters:
- name: id
in: query
@ -1508,7 +1508,7 @@ paths:
type: string
- name: state
in: query
description: 'The video playlist privacy (Pending = `1`, Rejected = `2`, Accepted = `3`)'
description: 'The abuse state (Pending = `1`, Rejected = `2`, Accepted = `3`)'
schema:
type: integer
enum:
@ -1554,7 +1554,7 @@ paths:
security:
- OAuth2: []
tags:
- Video Abuses
- Abuses
- Videos
parameters:
- $ref: '#/components/parameters/idOrUUID'
@ -1607,7 +1607,7 @@ paths:
- admin
- moderator
tags:
- Video Abuses
- Abuses
parameters:
- $ref: '#/components/parameters/idOrUUID'
- $ref: '#/components/parameters/abuseId'
@ -1626,11 +1626,11 @@ paths:
'204':
description: successful operation
'404':
description: video abuse not found
description: abuse not found
delete:
deprecated: true
tags:
- Video Abuses
- Abuses
summary: Delete an abuse
security:
- OAuth2:
@ -3320,7 +3320,7 @@ components:
name: abuseId
in: path
required: true
description: Video abuse id
description: Abuse id
schema:
type: integer
captionLanguage:
@ -5098,7 +5098,7 @@ components:
- `2` NEW_COMMENT_ON_MY_VIDEO
- `3` NEW_VIDEO_ABUSE_FOR_MODERATORS
- `3` NEW_ABUSE_FOR_MODERATORS
- `4` BLACKLIST_ON_MY_VIDEO