Add server API to abuse messages
This commit is contained in:
parent
20516920d2
commit
edbc932546
|
@ -1,20 +1,24 @@
|
|||
import * as express from 'express'
|
||||
import { createAccountAbuse, createVideoAbuse, createVideoCommentAbuse } from '@server/lib/moderation'
|
||||
import { AbuseModel } from '@server/models/abuse/abuse'
|
||||
import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
|
||||
import { getServerActor } from '@server/models/application/application'
|
||||
import { AbuseCreate, abusePredefinedReasonsMap, AbuseState, UserRight } from '../../../shared'
|
||||
import { getFormattedObjects } from '../../helpers/utils'
|
||||
import { sequelizeTypescript } from '../../initializers/database'
|
||||
import {
|
||||
abuseGetValidator,
|
||||
abuseListValidator,
|
||||
abuseListForAdminsValidator,
|
||||
abuseReportValidator,
|
||||
abusesSortValidator,
|
||||
abuseUpdateValidator,
|
||||
addAbuseMessageValidator,
|
||||
asyncMiddleware,
|
||||
asyncRetryTransactionMiddleware,
|
||||
authenticate,
|
||||
deleteAbuseMessageValidator,
|
||||
ensureUserHasRight,
|
||||
getAbuseValidator,
|
||||
paginationValidator,
|
||||
setDefaultPagination,
|
||||
setDefaultSort
|
||||
|
@ -30,8 +34,8 @@ abuseRouter.get('/',
|
|||
abusesSortValidator,
|
||||
setDefaultSort,
|
||||
setDefaultPagination,
|
||||
abuseListValidator,
|
||||
asyncMiddleware(listAbuses)
|
||||
abuseListForAdminsValidator,
|
||||
asyncMiddleware(listAbusesForAdmins)
|
||||
)
|
||||
abuseRouter.put('/:id',
|
||||
authenticate,
|
||||
|
@ -51,13 +55,33 @@ abuseRouter.delete('/:id',
|
|||
asyncRetryTransactionMiddleware(deleteAbuse)
|
||||
)
|
||||
|
||||
abuseRouter.get('/:id/messages',
|
||||
authenticate,
|
||||
asyncMiddleware(getAbuseValidator),
|
||||
asyncRetryTransactionMiddleware(listAbuseMessages)
|
||||
)
|
||||
|
||||
abuseRouter.post('/:id/messages',
|
||||
authenticate,
|
||||
asyncMiddleware(getAbuseValidator),
|
||||
addAbuseMessageValidator,
|
||||
asyncRetryTransactionMiddleware(addAbuseMessage)
|
||||
)
|
||||
|
||||
abuseRouter.delete('/:id/messages/:messageId',
|
||||
authenticate,
|
||||
asyncMiddleware(getAbuseValidator),
|
||||
asyncMiddleware(deleteAbuseMessageValidator),
|
||||
asyncRetryTransactionMiddleware(deleteAbuseMessage)
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
abuseRouter,
|
||||
|
||||
// FIXME: deprecated in 2.3. Remove these exports
|
||||
listAbuses,
|
||||
listAbusesForAdmins,
|
||||
updateAbuse,
|
||||
deleteAbuse,
|
||||
reportAbuse
|
||||
|
@ -65,11 +89,11 @@ export {
|
|||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function listAbuses (req: express.Request, res: express.Response) {
|
||||
async function listAbusesForAdmins (req: express.Request, res: express.Response) {
|
||||
const user = res.locals.oauth.token.user
|
||||
const serverActor = await getServerActor()
|
||||
|
||||
const resultList = await AbuseModel.listForApi({
|
||||
const resultList = await AbuseModel.listForAdminApi({
|
||||
start: req.query.start,
|
||||
count: req.query.count,
|
||||
sort: req.query.sort,
|
||||
|
@ -87,7 +111,10 @@ async function listAbuses (req: express.Request, res: express.Response) {
|
|||
user
|
||||
})
|
||||
|
||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||
return res.json({
|
||||
total: resultList.total,
|
||||
data: resultList.data.map(d => d.toFormattedAdminJSON())
|
||||
})
|
||||
}
|
||||
|
||||
async function updateAbuse (req: express.Request, res: express.Response) {
|
||||
|
@ -100,6 +127,8 @@ async function updateAbuse (req: express.Request, res: express.Response) {
|
|||
return abuse.save({ transaction: t })
|
||||
})
|
||||
|
||||
// TODO: Notification
|
||||
|
||||
// Do not send the delete to other instances, we updated OUR copy of this abuse
|
||||
|
||||
return res.type('json').status(204).end()
|
||||
|
@ -166,3 +195,41 @@ async function reportAbuse (req: express.Request, res: express.Response) {
|
|||
|
||||
return res.json({ abuse: { id } })
|
||||
}
|
||||
|
||||
async function listAbuseMessages (req: express.Request, res: express.Response) {
|
||||
const abuse = res.locals.abuse
|
||||
|
||||
const resultList = await AbuseMessageModel.listForApi(abuse.id)
|
||||
|
||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||
}
|
||||
|
||||
async function addAbuseMessage (req: express.Request, res: express.Response) {
|
||||
const abuse = res.locals.abuse
|
||||
const user = res.locals.oauth.token.user
|
||||
|
||||
const abuseMessage = await AbuseMessageModel.create({
|
||||
message: req.body.message,
|
||||
byModerator: abuse.reporterAccountId !== user.Account.id,
|
||||
accountId: user.Account.id,
|
||||
abuseId: abuse.id
|
||||
})
|
||||
|
||||
// TODO: Notification
|
||||
|
||||
return res.json({
|
||||
abuseMessage: {
|
||||
id: abuseMessage.id
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function deleteAbuseMessage (req: express.Request, res: express.Response) {
|
||||
const abuseMessage = res.locals.abuseMessage
|
||||
|
||||
await sequelizeTypescript.transaction(t => {
|
||||
return abuseMessage.destroy({ transaction: t })
|
||||
})
|
||||
|
||||
return res.sendStatus(204)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
import * as express from 'express'
|
||||
import * as RateLimit from 'express-rate-limit'
|
||||
import { tokensRouter } from '@server/controllers/api/users/token'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { MUser, MUserAccountDefault } from '@server/types/models'
|
||||
import { UserCreate, UserRight, UserRole, UserUpdate } from '../../../../shared'
|
||||
import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
|
||||
import { UserRegister } from '../../../../shared/models/users/user-register.model'
|
||||
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger'
|
||||
import { logger } from '../../../helpers/logger'
|
||||
import { generateRandomString, getFormattedObjects } from '../../../helpers/utils'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
import { WEBSERVER } from '../../../initializers/constants'
|
||||
import { sequelizeTypescript } from '../../../initializers/database'
|
||||
import { Emailer } from '../../../lib/emailer'
|
||||
import { Notifier } from '../../../lib/notifier'
|
||||
import { deleteUserToken } from '../../../lib/oauth-model'
|
||||
import { Redis } from '../../../lib/redis'
|
||||
import { createUserAccountAndChannelAndPlaylist, sendVerifyUserEmail } from '../../../lib/user'
|
||||
import {
|
||||
|
@ -18,9 +28,9 @@ import {
|
|||
setDefaultPagination,
|
||||
setDefaultSort,
|
||||
userAutocompleteValidator,
|
||||
usersListValidator,
|
||||
usersAddValidator,
|
||||
usersGetValidator,
|
||||
usersListValidator,
|
||||
usersRegisterValidator,
|
||||
usersRemoveValidator,
|
||||
usersSortValidator,
|
||||
|
@ -35,22 +45,13 @@ import {
|
|||
usersVerifyEmailValidator
|
||||
} from '../../../middlewares/validators'
|
||||
import { UserModel } from '../../../models/account/user'
|
||||
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger'
|
||||
import { meRouter } from './me'
|
||||
import { deleteUserToken } from '../../../lib/oauth-model'
|
||||
import { myAbusesRouter } from './my-abuses'
|
||||
import { myBlocklistRouter } from './my-blocklist'
|
||||
import { myVideoPlaylistsRouter } from './my-video-playlists'
|
||||
import { myVideosHistoryRouter } from './my-history'
|
||||
import { myNotificationsRouter } from './my-notifications'
|
||||
import { Notifier } from '../../../lib/notifier'
|
||||
import { mySubscriptionsRouter } from './my-subscriptions'
|
||||
import { CONFIG } from '../../../initializers/config'
|
||||
import { sequelizeTypescript } from '../../../initializers/database'
|
||||
import { UserAdminFlag } from '../../../../shared/models/users/user-flag.model'
|
||||
import { UserRegister } from '../../../../shared/models/users/user-register.model'
|
||||
import { MUser, MUserAccountDefault } from '@server/types/models'
|
||||
import { Hooks } from '@server/lib/plugins/hooks'
|
||||
import { tokensRouter } from '@server/controllers/api/users/token'
|
||||
import { myVideoPlaylistsRouter } from './my-video-playlists'
|
||||
|
||||
const auditLogger = auditLoggerFactory('users')
|
||||
|
||||
|
@ -72,6 +73,7 @@ usersRouter.use('/', mySubscriptionsRouter)
|
|||
usersRouter.use('/', myBlocklistRouter)
|
||||
usersRouter.use('/', myVideosHistoryRouter)
|
||||
usersRouter.use('/', myVideoPlaylistsRouter)
|
||||
usersRouter.use('/', myAbusesRouter)
|
||||
usersRouter.use('/', meRouter)
|
||||
|
||||
usersRouter.get('/autocomplete',
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import * as express from 'express'
|
||||
import { AbuseModel } from '@server/models/abuse/abuse'
|
||||
import {
|
||||
abuseListForUserValidator,
|
||||
abusesSortValidator,
|
||||
asyncMiddleware,
|
||||
authenticate,
|
||||
paginationValidator,
|
||||
setDefaultPagination,
|
||||
setDefaultSort
|
||||
} from '../../../middlewares'
|
||||
|
||||
const myAbusesRouter = express.Router()
|
||||
|
||||
myAbusesRouter.get('/me/abuses',
|
||||
authenticate,
|
||||
paginationValidator,
|
||||
abusesSortValidator,
|
||||
setDefaultSort,
|
||||
setDefaultPagination,
|
||||
abuseListForUserValidator,
|
||||
asyncMiddleware(listMyAbuses)
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
myAbusesRouter
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function listMyAbuses (req: express.Request, res: express.Response) {
|
||||
const resultList = await AbuseModel.listForUserApi({
|
||||
start: req.query.start,
|
||||
count: req.query.count,
|
||||
sort: req.query.sort,
|
||||
id: req.query.id,
|
||||
search: req.query.search,
|
||||
state: req.query.state,
|
||||
user: res.locals.oauth.token.User
|
||||
})
|
||||
|
||||
return res.json({
|
||||
total: resultList.total,
|
||||
data: resultList.data.map(d => d.toFormattedAdminJSON())
|
||||
})
|
||||
}
|
|
@ -2,7 +2,6 @@ import * as express from 'express'
|
|||
import { AbuseModel } from '@server/models/abuse/abuse'
|
||||
import { getServerActor } from '@server/models/application/application'
|
||||
import { AbuseCreate, UserRight, VideoAbuseCreate } from '../../../../shared'
|
||||
import { getFormattedObjects } from '../../../helpers/utils'
|
||||
import {
|
||||
abusesSortValidator,
|
||||
asyncMiddleware,
|
||||
|
@ -63,7 +62,7 @@ async function listVideoAbuses (req: express.Request, res: express.Response) {
|
|||
const user = res.locals.oauth.token.user
|
||||
const serverActor = await getServerActor()
|
||||
|
||||
const resultList = await AbuseModel.listForApi({
|
||||
const resultList = await AbuseModel.listForAdminApi({
|
||||
start: req.query.start,
|
||||
count: req.query.count,
|
||||
sort: req.query.sort,
|
||||
|
@ -81,7 +80,10 @@ async function listVideoAbuses (req: express.Request, res: express.Response) {
|
|||
user
|
||||
})
|
||||
|
||||
return res.json(getFormattedObjects(resultList.data, resultList.total))
|
||||
return res.json({
|
||||
total: resultList.total,
|
||||
data: resultList.data.map(d => d.toFormattedAdminJSON())
|
||||
})
|
||||
}
|
||||
|
||||
async function updateVideoAbuse (req: express.Request, res: express.Response) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { chain } from 'lodash'
|
|||
import * as path from 'path'
|
||||
import * as winston from 'winston'
|
||||
import { AUDIT_LOG_FILENAME } from '@server/initializers/constants'
|
||||
import { Abuse, User, VideoChannel, VideoDetails, VideoImport } from '../../shared'
|
||||
import { AdminAbuse, User, VideoChannel, VideoDetails, VideoImport } from '../../shared'
|
||||
import { CustomConfig } from '../../shared/models/server/custom-config.model'
|
||||
import { VideoComment } from '../../shared/models/videos/video-comment.model'
|
||||
import { CONFIG } from '../initializers/config'
|
||||
|
@ -219,7 +219,7 @@ const abuseKeysToKeep = [
|
|||
'createdAt'
|
||||
]
|
||||
class AbuseAuditView extends EntityAuditView {
|
||||
constructor (private readonly abuse: Abuse) {
|
||||
constructor (private readonly abuse: AdminAbuse) {
|
||||
super(abuseKeysToKeep, 'abuse', abuse)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants'
|
|||
import { exists, isArray } from './misc'
|
||||
|
||||
const ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.ABUSES
|
||||
const ABUSE_MESSAGES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.ABUSE_MESSAGES
|
||||
|
||||
function isAbuseReasonValid (value: string) {
|
||||
return exists(value) && validator.isLength(value, ABUSES_CONSTRAINTS_FIELDS.REASON)
|
||||
|
@ -46,13 +47,18 @@ function isAbuseVideoIsValid (value: AbuseVideoIs) {
|
|||
)
|
||||
}
|
||||
|
||||
function isAbuseMessageValid (value: string) {
|
||||
return exists(value) && validator.isLength(value, ABUSE_MESSAGES_CONSTRAINTS_FIELDS.MESSAGE)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
isAbuseReasonValid,
|
||||
isAbuseFilterValid,
|
||||
isAbusePredefinedReasonValid,
|
||||
areAbusePredefinedReasonsValid as isAbusePredefinedReasonsValid,
|
||||
isAbuseMessageValid,
|
||||
areAbusePredefinedReasonsValid,
|
||||
isAbuseTimestampValid,
|
||||
isAbuseTimestampCoherent,
|
||||
isAbuseModerationCommentValid,
|
||||
|
|
|
@ -206,6 +206,9 @@ const CONSTRAINTS_FIELDS = {
|
|||
REASON: { min: 2, max: 3000 }, // Length
|
||||
MODERATION_COMMENT: { min: 2, max: 3000 } // Length
|
||||
},
|
||||
ABUSE_MESSAGES: {
|
||||
MESSAGE: { min: 2, max: 3000 } // Length
|
||||
},
|
||||
VIDEO_BLACKLIST: {
|
||||
REASON: { min: 2, max: 300 } // Length
|
||||
},
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { QueryTypes, Transaction } from 'sequelize'
|
||||
import { Sequelize as SequelizeTypescript } from 'sequelize-typescript'
|
||||
import { AbuseModel } from '@server/models/abuse/abuse'
|
||||
import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
|
||||
import { VideoAbuseModel } from '@server/models/abuse/video-abuse'
|
||||
import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse'
|
||||
import { isTestInstance } from '../helpers/core-utils'
|
||||
|
@ -87,6 +88,7 @@ async function initDatabaseModels (silent: boolean) {
|
|||
TagModel,
|
||||
AccountVideoRateModel,
|
||||
UserModel,
|
||||
AbuseMessageModel,
|
||||
AbuseModel,
|
||||
VideoCommentAbuseModel,
|
||||
VideoAbuseModel,
|
||||
|
|
|
@ -5,7 +5,7 @@ import { join } from 'path'
|
|||
import { VideoChannelModel } from '@server/models/video/video-channel'
|
||||
import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist'
|
||||
import { MVideoImport, MVideoImportVideo } from '@server/types/models/video/video-import'
|
||||
import { Abuse, EmailPayload } from '@shared/models'
|
||||
import { UserAbuse, EmailPayload } from '@shared/models'
|
||||
import { SendEmailOptions } from '../../shared/models/server/emailer.model'
|
||||
import { isTestInstance, root } from '../helpers/core-utils'
|
||||
import { bunyanLogger, logger } from '../helpers/logger'
|
||||
|
@ -283,7 +283,7 @@ class Emailer {
|
|||
}
|
||||
|
||||
addAbuseModeratorsNotification (to: string[], parameters: {
|
||||
abuse: Abuse
|
||||
abuse: UserAbuse
|
||||
abuseInstance: MAbuseFull
|
||||
reporter: string
|
||||
}) {
|
||||
|
|
|
@ -213,7 +213,7 @@ async function createAbuse (options: {
|
|||
await sendAbuse(reporterAccount.Actor, abuseInstance, abuseInstance.FlaggedAccount, transaction)
|
||||
}
|
||||
|
||||
const abuseJSON = abuseInstance.toFormattedJSON()
|
||||
const abuseJSON = abuseInstance.toFormattedAdminJSON()
|
||||
auditLogger.create(reporterAccount.Actor.getIdentifier(), new AbuseAuditView(abuseJSON))
|
||||
|
||||
Notifier.Instance.notifyOnNewAbuse({
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
} from '@server/types/models/user'
|
||||
import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist'
|
||||
import { MVideoImportVideo } from '@server/types/models/video/video-import'
|
||||
import { Abuse } from '@shared/models'
|
||||
import { UserAbuse } from '@shared/models'
|
||||
import { UserNotificationSettingValue, UserNotificationType, UserRight } from '../../shared/models/users'
|
||||
import { VideoPrivacy, VideoState } from '../../shared/models/videos'
|
||||
import { logger } from '../helpers/logger'
|
||||
|
@ -73,7 +73,7 @@ class Notifier {
|
|||
.catch(err => logger.error('Cannot notify mentions of comment %s.', comment.url, { err }))
|
||||
}
|
||||
|
||||
notifyOnNewAbuse (parameters: { abuse: Abuse, abuseInstance: MAbuseFull, reporter: string }): void {
|
||||
notifyOnNewAbuse (parameters: { abuse: UserAbuse, abuseInstance: MAbuseFull, reporter: string }): void {
|
||||
this.notifyModeratorsOfNewAbuse(parameters)
|
||||
.catch(err => logger.error('Cannot notify of new abuse %d.', parameters.abuseInstance.id, { err }))
|
||||
}
|
||||
|
@ -350,7 +350,7 @@ class Notifier {
|
|||
}
|
||||
|
||||
private async notifyModeratorsOfNewAbuse (parameters: {
|
||||
abuse: Abuse
|
||||
abuse: UserAbuse
|
||||
abuseInstance: MAbuseFull
|
||||
reporter: string
|
||||
}) {
|
||||
|
|
|
@ -9,11 +9,7 @@ function ensureUserHasRight (userRight: UserRight) {
|
|||
const message = `User ${user.username} does not have right ${UserRight[userRight]} to access to ${req.path}.`
|
||||
logger.info(message)
|
||||
|
||||
return res.status(403)
|
||||
.json({
|
||||
error: message
|
||||
})
|
||||
.end()
|
||||
return res.status(403).json({ error: message })
|
||||
}
|
||||
|
||||
return next()
|
||||
|
|
|
@ -2,8 +2,9 @@ import * as express from 'express'
|
|||
import { body, param, query } from 'express-validator'
|
||||
import {
|
||||
isAbuseFilterValid,
|
||||
isAbuseMessageValid,
|
||||
isAbuseModerationCommentValid,
|
||||
isAbusePredefinedReasonsValid,
|
||||
areAbusePredefinedReasonsValid,
|
||||
isAbusePredefinedReasonValid,
|
||||
isAbuseReasonValid,
|
||||
isAbuseStateValid,
|
||||
|
@ -15,7 +16,8 @@ import { exists, isIdOrUUIDValid, isIdValid, toIntOrNull } from '@server/helpers
|
|||
import { doesCommentIdExist } from '@server/helpers/custom-validators/video-comments'
|
||||
import { logger } from '@server/helpers/logger'
|
||||
import { doesAbuseExist, doesAccountIdExist, doesVideoAbuseExist, doesVideoExist } from '@server/helpers/middlewares'
|
||||
import { AbuseCreate } from '@shared/models'
|
||||
import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
|
||||
import { AbuseCreate, UserRight } from '@shared/models'
|
||||
import { areValidationErrors } from './utils'
|
||||
|
||||
const abuseReportValidator = [
|
||||
|
@ -53,7 +55,7 @@ const abuseReportValidator = [
|
|||
|
||||
body('predefinedReasons')
|
||||
.optional()
|
||||
.custom(isAbusePredefinedReasonsValid)
|
||||
.custom(areAbusePredefinedReasonsValid)
|
||||
.withMessage('Should have a valid list of predefined reasons'),
|
||||
|
||||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
|
@ -111,7 +113,7 @@ const abuseUpdateValidator = [
|
|||
}
|
||||
]
|
||||
|
||||
const abuseListValidator = [
|
||||
const abuseListForAdminsValidator = [
|
||||
query('id')
|
||||
.optional()
|
||||
.custom(isIdValid).withMessage('Should have a valid id'),
|
||||
|
@ -146,7 +148,7 @@ const abuseListValidator = [
|
|||
.custom(exists).withMessage('Should have a valid video channel search'),
|
||||
|
||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
logger.debug('Checking abuseListValidator parameters', { parameters: req.body })
|
||||
logger.debug('Checking abuseListForAdminsValidator parameters', { parameters: req.body })
|
||||
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
||||
|
@ -154,6 +156,91 @@ const abuseListValidator = [
|
|||
}
|
||||
]
|
||||
|
||||
const abuseListForUserValidator = [
|
||||
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(isAbuseStateValid).withMessage('Should have a valid abuse state'),
|
||||
|
||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
logger.debug('Checking abuseListForUserValidator parameters', { parameters: req.body })
|
||||
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
||||
return next()
|
||||
}
|
||||
]
|
||||
|
||||
const getAbuseValidator = [
|
||||
param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'),
|
||||
|
||||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
logger.debug('Checking getAbuseValidator parameters', { parameters: req.body })
|
||||
|
||||
if (areValidationErrors(req, res)) return
|
||||
if (!await doesAbuseExist(req.params.id, res)) return
|
||||
|
||||
const user = res.locals.oauth.token.user
|
||||
const abuse = res.locals.abuse
|
||||
|
||||
if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuse.reporterAccountId !== user.Account.id) {
|
||||
const message = `User ${user.username} does not have right to get abuse ${abuse.id}`
|
||||
logger.warn(message)
|
||||
|
||||
return res.status(403).json({ error: message })
|
||||
}
|
||||
|
||||
return next()
|
||||
}
|
||||
]
|
||||
|
||||
const addAbuseMessageValidator = [
|
||||
body('message').custom(isAbuseMessageValid).not().isEmpty().withMessage('Should have a valid abuse message'),
|
||||
|
||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
logger.debug('Checking addAbuseMessageValidator parameters', { parameters: req.body })
|
||||
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
||||
return next()
|
||||
}
|
||||
]
|
||||
|
||||
const deleteAbuseMessageValidator = [
|
||||
param('messageId').custom(isIdValid).not().isEmpty().withMessage('Should have a valid message id'),
|
||||
|
||||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||
logger.debug('Checking deleteAbuseMessageValidator parameters', { parameters: req.body })
|
||||
|
||||
if (areValidationErrors(req, res)) return
|
||||
|
||||
const user = res.locals.oauth.token.user
|
||||
const abuse = res.locals.abuse
|
||||
|
||||
const messageId = parseInt(req.params.messageId + '', 10)
|
||||
const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id)
|
||||
|
||||
if (!abuseMessage) {
|
||||
return res.status(404).json({ error: 'Abuse message not found' })
|
||||
}
|
||||
|
||||
if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuseMessage.accountId !== user.Account.id) {
|
||||
return res.status(403).json({ error: 'Cannot delete this abuse message' })
|
||||
}
|
||||
|
||||
res.locals.abuseMessage = abuseMessage
|
||||
|
||||
return next()
|
||||
}
|
||||
]
|
||||
|
||||
// FIXME: deprecated in 2.3. Remove these validators
|
||||
|
||||
const videoAbuseReportValidator = [
|
||||
|
@ -167,7 +254,7 @@ const videoAbuseReportValidator = [
|
|||
.withMessage('Should have a valid reason'),
|
||||
body('predefinedReasons')
|
||||
.optional()
|
||||
.custom(isAbusePredefinedReasonsValid)
|
||||
.custom(areAbusePredefinedReasonsValid)
|
||||
.withMessage('Should have a valid list of predefined reasons'),
|
||||
body('startAt')
|
||||
.optional()
|
||||
|
@ -266,10 +353,14 @@ const videoAbuseListValidator = [
|
|||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
abuseListValidator,
|
||||
abuseListForAdminsValidator,
|
||||
abuseReportValidator,
|
||||
abuseGetValidator,
|
||||
addAbuseMessageValidator,
|
||||
abuseUpdateValidator,
|
||||
deleteAbuseMessageValidator,
|
||||
abuseListForUserValidator,
|
||||
getAbuseValidator,
|
||||
videoAbuseReportValidator,
|
||||
videoAbuseGetValidator,
|
||||
videoAbuseUpdateValidator,
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
import { AllowNull, BelongsTo, Column, CreatedAt, DataType, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript'
|
||||
import { isAbuseMessageValid } from '@server/helpers/custom-validators/abuses'
|
||||
import { AbuseMessage } from '@shared/models'
|
||||
import { AccountModel, ScopeNames as AccountScopeNames } from '../account/account'
|
||||
import { throwIfNotValid, getSort } from '../utils'
|
||||
import { AbuseModel } from './abuse'
|
||||
import { MAbuseMessageFormattable, MAbuseMessage } from '@server/types/models'
|
||||
|
||||
@Table({
|
||||
tableName: 'abuseMessage',
|
||||
indexes: [
|
||||
{
|
||||
fields: [ 'abuseId' ]
|
||||
},
|
||||
{
|
||||
fields: [ 'accountId' ]
|
||||
}
|
||||
]
|
||||
})
|
||||
export class AbuseMessageModel extends Model<AbuseMessageModel> {
|
||||
|
||||
@AllowNull(false)
|
||||
@Is('AbuseMessage', value => throwIfNotValid(value, isAbuseMessageValid, 'message'))
|
||||
@Column(DataType.TEXT)
|
||||
message: string
|
||||
|
||||
@AllowNull(false)
|
||||
@Column
|
||||
byModerator: boolean
|
||||
|
||||
@CreatedAt
|
||||
createdAt: Date
|
||||
|
||||
@UpdatedAt
|
||||
updatedAt: Date
|
||||
|
||||
@ForeignKey(() => AccountModel)
|
||||
@Column
|
||||
accountId: number
|
||||
|
||||
@BelongsTo(() => AccountModel, {
|
||||
foreignKey: {
|
||||
name: 'accountId',
|
||||
allowNull: true
|
||||
},
|
||||
onDelete: 'set null'
|
||||
})
|
||||
Account: AccountModel
|
||||
|
||||
@ForeignKey(() => AbuseModel)
|
||||
@Column
|
||||
abuseId: number
|
||||
|
||||
@BelongsTo(() => AbuseModel, {
|
||||
foreignKey: {
|
||||
name: 'abuseId',
|
||||
allowNull: false
|
||||
},
|
||||
onDelete: 'cascade'
|
||||
})
|
||||
Abuse: AbuseModel
|
||||
|
||||
static listForApi (abuseId: number) {
|
||||
const options = {
|
||||
where: { abuseId },
|
||||
|
||||
order: getSort('createdAt'),
|
||||
|
||||
include: [
|
||||
{
|
||||
model: AccountModel.scope(AccountScopeNames.SUMMARY),
|
||||
required: false
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return AbuseMessageModel.findAndCountAll(options)
|
||||
.then(({ rows, count }) => ({ data: rows, total: count }))
|
||||
}
|
||||
|
||||
static loadByIdAndAbuseId (messageId: number, abuseId: number): Promise<MAbuseMessage> {
|
||||
return AbuseMessageModel.findOne({
|
||||
where: {
|
||||
id: messageId,
|
||||
abuseId
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
toFormattedJSON (this: MAbuseMessageFormattable): AbuseMessage {
|
||||
const account = this.Account
|
||||
? this.Account.toFormattedSummaryJSON()
|
||||
: null
|
||||
|
||||
return {
|
||||
id: this.id,
|
||||
byModerator: this.byModerator,
|
||||
message: this.message,
|
||||
|
||||
account
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,8 +26,10 @@ export type BuildAbusesQueryOptions = {
|
|||
state?: AbuseState
|
||||
|
||||
// accountIds
|
||||
serverAccountId: number
|
||||
userAccountId: number
|
||||
serverAccountId?: number
|
||||
userAccountId?: number
|
||||
|
||||
reporterAccountId?: number
|
||||
}
|
||||
|
||||
function buildAbuseListQuery (options: BuildAbusesQueryOptions, type: 'count' | 'id') {
|
||||
|
@ -45,7 +47,14 @@ function buildAbuseListQuery (options: BuildAbusesQueryOptions, type: 'count' |
|
|||
'LEFT JOIN "videoComment" ON "commentAbuse"."videoCommentId" = "videoComment"."id"'
|
||||
]
|
||||
|
||||
whereAnd.push('"abuse"."reporterAccountId" NOT IN (' + buildBlockedAccountSQL([ options.serverAccountId, options.userAccountId ]) + ')')
|
||||
if (options.serverAccountId || options.userAccountId) {
|
||||
whereAnd.push('"abuse"."reporterAccountId" NOT IN (' + buildBlockedAccountSQL([ options.serverAccountId, options.userAccountId ]) + ')')
|
||||
}
|
||||
|
||||
if (options.reporterAccountId) {
|
||||
whereAnd.push('"abuse"."reporterAccountId" = :reporterAccountId')
|
||||
replacements.reporterAccountId = options.reporterAccountId
|
||||
}
|
||||
|
||||
if (options.search) {
|
||||
const searchWhereOr = [
|
||||
|
|
|
@ -18,7 +18,6 @@ import {
|
|||
} from 'sequelize-typescript'
|
||||
import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses'
|
||||
import {
|
||||
Abuse,
|
||||
AbuseFilter,
|
||||
AbuseObject,
|
||||
AbusePredefinedReasons,
|
||||
|
@ -26,11 +25,14 @@ import {
|
|||
AbusePredefinedReasonsString,
|
||||
AbuseState,
|
||||
AbuseVideoIs,
|
||||
VideoAbuse,
|
||||
VideoCommentAbuse
|
||||
AdminVideoAbuse,
|
||||
AdminAbuse,
|
||||
AdminVideoCommentAbuse,
|
||||
UserAbuse,
|
||||
UserVideoAbuse
|
||||
} from '@shared/models'
|
||||
import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants'
|
||||
import { MAbuse, MAbuseAP, MAbuseFormattable, MUserAccountId } from '../../types/models'
|
||||
import { MAbuse, MAbuseAdminFormattable, MAbuseAP, MUserAccountId, MAbuseUserFormattable } from '../../types/models'
|
||||
import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account'
|
||||
import { getSort, throwIfNotValid } from '../utils'
|
||||
import { ThumbnailModel } from '../video/thumbnail'
|
||||
|
@ -51,6 +53,16 @@ export enum ScopeNames {
|
|||
return {
|
||||
attributes: {
|
||||
include: [
|
||||
[
|
||||
literal(
|
||||
'(' +
|
||||
'SELECT count(*) ' +
|
||||
'FROM "abuseMessage" ' +
|
||||
'WHERE "abuseId" = "AbuseModel"."id"' +
|
||||
')'
|
||||
),
|
||||
'countMessages'
|
||||
],
|
||||
[
|
||||
// we don't care about this count for deleted videos, so there are not included
|
||||
literal(
|
||||
|
@ -285,7 +297,7 @@ export class AbuseModel extends Model<AbuseModel> {
|
|||
return AbuseModel.findOne(query)
|
||||
}
|
||||
|
||||
static async listForApi (parameters: {
|
||||
static async listForAdminApi (parameters: {
|
||||
start: number
|
||||
count: number
|
||||
sort: string
|
||||
|
@ -353,71 +365,98 @@ export class AbuseModel extends Model<AbuseModel> {
|
|||
return { total, data }
|
||||
}
|
||||
|
||||
toFormattedJSON (this: MAbuseFormattable): Abuse {
|
||||
static async listForUserApi (parameters: {
|
||||
user: MUserAccountId
|
||||
|
||||
start: number
|
||||
count: number
|
||||
sort: string
|
||||
|
||||
id?: number
|
||||
search?: string
|
||||
state?: AbuseState
|
||||
}) {
|
||||
const {
|
||||
start,
|
||||
count,
|
||||
sort,
|
||||
search,
|
||||
user,
|
||||
state,
|
||||
id
|
||||
} = parameters
|
||||
|
||||
const queryOptions: BuildAbusesQueryOptions = {
|
||||
start,
|
||||
count,
|
||||
sort,
|
||||
id,
|
||||
search,
|
||||
state,
|
||||
reporterAccountId: user.Account.id
|
||||
}
|
||||
|
||||
const [ total, data ] = await Promise.all([
|
||||
AbuseModel.internalCountForApi(queryOptions),
|
||||
AbuseModel.internalListForApi(queryOptions)
|
||||
])
|
||||
|
||||
return { total, data }
|
||||
}
|
||||
|
||||
buildBaseVideoCommentAbuse (this: MAbuseUserFormattable) {
|
||||
if (!this.VideoCommentAbuse) return null
|
||||
|
||||
const abuseModel = this.VideoCommentAbuse
|
||||
const entity = abuseModel.VideoComment
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
threadId: entity.getThreadId(),
|
||||
|
||||
text: entity.text ?? '',
|
||||
|
||||
deleted: entity.isDeleted(),
|
||||
|
||||
video: {
|
||||
id: entity.Video.id,
|
||||
name: entity.Video.name,
|
||||
uuid: entity.Video.uuid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildBaseVideoAbuse (this: MAbuseUserFormattable): UserVideoAbuse {
|
||||
if (!this.VideoAbuse) return null
|
||||
|
||||
const abuseModel = this.VideoAbuse
|
||||
const entity = abuseModel.Video || abuseModel.deletedVideo
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
uuid: entity.uuid,
|
||||
name: entity.name,
|
||||
nsfw: entity.nsfw,
|
||||
|
||||
startAt: abuseModel.startAt,
|
||||
endAt: abuseModel.endAt,
|
||||
|
||||
deleted: !abuseModel.Video,
|
||||
blacklisted: abuseModel.Video?.isBlacklisted() || false,
|
||||
thumbnailPath: abuseModel.Video?.getMiniatureStaticPath(),
|
||||
|
||||
channel: abuseModel.Video?.VideoChannel.toFormattedJSON() || abuseModel.deletedVideo?.channel,
|
||||
}
|
||||
}
|
||||
|
||||
buildBaseAbuse (this: MAbuseUserFormattable, countMessages: number): UserAbuse {
|
||||
const predefinedReasons = AbuseModel.getPredefinedReasonsStrings(this.predefinedReasons)
|
||||
|
||||
const countReportsForVideo = this.get('countReportsForVideo') as number
|
||||
const nthReportForVideo = this.get('nthReportForVideo') as number
|
||||
|
||||
const countReportsForReporter = this.get('countReportsForReporter') as number
|
||||
const countReportsForReportee = this.get('countReportsForReportee') as number
|
||||
|
||||
let video: VideoAbuse = null
|
||||
let comment: VideoCommentAbuse = null
|
||||
|
||||
if (this.VideoAbuse) {
|
||||
const abuseModel = this.VideoAbuse
|
||||
const entity = abuseModel.Video || abuseModel.deletedVideo
|
||||
|
||||
video = {
|
||||
id: entity.id,
|
||||
uuid: entity.uuid,
|
||||
name: entity.name,
|
||||
nsfw: entity.nsfw,
|
||||
|
||||
startAt: abuseModel.startAt,
|
||||
endAt: abuseModel.endAt,
|
||||
|
||||
deleted: !abuseModel.Video,
|
||||
blacklisted: abuseModel.Video?.isBlacklisted() || false,
|
||||
thumbnailPath: abuseModel.Video?.getMiniatureStaticPath(),
|
||||
|
||||
channel: abuseModel.Video?.VideoChannel.toFormattedJSON() || abuseModel.deletedVideo?.channel,
|
||||
|
||||
countReports: countReportsForVideo,
|
||||
nthReport: nthReportForVideo
|
||||
}
|
||||
}
|
||||
|
||||
if (this.VideoCommentAbuse) {
|
||||
const abuseModel = this.VideoCommentAbuse
|
||||
const entity = abuseModel.VideoComment
|
||||
|
||||
comment = {
|
||||
id: entity.id,
|
||||
threadId: entity.getThreadId(),
|
||||
|
||||
text: entity.text ?? '',
|
||||
|
||||
deleted: entity.isDeleted(),
|
||||
|
||||
video: {
|
||||
id: entity.Video.id,
|
||||
name: entity.Video.name,
|
||||
uuid: entity.Video.uuid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: this.id,
|
||||
reason: this.reason,
|
||||
predefinedReasons,
|
||||
|
||||
reporterAccount: this.ReporterAccount
|
||||
? this.ReporterAccount.toFormattedJSON()
|
||||
: null,
|
||||
|
||||
flaggedAccount: this.FlaggedAccount
|
||||
? this.FlaggedAccount.toFormattedJSON()
|
||||
: null,
|
||||
|
@ -429,11 +468,41 @@ export class AbuseModel extends Model<AbuseModel> {
|
|||
|
||||
moderationComment: this.moderationComment,
|
||||
|
||||
countMessages,
|
||||
|
||||
createdAt: this.createdAt,
|
||||
updatedAt: this.updatedAt
|
||||
}
|
||||
}
|
||||
|
||||
toFormattedAdminJSON (this: MAbuseAdminFormattable): AdminAbuse {
|
||||
const countReportsForVideo = this.get('countReportsForVideo') as number
|
||||
const nthReportForVideo = this.get('nthReportForVideo') as number
|
||||
|
||||
const countReportsForReporter = this.get('countReportsForReporter') as number
|
||||
const countReportsForReportee = this.get('countReportsForReportee') as number
|
||||
|
||||
const countMessages = this.get('countMessages') as number
|
||||
|
||||
const baseVideo = this.buildBaseVideoAbuse()
|
||||
const video: AdminVideoAbuse = baseVideo
|
||||
? Object.assign(baseVideo, {
|
||||
countReports: countReportsForVideo,
|
||||
nthReport: nthReportForVideo
|
||||
})
|
||||
: null
|
||||
|
||||
const comment: AdminVideoCommentAbuse = this.buildBaseVideoCommentAbuse()
|
||||
|
||||
const abuse = this.buildBaseAbuse(countMessages || 0)
|
||||
|
||||
return Object.assign(abuse, {
|
||||
video,
|
||||
comment,
|
||||
|
||||
createdAt: this.createdAt,
|
||||
updatedAt: this.updatedAt,
|
||||
reporterAccount: this.ReporterAccount
|
||||
? this.ReporterAccount.toFormattedJSON()
|
||||
: null,
|
||||
|
||||
countReportsForReporter: (countReportsForReporter || 0),
|
||||
countReportsForReportee: (countReportsForReportee || 0),
|
||||
|
@ -443,7 +512,20 @@ export class AbuseModel extends Model<AbuseModel> {
|
|||
endAt: null,
|
||||
count: countReportsForVideo || 0,
|
||||
nth: nthReportForVideo || 0
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
toFormattedUserJSON (this: MAbuseUserFormattable): UserAbuse {
|
||||
const countMessages = this.get('countMessages') as number
|
||||
|
||||
const video = this.buildBaseVideoAbuse()
|
||||
const comment: AdminVideoCommentAbuse = this.buildBaseVideoCommentAbuse()
|
||||
const abuse = this.buildBaseAbuse(countMessages || 0)
|
||||
|
||||
return Object.assign(abuse, {
|
||||
video,
|
||||
comment
|
||||
})
|
||||
}
|
||||
|
||||
toActivityPubObject (this: MAbuseAP): AbuseObject {
|
||||
|
|
|
@ -13,7 +13,11 @@ import {
|
|||
setAccessTokensToServers,
|
||||
updateAbuse,
|
||||
uploadVideo,
|
||||
userLogin
|
||||
userLogin,
|
||||
generateUserAccessToken,
|
||||
addAbuseMessage,
|
||||
listAbuseMessages,
|
||||
deleteAbuseMessage
|
||||
} from '../../../../shared/extra-utils'
|
||||
import {
|
||||
checkBadCountPagination,
|
||||
|
@ -26,7 +30,9 @@ describe('Test abuses API validators', function () {
|
|||
|
||||
let server: ServerInfo
|
||||
let userAccessToken = ''
|
||||
let userAccessToken2 = ''
|
||||
let abuseId: number
|
||||
let messageId: number
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
|
@ -42,11 +48,15 @@ describe('Test abuses API validators', function () {
|
|||
await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
|
||||
userAccessToken = await userLogin(server, { username, password })
|
||||
|
||||
{
|
||||
userAccessToken2 = await generateUserAccessToken(server, 'user_2')
|
||||
}
|
||||
|
||||
const res = await uploadVideo(server.url, server.accessToken, {})
|
||||
server.video = res.body.video
|
||||
})
|
||||
|
||||
describe('When listing abuses', function () {
|
||||
describe('When listing abuses for admins', function () {
|
||||
const path = basePath
|
||||
|
||||
it('Should fail with a bad start pagination', async function () {
|
||||
|
@ -113,47 +123,89 @@ describe('Test abuses API validators', function () {
|
|||
})
|
||||
})
|
||||
|
||||
describe('When listing abuses for users', function () {
|
||||
const path = '/api/v1/users/me/abuses'
|
||||
|
||||
it('Should fail with a bad start pagination', async function () {
|
||||
await checkBadStartPagination(server.url, path, userAccessToken)
|
||||
})
|
||||
|
||||
it('Should fail with a bad count pagination', async function () {
|
||||
await checkBadCountPagination(server.url, path, userAccessToken)
|
||||
})
|
||||
|
||||
it('Should fail with an incorrect sort', async function () {
|
||||
await checkBadSortPagination(server.url, path, userAccessToken)
|
||||
})
|
||||
|
||||
it('Should fail with a non authenticated user', async function () {
|
||||
await makeGetRequest({
|
||||
url: server.url,
|
||||
path,
|
||||
statusCodeExpected: 401
|
||||
})
|
||||
})
|
||||
|
||||
it('Should fail with a bad id filter', async function () {
|
||||
await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { id: 'toto' } })
|
||||
})
|
||||
|
||||
it('Should fail with a bad state filter', async function () {
|
||||
await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { state: 'toto' } })
|
||||
await makeGetRequest({ url: server.url, path, token: userAccessToken, query: { state: 0 } })
|
||||
})
|
||||
|
||||
it('Should succeed with the correct params', async function () {
|
||||
const query = {
|
||||
id: 13,
|
||||
state: 2
|
||||
}
|
||||
|
||||
await makeGetRequest({ url: server.url, path, token: userAccessToken, query, statusCodeExpected: 200 })
|
||||
})
|
||||
})
|
||||
|
||||
describe('When reporting an abuse', function () {
|
||||
const path = basePath
|
||||
|
||||
it('Should fail with nothing', async function () {
|
||||
const fields = {}
|
||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
||||
await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should fail with a wrong video', async function () {
|
||||
const fields = { video: { id: 'blabla' }, reason: 'my super reason' }
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: server.accessToken, fields })
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should fail with an unknown video', async function () {
|
||||
const fields = { video: { id: 42 }, reason: 'my super reason' }
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: server.accessToken, fields, statusCodeExpected: 404 })
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: userAccessToken, fields, statusCodeExpected: 404 })
|
||||
})
|
||||
|
||||
it('Should fail with a wrong comment', async function () {
|
||||
const fields = { comment: { id: 'blabla' }, reason: 'my super reason' }
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: server.accessToken, fields })
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should fail with an unknown comment', async function () {
|
||||
const fields = { comment: { id: 42 }, reason: 'my super reason' }
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: server.accessToken, fields, statusCodeExpected: 404 })
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: userAccessToken, fields, statusCodeExpected: 404 })
|
||||
})
|
||||
|
||||
it('Should fail with a wrong account', async function () {
|
||||
const fields = { account: { id: 'blabla' }, reason: 'my super reason' }
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: server.accessToken, fields })
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should fail with an unknown account', async function () {
|
||||
const fields = { account: { id: 42 }, reason: 'my super reason' }
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: server.accessToken, fields, statusCodeExpected: 404 })
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: userAccessToken, fields, statusCodeExpected: 404 })
|
||||
})
|
||||
|
||||
it('Should fail with not account, comment or video', async function () {
|
||||
const fields = { reason: 'my super reason' }
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: server.accessToken, fields, statusCodeExpected: 400 })
|
||||
await makePostBodyRequest({ url: server.url, path: path, token: userAccessToken, fields, statusCodeExpected: 400 })
|
||||
})
|
||||
|
||||
it('Should fail with a non authenticated user', async function () {
|
||||
|
@ -165,38 +217,38 @@ describe('Test abuses API validators', function () {
|
|||
it('Should fail with a reason too short', async function () {
|
||||
const fields = { video: { id: server.video.id }, reason: 'h' }
|
||||
|
||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
||||
await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should fail with a too big reason', async function () {
|
||||
const fields = { video: { id: server.video.id }, reason: 'super'.repeat(605) }
|
||||
|
||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
||||
await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should succeed with the correct parameters (basic)', async function () {
|
||||
const fields: AbuseCreate = { video: { id: server.video.id }, reason: 'my super reason' }
|
||||
|
||||
const res = await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 200 })
|
||||
const res = await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: 200 })
|
||||
abuseId = res.body.abuse.id
|
||||
})
|
||||
|
||||
it('Should fail with a wrong predefined reason', async function () {
|
||||
const fields = { video: { id: server.video.id }, reason: 'my super reason', predefinedReasons: [ 'wrongPredefinedReason' ] }
|
||||
|
||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
||||
await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should fail with negative timestamps', async function () {
|
||||
const fields = { video: { id: server.video.id, startAt: -1 }, reason: 'my super reason' }
|
||||
|
||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
||||
await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should fail mith misordered startAt/endAt', async function () {
|
||||
const fields = { video: { id: server.video.id, startAt: 5, endAt: 1 }, reason: 'my super reason' }
|
||||
|
||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields })
|
||||
await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields })
|
||||
})
|
||||
|
||||
it('Should succeed with the corret parameters (advanced)', async function () {
|
||||
|
@ -210,7 +262,7 @@ describe('Test abuses API validators', function () {
|
|||
predefinedReasons: [ 'serverRules' ]
|
||||
}
|
||||
|
||||
await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 200 })
|
||||
await makePostBodyRequest({ url: server.url, path, token: userAccessToken, fields, statusCodeExpected: 200 })
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -244,6 +296,73 @@ describe('Test abuses API validators', function () {
|
|||
})
|
||||
})
|
||||
|
||||
describe('When creating an abuse message', function () {
|
||||
const message = 'my super message'
|
||||
|
||||
it('Should fail with an invalid abuse id', async function () {
|
||||
await addAbuseMessage(server.url, userAccessToken2, 888, message, 404)
|
||||
})
|
||||
|
||||
it('Should fail with a non authenticated user', async function () {
|
||||
await addAbuseMessage(server.url, 'fake_token', abuseId, message, 401)
|
||||
})
|
||||
|
||||
it('Should fail with an invalid logged in user', async function () {
|
||||
await addAbuseMessage(server.url, userAccessToken2, abuseId, message, 403)
|
||||
})
|
||||
|
||||
it('Should fail with an invalid message', async function () {
|
||||
await addAbuseMessage(server.url, userAccessToken, abuseId, 'a'.repeat(5000), 400)
|
||||
})
|
||||
|
||||
it('Should suceed with the correct params', async function () {
|
||||
const res = await addAbuseMessage(server.url, userAccessToken, abuseId, message)
|
||||
messageId = res.body.abuseMessage.id
|
||||
})
|
||||
})
|
||||
|
||||
describe('When listing abuse message', function () {
|
||||
|
||||
it('Should fail with an invalid abuse id', async function () {
|
||||
await listAbuseMessages(server.url, userAccessToken, 888, 404)
|
||||
})
|
||||
|
||||
it('Should fail with a non authenticated user', async function () {
|
||||
await listAbuseMessages(server.url, 'fake_token', abuseId, 401)
|
||||
})
|
||||
|
||||
it('Should fail with an invalid logged in user', async function () {
|
||||
await listAbuseMessages(server.url, userAccessToken2, abuseId, 403)
|
||||
})
|
||||
|
||||
it('Should succeed with the correct params', async function () {
|
||||
await listAbuseMessages(server.url, userAccessToken, abuseId)
|
||||
})
|
||||
})
|
||||
|
||||
describe('When deleting an abuse message', function () {
|
||||
|
||||
it('Should fail with an invalid abuse id', async function () {
|
||||
await deleteAbuseMessage(server.url, userAccessToken, 888, messageId, 404)
|
||||
})
|
||||
|
||||
it('Should fail with an invalid message id', async function () {
|
||||
await deleteAbuseMessage(server.url, userAccessToken, abuseId, 888, 404)
|
||||
})
|
||||
|
||||
it('Should fail with a non authenticated user', async function () {
|
||||
await deleteAbuseMessage(server.url, 'fake_token', abuseId, messageId, 401)
|
||||
})
|
||||
|
||||
it('Should fail with an invalid logged in user', async function () {
|
||||
await deleteAbuseMessage(server.url, userAccessToken2, abuseId, messageId, 403)
|
||||
})
|
||||
|
||||
it('Should succeed with the correct params', async function () {
|
||||
await deleteAbuseMessage(server.url, userAccessToken, abuseId, messageId)
|
||||
})
|
||||
})
|
||||
|
||||
describe('When deleting a video abuse', function () {
|
||||
|
||||
it('Should fail with a non authenticated user', async function () {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import 'mocha'
|
||||
import * as chai from 'chai'
|
||||
import { Abuse, AbuseFilter, AbusePredefinedReasonsString, AbuseState, VideoComment, Account } from '@shared/models'
|
||||
import { AbuseFilter, AbusePredefinedReasonsString, AbuseState, Account, AdminAbuse, UserAbuse, VideoComment, AbuseMessage } from '@shared/models'
|
||||
import {
|
||||
addVideoCommentThread,
|
||||
cleanupTests,
|
||||
|
@ -10,11 +10,15 @@ import {
|
|||
deleteAbuse,
|
||||
deleteVideoComment,
|
||||
flushAndRunMultipleServers,
|
||||
getAbusesList,
|
||||
generateUserAccessToken,
|
||||
getAccount,
|
||||
getAdminAbusesList,
|
||||
getUserAbusesList,
|
||||
getVideoCommentThreads,
|
||||
getVideoIdFromUUID,
|
||||
getVideosList,
|
||||
immutableAssign,
|
||||
removeUser,
|
||||
removeVideo,
|
||||
reportAbuse,
|
||||
ServerInfo,
|
||||
|
@ -23,9 +27,9 @@ import {
|
|||
uploadVideo,
|
||||
uploadVideoAndGetId,
|
||||
userLogin,
|
||||
getAccount,
|
||||
removeUser,
|
||||
generateUserAccessToken
|
||||
addAbuseMessage,
|
||||
listAbuseMessages,
|
||||
deleteAbuseMessage
|
||||
} from '../../../../shared/extra-utils/index'
|
||||
import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
|
||||
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
||||
|
@ -40,8 +44,8 @@ const expect = chai.expect
|
|||
|
||||
describe('Test abuses', function () {
|
||||
let servers: ServerInfo[] = []
|
||||
let abuseServer1: Abuse
|
||||
let abuseServer2: Abuse
|
||||
let abuseServer1: AdminAbuse
|
||||
let abuseServer2: AdminAbuse
|
||||
|
||||
before(async function () {
|
||||
this.timeout(50000)
|
||||
|
@ -87,7 +91,7 @@ describe('Test abuses', function () {
|
|||
})
|
||||
|
||||
it('Should not have abuses', async function () {
|
||||
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
|
||||
expect(res.body.total).to.equal(0)
|
||||
expect(res.body.data).to.be.an('array')
|
||||
|
@ -105,13 +109,13 @@ describe('Test abuses', function () {
|
|||
})
|
||||
|
||||
it('Should have 1 video abuses on server 1 and 0 on server 2', async function () {
|
||||
const res1 = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const res1 = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
|
||||
expect(res1.body.total).to.equal(1)
|
||||
expect(res1.body.data).to.be.an('array')
|
||||
expect(res1.body.data.length).to.equal(1)
|
||||
|
||||
const abuse: Abuse = res1.body.data[0]
|
||||
const abuse: AdminAbuse = res1.body.data[0]
|
||||
expect(abuse.reason).to.equal('my super bad reason')
|
||||
|
||||
expect(abuse.reporterAccount.name).to.equal('root')
|
||||
|
@ -131,7 +135,7 @@ describe('Test abuses', function () {
|
|||
expect(abuse.countReportsForReporter).to.equal(1)
|
||||
expect(abuse.countReportsForReportee).to.equal(1)
|
||||
|
||||
const res2 = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken })
|
||||
const res2 = await getAdminAbusesList({ 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)
|
||||
|
@ -141,19 +145,20 @@ describe('Test abuses', function () {
|
|||
this.timeout(10000)
|
||||
|
||||
const reason = 'my super bad reason 2'
|
||||
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, videoId: servers[1].video.id, reason })
|
||||
const videoId = await getVideoIdFromUUID(servers[0].url, servers[1].video.uuid)
|
||||
await reportAbuse({ url: servers[0].url, token: servers[0].accessToken, videoId, reason })
|
||||
|
||||
// We wait requests propagation
|
||||
await waitJobs(servers)
|
||||
})
|
||||
|
||||
it('Should have 2 video abuses on server 1 and 1 on server 2', async function () {
|
||||
const res1 = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const res1 = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
|
||||
expect(res1.body.total).to.equal(2)
|
||||
expect(res1.body.data.length).to.equal(2)
|
||||
|
||||
const abuse1: Abuse = res1.body.data[0]
|
||||
const abuse1: AdminAbuse = res1.body.data[0]
|
||||
expect(abuse1.reason).to.equal('my super bad reason')
|
||||
expect(abuse1.reporterAccount.name).to.equal('root')
|
||||
expect(abuse1.reporterAccount.host).to.equal(servers[0].host)
|
||||
|
@ -171,7 +176,7 @@ describe('Test abuses', function () {
|
|||
expect(abuse1.state.label).to.equal('Pending')
|
||||
expect(abuse1.moderationComment).to.be.null
|
||||
|
||||
const abuse2: Abuse = res1.body.data[1]
|
||||
const abuse2: AdminAbuse = res1.body.data[1]
|
||||
expect(abuse2.reason).to.equal('my super bad reason 2')
|
||||
|
||||
expect(abuse2.reporterAccount.name).to.equal('root')
|
||||
|
@ -188,7 +193,7 @@ describe('Test abuses', function () {
|
|||
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 })
|
||||
const res2 = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken })
|
||||
expect(res2.body.total).to.equal(1)
|
||||
expect(res2.body.data.length).to.equal(1)
|
||||
|
||||
|
@ -213,7 +218,7 @@ describe('Test abuses', function () {
|
|||
await reportAbuse({ url: servers[1].url, token: servers[1].accessToken, videoId, reason: 'will mute this' })
|
||||
await waitJobs(servers)
|
||||
|
||||
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
expect(res.body.total).to.equal(3)
|
||||
}
|
||||
|
||||
|
@ -222,7 +227,7 @@ describe('Test abuses', function () {
|
|||
{
|
||||
await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
|
||||
|
||||
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const res = await getAdminAbusesList({ 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')
|
||||
|
@ -232,7 +237,7 @@ describe('Test abuses', function () {
|
|||
{
|
||||
await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
|
||||
|
||||
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
expect(res.body.total).to.equal(3)
|
||||
}
|
||||
})
|
||||
|
@ -243,7 +248,7 @@ describe('Test abuses', function () {
|
|||
{
|
||||
await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, servers[1].host)
|
||||
|
||||
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const res = await getAdminAbusesList({ 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')
|
||||
|
@ -253,7 +258,7 @@ describe('Test abuses', function () {
|
|||
{
|
||||
await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, serverToBlock)
|
||||
|
||||
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
expect(res.body.total).to.equal(3)
|
||||
}
|
||||
})
|
||||
|
@ -265,11 +270,11 @@ describe('Test abuses', function () {
|
|||
|
||||
await waitJobs(servers)
|
||||
|
||||
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken })
|
||||
const res = await getAdminAbusesList({ url: servers[1].url, token: servers[1].accessToken })
|
||||
expect(res.body.total).to.equal(2, "wrong number of videos returned")
|
||||
expect(res.body.data).to.have.lengthOf(2, "wrong number of videos returned")
|
||||
|
||||
const abuse: Abuse = res.body.data[0]
|
||||
const abuse: AdminAbuse = res.body.data[0]
|
||||
expect(abuse.id).to.equal(abuseServer2.id, "wrong origin server id for first video")
|
||||
expect(abuse.video.id).to.equal(abuseServer2.video.id, "wrong video id")
|
||||
expect(abuse.video.channel).to.exist
|
||||
|
@ -303,8 +308,8 @@ describe('Test abuses', function () {
|
|||
await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId: servers[0].video.id, reason: reason4 })
|
||||
|
||||
{
|
||||
const res2 = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const abuses = res2.body.data as Abuse[]
|
||||
const res2 = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const abuses = res2.body.data as AdminAbuse[]
|
||||
|
||||
const abuseVideo3 = res2.body.data.find(a => a.video.id === video3.id)
|
||||
expect(abuseVideo3).to.not.be.undefined
|
||||
|
@ -333,10 +338,10 @@ describe('Test abuses', function () {
|
|||
endAt: 5
|
||||
})).body.abuse
|
||||
|
||||
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const res = await getAdminAbusesList({ 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 AdminAbuse[]).find(a => a.id === createdAbuse.id)
|
||||
expect(abuse.reason).to.equals(reason5)
|
||||
expect(abuse.predefinedReasons).to.deep.equals(predefinedReasons5, "predefined reasons do not match the one reported")
|
||||
expect(abuse.video.startAt).to.equal(1, "starting timestamp doesn't match the one reported")
|
||||
|
@ -352,14 +357,14 @@ describe('Test abuses', function () {
|
|||
await waitJobs(servers)
|
||||
|
||||
{
|
||||
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken })
|
||||
const res = await getAdminAbusesList({ 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 getAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
expect(res.body.total).to.equal(6)
|
||||
}
|
||||
})
|
||||
|
@ -367,7 +372,7 @@ describe('Test abuses', function () {
|
|||
it('Should list and filter video abuses', async function () {
|
||||
this.timeout(10000)
|
||||
|
||||
async function list (query: Omit<Parameters<typeof getAbusesList>[0], 'url' | 'token'>) {
|
||||
async function list (query: Omit<Parameters<typeof getAdminAbusesList>[0], 'url' | 'token'>) {
|
||||
const options = {
|
||||
url: servers[0].url,
|
||||
token: servers[0].accessToken
|
||||
|
@ -375,9 +380,9 @@ describe('Test abuses', function () {
|
|||
|
||||
Object.assign(options, query)
|
||||
|
||||
const res = await getAbusesList(options)
|
||||
const res = await getAdminAbusesList(options)
|
||||
|
||||
return res.body.data as Abuse[]
|
||||
return res.body.data as AdminAbuse[]
|
||||
}
|
||||
|
||||
expect(await list({ id: 56 })).to.have.lengthOf(0)
|
||||
|
@ -446,12 +451,12 @@ describe('Test abuses', function () {
|
|||
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' })
|
||||
const res = await getAdminAbusesList({ 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]
|
||||
const abuse: AdminAbuse = res.body.data[0]
|
||||
expect(abuse.reason).to.equal('it is a bad comment')
|
||||
|
||||
expect(abuse.reporterAccount.name).to.equal('root')
|
||||
|
@ -471,7 +476,7 @@ describe('Test abuses', function () {
|
|||
}
|
||||
|
||||
{
|
||||
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
|
||||
const res = await getAdminAbusesList({ 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)
|
||||
}
|
||||
|
@ -491,16 +496,16 @@ describe('Test abuses', function () {
|
|||
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' })
|
||||
const res1 = await getAdminAbusesList({ 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]
|
||||
const abuse: AdminAbuse = 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]
|
||||
const abuse2: AdminAbuse = res1.body.data[1]
|
||||
|
||||
expect(abuse2.reason).to.equal('it is a really bad comment')
|
||||
|
||||
|
@ -523,7 +528,7 @@ describe('Test abuses', function () {
|
|||
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' })
|
||||
const res2 = await getAdminAbusesList({ 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)
|
||||
|
||||
|
@ -550,11 +555,11 @@ describe('Test abuses', function () {
|
|||
|
||||
await waitJobs(servers)
|
||||
|
||||
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'comment' })
|
||||
const res = await getAdminAbusesList({ 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)
|
||||
const abuse = (res.body.data as AdminAbuse[]).find(a => a.comment?.id === commentServer2.id)
|
||||
expect(abuse).to.not.be.undefined
|
||||
|
||||
expect(abuse.comment.text).to.be.empty
|
||||
|
@ -570,36 +575,46 @@ describe('Test abuses', function () {
|
|||
await waitJobs(servers)
|
||||
|
||||
{
|
||||
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
|
||||
const res = await getAdminAbusesList({ 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' })
|
||||
const res = await getAdminAbusesList({ 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' })
|
||||
const res = await getAdminAbusesList({
|
||||
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' })
|
||||
const res = await getAdminAbusesList({
|
||||
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' }))
|
||||
const res1 = await getAdminAbusesList(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' }))
|
||||
const res2 = await getAdminAbusesList(immutableAssign(baseParams, { sort: '-createdAt' }))
|
||||
expect(res2.body.data).to.have.lengthOf(1)
|
||||
expect(res2.body.data[0].comment.text).to.equal('comment server 1')
|
||||
}
|
||||
|
@ -638,12 +653,12 @@ describe('Test abuses', function () {
|
|||
|
||||
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' })
|
||||
const res = await getAdminAbusesList({ 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]
|
||||
const abuse: AdminAbuse = res.body.data[0]
|
||||
expect(abuse.reason).to.equal('it is a bad account')
|
||||
|
||||
expect(abuse.reporterAccount.name).to.equal('root')
|
||||
|
@ -657,7 +672,7 @@ describe('Test abuses', function () {
|
|||
}
|
||||
|
||||
{
|
||||
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'comment' })
|
||||
const res = await getAdminAbusesList({ 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)
|
||||
}
|
||||
|
@ -675,14 +690,14 @@ describe('Test abuses', function () {
|
|||
})
|
||||
|
||||
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' })
|
||||
const res1 = await getAdminAbusesList({ 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]
|
||||
const abuse: AdminAbuse = res1.body.data[0]
|
||||
expect(abuse.reason).to.equal('it is a bad account')
|
||||
|
||||
const abuse2: Abuse = res1.body.data[1]
|
||||
const abuse2: AdminAbuse = res1.body.data[1]
|
||||
expect(abuse2.reason).to.equal('it is a really bad account')
|
||||
|
||||
expect(abuse2.reporterAccount.name).to.equal('root')
|
||||
|
@ -696,7 +711,7 @@ describe('Test abuses', function () {
|
|||
|
||||
expect(abuse2.moderationComment).to.be.null
|
||||
|
||||
const res2 = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'account' })
|
||||
const res2 = await getAdminAbusesList({ 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)
|
||||
|
||||
|
@ -721,11 +736,11 @@ describe('Test abuses', function () {
|
|||
|
||||
await waitJobs(servers)
|
||||
|
||||
const res = await getAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'account' })
|
||||
const res = await getAdminAbusesList({ 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')
|
||||
const abuse = (res.body.data as AdminAbuse[]).find(a => a.reason === 'it is a really bad account')
|
||||
expect(abuse).to.not.be.undefined
|
||||
})
|
||||
|
||||
|
@ -737,13 +752,13 @@ describe('Test abuses', function () {
|
|||
await waitJobs(servers)
|
||||
|
||||
{
|
||||
const res = await getAbusesList({ url: servers[1].url, token: servers[1].accessToken, filter: 'account' })
|
||||
const res = await getAdminAbusesList({ 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' })
|
||||
const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, filter: 'account' })
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
abuseServer1 = res.body.data[0]
|
||||
|
@ -757,7 +772,7 @@ describe('Test abuses', 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 })
|
||||
const res = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, id: abuseServer1.id })
|
||||
expect(res.body.data[0].state.id).to.equal(AbuseState.REJECTED)
|
||||
})
|
||||
|
||||
|
@ -765,12 +780,184 @@ describe('Test abuses', 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 })
|
||||
const res = await getAdminAbusesList({ 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')
|
||||
})
|
||||
})
|
||||
|
||||
describe('My abuses', async function () {
|
||||
let abuseId1: number
|
||||
let userAccessToken: string
|
||||
|
||||
before(async function () {
|
||||
userAccessToken = await generateUserAccessToken(servers[0], 'user_42')
|
||||
|
||||
await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId: servers[0].video.id, reason: 'user reason 1' })
|
||||
|
||||
const videoId = await getVideoIdFromUUID(servers[0].url, servers[1].video.uuid)
|
||||
await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId, reason: 'user reason 2' })
|
||||
})
|
||||
|
||||
it('Should correctly list my abuses', async function () {
|
||||
{
|
||||
const res = await getUserAbusesList({ url: servers[0].url, token: userAccessToken, start: 0, count: 5, sort: 'createdAt' })
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const abuses: UserAbuse[] = res.body.data
|
||||
expect(abuses[0].reason).to.equal('user reason 1')
|
||||
expect(abuses[1].reason).to.equal('user reason 2')
|
||||
|
||||
abuseId1 = abuses[0].id
|
||||
}
|
||||
|
||||
{
|
||||
const res = await getUserAbusesList({ url: servers[0].url, token: userAccessToken, start: 1, count: 1, sort: 'createdAt' })
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const abuses: UserAbuse[] = res.body.data
|
||||
expect(abuses[0].reason).to.equal('user reason 2')
|
||||
}
|
||||
|
||||
{
|
||||
const res = await getUserAbusesList({ url: servers[0].url, token: userAccessToken, start: 1, count: 1, sort: '-createdAt' })
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const abuses: UserAbuse[] = res.body.data
|
||||
expect(abuses[0].reason).to.equal('user reason 1')
|
||||
}
|
||||
})
|
||||
|
||||
it('Should correctly filter my abuses by id', async function () {
|
||||
const res = await getUserAbusesList({ url: servers[0].url, token: userAccessToken, id: abuseId1 })
|
||||
|
||||
expect(res.body.total).to.equal(1)
|
||||
|
||||
const abuses: UserAbuse[] = res.body.data
|
||||
expect(abuses[0].reason).to.equal('user reason 1')
|
||||
})
|
||||
|
||||
it('Should correctly filter my abuses by search', async function () {
|
||||
const res = await getUserAbusesList({
|
||||
url: servers[0].url,
|
||||
token: userAccessToken,
|
||||
search: 'server 2'
|
||||
})
|
||||
|
||||
expect(res.body.total).to.equal(1)
|
||||
|
||||
const abuses: UserAbuse[] = res.body.data
|
||||
expect(abuses[0].reason).to.equal('user reason 2')
|
||||
})
|
||||
|
||||
it('Should correctly filter my abuses by state', async function () {
|
||||
const body = { state: AbuseState.REJECTED }
|
||||
await updateAbuse(servers[0].url, servers[0].accessToken, abuseId1, body)
|
||||
|
||||
const res = await getUserAbusesList({
|
||||
url: servers[0].url,
|
||||
token: userAccessToken,
|
||||
state: AbuseState.REJECTED
|
||||
})
|
||||
|
||||
expect(res.body.total).to.equal(1)
|
||||
|
||||
const abuses: UserAbuse[] = res.body.data
|
||||
expect(abuses[0].reason).to.equal('user reason 1')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Abuse messages', async function () {
|
||||
let abuseId: number
|
||||
let userAccessToken: string
|
||||
let abuseMessageUserId: number
|
||||
let abuseMessageModerationId: number
|
||||
|
||||
before(async function () {
|
||||
userAccessToken = await generateUserAccessToken(servers[0], 'user_43')
|
||||
|
||||
const res = await reportAbuse({
|
||||
url: servers[0].url,
|
||||
token: userAccessToken,
|
||||
videoId: servers[0].video.id,
|
||||
reason: 'user 43 reason 1'
|
||||
})
|
||||
|
||||
abuseId = res.body.abuse.id
|
||||
})
|
||||
|
||||
it('Should create some messages on the abuse', async function () {
|
||||
await addAbuseMessage(servers[0].url, userAccessToken, abuseId, 'message 1')
|
||||
await addAbuseMessage(servers[0].url, servers[0].accessToken, abuseId, 'message 2')
|
||||
await addAbuseMessage(servers[0].url, servers[0].accessToken, abuseId, 'message 3')
|
||||
await addAbuseMessage(servers[0].url, userAccessToken, abuseId, 'message 4')
|
||||
})
|
||||
|
||||
it('Should have the correct messages count when listing abuses', async function () {
|
||||
const results = await Promise.all([
|
||||
getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken, start: 0, count: 50 }),
|
||||
getUserAbusesList({ url: servers[0].url, token: userAccessToken, start: 0, count: 50 })
|
||||
])
|
||||
|
||||
for (const res of results) {
|
||||
const abuses: AdminAbuse[] = res.body.data
|
||||
const abuse = abuses.find(a => a.id === abuseId)
|
||||
expect(abuse.countMessages).to.equal(4)
|
||||
}
|
||||
})
|
||||
|
||||
it('Should correctly list messages of this abuse', async function () {
|
||||
const results = await Promise.all([
|
||||
listAbuseMessages(servers[0].url, servers[0].accessToken, abuseId),
|
||||
listAbuseMessages(servers[0].url, userAccessToken, abuseId)
|
||||
])
|
||||
|
||||
for (const res of results) {
|
||||
expect(res.body.total).to.equal(4)
|
||||
|
||||
const abuseMessages: AbuseMessage[] = res.body.data
|
||||
|
||||
expect(abuseMessages[0].message).to.equal('message 1')
|
||||
expect(abuseMessages[0].byModerator).to.be.false
|
||||
expect(abuseMessages[0].account.name).to.equal('user_43')
|
||||
|
||||
abuseMessageUserId = abuseMessages[0].id
|
||||
|
||||
expect(abuseMessages[1].message).to.equal('message 2')
|
||||
expect(abuseMessages[1].byModerator).to.be.true
|
||||
expect(abuseMessages[1].account.name).to.equal('root')
|
||||
|
||||
expect(abuseMessages[2].message).to.equal('message 3')
|
||||
expect(abuseMessages[2].byModerator).to.be.true
|
||||
expect(abuseMessages[2].account.name).to.equal('root')
|
||||
abuseMessageModerationId = abuseMessages[2].id
|
||||
|
||||
expect(abuseMessages[3].message).to.equal('message 4')
|
||||
expect(abuseMessages[3].byModerator).to.be.false
|
||||
expect(abuseMessages[3].account.name).to.equal('user_43')
|
||||
}
|
||||
})
|
||||
|
||||
it('Should delete messages', async function () {
|
||||
await deleteAbuseMessage(servers[0].url, servers[0].accessToken, abuseId, abuseMessageModerationId)
|
||||
await deleteAbuseMessage(servers[0].url, userAccessToken, abuseId, abuseMessageUserId)
|
||||
|
||||
const results = await Promise.all([
|
||||
listAbuseMessages(servers[0].url, servers[0].accessToken, abuseId),
|
||||
listAbuseMessages(servers[0].url, userAccessToken, abuseId)
|
||||
])
|
||||
|
||||
for (const res of results) {
|
||||
expect(res.body.total).to.equal(2)
|
||||
|
||||
const abuseMessages: AbuseMessage[] = res.body.data
|
||||
|
||||
expect(abuseMessages[0].message).to.equal('message 2')
|
||||
expect(abuseMessages[1].message).to.equal('message 4')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await cleanupTests(servers)
|
||||
})
|
||||
|
|
|
@ -11,8 +11,8 @@ import {
|
|||
createUser,
|
||||
deleteMe,
|
||||
flushAndRunServer,
|
||||
getAbusesList,
|
||||
getAccountRatings,
|
||||
getAdminAbusesList,
|
||||
getBlacklistedVideosList,
|
||||
getCustomConfig,
|
||||
getMyUserInformation,
|
||||
|
@ -928,7 +928,7 @@ describe('Test users', function () {
|
|||
const reason = 'my super bad reason'
|
||||
await reportAbuse({ url: server.url, token: user17AccessToken, videoId, reason })
|
||||
|
||||
const res1 = await getAbusesList({ url: server.url, token: server.accessToken })
|
||||
const res1 = await getAdminAbusesList({ url: server.url, token: server.accessToken })
|
||||
const abuseId = res1.body.data[0].id
|
||||
|
||||
const res2 = await getUserInformation(server.url, server.accessToken, user17Id, true)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import 'mocha'
|
||||
import * as chai from 'chai'
|
||||
import { Abuse, AbusePredefinedReasonsString, AbuseState } from '@shared/models'
|
||||
import { AbusePredefinedReasonsString, AbuseState, AdminAbuse } from '@shared/models'
|
||||
import {
|
||||
cleanupTests,
|
||||
createUser,
|
||||
|
@ -33,7 +33,7 @@ const expect = chai.expect
|
|||
|
||||
describe('Test video abuses', function () {
|
||||
let servers: ServerInfo[] = []
|
||||
let abuseServer2: Abuse
|
||||
let abuseServer2: AdminAbuse
|
||||
|
||||
before(async function () {
|
||||
this.timeout(50000)
|
||||
|
@ -97,7 +97,7 @@ describe('Test video abuses', function () {
|
|||
expect(res1.body.data).to.be.an('array')
|
||||
expect(res1.body.data.length).to.equal(1)
|
||||
|
||||
const abuse: Abuse = res1.body.data[0]
|
||||
const abuse: AdminAbuse = res1.body.data[0]
|
||||
expect(abuse.reason).to.equal('my super bad reason')
|
||||
expect(abuse.reporterAccount.name).to.equal('root')
|
||||
expect(abuse.reporterAccount.host).to.equal('localhost:' + servers[0].port)
|
||||
|
@ -130,7 +130,7 @@ describe('Test video abuses', function () {
|
|||
expect(res1.body.data).to.be.an('array')
|
||||
expect(res1.body.data.length).to.equal(2)
|
||||
|
||||
const abuse1: Abuse = res1.body.data[0]
|
||||
const abuse1: AdminAbuse = res1.body.data[0]
|
||||
expect(abuse1.reason).to.equal('my super bad reason')
|
||||
expect(abuse1.reporterAccount.name).to.equal('root')
|
||||
expect(abuse1.reporterAccount.host).to.equal('localhost:' + servers[0].port)
|
||||
|
@ -141,7 +141,7 @@ describe('Test video abuses', function () {
|
|||
expect(abuse1.video.countReports).to.equal(1)
|
||||
expect(abuse1.video.nthReport).to.equal(1)
|
||||
|
||||
const abuse2: Abuse = res1.body.data[1]
|
||||
const abuse2: AdminAbuse = res1.body.data[1]
|
||||
expect(abuse2.reason).to.equal('my super bad reason 2')
|
||||
expect(abuse2.reporterAccount.name).to.equal('root')
|
||||
expect(abuse2.reporterAccount.host).to.equal('localhost:' + servers[0].port)
|
||||
|
@ -245,7 +245,7 @@ describe('Test video abuses', function () {
|
|||
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 abuse: Abuse = res.body.data[0]
|
||||
const abuse: AdminAbuse = res.body.data[0]
|
||||
expect(abuse.video.id).to.equal(abuseServer2.video.id, "wrong video id")
|
||||
expect(abuse.video.channel).to.exist
|
||||
expect(abuse.video.deleted).to.be.true
|
||||
|
@ -279,7 +279,7 @@ describe('Test video abuses', function () {
|
|||
const res2 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||
|
||||
{
|
||||
for (const abuse of res2.body.data as Abuse[]) {
|
||||
for (const abuse of res2.body.data as AdminAbuse[]) {
|
||||
if (abuse.video.id === video3.id) {
|
||||
expect(abuse.video.countReports).to.equal(1, "wrong reports count for video 3")
|
||||
expect(abuse.video.nthReport).to.equal(1, "wrong report position in report list for video 3")
|
||||
|
@ -311,7 +311,7 @@ describe('Test video abuses', function () {
|
|||
const res = await getVideoAbusesList({ 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 AdminAbuse[]).find(a => a.id === createdAbuse.id)
|
||||
expect(abuse.reason).to.equals(reason5)
|
||||
expect(abuse.predefinedReasons).to.deep.equals(predefinedReasons5, "predefined reasons do not match the one reported")
|
||||
expect(abuse.video.startAt).to.equal(1, "starting timestamp doesn't match the one reported")
|
||||
|
@ -350,7 +350,7 @@ describe('Test video abuses', function () {
|
|||
|
||||
const res = await getVideoAbusesList(options)
|
||||
|
||||
return res.body.data as Abuse[]
|
||||
return res.body.data as AdminAbuse[]
|
||||
}
|
||||
|
||||
expect(await list({ id: 56 })).to.have.lengthOf(0)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
|
||||
import { PickWith } from '@shared/core-utils'
|
||||
import { AbuseModel } from '../../../models/abuse/abuse'
|
||||
import { MAccountFormattable } from '../account'
|
||||
|
||||
type Use<K extends keyof AbuseMessageModel, M> = PickWith<AbuseMessageModel, K, M>
|
||||
|
||||
// ############################################################################
|
||||
|
||||
export type MAbuseMessage = Omit<AbuseMessageModel, 'Account' | 'Abuse' | 'toFormattedJSON'>
|
||||
|
||||
export type MAbuseMessageId = Pick<AbuseModel, 'id'>
|
||||
|
||||
// ############################################################################
|
||||
|
||||
// Format for API
|
||||
|
||||
export type MAbuseMessageFormattable =
|
||||
MAbuseMessage &
|
||||
Use<'Account', MAccountFormattable>
|
|
@ -95,9 +95,15 @@ export type MAbuseFull =
|
|||
|
||||
// Format for API or AP object
|
||||
|
||||
export type MAbuseFormattable =
|
||||
export type MAbuseAdminFormattable =
|
||||
MAbuse &
|
||||
Use<'ReporterAccount', MAccountFormattable> &
|
||||
Use<'FlaggedAccount', MAccountFormattable> &
|
||||
Use<'VideoAbuse', MVideoAbuseFormattable> &
|
||||
Use<'VideoCommentAbuse', MCommentAbuseFormattable>
|
||||
|
||||
export type MAbuseUserFormattable =
|
||||
MAbuse &
|
||||
Use<'FlaggedAccount', MAccountFormattable> &
|
||||
Use<'VideoAbuse', MVideoAbuseFormattable> &
|
||||
Use<'VideoCommentAbuse', MCommentAbuseFormattable>
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export * from './abuse'
|
||||
export * from './abuse-message'
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { RegisterServerAuthExternalOptions } from '@server/types'
|
||||
import {
|
||||
MAbuse,
|
||||
MAbuseMessage,
|
||||
MAccountBlocklist,
|
||||
MActorUrl,
|
||||
MStreamingPlaylist,
|
||||
|
@ -78,6 +79,7 @@ declare module 'express' {
|
|||
videoCaption?: MVideoCaptionVideo
|
||||
|
||||
abuse?: MAbuse
|
||||
abuseMessage?: MAbuseMessage
|
||||
|
||||
videoStreamingPlaylist?: MStreamingPlaylist
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ function reportAbuse (options: {
|
|||
})
|
||||
}
|
||||
|
||||
function getAbusesList (options: {
|
||||
function getAdminAbusesList (options: {
|
||||
url: string
|
||||
token: string
|
||||
|
||||
|
@ -117,6 +117,48 @@ function getAbusesList (options: {
|
|||
})
|
||||
}
|
||||
|
||||
function getUserAbusesList (options: {
|
||||
url: string
|
||||
token: string
|
||||
|
||||
start?: number
|
||||
count?: number
|
||||
sort?: string
|
||||
|
||||
id?: number
|
||||
search?: string
|
||||
state?: AbuseState
|
||||
}) {
|
||||
const {
|
||||
url,
|
||||
token,
|
||||
start,
|
||||
count,
|
||||
sort,
|
||||
id,
|
||||
search,
|
||||
state
|
||||
} = options
|
||||
const path = '/api/v1/users/me/abuses'
|
||||
|
||||
const query = {
|
||||
id,
|
||||
search,
|
||||
state,
|
||||
start,
|
||||
count,
|
||||
sort: sort || 'createdAt'
|
||||
}
|
||||
|
||||
return makeGetRequest({
|
||||
url,
|
||||
path,
|
||||
token,
|
||||
query,
|
||||
statusCodeExpected: 200
|
||||
})
|
||||
}
|
||||
|
||||
function updateAbuse (
|
||||
url: string,
|
||||
token: string,
|
||||
|
@ -146,11 +188,49 @@ function deleteAbuse (url: string, token: string, abuseId: number, statusCodeExp
|
|||
})
|
||||
}
|
||||
|
||||
function listAbuseMessages (url: string, token: string, abuseId: number, statusCodeExpected = 200) {
|
||||
const path = '/api/v1/abuses/' + abuseId + '/messages'
|
||||
|
||||
return makeGetRequest({
|
||||
url,
|
||||
token,
|
||||
path,
|
||||
statusCodeExpected
|
||||
})
|
||||
}
|
||||
|
||||
function deleteAbuseMessage (url: string, token: string, abuseId: number, messageId: number, statusCodeExpected = 204) {
|
||||
const path = '/api/v1/abuses/' + abuseId + '/messages/' + messageId
|
||||
|
||||
return makeDeleteRequest({
|
||||
url,
|
||||
token,
|
||||
path,
|
||||
statusCodeExpected
|
||||
})
|
||||
}
|
||||
|
||||
function addAbuseMessage (url: string, token: string, abuseId: number, message: string, statusCodeExpected = 200) {
|
||||
const path = '/api/v1/abuses/' + abuseId + '/messages'
|
||||
|
||||
return makePostBodyRequest({
|
||||
url,
|
||||
token,
|
||||
path,
|
||||
fields: { message },
|
||||
statusCodeExpected
|
||||
})
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export {
|
||||
reportAbuse,
|
||||
getAbusesList,
|
||||
getAdminAbusesList,
|
||||
updateAbuse,
|
||||
deleteAbuse
|
||||
deleteAbuse,
|
||||
getUserAbusesList,
|
||||
listAbuseMessages,
|
||||
deleteAbuseMessage,
|
||||
addAbuseMessage
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { AccountSummary } from '@shared/models'
|
||||
|
||||
export interface AbuseMessage {
|
||||
id: number
|
||||
message: string
|
||||
byModerator: boolean
|
||||
|
||||
account: AccountSummary
|
||||
}
|
|
@ -4,7 +4,7 @@ import { AbusePredefinedReasonsString } from './abuse-reason.model'
|
|||
import { VideoConstant } from '../../videos/video-constant.model'
|
||||
import { VideoChannel } from '../../videos/channel/video-channel.model'
|
||||
|
||||
export interface VideoAbuse {
|
||||
export interface AdminVideoAbuse {
|
||||
id: number
|
||||
name: string
|
||||
uuid: string
|
||||
|
@ -23,7 +23,7 @@ export interface VideoAbuse {
|
|||
nthReport: number
|
||||
}
|
||||
|
||||
export interface VideoCommentAbuse {
|
||||
export interface AdminVideoCommentAbuse {
|
||||
id: number
|
||||
threadId: number
|
||||
|
||||
|
@ -38,7 +38,7 @@ export interface VideoCommentAbuse {
|
|||
deleted: boolean
|
||||
}
|
||||
|
||||
export interface Abuse {
|
||||
export interface AdminAbuse {
|
||||
id: number
|
||||
|
||||
reason: string
|
||||
|
@ -50,8 +50,8 @@ export interface Abuse {
|
|||
state: VideoConstant<AbuseState>
|
||||
moderationComment?: string
|
||||
|
||||
video?: VideoAbuse
|
||||
comment?: VideoCommentAbuse
|
||||
video?: AdminVideoAbuse
|
||||
comment?: AdminVideoCommentAbuse
|
||||
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
|
@ -59,6 +59,8 @@ export interface Abuse {
|
|||
countReportsForReporter?: number
|
||||
countReportsForReportee?: number
|
||||
|
||||
countMessages: number
|
||||
|
||||
// FIXME: deprecated in 2.3, remove the following properties
|
||||
|
||||
// @deprecated
|
||||
|
@ -71,3 +73,10 @@ export interface Abuse {
|
|||
// @deprecated
|
||||
nth?: number
|
||||
}
|
||||
|
||||
export type UserVideoAbuse = Omit<AdminVideoAbuse, 'countReports' | 'nthReport'>
|
||||
|
||||
export type UserVideoCommentAbuse = AdminVideoCommentAbuse
|
||||
|
||||
export type UserAbuse = Omit<AdminAbuse, 'reporterAccount' | 'countReportsForReportee' | 'countReportsForReporter' | 'startAt' | 'endAt'
|
||||
| 'count' | 'nth'>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
export * from './abuse-create.model'
|
||||
export * from './abuse-filter.type'
|
||||
export * from './abuse-message.model'
|
||||
export * from './abuse-reason.model'
|
||||
export * from './abuse-state.model'
|
||||
export * from './abuse-update.model'
|
||||
|
|
Loading…
Reference in New Issue