<a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:pending' }" class="dropdown-item" i18n>Unsolved reports</a>
<a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:accepted' }" class="dropdown-item" i18n>Accepted reports</a>
<a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'state:rejected' }" class="dropdown-item" i18n>Refused reports</a>
- <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'is:blacklisted' }" class="dropdown-item" i18n>Reports with blacklisted videos</a>
- <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'is:deleted' }" class="dropdown-item" i18n>Reports with deleted videos</a>
+ <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'videoIs:blacklisted' }" class="dropdown-item" i18n>Reports with blacklisted videos</a>
+ <a [routerLink]="[ '/admin/moderation/video-abuses/list' ]" [queryParams]="{ 'search': 'videoIs:deleted' }" class="dropdown-item" i18n>Reports with deleted videos</a>
</div>
</div>
<input
-import { Injectable } from '@angular/core'
-import { HttpParams } from '@angular/common/http'
import { SortMeta } from 'primeng/api'
-import { ComponentPagination, ComponentPaginationLight } from './component-pagination.model'
-
+import { HttpParams } from '@angular/common/http'
+import { Injectable } from '@angular/core'
+import { ComponentPaginationLight } from './component-pagination.model'
import { RestPagination } from './rest-pagination'
+interface QueryStringFilterPrefixes {
+ [key: string]: {
+ prefix: string
+ handler?: (v: string) => string | number
+ multiple?: boolean
+ }
+}
+
+type ParseQueryStringFilterResult = {
+ [key: string]: string | number | (string | number)[]
+}
+
@Injectable()
export class RestService {
return { start, count }
}
+
+ parseQueryStringFilter (q: string, prefixes: QueryStringFilterPrefixes): ParseQueryStringFilterResult {
+ if (!q) return {}
+
+ // Tokenize the strings using spaces
+ const tokens = q.split(' ').filter(token => !!token)
+
+ // Build prefix array
+ const prefixeStrings = Object.values(prefixes)
+ .map(p => p.prefix)
+
+ // Search is the querystring minus defined filters
+ const searchTokens = tokens.filter(t => {
+ return prefixeStrings.every(prefixString => t.startsWith(prefixString) === false)
+ })
+
+ const additionalFilters: ParseQueryStringFilterResult = {}
+
+ for (const prefixKey of Object.keys(prefixes)) {
+ const prefixObj = prefixes[prefixKey]
+ const prefix = prefixObj.prefix
+
+ const matchedTokens = tokens.filter(t => t.startsWith(prefix))
+ .map(t => t.slice(prefix.length)) // Keep the value filter
+ .map(t => {
+ if (prefixObj.handler) return prefixObj.handler(t)
+
+ return t
+ })
+ .filter(t => !!t)
+
+ if (matchedTokens.length === 0) continue
+
+ additionalFilters[prefixKey] = prefixObj.multiple === true
+ ? matchedTokens
+ : matchedTokens[0]
+ }
+
+ return {
+ search: searchTokens.join(' '),
+
+ ...additionalFilters
+ }
+ }
}
import { Injectable } from '@angular/core'
import { SortMeta } from 'primeng/api'
import { Observable } from 'rxjs'
-import { ResultList, VideoAbuse, VideoAbuseUpdate } from '../../../../../shared'
+import { ResultList, VideoAbuse, VideoAbuseUpdate, VideoAbuseState } from '../../../../../shared'
import { environment } from '../../../environments/environment'
import { RestExtractor, RestPagination, RestService } from '../rest'
let params = new HttpParams()
params = this.restService.addRestGetParams(params, pagination, sort)
- if (search) params = params.append('search', search)
+ if (search) {
+ const filters = this.restService.parseQueryStringFilter(search, {
+ id: { prefix: '#' },
+ state: {
+ prefix: 'state:',
+ handler: v => {
+ if (v === 'accepted') return VideoAbuseState.ACCEPTED
+ if (v === 'pending') return VideoAbuseState.PENDING
+ if (v === 'rejected') return VideoAbuseState.REJECTED
+
+ return undefined
+ }
+ },
+ videoIs: {
+ prefix: 'videoIs:',
+ handler: v => {
+ if (v === 'deleted') return v
+ if (v === 'blacklisted') return v
+
+ return undefined
+ }
+ },
+ searchReporter: { prefix: 'reporter:' },
+ searchReportee: { prefix: 'reportee:' }
+ })
+
+ params = this.restService.addObjectParams(params, filters)
+ }
return this.authHttp.get<ResultList<VideoAbuse>>(url, { params })
.pipe(
videoAbuseGetValidator,
videoAbuseReportValidator,
videoAbusesSortValidator,
- videoAbuseUpdateValidator
+ videoAbuseUpdateValidator,
+ videoAbuseListValidator
} from '../../../middlewares'
import { AccountModel } from '../../../models/account/account'
import { VideoAbuseModel } from '../../../models/video/video-abuse'
videoAbusesSortValidator,
setDefaultSort,
setDefaultPagination,
+ videoAbuseListValidator,
asyncMiddleware(listVideoAbuses)
)
abuseVideoRouter.put('/:videoId/abuse/:id',
start: req.query.start,
count: req.query.count,
sort: req.query.sort,
+ id: req.query.id,
search: req.query.search,
+ state: req.query.state,
+ videoIs: req.query.videoIs,
+ searchReporter: req.query.searchReporter,
+ searchReportee: req.query.searchReportee,
+ searchVideo: req.query.searchVideo,
+ searchVideoChannel: req.query.searchVideoChannel,
serverAccountId: serverActor.Account.id,
user
})
import validator from 'validator'
+
import { CONSTRAINTS_FIELDS, VIDEO_ABUSE_STATES } from '../../initializers/constants'
import { exists } from './misc'
+import { VideoAbuseVideoIs } from '@shared/models/videos/abuse/video-abuse-video-is.type'
const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
return exists(value) && VIDEO_ABUSE_STATES[value] !== undefined
}
+function isAbuseVideoIsValid (value: VideoAbuseVideoIs) {
+ return exists(value) && (
+ value === 'deleted' ||
+ value === 'blacklisted'
+ )
+}
+
// ---------------------------------------------------------------------------
export {
isVideoAbuseStateValid,
isVideoAbuseReasonValid,
+ isAbuseVideoIsValid,
isVideoAbuseModerationCommentValid
}
import * as express from 'express'
-import { body, param } from 'express-validator'
-import { isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc'
-import { logger } from '../../../helpers/logger'
-import { areValidationErrors } from '../utils'
+import { body, param, query } from 'express-validator'
+import { exists, isIdOrUUIDValid, isIdValid } from '../../../helpers/custom-validators/misc'
import {
+ isAbuseVideoIsValid,
isVideoAbuseModerationCommentValid,
isVideoAbuseReasonValid,
isVideoAbuseStateValid
} from '../../../helpers/custom-validators/video-abuses'
+import { logger } from '../../../helpers/logger'
import { doesVideoAbuseExist, doesVideoExist } from '../../../helpers/middlewares'
+import { areValidationErrors } from '../utils'
const videoAbuseReportValidator = [
param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
}
]
+const videoAbuseListValidator = [
+ query('id')
+ .optional()
+ .custom(isIdValid).withMessage('Should have a valid id'),
+ query('search')
+ .optional()
+ .custom(exists).withMessage('Should have a valid search'),
+ query('state')
+ .optional()
+ .custom(isVideoAbuseStateValid).withMessage('Should have a valid video abuse state'),
+ query('videoIs')
+ .optional()
+ .custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'),
+ query('searchReporter')
+ .optional()
+ .custom(exists).withMessage('Should have a valid reporter search'),
+ query('searchReportee')
+ .optional()
+ .custom(exists).withMessage('Should have a valid reportee search'),
+ query('searchVideo')
+ .optional()
+ .custom(exists).withMessage('Should have a valid video search'),
+ query('searchVideoChannel')
+ .optional()
+ .custom(exists).withMessage('Should have a valid video channel search'),
+
+ (req: express.Request, res: express.Response, next: express.NextFunction) => {
+ logger.debug('Checking videoAbuseListValidator parameters', { parameters: req.body })
+
+ if (areValidationErrors(req, res)) return
+
+ return next()
+ }
+]
+
// ---------------------------------------------------------------------------
export {
+ videoAbuseListValidator,
videoAbuseReportValidator,
videoAbuseGetValidator,
videoAbuseUpdateValidator
return { direction, field }
}
-function searchAttribute (sourceField, targetField) {
- if (sourceField) {
- return {
- [targetField]: {
- [Op.iLike]: `%${sourceField}%`
- }
- }
- } else {
- return {}
- }
-}
-
-interface QueryStringFilterPrefixes {
- [key: string]: string | { prefix: string, handler: Function, multiple?: boolean }
-}
-
-function parseQueryStringFilter (q: string, prefixes: QueryStringFilterPrefixes): {
- search: string
- [key: string]: string | number | string[] | number[]
-} {
- const tokens = q // tokenize only if we have a querystring
- ? [].concat.apply([], q.split('"').map((v, i) => i % 2 ? v : v.split(' '))).filter(Boolean) // split by space unless using double quotes
- : []
-
- const objectMap = (obj, fn) => Object.fromEntries(
- Object.entries(obj).map(
- ([ k, v ], i) => [ k, fn(v, k, i) ]
- )
- )
+function searchAttribute (sourceField?: string, targetField?: string) {
+ if (!sourceField) return {}
return {
- // search is the querystring minus defined filters
- search: tokens.filter(e => !Object.values(prefixes).some(p => {
- if (typeof p === 'string') {
- return e.startsWith(p)
- } else {
- return e.startsWith(p.prefix)
- }
- })).join(' '),
- // filters defined in prefixes are added under their own name
- ...objectMap(prefixes, p => {
- if (typeof p === 'string') {
- return tokens.filter(e => e.startsWith(p)).map(e => e.slice(p.length)) // we keep the matched item, and remove its prefix
- } else {
- const _tokens = tokens.filter(e => e.startsWith(p.prefix)).map(e => e.slice(p.prefix.length)).map(p.handler)
- // multiple is false by default, meaning we usually just keep the first occurence of a given prefix
- if (!p.multiple && _tokens.length > 0) {
- return _tokens[0]
- } else if (!p.multiple) {
- return ''
- }
- return _tokens
- }
- })
+ [targetField]: {
+ [Op.iLike]: `%${sourceField}%`
+ }
}
}
getFollowsSort,
buildDirectionAndField,
createSafeIn,
- searchAttribute,
- parseQueryStringFilter
+ searchAttribute
}
// ---------------------------------------------------------------------------
+import * as Bluebird from 'bluebird'
+import { literal, Op } from 'sequelize'
import {
- AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt, Scopes
+ AllowNull,
+ BelongsTo,
+ Column,
+ CreatedAt,
+ DataType,
+ Default,
+ ForeignKey,
+ Is,
+ Model,
+ Scopes,
+ Table,
+ UpdatedAt
} from 'sequelize-typescript'
+import { VideoAbuseVideoIs } from '@shared/models/videos/abuse/video-abuse-video-is.type'
+import { VideoAbuseState, VideoDetails } from '../../../shared'
import { VideoAbuseObject } from '../../../shared/models/activitypub/objects'
import { VideoAbuse } from '../../../shared/models/videos'
import {
isVideoAbuseReasonValid,
isVideoAbuseStateValid
} from '../../helpers/custom-validators/video-abuses'
-import { AccountModel } from '../account/account'
-import { buildBlockedAccountSQL, getSort, throwIfNotValid, searchAttribute, parseQueryStringFilter } from '../utils'
-import { VideoModel } from './video'
-import { VideoAbuseState, VideoDetails } from '../../../shared'
import { CONSTRAINTS_FIELDS, VIDEO_ABUSE_STATES } from '../../initializers/constants'
import { MUserAccountId, MVideoAbuse, MVideoAbuseFormattable, MVideoAbuseVideo } from '../../typings/models'
-import * as Bluebird from 'bluebird'
-import { literal, Op } from 'sequelize'
+import { AccountModel } from '../account/account'
+import { buildBlockedAccountSQL, getSort, searchAttribute, throwIfNotValid } from '../utils'
import { ThumbnailModel } from './thumbnail'
+import { VideoModel } from './video'
import { VideoBlacklistModel } from './video-blacklist'
import { ScopeNames as VideoChannelScopeNames, SummaryOptions, VideoChannelModel } from './video-channel'
// filters
id?: number
+
state?: VideoAbuseState
- is?: 'deleted' | 'blacklisted'
+ videoIs?: VideoAbuseVideoIs
// accountIds
serverAccountId: number
userAccountId: number
}) => {
- let where = {
+ const where = {
reporterAccountId: {
[Op.notIn]: literal('(' + buildBlockedAccountSQL(options.serverAccountId, options.userAccountId) + ')')
}
}
if (options.search) {
- where = Object.assign(where, {
+ Object.assign(where, {
[Op.or]: [
{
[Op.and]: [
})
}
- if (options.id) {
- where = Object.assign(where, {
- id: options.id
- })
- }
+ if (options.id) Object.assign(where, { id: options.id })
+ if (options.state) Object.assign(where, { state: options.state })
- if (options.state) {
- where = Object.assign(where, {
- state: options.state
+ if (options.videoIs === 'deleted') {
+ Object.assign(where, {
+ deletedVideo: {
+ [Op.not]: null
+ }
})
}
- let onlyBlacklisted = false
- if (options.is === 'deleted') {
- where = Object.assign(where, {
- deletedVideo: { [Op.not]: null }
- })
- } else if (options.is === 'blacklisted') {
- onlyBlacklisted = true
- }
+ const onlyBlacklisted = options.videoIs === 'blacklisted'
return {
attributes: {
},
{
model: VideoModel,
- required: onlyBlacklisted,
+ required: !!(onlyBlacklisted || options.searchVideo || options.searchReportee || options.searchVideoChannel),
where: searchAttribute(options.searchVideo, 'name'),
include: [
{
start: number
count: number
sort: string
- search?: string
+
serverAccountId: number
user?: MUserAccountId
+
+ id?: number
+ state?: VideoAbuseState
+ videoIs?: VideoAbuseVideoIs
+
+ search?: string
+ searchReporter?: string
+ searchReportee?: string
+ searchVideo?: string
+ searchVideoChannel?: string
}) {
- const { start, count, sort, search, user, serverAccountId } = parameters
+ const {
+ start,
+ count,
+ sort,
+ search,
+ user,
+ serverAccountId,
+ state,
+ videoIs,
+ searchReportee,
+ searchVideo,
+ searchVideoChannel,
+ searchReporter,
+ id
+ } = parameters
+
const userAccountId = user ? user.Account.id : undefined
const query = {
}
const filters = {
- ...parseQueryStringFilter(search, {
- id: {
- prefix: '#',
- handler: v => v
- },
- state: {
- prefix: 'state:',
- handler: v => {
- if (v === 'accepted') return VideoAbuseState.ACCEPTED
- if (v === 'pending') return VideoAbuseState.PENDING
- if (v === 'rejected') return VideoAbuseState.REJECTED
- return undefined
- }
- },
- is: {
- prefix: 'is:',
- handler: v => {
- if (v === 'deleted') return v
- if (v === 'blacklisted') return v
- return undefined
- }
- },
- searchReporter: {
- prefix: 'reporter:',
- handler: v => v
- },
- searchReportee: {
- prefix: 'reportee:',
- handler: v => v
- }
- }),
+ id,
+ search,
+ state,
+ videoIs,
+ searchReportee,
+ searchVideo,
+ searchVideoChannel,
+ searchReporter,
serverAccountId,
userAccountId
}
statusCodeExpected: 403
})
})
+
+ it('Should fail with a bad id filter', async function () {
+ await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { id: 'toto' } })
+ })
+
+ it('Should fail with a bad state filter', async function () {
+ await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { state: 'toto' } })
+ })
+
+ it('Should fail with a bad videoIs filter', async function () {
+ await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { videoIs: 'toto' } })
+ })
+
+ it('Should succeed with the correct params', async function () {
+ await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { id: 13 }, statusCodeExpected: 200 })
+ })
})
describe('When reporting a video abuse', function () {
const reason = 'my super bad reason'
await reportVideoAbuse(server.url, user17AccessToken, videoId, reason)
- const res1 = await getVideoAbusesList(server.url, server.accessToken)
+ const res1 = await getVideoAbusesList({ url: server.url, token: server.accessToken })
const abuseId = res1.body.data[0].id
const res2 = await getUserInformation(server.url, server.accessToken, user17Id, true)
})
it('Should not have video abuses', async function () {
- const res = await getVideoAbusesList(servers[0].url, servers[0].accessToken)
+ const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(0)
expect(res.body.data).to.be.an('array')
})
it('Should have 1 video abuses on server 1 and 0 on server 2', async function () {
- const res1 = await getVideoAbusesList(servers[0].url, servers[0].accessToken)
+ const res1 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res1.body.total).to.equal(1)
expect(res1.body.data).to.be.an('array')
expect(abuse.countReportsForReporter).to.equal(1)
expect(abuse.countReportsForReportee).to.equal(1)
- const res2 = await getVideoAbusesList(servers[1].url, servers[1].accessToken)
+ const res2 = await getVideoAbusesList({ 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)
})
it('Should have 2 video abuses on server 1 and 1 on server 2', async function () {
- const res1 = await getVideoAbusesList(servers[0].url, servers[0].accessToken)
+ const res1 = await getVideoAbusesList({ 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)
expect(abuse2.state.label).to.equal('Pending')
expect(abuse2.moderationComment).to.be.null
- const res2 = await getVideoAbusesList(servers[1].url, servers[1].accessToken)
+ const res2 = await getVideoAbusesList({ 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)
const body = { state: VideoAbuseState.REJECTED }
await updateVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id, body)
- const res = await getVideoAbusesList(servers[1].url, servers[1].accessToken)
+ const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
expect(res.body.data[0].state.id).to.equal(VideoAbuseState.REJECTED)
})
const body = { state: VideoAbuseState.ACCEPTED, moderationComment: 'It is valid' }
await updateVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id, body)
- const res = await getVideoAbusesList(servers[1].url, servers[1].accessToken)
+ const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken })
expect(res.body.data[0].state.id).to.equal(VideoAbuseState.ACCEPTED)
expect(res.body.data[0].moderationComment).to.equal('It is valid')
})
await reportVideoAbuse(servers[1].url, servers[1].accessToken, servers[0].video.uuid, 'will mute this')
await waitJobs(servers)
- const res = await getVideoAbusesList(servers[0].url, servers[0].accessToken)
+ const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(3)
}
{
await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
- const res = await getVideoAbusesList(servers[0].url, servers[0].accessToken)
+ const res = await getVideoAbusesList({ 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')
{
await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
- const res = await getVideoAbusesList(servers[0].url, servers[0].accessToken)
+ const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(3)
}
})
{
await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, servers[1].host)
- const res = await getVideoAbusesList(servers[0].url, servers[0].accessToken)
+ const res = await getVideoAbusesList({ 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')
{
await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, serverToBlock)
- const res = await getVideoAbusesList(servers[0].url, servers[0].accessToken)
+ const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(3)
}
})
await waitJobs(servers)
- const res = await getVideoAbusesList(servers[1].url, servers[1].accessToken)
+ const res = await getVideoAbusesList({ 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")
const reason4 = 'my super bad reason 4'
await reportVideoAbuse(servers[0].url, userAccessToken, servers[0].video.id, reason4)
- const res2 = await getVideoAbusesList(servers[0].url, servers[0].accessToken)
+ const res2 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
{
for (const abuse of res2.body.data as VideoAbuse[]) {
await waitJobs(servers)
{
- const res = await getVideoAbusesList(servers[1].url, servers[1].accessToken)
+ const res = await getVideoAbusesList({ 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(servers[0].url, servers[0].accessToken)
+ const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
expect(res.body.total).to.equal(5)
}
})
+ it('Should list and filter video abuses', async function () {
+ async function list (query: Omit<Parameters<typeof getVideoAbusesList>[0], 'url' | 'token'>) {
+ const options = {
+ url: servers[0].url,
+ token: servers[0].accessToken
+ }
+
+ Object.assign(options, query)
+
+ const res = await getVideoAbusesList(options)
+
+ return res.body.data as VideoAbuse[]
+ }
+
+ expect(await list({ id: 56 })).to.have.lengthOf(0)
+ expect(await list({ id: 1 })).to.have.lengthOf(1)
+
+ expect(await list({ search: 'my super name for server 1' })).to.have.lengthOf(3)
+ expect(await list({ search: 'aaaaaaaaaaaaaaaaaaaaaaaaaa' })).to.have.lengthOf(0)
+
+ expect(await list({ searchVideo: 'my second super name for server 1' })).to.have.lengthOf(1)
+
+ expect(await list({ searchVideoChannel: 'root' })).to.have.lengthOf(3)
+ expect(await list({ searchVideoChannel: 'aaaa' })).to.have.lengthOf(0)
+
+ expect(await list({ searchReporter: 'user2' })).to.have.lengthOf(1)
+ expect(await list({ searchReporter: 'root' })).to.have.lengthOf(4)
+
+ expect(await list({ searchReportee: 'root' })).to.have.lengthOf(3)
+ expect(await list({ searchReportee: 'aaaa' })).to.have.lengthOf(0)
+
+ expect(await list({ videoIs: 'deleted' })).to.have.lengthOf(1)
+ expect(await list({ videoIs: 'blacklisted' })).to.have.lengthOf(0)
+
+ expect(await list({ state: VideoAbuseState.ACCEPTED })).to.have.lengthOf(0)
+ expect(await list({ state: VideoAbuseState.PENDING })).to.have.lengthOf(5)
+ })
+
after(async function () {
await cleanupTests(servers)
})
import * as request from 'supertest'
import { VideoAbuseUpdate } from '../../models/videos/abuse/video-abuse-update.model'
-import { makeDeleteRequest, makePutBodyRequest } from '../requests/requests'
+import { makeDeleteRequest, makePutBodyRequest, makeGetRequest } from '../requests/requests'
+import { VideoAbuseState } from '@shared/models'
+import { VideoAbuseVideoIs } from '@shared/models/videos/abuse/video-abuse-video-is.type'
function reportVideoAbuse (url: string, token: string, videoId: number | string, reason: string, specialStatus = 200) {
const path = '/api/v1/videos/' + videoId + '/abuse'
.expect(specialStatus)
}
-function getVideoAbusesList (url: string, token: string) {
+function getVideoAbusesList (options: {
+ url: string
+ token: string
+ id?: number
+ search?: string
+ state?: VideoAbuseState
+ videoIs?: VideoAbuseVideoIs
+ searchReporter?: string
+ searchReportee?: string
+ searchVideo?: string
+ searchVideoChannel?: string
+}) {
+ const {
+ url,
+ token,
+ id,
+ search,
+ state,
+ videoIs,
+ searchReporter,
+ searchReportee,
+ searchVideo,
+ searchVideoChannel
+ } = options
const path = '/api/v1/videos/abuse'
- return request(url)
- .get(path)
- .query({ sort: 'createdAt' })
- .set('Accept', 'application/json')
- .set('Authorization', 'Bearer ' + token)
- .expect(200)
- .expect('Content-Type', /json/)
+ const query = {
+ sort: 'createdAt',
+ id,
+ search,
+ state,
+ videoIs,
+ searchReporter,
+ searchReportee,
+ searchVideo,
+ searchVideoChannel
+ }
+
+ return makeGetRequest({
+ url,
+ path,
+ token,
+ query,
+ statusCodeExpected: 200
+ })
}
function updateVideoAbuse (
--- /dev/null
+export type VideoAbuseVideoIs = 'deleted' | 'blacklisted'