Add new abuses tests
This commit is contained in:
parent
811cef146c
commit
310b5219b3
|
@ -138,8 +138,8 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="6">
|
<td colspan="6">
|
||||||
<div class="no-results">
|
<div class="no-results">
|
||||||
<ng-container *ngIf="search" i18n>No video abuses found matching current filters.</ng-container>
|
<ng-container *ngIf="search" i18n>No 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.</ng-container>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -118,7 +118,7 @@ export class UserNotification implements UserNotificationServer {
|
||||||
this.commentUrl = [ this.buildVideoUrl(this.comment.video), { threadId: this.comment.threadId } ]
|
this.commentUrl = [ this.buildVideoUrl(this.comment.video), { threadId: this.comment.threadId } ]
|
||||||
break
|
break
|
||||||
|
|
||||||
case UserNotificationType.NEW_VIDEO_ABUSE_FOR_MODERATORS:
|
case UserNotificationType.NEW_ABUSE_FOR_MODERATORS:
|
||||||
this.abuseUrl = '/admin/moderation/abuses/list'
|
this.abuseUrl = '/admin/moderation/abuses/list'
|
||||||
|
|
||||||
if (this.abuse.video) this.videoUrl = this.buildVideoUrl(this.abuse.video)
|
if (this.abuse.video) this.videoUrl = this.buildVideoUrl(this.abuse.video)
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</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>
|
<my-global-icon iconName="flag" aria-hidden="true"></my-global-icon>
|
||||||
|
|
||||||
<div class="message" i18n>
|
<div class="message" i18n>
|
||||||
|
|
|
@ -140,7 +140,6 @@ export class VideoReportComponent extends FormReactive implements OnInit {
|
||||||
const { hasStart, startAt, hasEnd, endAt } = this.form.get('timestamp').value
|
const { hasStart, startAt, hasEnd, endAt } = this.form.get('timestamp').value
|
||||||
|
|
||||||
this.abuseService.reportVideo({
|
this.abuseService.reportVideo({
|
||||||
accountId: this.video.account.id,
|
|
||||||
reason,
|
reason,
|
||||||
predefinedReasons,
|
predefinedReasons,
|
||||||
video: {
|
video: {
|
||||||
|
|
|
@ -100,7 +100,7 @@ async function updateAbuse (req: express.Request, res: express.Response) {
|
||||||
return abuse.save({ transaction: t })
|
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()
|
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 })
|
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()
|
return res.type('json').status(204).end()
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,5 @@ async function removeUserHistory (req: express.Request, res: express.Response) {
|
||||||
return UserVideoHistoryModel.removeUserHistoryBefore(user, beforeDate, t)
|
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()
|
return res.type('json').status(204).end()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@ import { AbuseFilter, abusePredefinedReasonsMap, AbusePredefinedReasonsString, A
|
||||||
import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants'
|
import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants'
|
||||||
import { exists, isArray } from './misc'
|
import { exists, isArray } from './misc'
|
||||||
|
|
||||||
const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.ABUSES
|
const ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.ABUSES
|
||||||
|
|
||||||
function isAbuseReasonValid (value: string) {
|
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) {
|
function isAbusePredefinedReasonValid (value: AbusePredefinedReasonsString) {
|
||||||
|
@ -32,7 +32,7 @@ function isAbuseTimestampCoherent (endAt: number, { req }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAbuseModerationCommentValid (value: string) {
|
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) {
|
function isAbuseStateValid (value: string) {
|
||||||
|
|
|
@ -68,7 +68,7 @@ async function doesVideoCommentExist (idArg: number | string, video: MVideoId, r
|
||||||
|
|
||||||
async function doesCommentIdExist (idArg: number | string, res: express.Response) {
|
async function doesCommentIdExist (idArg: number | string, res: express.Response) {
|
||||||
const id = parseInt(idArg + '', 10)
|
const id = parseInt(idArg + '', 10)
|
||||||
const videoComment = await VideoCommentModel.loadById(id)
|
const videoComment = await VideoCommentModel.loadByIdAndPopulateVideoAndAccountAndReply(id)
|
||||||
|
|
||||||
if (!videoComment) {
|
if (!videoComment) {
|
||||||
res.status(404)
|
res.status(404)
|
||||||
|
@ -77,7 +77,7 @@ async function doesCommentIdExist (idArg: number | string, res: express.Response
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
res.locals.videoComment = videoComment
|
res.locals.videoCommentFull = videoComment
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ async function doesAbuseExist (abuseId: number | string, res: Response) {
|
||||||
|
|
||||||
if (!abuse) {
|
if (!abuse) {
|
||||||
res.status(404)
|
res.status(404)
|
||||||
.json({ error: 'Video abuse not found' })
|
.json({ error: 'Abuse not found' })
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,12 +43,10 @@ async function up (utils: {
|
||||||
await utils.sequelize.query(`
|
await utils.sequelize.query(`
|
||||||
CREATE TABLE IF NOT EXISTS "commentAbuse" (
|
CREATE TABLE IF NOT EXISTS "commentAbuse" (
|
||||||
"id" serial,
|
"id" serial,
|
||||||
"deletedComment" jsonb DEFAULT NULL,
|
|
||||||
"abuseId" integer NOT NULL REFERENCES "abuse" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
|
"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,
|
"videoCommentId" integer REFERENCES "videoComment" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
|
||||||
"createdAt" timestamp WITH time zone NOT NULL,
|
"createdAt" timestamp WITH time zone NOT NULL,
|
||||||
"updatedAt" 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")
|
PRIMARY KEY ("id")
|
||||||
);
|
);
|
||||||
`)
|
`)
|
||||||
|
|
|
@ -325,6 +325,7 @@ class Emailer {
|
||||||
subject: `New comment abuse report from ${reporter}`,
|
subject: `New comment abuse report from ${reporter}`,
|
||||||
locals: {
|
locals: {
|
||||||
commentUrl,
|
commentUrl,
|
||||||
|
videoName: comment.Video.name,
|
||||||
isLocal: comment.isOwned(),
|
isLocal: comment.isOwned(),
|
||||||
commentCreatedAt: new Date(comment.createdAt).toLocaleString(),
|
commentCreatedAt: new Date(comment.createdAt).toLocaleString(),
|
||||||
reason: abuse.reason,
|
reason: abuse.reason,
|
||||||
|
|
|
@ -7,7 +7,8 @@ block title
|
||||||
block content
|
block content
|
||||||
p
|
p
|
||||||
| #[a(href=WEBSERVER.URL) #{WEBSERVER.HOST}] received an abuse report for the #{isLocal ? '' : 'remote '}comment "
|
| #[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}
|
| created on #{commentCreatedAt}
|
||||||
|
|
||||||
p The reporter, #{reporter}, cited the following reason(s):
|
p The reporter, #{reporter}, cited the following reason(s):
|
||||||
|
|
|
@ -371,7 +371,7 @@ class Notifier {
|
||||||
|
|
||||||
async function notificationCreator (user: MUserWithNotificationSetting) {
|
async function notificationCreator (user: MUserWithNotificationSetting) {
|
||||||
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
const notification = await UserNotificationModel.create<UserNotificationModelForApi>({
|
||||||
type: UserNotificationType.NEW_VIDEO_ABUSE_FOR_MODERATORS,
|
type: UserNotificationType.NEW_ABUSE_FOR_MODERATORS,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
abuseId: abuse.id
|
abuseId: abuse.id
|
||||||
})
|
})
|
||||||
|
|
|
@ -128,7 +128,7 @@ const abuseListValidator = [
|
||||||
.custom(exists).withMessage('Should have a valid search'),
|
.custom(exists).withMessage('Should have a valid search'),
|
||||||
query('state')
|
query('state')
|
||||||
.optional()
|
.optional()
|
||||||
.custom(isAbuseStateValid).withMessage('Should have a valid video abuse state'),
|
.custom(isAbuseStateValid).withMessage('Should have a valid abuse state'),
|
||||||
query('videoIs')
|
query('videoIs')
|
||||||
.optional()
|
.optional()
|
||||||
.custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'),
|
.custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'),
|
||||||
|
|
|
@ -362,8 +362,8 @@ export class AbuseModel extends Model<AbuseModel> {
|
||||||
const countReportsForReporter = this.get('countReportsForReporter') as number
|
const countReportsForReporter = this.get('countReportsForReporter') as number
|
||||||
const countReportsForReportee = this.get('countReportsForReportee') as number
|
const countReportsForReportee = this.get('countReportsForReportee') as number
|
||||||
|
|
||||||
let video: VideoAbuse
|
let video: VideoAbuse = null
|
||||||
let comment: VideoCommentAbuse
|
let comment: VideoCommentAbuse = null
|
||||||
|
|
||||||
if (this.VideoAbuse) {
|
if (this.VideoAbuse) {
|
||||||
const abuseModel = this.VideoAbuse
|
const abuseModel = this.VideoAbuse
|
||||||
|
@ -391,13 +391,13 @@ export class AbuseModel extends Model<AbuseModel> {
|
||||||
|
|
||||||
if (this.VideoCommentAbuse) {
|
if (this.VideoCommentAbuse) {
|
||||||
const abuseModel = this.VideoCommentAbuse
|
const abuseModel = this.VideoCommentAbuse
|
||||||
const entity = abuseModel.VideoComment || abuseModel.deletedComment
|
const entity = abuseModel.VideoComment
|
||||||
|
|
||||||
comment = {
|
comment = {
|
||||||
id: entity.id,
|
id: entity.id,
|
||||||
text: entity.text,
|
text: entity.text ?? '',
|
||||||
|
|
||||||
deleted: !abuseModel.VideoComment,
|
deleted: entity.isDeleted(),
|
||||||
|
|
||||||
video: {
|
video: {
|
||||||
id: entity.Video.id,
|
id: entity.Video.id,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
|
import { BelongsTo, Column, CreatedAt, ForeignKey, Model, Table, UpdatedAt } from 'sequelize-typescript'
|
||||||
import { VideoComment } from '@shared/models'
|
|
||||||
import { VideoCommentModel } from '../video/video-comment'
|
import { VideoCommentModel } from '../video/video-comment'
|
||||||
import { AbuseModel } from './abuse'
|
import { AbuseModel } from './abuse'
|
||||||
|
|
||||||
|
@ -22,11 +21,6 @@ export class VideoCommentAbuseModel extends Model<VideoCommentAbuseModel> {
|
||||||
@UpdatedAt
|
@UpdatedAt
|
||||||
updatedAt: Date
|
updatedAt: Date
|
||||||
|
|
||||||
@AllowNull(true)
|
|
||||||
@Default(null)
|
|
||||||
@Column(DataType.JSONB)
|
|
||||||
deletedComment: VideoComment & { Video: { name: string, id: number, uuid: string }}
|
|
||||||
|
|
||||||
@ForeignKey(() => AbuseModel)
|
@ForeignKey(() => AbuseModel)
|
||||||
@Column
|
@Column
|
||||||
abuseId: number
|
abuseId: number
|
||||||
|
|
|
@ -109,7 +109,7 @@ function buildAccountInclude (required: boolean, withActor = false) {
|
||||||
required: true,
|
required: true,
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
attributes: [ 'uuid' ],
|
attributes: [ 'id', 'name', 'uuid' ],
|
||||||
model: VideoModel.unscoped(),
|
model: VideoModel.unscoped(),
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
|
@ -492,6 +492,8 @@ export class UserNotificationModel extends Model<UserNotificationModel> {
|
||||||
threadId: abuse.VideoCommentAbuse.VideoComment.getThreadId(),
|
threadId: abuse.VideoCommentAbuse.VideoComment.getThreadId(),
|
||||||
|
|
||||||
video: {
|
video: {
|
||||||
|
id: abuse.VideoCommentAbuse.VideoComment.Video.id,
|
||||||
|
name: abuse.VideoCommentAbuse.VideoComment.Video.name,
|
||||||
uuid: abuse.VideoCommentAbuse.VideoComment.Video.uuid
|
uuid: abuse.VideoCommentAbuse.VideoComment.Video.uuid
|
||||||
}
|
}
|
||||||
} : undefined
|
} : undefined
|
||||||
|
|
|
@ -3,7 +3,6 @@ import { uniq } from 'lodash'
|
||||||
import { FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction } from 'sequelize'
|
import { FindOptions, Op, Order, ScopeOptions, Sequelize, Transaction } from 'sequelize'
|
||||||
import {
|
import {
|
||||||
AllowNull,
|
AllowNull,
|
||||||
BeforeDestroy,
|
|
||||||
BelongsTo,
|
BelongsTo,
|
||||||
Column,
|
Column,
|
||||||
CreatedAt,
|
CreatedAt,
|
||||||
|
@ -16,7 +15,6 @@ import {
|
||||||
Table,
|
Table,
|
||||||
UpdatedAt
|
UpdatedAt
|
||||||
} from 'sequelize-typescript'
|
} from 'sequelize-typescript'
|
||||||
import { logger } from '@server/helpers/logger'
|
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
import { MAccount, MAccountId, MUserAccountId } from '@server/types/models'
|
import { MAccount, MAccountId, MUserAccountId } from '@server/types/models'
|
||||||
import { VideoPrivacy } from '@shared/models'
|
import { VideoPrivacy } from '@shared/models'
|
||||||
|
@ -242,51 +240,13 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
|
||||||
|
|
||||||
@HasMany(() => VideoCommentAbuseModel, {
|
@HasMany(() => VideoCommentAbuseModel, {
|
||||||
foreignKey: {
|
foreignKey: {
|
||||||
name: 'commentId',
|
name: 'videoCommentId',
|
||||||
allowNull: true
|
allowNull: true
|
||||||
},
|
},
|
||||||
onDelete: 'set null'
|
onDelete: 'set null'
|
||||||
})
|
})
|
||||||
CommentAbuses: VideoCommentAbuseModel[]
|
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> {
|
static loadById (id: number, t?: Transaction): Bluebird<MComment> {
|
||||||
const query: FindOptions = {
|
const query: FindOptions = {
|
||||||
where: {
|
where: {
|
||||||
|
|
|
@ -21,9 +21,7 @@ import {
|
||||||
checkBadStartPagination
|
checkBadStartPagination
|
||||||
} from '../../../../shared/extra-utils/requests/check-api-params'
|
} from '../../../../shared/extra-utils/requests/check-api-params'
|
||||||
|
|
||||||
// FIXME: deprecated in 2.3. Remove this controller
|
describe('Test abuses API validators', function () {
|
||||||
|
|
||||||
describe('Test video abuses API validators', function () {
|
|
||||||
const basePath = '/api/v1/abuses/'
|
const basePath = '/api/v1/abuses/'
|
||||||
|
|
||||||
let server: ServerInfo
|
let server: ServerInfo
|
||||||
|
|
|
@ -2,21 +2,30 @@
|
||||||
|
|
||||||
import 'mocha'
|
import 'mocha'
|
||||||
import * as chai from 'chai'
|
import * as chai from 'chai'
|
||||||
import { Abuse, AbusePredefinedReasonsString, AbuseState } from '@shared/models'
|
import { Abuse, AbuseFilter, AbusePredefinedReasonsString, AbuseState, VideoComment, Account } from '@shared/models'
|
||||||
import {
|
import {
|
||||||
|
addVideoCommentThread,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createUser,
|
createUser,
|
||||||
deleteVideoAbuse,
|
deleteAbuse,
|
||||||
|
deleteVideoComment,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
getVideoAbusesList,
|
getAbusesList,
|
||||||
|
getVideoCommentThreads,
|
||||||
|
getVideoIdFromUUID,
|
||||||
getVideosList,
|
getVideosList,
|
||||||
|
immutableAssign,
|
||||||
removeVideo,
|
removeVideo,
|
||||||
reportVideoAbuse,
|
reportAbuse,
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
updateVideoAbuse,
|
updateAbuse,
|
||||||
uploadVideo,
|
uploadVideo,
|
||||||
userLogin
|
uploadVideoAndGetId,
|
||||||
|
userLogin,
|
||||||
|
getAccount,
|
||||||
|
removeUser,
|
||||||
|
generateUserAccessToken
|
||||||
} from '../../../../shared/extra-utils/index'
|
} from '../../../../shared/extra-utils/index'
|
||||||
import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
|
import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
|
||||||
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
||||||
|
@ -31,6 +40,7 @@ const expect = chai.expect
|
||||||
|
|
||||||
describe('Test abuses', function () {
|
describe('Test abuses', function () {
|
||||||
let servers: ServerInfo[] = []
|
let servers: ServerInfo[] = []
|
||||||
|
let abuseServer1: Abuse
|
||||||
let abuseServer2: Abuse
|
let abuseServer2: Abuse
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
|
@ -44,6 +54,12 @@ describe('Test abuses', function () {
|
||||||
|
|
||||||
// Server 1 and server 2 follow each other
|
// Server 1 and server 2 follow each other
|
||||||
await doubleFollow(servers[0], servers[1])
|
await doubleFollow(servers[0], servers[1])
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Video abuses', function () {
|
||||||
|
|
||||||
|
before(async function () {
|
||||||
|
this.timeout(50000)
|
||||||
|
|
||||||
// Upload some videos on each servers
|
// Upload some videos on each servers
|
||||||
const video1Attributes = {
|
const video1Attributes = {
|
||||||
|
@ -70,8 +86,8 @@ describe('Test abuses', function () {
|
||||||
servers[1].video = videos.find(video => video.name === 'my super name for server 2')
|
servers[1].video = videos.find(video => video.name === 'my super name for server 2')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not have video abuses', async function () {
|
it('Should not have abuses', async function () {
|
||||||
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(0)
|
expect(res.body.total).to.equal(0)
|
||||||
expect(res.body.data).to.be.an('array')
|
expect(res.body.data).to.be.an('array')
|
||||||
|
@ -82,14 +98,14 @@ describe('Test abuses', function () {
|
||||||
this.timeout(15000)
|
this.timeout(15000)
|
||||||
|
|
||||||
const reason = 'my super bad reason'
|
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
|
// We wait requests propagation, even if the server 1 is not supposed to make a request to server 2
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have 1 video abuses on server 1 and 0 on server 2', async function () {
|
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.total).to.equal(1)
|
||||||
expect(res1.body.data).to.be.an('array')
|
expect(res1.body.data).to.be.an('array')
|
||||||
|
@ -97,16 +113,25 @@ describe('Test abuses', function () {
|
||||||
|
|
||||||
const abuse: Abuse = res1.body.data[0]
|
const abuse: Abuse = res1.body.data[0]
|
||||||
expect(abuse.reason).to.equal('my super bad reason')
|
expect(abuse.reason).to.equal('my super bad reason')
|
||||||
|
|
||||||
expect(abuse.reporterAccount.name).to.equal('root')
|
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.id).to.equal(servers[0].video.id)
|
||||||
expect(abuse.video.channel).to.exist
|
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.countReportsForReporter).to.equal(1)
|
||||||
expect(abuse.countReportsForReportee).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.total).to.equal(0)
|
||||||
expect(res2.body.data).to.be.an('array')
|
expect(res2.body.data).to.be.an('array')
|
||||||
expect(res2.body.data.length).to.equal(0)
|
expect(res2.body.data.length).to.equal(0)
|
||||||
|
@ -116,86 +141,88 @@ describe('Test abuses', function () {
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
|
|
||||||
const reason = 'my super bad reason 2'
|
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
|
// We wait requests propagation
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have 2 video abuses on server 1 and 1 on server 2', async function () {
|
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.total).to.equal(2)
|
||||||
expect(res1.body.data).to.be.an('array')
|
|
||||||
expect(res1.body.data.length).to.equal(2)
|
expect(res1.body.data.length).to.equal(2)
|
||||||
|
|
||||||
const abuse1: Abuse = res1.body.data[0]
|
const abuse1: Abuse = res1.body.data[0]
|
||||||
expect(abuse1.reason).to.equal('my super bad reason')
|
expect(abuse1.reason).to.equal('my super bad reason')
|
||||||
expect(abuse1.reporterAccount.name).to.equal('root')
|
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.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.id).to.equal(AbuseState.PENDING)
|
||||||
expect(abuse1.state.label).to.equal('Pending')
|
expect(abuse1.state.label).to.equal('Pending')
|
||||||
expect(abuse1.moderationComment).to.be.null
|
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]
|
const abuse2: Abuse = res1.body.data[1]
|
||||||
expect(abuse2.reason).to.equal('my super bad reason 2')
|
expect(abuse2.reason).to.equal('my super bad reason 2')
|
||||||
|
|
||||||
expect(abuse2.reporterAccount.name).to.equal('root')
|
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.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.id).to.equal(AbuseState.PENDING)
|
||||||
expect(abuse2.state.label).to.equal('Pending')
|
expect(abuse2.state.label).to.equal('Pending')
|
||||||
expect(abuse2.moderationComment).to.be.null
|
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.total).to.equal(1)
|
||||||
expect(res2.body.data).to.be.an('array')
|
|
||||||
expect(res2.body.data.length).to.equal(1)
|
expect(res2.body.data.length).to.equal(1)
|
||||||
|
|
||||||
abuseServer2 = res2.body.data[0]
|
abuseServer2 = res2.body.data[0]
|
||||||
expect(abuseServer2.reason).to.equal('my super bad reason 2')
|
expect(abuseServer2.reason).to.equal('my super bad reason 2')
|
||||||
expect(abuseServer2.reporterAccount.name).to.equal('root')
|
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.id).to.equal(AbuseState.PENDING)
|
||||||
expect(abuseServer2.state.label).to.equal('Pending')
|
expect(abuseServer2.state.label).to.equal('Pending')
|
||||||
expect(abuseServer2.moderationComment).to.be.null
|
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 () {
|
it('Should hide video abuses from blocked accounts', async function () {
|
||||||
this.timeout(10000)
|
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)
|
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)
|
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)
|
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)
|
expect(res.body.total).to.equal(2)
|
||||||
|
|
||||||
const abuse = res.body.data.find(a => a.reason === 'will mute this')
|
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)
|
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)
|
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)
|
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)
|
expect(res.body.total).to.equal(2)
|
||||||
|
|
||||||
const abuse = res.body.data.find(a => a.reason === 'will mute this')
|
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)
|
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)
|
expect(res.body.total).to.equal(3)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -238,12 +265,12 @@ describe('Test abuses', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
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.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).to.have.lengthOf(2, "wrong number of videos returned")
|
||||||
expect(res.body.data[0].id).to.equal(abuseServer2.id, "wrong origin server id for first video")
|
|
||||||
|
|
||||||
const abuse: Abuse = res.body.data[0]
|
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.id).to.equal(abuseServer2.video.id, "wrong video id")
|
||||||
expect(abuse.video.channel).to.exist
|
expect(abuse.video.channel).to.exist
|
||||||
expect(abuse.video.deleted).to.be.true
|
expect(abuse.video.deleted).to.be.true
|
||||||
|
@ -270,24 +297,24 @@ describe('Test abuses', function () {
|
||||||
|
|
||||||
// resume with the test
|
// resume with the test
|
||||||
const reason3 = 'my super bad reason 3'
|
const reason3 = 'my super bad reason 3'
|
||||||
await reportVideoAbuse(servers[0].url, servers[0].accessToken, video3.id, reason3)
|
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, videoId: video3.id, reason: reason3 })
|
||||||
const reason4 = 'my super bad reason 4'
|
|
||||||
await reportVideoAbuse(servers[0].url, userAccessToken, servers[0].video.id, reason4)
|
|
||||||
|
|
||||||
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[]) {
|
const res2 = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||||
if (abuse.video.id === video3.id) {
|
const abuses = res2.body.data as Abuse[]
|
||||||
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")
|
const abuseVideo3 = res2.body.data.find(a => a.video.id === video3.id)
|
||||||
expect(abuse.countReportsForReportee).to.equal(1, "wrong reports count for reporter on video 3 abuse")
|
expect(abuseVideo3).to.not.be.undefined
|
||||||
expect(abuse.countReportsForReporter).to.equal(3, "wrong reports count for reportee on video 3 abuse")
|
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")
|
||||||
if (abuse.video.id === servers[0].video.id) {
|
expect(abuseVideo3.countReportsForReportee).to.equal(1, "wrong reports count for reporter on video 3 abuse")
|
||||||
expect(abuse.countReportsForReportee).to.equal(3, "wrong reports count for reporter on video 1 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 reason5 = 'my super bad reason 5'
|
||||||
const predefinedReasons5: AbusePredefinedReasonsString[] = [ 'violentOrRepulsive', 'captions' ]
|
const predefinedReasons5: AbusePredefinedReasonsString[] = [ 'violentOrRepulsive', 'captions' ]
|
||||||
const createdAbuse = (await reportVideoAbuse(
|
const createdAbuse = (await reportAbuse({
|
||||||
servers[0].url,
|
url: servers[0].url,
|
||||||
servers[0].accessToken,
|
token: servers[0].accessToken,
|
||||||
servers[0].video.id,
|
videoId: servers[0].video.id,
|
||||||
reason5,
|
reason: reason5,
|
||||||
predefinedReasons5,
|
predefinedReasons: predefinedReasons5,
|
||||||
1,
|
startAt: 1,
|
||||||
5
|
endAt: 5
|
||||||
)).body.abuse
|
})).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)
|
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 () {
|
it('Should delete the video abuse', async function () {
|
||||||
this.timeout(10000)
|
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)
|
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.total).to.equal(1)
|
||||||
expect(res.body.data.length).to.equal(1)
|
expect(res.body.data.length).to.equal(1)
|
||||||
expect(res.body.data[0].id).to.not.equal(abuseServer2.id)
|
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)
|
expect(res.body.total).to.equal(6)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should list and filter video abuses', async function () {
|
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 = {
|
const options = {
|
||||||
url: servers[0].url,
|
url: servers[0].url,
|
||||||
token: servers[0].accessToken
|
token: servers[0].accessToken
|
||||||
|
@ -346,7 +375,7 @@ describe('Test abuses', function () {
|
||||||
|
|
||||||
Object.assign(options, query)
|
Object.assign(options, query)
|
||||||
|
|
||||||
const res = await getVideoAbusesList(options)
|
const res = await getAbusesList(options)
|
||||||
|
|
||||||
return res.body.data as Abuse[]
|
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: 'violentOrRepulsive' })).to.have.lengthOf(1)
|
||||||
expect(await list({ predefinedReason: 'serverRules' })).to.have.lengthOf(0)
|
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 () {
|
after(async function () {
|
||||||
await cleanupTests(servers)
|
await cleanupTests(servers)
|
||||||
|
|
|
@ -3,10 +3,16 @@
|
||||||
import 'mocha'
|
import 'mocha'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import {
|
import {
|
||||||
|
addVideoCommentThread,
|
||||||
addVideoToBlacklist,
|
addVideoToBlacklist,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
|
createUser,
|
||||||
follow,
|
follow,
|
||||||
|
generateUserAccessToken,
|
||||||
|
getAccount,
|
||||||
getCustomConfig,
|
getCustomConfig,
|
||||||
|
getVideoCommentThreads,
|
||||||
|
getVideoIdFromUUID,
|
||||||
immutableAssign,
|
immutableAssign,
|
||||||
MockInstancesIndex,
|
MockInstancesIndex,
|
||||||
registerUser,
|
registerUser,
|
||||||
|
@ -23,7 +29,9 @@ import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
||||||
import {
|
import {
|
||||||
checkAutoInstanceFollowing,
|
checkAutoInstanceFollowing,
|
||||||
CheckerBaseParams,
|
CheckerBaseParams,
|
||||||
|
checkNewAccountAbuseForModerators,
|
||||||
checkNewBlacklistOnMyVideo,
|
checkNewBlacklistOnMyVideo,
|
||||||
|
checkNewCommentAbuseForModerators,
|
||||||
checkNewInstanceFollower,
|
checkNewInstanceFollower,
|
||||||
checkNewVideoAbuseForModerators,
|
checkNewVideoAbuseForModerators,
|
||||||
checkNewVideoFromSubscription,
|
checkNewVideoFromSubscription,
|
||||||
|
@ -91,11 +99,74 @@ describe('Test moderation notifications', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
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 waitJobs(servers)
|
||||||
await checkNewVideoAbuseForModerators(baseParams, video.uuid, name, 'presence')
|
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 () {
|
describe('Video blacklist on my video', function () {
|
||||||
|
|
|
@ -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 () {
|
it('Should send the notification email', async function () {
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ export module UserNotificationIncludes {
|
||||||
Pick<VideoCommentAbuseModel, 'id'> &
|
Pick<VideoCommentAbuseModel, 'id'> &
|
||||||
PickWith<VideoCommentAbuseModel, 'VideoComment',
|
PickWith<VideoCommentAbuseModel, 'VideoComment',
|
||||||
Pick<VideoCommentModel, 'id' | 'originCommentId' | 'getThreadId'> &
|
Pick<VideoCommentModel, 'id' | 'originCommentId' | 'getThreadId'> &
|
||||||
PickWith<VideoCommentModel, 'Video', Pick<VideoModel, 'uuid'>>>
|
PickWith<VideoCommentModel, 'Video', Pick<VideoModel, 'id' | 'name' | 'uuid'>>>
|
||||||
|
|
||||||
export type AbuseInclude =
|
export type AbuseInclude =
|
||||||
Pick<AbuseModel, 'id'> &
|
Pick<AbuseModel, 'id'> &
|
||||||
|
|
1
server/typings/express/index.d.ts
vendored
1
server/typings/express/index.d.ts
vendored
|
@ -91,7 +91,6 @@ declare module 'express' {
|
||||||
|
|
||||||
accountVideoRate?: MAccountVideoRateAccountVideo
|
accountVideoRate?: MAccountVideoRateAccountVideo
|
||||||
|
|
||||||
videoComment?: MComment
|
|
||||||
videoCommentFull?: MCommentOwnerVideoReply
|
videoCommentFull?: MCommentOwnerVideoReply
|
||||||
videoCommentThread?: MComment
|
videoCommentThread?: MComment
|
||||||
|
|
||||||
|
|
|
@ -57,10 +57,15 @@ function reportAbuse (options: {
|
||||||
function getAbusesList (options: {
|
function getAbusesList (options: {
|
||||||
url: string
|
url: string
|
||||||
token: string
|
token: string
|
||||||
|
|
||||||
|
start?: number
|
||||||
|
count?: number
|
||||||
|
sort?: string
|
||||||
|
|
||||||
id?: number
|
id?: number
|
||||||
predefinedReason?: AbusePredefinedReasonsString
|
predefinedReason?: AbusePredefinedReasonsString
|
||||||
search?: string
|
search?: string
|
||||||
filter?: AbuseFilter,
|
filter?: AbuseFilter
|
||||||
state?: AbuseState
|
state?: AbuseState
|
||||||
videoIs?: AbuseVideoIs
|
videoIs?: AbuseVideoIs
|
||||||
searchReporter?: string
|
searchReporter?: string
|
||||||
|
@ -71,6 +76,9 @@ function getAbusesList (options: {
|
||||||
const {
|
const {
|
||||||
url,
|
url,
|
||||||
token,
|
token,
|
||||||
|
start,
|
||||||
|
count,
|
||||||
|
sort,
|
||||||
id,
|
id,
|
||||||
predefinedReason,
|
predefinedReason,
|
||||||
search,
|
search,
|
||||||
|
@ -85,13 +93,15 @@ function getAbusesList (options: {
|
||||||
const path = '/api/v1/abuses'
|
const path = '/api/v1/abuses'
|
||||||
|
|
||||||
const query = {
|
const query = {
|
||||||
sort: 'createdAt',
|
|
||||||
id,
|
id,
|
||||||
predefinedReason,
|
predefinedReason,
|
||||||
search,
|
search,
|
||||||
state,
|
state,
|
||||||
filter,
|
filter,
|
||||||
videoIs,
|
videoIs,
|
||||||
|
start,
|
||||||
|
count,
|
||||||
|
sort: sort || 'createdAt',
|
||||||
searchReporter,
|
searchReporter,
|
||||||
searchReportee,
|
searchReportee,
|
||||||
searchVideo,
|
searchVideo,
|
||||||
|
|
|
@ -37,8 +37,8 @@ interface ServerInfo {
|
||||||
video?: {
|
video?: {
|
||||||
id: number
|
id: number
|
||||||
uuid: string
|
uuid: string
|
||||||
name: string
|
name?: string
|
||||||
account: {
|
account?: {
|
||||||
name: string
|
name: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,13 +139,17 @@ async function checkNotification (
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkVideo (video: any, videoName?: string, videoUUID?: string) {
|
function checkVideo (video: any, videoName?: string, videoUUID?: string) {
|
||||||
|
if (videoName) {
|
||||||
expect(video.name).to.be.a('string')
|
expect(video.name).to.be.a('string')
|
||||||
expect(video.name).to.not.be.empty
|
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.be.a('string')
|
||||||
expect(video.uuid).to.not.be.empty
|
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')
|
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) {
|
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) {
|
function notificationChecker (notification: UserNotification, type: CheckerType) {
|
||||||
if (type === 'presence') {
|
if (type === 'presence') {
|
||||||
|
@ -460,6 +464,56 @@ async function checkNewVideoAbuseForModerators (base: CheckerBaseParams, videoUU
|
||||||
await checkNotification(base, notificationChecker, emailNotificationFinder, type)
|
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) {
|
async function checkVideoAutoBlacklistForModerators (base: CheckerBaseParams, videoUUID: string, videoName: string, type: CheckerType) {
|
||||||
const notificationType = UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
|
const notificationType = UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS
|
||||||
|
|
||||||
|
@ -541,6 +595,9 @@ async function prepareNotificationsTest (serversCount = 3) {
|
||||||
smtp: {
|
smtp: {
|
||||||
hostname: 'localhost',
|
hostname: 'localhost',
|
||||||
port
|
port
|
||||||
|
},
|
||||||
|
signup: {
|
||||||
|
limit: 20
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const servers = await flushAndRunMultipleServers(serversCount, overrideConfig)
|
const servers = await flushAndRunMultipleServers(serversCount, overrideConfig)
|
||||||
|
@ -623,5 +680,7 @@ export {
|
||||||
markAsReadNotifications,
|
markAsReadNotifications,
|
||||||
getLastNotification,
|
getLastNotification,
|
||||||
checkNewInstanceFollower,
|
checkNewInstanceFollower,
|
||||||
prepareNotificationsTest
|
prepareNotificationsTest,
|
||||||
|
checkNewCommentAbuseForModerators,
|
||||||
|
checkNewAccountAbuseForModerators
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { FollowState } from '../actors'
|
||||||
export enum UserNotificationType {
|
export enum UserNotificationType {
|
||||||
NEW_VIDEO_FROM_SUBSCRIPTION = 1,
|
NEW_VIDEO_FROM_SUBSCRIPTION = 1,
|
||||||
NEW_COMMENT_ON_MY_VIDEO = 2,
|
NEW_COMMENT_ON_MY_VIDEO = 2,
|
||||||
NEW_VIDEO_ABUSE_FOR_MODERATORS = 3,
|
NEW_ABUSE_FOR_MODERATORS = 3,
|
||||||
|
|
||||||
BLACKLIST_ON_MY_VIDEO = 4,
|
BLACKLIST_ON_MY_VIDEO = 4,
|
||||||
UNBLACKLIST_ON_MY_VIDEO = 5,
|
UNBLACKLIST_ON_MY_VIDEO = 5,
|
||||||
|
|
|
@ -106,9 +106,9 @@ tags:
|
||||||
Managing plugins installed from a local path or from NPM, or search for new ones.
|
Managing plugins installed from a local path or from NPM, or search for new ones.
|
||||||
externalDocs:
|
externalDocs:
|
||||||
url: https://docs.joinpeertube.org/#/api-plugins
|
url: https://docs.joinpeertube.org/#/api-plugins
|
||||||
- name: Video Abuses
|
- name: Abuses
|
||||||
description: |
|
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
|
- name: Video
|
||||||
description: |
|
description: |
|
||||||
Operations dealing with listing, uploading, fetching or modifying videos.
|
Operations dealing with listing, uploading, fetching or modifying videos.
|
||||||
|
@ -166,7 +166,7 @@ x-tagGroups:
|
||||||
- Search
|
- Search
|
||||||
- name: Moderation
|
- name: Moderation
|
||||||
tags:
|
tags:
|
||||||
- Video Abuses
|
- Abuses
|
||||||
- Video Blocks
|
- Video Blocks
|
||||||
- Account Blocks
|
- Account Blocks
|
||||||
- Server Blocks
|
- Server Blocks
|
||||||
|
@ -1474,13 +1474,13 @@ paths:
|
||||||
/videos/abuse:
|
/videos/abuse:
|
||||||
get:
|
get:
|
||||||
deprecated: true
|
deprecated: true
|
||||||
summary: List video abuses
|
summary: List abuses
|
||||||
security:
|
security:
|
||||||
- OAuth2:
|
- OAuth2:
|
||||||
- admin
|
- admin
|
||||||
- moderator
|
- moderator
|
||||||
tags:
|
tags:
|
||||||
- Video Abuses
|
- Abuses
|
||||||
parameters:
|
parameters:
|
||||||
- name: id
|
- name: id
|
||||||
in: query
|
in: query
|
||||||
|
@ -1508,7 +1508,7 @@ paths:
|
||||||
type: string
|
type: string
|
||||||
- name: state
|
- name: state
|
||||||
in: query
|
in: query
|
||||||
description: 'The video playlist privacy (Pending = `1`, Rejected = `2`, Accepted = `3`)'
|
description: 'The abuse state (Pending = `1`, Rejected = `2`, Accepted = `3`)'
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
enum:
|
enum:
|
||||||
|
@ -1554,7 +1554,7 @@ paths:
|
||||||
security:
|
security:
|
||||||
- OAuth2: []
|
- OAuth2: []
|
||||||
tags:
|
tags:
|
||||||
- Video Abuses
|
- Abuses
|
||||||
- Videos
|
- Videos
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: '#/components/parameters/idOrUUID'
|
- $ref: '#/components/parameters/idOrUUID'
|
||||||
|
@ -1607,7 +1607,7 @@ paths:
|
||||||
- admin
|
- admin
|
||||||
- moderator
|
- moderator
|
||||||
tags:
|
tags:
|
||||||
- Video Abuses
|
- Abuses
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: '#/components/parameters/idOrUUID'
|
- $ref: '#/components/parameters/idOrUUID'
|
||||||
- $ref: '#/components/parameters/abuseId'
|
- $ref: '#/components/parameters/abuseId'
|
||||||
|
@ -1626,11 +1626,11 @@ paths:
|
||||||
'204':
|
'204':
|
||||||
description: successful operation
|
description: successful operation
|
||||||
'404':
|
'404':
|
||||||
description: video abuse not found
|
description: abuse not found
|
||||||
delete:
|
delete:
|
||||||
deprecated: true
|
deprecated: true
|
||||||
tags:
|
tags:
|
||||||
- Video Abuses
|
- Abuses
|
||||||
summary: Delete an abuse
|
summary: Delete an abuse
|
||||||
security:
|
security:
|
||||||
- OAuth2:
|
- OAuth2:
|
||||||
|
@ -3320,7 +3320,7 @@ components:
|
||||||
name: abuseId
|
name: abuseId
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: Video abuse id
|
description: Abuse id
|
||||||
schema:
|
schema:
|
||||||
type: integer
|
type: integer
|
||||||
captionLanguage:
|
captionLanguage:
|
||||||
|
@ -5098,7 +5098,7 @@ components:
|
||||||
|
|
||||||
- `2` NEW_COMMENT_ON_MY_VIDEO
|
- `2` NEW_COMMENT_ON_MY_VIDEO
|
||||||
|
|
||||||
- `3` NEW_VIDEO_ABUSE_FOR_MODERATORS
|
- `3` NEW_ABUSE_FOR_MODERATORS
|
||||||
|
|
||||||
- `4` BLACKLIST_ON_MY_VIDEO
|
- `4` BLACKLIST_ON_MY_VIDEO
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user