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 * as express from 'express'
|
||||||
import { createAccountAbuse, createVideoAbuse, createVideoCommentAbuse } from '@server/lib/moderation'
|
import { createAccountAbuse, createVideoAbuse, createVideoCommentAbuse } from '@server/lib/moderation'
|
||||||
import { AbuseModel } from '@server/models/abuse/abuse'
|
import { AbuseModel } from '@server/models/abuse/abuse'
|
||||||
|
import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
import { AbuseCreate, abusePredefinedReasonsMap, AbuseState, UserRight } from '../../../shared'
|
import { AbuseCreate, abusePredefinedReasonsMap, AbuseState, UserRight } from '../../../shared'
|
||||||
import { getFormattedObjects } from '../../helpers/utils'
|
import { getFormattedObjects } from '../../helpers/utils'
|
||||||
import { sequelizeTypescript } from '../../initializers/database'
|
import { sequelizeTypescript } from '../../initializers/database'
|
||||||
import {
|
import {
|
||||||
abuseGetValidator,
|
abuseGetValidator,
|
||||||
abuseListValidator,
|
abuseListForAdminsValidator,
|
||||||
abuseReportValidator,
|
abuseReportValidator,
|
||||||
abusesSortValidator,
|
abusesSortValidator,
|
||||||
abuseUpdateValidator,
|
abuseUpdateValidator,
|
||||||
|
addAbuseMessageValidator,
|
||||||
asyncMiddleware,
|
asyncMiddleware,
|
||||||
asyncRetryTransactionMiddleware,
|
asyncRetryTransactionMiddleware,
|
||||||
authenticate,
|
authenticate,
|
||||||
|
deleteAbuseMessageValidator,
|
||||||
ensureUserHasRight,
|
ensureUserHasRight,
|
||||||
|
getAbuseValidator,
|
||||||
paginationValidator,
|
paginationValidator,
|
||||||
setDefaultPagination,
|
setDefaultPagination,
|
||||||
setDefaultSort
|
setDefaultSort
|
||||||
|
@ -30,8 +34,8 @@ abuseRouter.get('/',
|
||||||
abusesSortValidator,
|
abusesSortValidator,
|
||||||
setDefaultSort,
|
setDefaultSort,
|
||||||
setDefaultPagination,
|
setDefaultPagination,
|
||||||
abuseListValidator,
|
abuseListForAdminsValidator,
|
||||||
asyncMiddleware(listAbuses)
|
asyncMiddleware(listAbusesForAdmins)
|
||||||
)
|
)
|
||||||
abuseRouter.put('/:id',
|
abuseRouter.put('/:id',
|
||||||
authenticate,
|
authenticate,
|
||||||
|
@ -51,13 +55,33 @@ abuseRouter.delete('/:id',
|
||||||
asyncRetryTransactionMiddleware(deleteAbuse)
|
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 {
|
export {
|
||||||
abuseRouter,
|
abuseRouter,
|
||||||
|
|
||||||
// FIXME: deprecated in 2.3. Remove these exports
|
// FIXME: deprecated in 2.3. Remove these exports
|
||||||
listAbuses,
|
listAbusesForAdmins,
|
||||||
updateAbuse,
|
updateAbuse,
|
||||||
deleteAbuse,
|
deleteAbuse,
|
||||||
reportAbuse
|
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 user = res.locals.oauth.token.user
|
||||||
const serverActor = await getServerActor()
|
const serverActor = await getServerActor()
|
||||||
|
|
||||||
const resultList = await AbuseModel.listForApi({
|
const resultList = await AbuseModel.listForAdminApi({
|
||||||
start: req.query.start,
|
start: req.query.start,
|
||||||
count: req.query.count,
|
count: req.query.count,
|
||||||
sort: req.query.sort,
|
sort: req.query.sort,
|
||||||
|
@ -87,7 +111,10 @@ async function listAbuses (req: express.Request, res: express.Response) {
|
||||||
user
|
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) {
|
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 })
|
return abuse.save({ transaction: t })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// TODO: Notification
|
||||||
|
|
||||||
// Do not send the delete to other instances, we updated OUR copy of this abuse
|
// Do not send the delete to other instances, we updated OUR copy of this abuse
|
||||||
|
|
||||||
return res.type('json').status(204).end()
|
return res.type('json').status(204).end()
|
||||||
|
@ -166,3 +195,41 @@ async function reportAbuse (req: express.Request, res: express.Response) {
|
||||||
|
|
||||||
return res.json({ abuse: { id } })
|
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 express from 'express'
|
||||||
import * as RateLimit from 'express-rate-limit'
|
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 { 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 { logger } from '../../../helpers/logger'
|
||||||
import { generateRandomString, getFormattedObjects } from '../../../helpers/utils'
|
import { generateRandomString, getFormattedObjects } from '../../../helpers/utils'
|
||||||
|
import { CONFIG } from '../../../initializers/config'
|
||||||
import { WEBSERVER } from '../../../initializers/constants'
|
import { WEBSERVER } from '../../../initializers/constants'
|
||||||
|
import { sequelizeTypescript } from '../../../initializers/database'
|
||||||
import { Emailer } from '../../../lib/emailer'
|
import { Emailer } from '../../../lib/emailer'
|
||||||
|
import { Notifier } from '../../../lib/notifier'
|
||||||
|
import { deleteUserToken } from '../../../lib/oauth-model'
|
||||||
import { Redis } from '../../../lib/redis'
|
import { Redis } from '../../../lib/redis'
|
||||||
import { createUserAccountAndChannelAndPlaylist, sendVerifyUserEmail } from '../../../lib/user'
|
import { createUserAccountAndChannelAndPlaylist, sendVerifyUserEmail } from '../../../lib/user'
|
||||||
import {
|
import {
|
||||||
|
@ -18,9 +28,9 @@ import {
|
||||||
setDefaultPagination,
|
setDefaultPagination,
|
||||||
setDefaultSort,
|
setDefaultSort,
|
||||||
userAutocompleteValidator,
|
userAutocompleteValidator,
|
||||||
usersListValidator,
|
|
||||||
usersAddValidator,
|
usersAddValidator,
|
||||||
usersGetValidator,
|
usersGetValidator,
|
||||||
|
usersListValidator,
|
||||||
usersRegisterValidator,
|
usersRegisterValidator,
|
||||||
usersRemoveValidator,
|
usersRemoveValidator,
|
||||||
usersSortValidator,
|
usersSortValidator,
|
||||||
|
@ -35,22 +45,13 @@ import {
|
||||||
usersVerifyEmailValidator
|
usersVerifyEmailValidator
|
||||||
} from '../../../middlewares/validators'
|
} from '../../../middlewares/validators'
|
||||||
import { UserModel } from '../../../models/account/user'
|
import { UserModel } from '../../../models/account/user'
|
||||||
import { auditLoggerFactory, getAuditIdFromRes, UserAuditView } from '../../../helpers/audit-logger'
|
|
||||||
import { meRouter } from './me'
|
import { meRouter } from './me'
|
||||||
import { deleteUserToken } from '../../../lib/oauth-model'
|
import { myAbusesRouter } from './my-abuses'
|
||||||
import { myBlocklistRouter } from './my-blocklist'
|
import { myBlocklistRouter } from './my-blocklist'
|
||||||
import { myVideoPlaylistsRouter } from './my-video-playlists'
|
|
||||||
import { myVideosHistoryRouter } from './my-history'
|
import { myVideosHistoryRouter } from './my-history'
|
||||||
import { myNotificationsRouter } from './my-notifications'
|
import { myNotificationsRouter } from './my-notifications'
|
||||||
import { Notifier } from '../../../lib/notifier'
|
|
||||||
import { mySubscriptionsRouter } from './my-subscriptions'
|
import { mySubscriptionsRouter } from './my-subscriptions'
|
||||||
import { CONFIG } from '../../../initializers/config'
|
import { myVideoPlaylistsRouter } from './my-video-playlists'
|
||||||
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'
|
|
||||||
|
|
||||||
const auditLogger = auditLoggerFactory('users')
|
const auditLogger = auditLoggerFactory('users')
|
||||||
|
|
||||||
|
@ -72,6 +73,7 @@ usersRouter.use('/', mySubscriptionsRouter)
|
||||||
usersRouter.use('/', myBlocklistRouter)
|
usersRouter.use('/', myBlocklistRouter)
|
||||||
usersRouter.use('/', myVideosHistoryRouter)
|
usersRouter.use('/', myVideosHistoryRouter)
|
||||||
usersRouter.use('/', myVideoPlaylistsRouter)
|
usersRouter.use('/', myVideoPlaylistsRouter)
|
||||||
|
usersRouter.use('/', myAbusesRouter)
|
||||||
usersRouter.use('/', meRouter)
|
usersRouter.use('/', meRouter)
|
||||||
|
|
||||||
usersRouter.get('/autocomplete',
|
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 { AbuseModel } from '@server/models/abuse/abuse'
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
import { AbuseCreate, UserRight, VideoAbuseCreate } from '../../../../shared'
|
import { AbuseCreate, UserRight, VideoAbuseCreate } from '../../../../shared'
|
||||||
import { getFormattedObjects } from '../../../helpers/utils'
|
|
||||||
import {
|
import {
|
||||||
abusesSortValidator,
|
abusesSortValidator,
|
||||||
asyncMiddleware,
|
asyncMiddleware,
|
||||||
|
@ -63,7 +62,7 @@ async function listVideoAbuses (req: express.Request, res: express.Response) {
|
||||||
const user = res.locals.oauth.token.user
|
const user = res.locals.oauth.token.user
|
||||||
const serverActor = await getServerActor()
|
const serverActor = await getServerActor()
|
||||||
|
|
||||||
const resultList = await AbuseModel.listForApi({
|
const resultList = await AbuseModel.listForAdminApi({
|
||||||
start: req.query.start,
|
start: req.query.start,
|
||||||
count: req.query.count,
|
count: req.query.count,
|
||||||
sort: req.query.sort,
|
sort: req.query.sort,
|
||||||
|
@ -81,7 +80,10 @@ async function listVideoAbuses (req: express.Request, res: express.Response) {
|
||||||
user
|
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) {
|
async function updateVideoAbuse (req: express.Request, res: express.Response) {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { chain } from 'lodash'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import * as winston from 'winston'
|
import * as winston from 'winston'
|
||||||
import { AUDIT_LOG_FILENAME } from '@server/initializers/constants'
|
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 { CustomConfig } from '../../shared/models/server/custom-config.model'
|
||||||
import { VideoComment } from '../../shared/models/videos/video-comment.model'
|
import { VideoComment } from '../../shared/models/videos/video-comment.model'
|
||||||
import { CONFIG } from '../initializers/config'
|
import { CONFIG } from '../initializers/config'
|
||||||
|
@ -219,7 +219,7 @@ const abuseKeysToKeep = [
|
||||||
'createdAt'
|
'createdAt'
|
||||||
]
|
]
|
||||||
class AbuseAuditView extends EntityAuditView {
|
class AbuseAuditView extends EntityAuditView {
|
||||||
constructor (private readonly abuse: Abuse) {
|
constructor (private readonly abuse: AdminAbuse) {
|
||||||
super(abuseKeysToKeep, 'abuse', abuse)
|
super(abuseKeysToKeep, 'abuse', abuse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants'
|
||||||
import { exists, isArray } from './misc'
|
import { exists, isArray } from './misc'
|
||||||
|
|
||||||
const ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.ABUSES
|
const ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.ABUSES
|
||||||
|
const ABUSE_MESSAGES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.ABUSE_MESSAGES
|
||||||
|
|
||||||
function isAbuseReasonValid (value: string) {
|
function isAbuseReasonValid (value: string) {
|
||||||
return exists(value) && validator.isLength(value, ABUSES_CONSTRAINTS_FIELDS.REASON)
|
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 {
|
export {
|
||||||
isAbuseReasonValid,
|
isAbuseReasonValid,
|
||||||
isAbuseFilterValid,
|
isAbuseFilterValid,
|
||||||
isAbusePredefinedReasonValid,
|
isAbusePredefinedReasonValid,
|
||||||
areAbusePredefinedReasonsValid as isAbusePredefinedReasonsValid,
|
isAbuseMessageValid,
|
||||||
|
areAbusePredefinedReasonsValid,
|
||||||
isAbuseTimestampValid,
|
isAbuseTimestampValid,
|
||||||
isAbuseTimestampCoherent,
|
isAbuseTimestampCoherent,
|
||||||
isAbuseModerationCommentValid,
|
isAbuseModerationCommentValid,
|
||||||
|
|
|
@ -206,6 +206,9 @@ const CONSTRAINTS_FIELDS = {
|
||||||
REASON: { min: 2, max: 3000 }, // Length
|
REASON: { min: 2, max: 3000 }, // Length
|
||||||
MODERATION_COMMENT: { min: 2, max: 3000 } // Length
|
MODERATION_COMMENT: { min: 2, max: 3000 } // Length
|
||||||
},
|
},
|
||||||
|
ABUSE_MESSAGES: {
|
||||||
|
MESSAGE: { min: 2, max: 3000 } // Length
|
||||||
|
},
|
||||||
VIDEO_BLACKLIST: {
|
VIDEO_BLACKLIST: {
|
||||||
REASON: { min: 2, max: 300 } // Length
|
REASON: { min: 2, max: 300 } // Length
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { QueryTypes, Transaction } from 'sequelize'
|
import { QueryTypes, Transaction } from 'sequelize'
|
||||||
import { Sequelize as SequelizeTypescript } from 'sequelize-typescript'
|
import { Sequelize as SequelizeTypescript } from 'sequelize-typescript'
|
||||||
import { AbuseModel } from '@server/models/abuse/abuse'
|
import { AbuseModel } from '@server/models/abuse/abuse'
|
||||||
|
import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
|
||||||
import { VideoAbuseModel } from '@server/models/abuse/video-abuse'
|
import { VideoAbuseModel } from '@server/models/abuse/video-abuse'
|
||||||
import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse'
|
import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse'
|
||||||
import { isTestInstance } from '../helpers/core-utils'
|
import { isTestInstance } from '../helpers/core-utils'
|
||||||
|
@ -87,6 +88,7 @@ async function initDatabaseModels (silent: boolean) {
|
||||||
TagModel,
|
TagModel,
|
||||||
AccountVideoRateModel,
|
AccountVideoRateModel,
|
||||||
UserModel,
|
UserModel,
|
||||||
|
AbuseMessageModel,
|
||||||
AbuseModel,
|
AbuseModel,
|
||||||
VideoCommentAbuseModel,
|
VideoCommentAbuseModel,
|
||||||
VideoAbuseModel,
|
VideoAbuseModel,
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { join } from 'path'
|
||||||
import { VideoChannelModel } from '@server/models/video/video-channel'
|
import { VideoChannelModel } from '@server/models/video/video-channel'
|
||||||
import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist'
|
import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist'
|
||||||
import { MVideoImport, MVideoImportVideo } from '@server/types/models/video/video-import'
|
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 { SendEmailOptions } from '../../shared/models/server/emailer.model'
|
||||||
import { isTestInstance, root } from '../helpers/core-utils'
|
import { isTestInstance, root } from '../helpers/core-utils'
|
||||||
import { bunyanLogger, logger } from '../helpers/logger'
|
import { bunyanLogger, logger } from '../helpers/logger'
|
||||||
|
@ -283,7 +283,7 @@ class Emailer {
|
||||||
}
|
}
|
||||||
|
|
||||||
addAbuseModeratorsNotification (to: string[], parameters: {
|
addAbuseModeratorsNotification (to: string[], parameters: {
|
||||||
abuse: Abuse
|
abuse: UserAbuse
|
||||||
abuseInstance: MAbuseFull
|
abuseInstance: MAbuseFull
|
||||||
reporter: string
|
reporter: string
|
||||||
}) {
|
}) {
|
||||||
|
|
|
@ -213,7 +213,7 @@ async function createAbuse (options: {
|
||||||
await sendAbuse(reporterAccount.Actor, abuseInstance, abuseInstance.FlaggedAccount, transaction)
|
await sendAbuse(reporterAccount.Actor, abuseInstance, abuseInstance.FlaggedAccount, transaction)
|
||||||
}
|
}
|
||||||
|
|
||||||
const abuseJSON = abuseInstance.toFormattedJSON()
|
const abuseJSON = abuseInstance.toFormattedAdminJSON()
|
||||||
auditLogger.create(reporterAccount.Actor.getIdentifier(), new AbuseAuditView(abuseJSON))
|
auditLogger.create(reporterAccount.Actor.getIdentifier(), new AbuseAuditView(abuseJSON))
|
||||||
|
|
||||||
Notifier.Instance.notifyOnNewAbuse({
|
Notifier.Instance.notifyOnNewAbuse({
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
} from '@server/types/models/user'
|
} from '@server/types/models/user'
|
||||||
import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist'
|
import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist'
|
||||||
import { MVideoImportVideo } from '@server/types/models/video/video-import'
|
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 { UserNotificationSettingValue, UserNotificationType, UserRight } from '../../shared/models/users'
|
||||||
import { VideoPrivacy, VideoState } from '../../shared/models/videos'
|
import { VideoPrivacy, VideoState } from '../../shared/models/videos'
|
||||||
import { logger } from '../helpers/logger'
|
import { logger } from '../helpers/logger'
|
||||||
|
@ -73,7 +73,7 @@ class Notifier {
|
||||||
.catch(err => logger.error('Cannot notify mentions of comment %s.', comment.url, { err }))
|
.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)
|
this.notifyModeratorsOfNewAbuse(parameters)
|
||||||
.catch(err => logger.error('Cannot notify of new abuse %d.', parameters.abuseInstance.id, { err }))
|
.catch(err => logger.error('Cannot notify of new abuse %d.', parameters.abuseInstance.id, { err }))
|
||||||
}
|
}
|
||||||
|
@ -350,7 +350,7 @@ class Notifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async notifyModeratorsOfNewAbuse (parameters: {
|
private async notifyModeratorsOfNewAbuse (parameters: {
|
||||||
abuse: Abuse
|
abuse: UserAbuse
|
||||||
abuseInstance: MAbuseFull
|
abuseInstance: MAbuseFull
|
||||||
reporter: string
|
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}.`
|
const message = `User ${user.username} does not have right ${UserRight[userRight]} to access to ${req.path}.`
|
||||||
logger.info(message)
|
logger.info(message)
|
||||||
|
|
||||||
return res.status(403)
|
return res.status(403).json({ error: message })
|
||||||
.json({
|
|
||||||
error: message
|
|
||||||
})
|
|
||||||
.end()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return next()
|
return next()
|
||||||
|
|
|
@ -2,8 +2,9 @@ import * as express from 'express'
|
||||||
import { body, param, query } from 'express-validator'
|
import { body, param, query } from 'express-validator'
|
||||||
import {
|
import {
|
||||||
isAbuseFilterValid,
|
isAbuseFilterValid,
|
||||||
|
isAbuseMessageValid,
|
||||||
isAbuseModerationCommentValid,
|
isAbuseModerationCommentValid,
|
||||||
isAbusePredefinedReasonsValid,
|
areAbusePredefinedReasonsValid,
|
||||||
isAbusePredefinedReasonValid,
|
isAbusePredefinedReasonValid,
|
||||||
isAbuseReasonValid,
|
isAbuseReasonValid,
|
||||||
isAbuseStateValid,
|
isAbuseStateValid,
|
||||||
|
@ -15,7 +16,8 @@ import { exists, isIdOrUUIDValid, isIdValid, toIntOrNull } from '@server/helpers
|
||||||
import { doesCommentIdExist } from '@server/helpers/custom-validators/video-comments'
|
import { doesCommentIdExist } from '@server/helpers/custom-validators/video-comments'
|
||||||
import { logger } from '@server/helpers/logger'
|
import { logger } from '@server/helpers/logger'
|
||||||
import { doesAbuseExist, doesAccountIdExist, doesVideoAbuseExist, doesVideoExist } from '@server/helpers/middlewares'
|
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'
|
import { areValidationErrors } from './utils'
|
||||||
|
|
||||||
const abuseReportValidator = [
|
const abuseReportValidator = [
|
||||||
|
@ -53,7 +55,7 @@ const abuseReportValidator = [
|
||||||
|
|
||||||
body('predefinedReasons')
|
body('predefinedReasons')
|
||||||
.optional()
|
.optional()
|
||||||
.custom(isAbusePredefinedReasonsValid)
|
.custom(areAbusePredefinedReasonsValid)
|
||||||
.withMessage('Should have a valid list of predefined reasons'),
|
.withMessage('Should have a valid list of predefined reasons'),
|
||||||
|
|
||||||
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
||||||
|
@ -111,7 +113,7 @@ const abuseUpdateValidator = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
const abuseListValidator = [
|
const abuseListForAdminsValidator = [
|
||||||
query('id')
|
query('id')
|
||||||
.optional()
|
.optional()
|
||||||
.custom(isIdValid).withMessage('Should have a valid id'),
|
.custom(isIdValid).withMessage('Should have a valid id'),
|
||||||
|
@ -146,7 +148,7 @@ const abuseListValidator = [
|
||||||
.custom(exists).withMessage('Should have a valid video channel search'),
|
.custom(exists).withMessage('Should have a valid video channel search'),
|
||||||
|
|
||||||
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
(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
|
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
|
// FIXME: deprecated in 2.3. Remove these validators
|
||||||
|
|
||||||
const videoAbuseReportValidator = [
|
const videoAbuseReportValidator = [
|
||||||
|
@ -167,7 +254,7 @@ const videoAbuseReportValidator = [
|
||||||
.withMessage('Should have a valid reason'),
|
.withMessage('Should have a valid reason'),
|
||||||
body('predefinedReasons')
|
body('predefinedReasons')
|
||||||
.optional()
|
.optional()
|
||||||
.custom(isAbusePredefinedReasonsValid)
|
.custom(areAbusePredefinedReasonsValid)
|
||||||
.withMessage('Should have a valid list of predefined reasons'),
|
.withMessage('Should have a valid list of predefined reasons'),
|
||||||
body('startAt')
|
body('startAt')
|
||||||
.optional()
|
.optional()
|
||||||
|
@ -266,10 +353,14 @@ const videoAbuseListValidator = [
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
abuseListValidator,
|
abuseListForAdminsValidator,
|
||||||
abuseReportValidator,
|
abuseReportValidator,
|
||||||
abuseGetValidator,
|
abuseGetValidator,
|
||||||
|
addAbuseMessageValidator,
|
||||||
abuseUpdateValidator,
|
abuseUpdateValidator,
|
||||||
|
deleteAbuseMessageValidator,
|
||||||
|
abuseListForUserValidator,
|
||||||
|
getAbuseValidator,
|
||||||
videoAbuseReportValidator,
|
videoAbuseReportValidator,
|
||||||
videoAbuseGetValidator,
|
videoAbuseGetValidator,
|
||||||
videoAbuseUpdateValidator,
|
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
|
state?: AbuseState
|
||||||
|
|
||||||
// accountIds
|
// accountIds
|
||||||
serverAccountId: number
|
serverAccountId?: number
|
||||||
userAccountId: number
|
userAccountId?: number
|
||||||
|
|
||||||
|
reporterAccountId?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildAbuseListQuery (options: BuildAbusesQueryOptions, type: 'count' | 'id') {
|
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"'
|
'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) {
|
if (options.search) {
|
||||||
const searchWhereOr = [
|
const searchWhereOr = [
|
||||||
|
|
|
@ -18,7 +18,6 @@ import {
|
||||||
} from 'sequelize-typescript'
|
} from 'sequelize-typescript'
|
||||||
import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses'
|
import { isAbuseModerationCommentValid, isAbuseReasonValid, isAbuseStateValid } from '@server/helpers/custom-validators/abuses'
|
||||||
import {
|
import {
|
||||||
Abuse,
|
|
||||||
AbuseFilter,
|
AbuseFilter,
|
||||||
AbuseObject,
|
AbuseObject,
|
||||||
AbusePredefinedReasons,
|
AbusePredefinedReasons,
|
||||||
|
@ -26,11 +25,14 @@ import {
|
||||||
AbusePredefinedReasonsString,
|
AbusePredefinedReasonsString,
|
||||||
AbuseState,
|
AbuseState,
|
||||||
AbuseVideoIs,
|
AbuseVideoIs,
|
||||||
VideoAbuse,
|
AdminVideoAbuse,
|
||||||
VideoCommentAbuse
|
AdminAbuse,
|
||||||
|
AdminVideoCommentAbuse,
|
||||||
|
UserAbuse,
|
||||||
|
UserVideoAbuse
|
||||||
} from '@shared/models'
|
} from '@shared/models'
|
||||||
import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants'
|
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 { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account'
|
||||||
import { getSort, throwIfNotValid } from '../utils'
|
import { getSort, throwIfNotValid } from '../utils'
|
||||||
import { ThumbnailModel } from '../video/thumbnail'
|
import { ThumbnailModel } from '../video/thumbnail'
|
||||||
|
@ -51,6 +53,16 @@ export enum ScopeNames {
|
||||||
return {
|
return {
|
||||||
attributes: {
|
attributes: {
|
||||||
include: [
|
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
|
// we don't care about this count for deleted videos, so there are not included
|
||||||
literal(
|
literal(
|
||||||
|
@ -285,7 +297,7 @@ export class AbuseModel extends Model<AbuseModel> {
|
||||||
return AbuseModel.findOne(query)
|
return AbuseModel.findOne(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
static async listForApi (parameters: {
|
static async listForAdminApi (parameters: {
|
||||||
start: number
|
start: number
|
||||||
count: number
|
count: number
|
||||||
sort: string
|
sort: string
|
||||||
|
@ -353,71 +365,98 @@ export class AbuseModel extends Model<AbuseModel> {
|
||||||
return { total, data }
|
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 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 {
|
return {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
reason: this.reason,
|
reason: this.reason,
|
||||||
predefinedReasons,
|
predefinedReasons,
|
||||||
|
|
||||||
reporterAccount: this.ReporterAccount
|
|
||||||
? this.ReporterAccount.toFormattedJSON()
|
|
||||||
: null,
|
|
||||||
|
|
||||||
flaggedAccount: this.FlaggedAccount
|
flaggedAccount: this.FlaggedAccount
|
||||||
? this.FlaggedAccount.toFormattedJSON()
|
? this.FlaggedAccount.toFormattedJSON()
|
||||||
: null,
|
: null,
|
||||||
|
@ -429,11 +468,41 @@ export class AbuseModel extends Model<AbuseModel> {
|
||||||
|
|
||||||
moderationComment: this.moderationComment,
|
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,
|
video,
|
||||||
comment,
|
comment,
|
||||||
|
|
||||||
createdAt: this.createdAt,
|
reporterAccount: this.ReporterAccount
|
||||||
updatedAt: this.updatedAt,
|
? this.ReporterAccount.toFormattedJSON()
|
||||||
|
: null,
|
||||||
|
|
||||||
countReportsForReporter: (countReportsForReporter || 0),
|
countReportsForReporter: (countReportsForReporter || 0),
|
||||||
countReportsForReportee: (countReportsForReportee || 0),
|
countReportsForReportee: (countReportsForReportee || 0),
|
||||||
|
@ -443,7 +512,20 @@ export class AbuseModel extends Model<AbuseModel> {
|
||||||
endAt: null,
|
endAt: null,
|
||||||
count: countReportsForVideo || 0,
|
count: countReportsForVideo || 0,
|
||||||
nth: nthReportForVideo || 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 {
|
toActivityPubObject (this: MAbuseAP): AbuseObject {
|
||||||
|
|
|
@ -13,7 +13,11 @@ import {
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
updateAbuse,
|
updateAbuse,
|
||||||
uploadVideo,
|
uploadVideo,
|
||||||
userLogin
|
userLogin,
|
||||||
|
generateUserAccessToken,
|
||||||
|
addAbuseMessage,
|
||||||
|
listAbuseMessages,
|
||||||
|
deleteAbuseMessage
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
import {
|
import {
|
||||||
checkBadCountPagination,
|
checkBadCountPagination,
|
||||||
|
@ -26,7 +30,9 @@ describe('Test abuses API validators', function () {
|
||||||
|
|
||||||
let server: ServerInfo
|
let server: ServerInfo
|
||||||
let userAccessToken = ''
|
let userAccessToken = ''
|
||||||
|
let userAccessToken2 = ''
|
||||||
let abuseId: number
|
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 })
|
await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password })
|
||||||
userAccessToken = await userLogin(server, { username, password })
|
userAccessToken = await userLogin(server, { username, password })
|
||||||
|
|
||||||
|
{
|
||||||
|
userAccessToken2 = await generateUserAccessToken(server, 'user_2')
|
||||||
|
}
|
||||||
|
|
||||||
const res = await uploadVideo(server.url, server.accessToken, {})
|
const res = await uploadVideo(server.url, server.accessToken, {})
|
||||||
server.video = res.body.video
|
server.video = res.body.video
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('When listing abuses', function () {
|
describe('When listing abuses for admins', function () {
|
||||||
const path = basePath
|
const path = basePath
|
||||||
|
|
||||||
it('Should fail with a bad start pagination', async function () {
|
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 () {
|
describe('When reporting an abuse', function () {
|
||||||
const path = basePath
|
const path = basePath
|
||||||
|
|
||||||
it('Should fail with nothing', async function () {
|
it('Should fail with nothing', async function () {
|
||||||
const fields = {}
|
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 () {
|
it('Should fail with a wrong video', async function () {
|
||||||
const fields = { video: { id: 'blabla' }, reason: 'my super reason' }
|
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 () {
|
it('Should fail with an unknown video', async function () {
|
||||||
const fields = { video: { id: 42 }, reason: 'my super reason' }
|
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 () {
|
it('Should fail with a wrong comment', async function () {
|
||||||
const fields = { comment: { id: 'blabla' }, reason: 'my super reason' }
|
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 () {
|
it('Should fail with an unknown comment', async function () {
|
||||||
const fields = { comment: { id: 42 }, reason: 'my super reason' }
|
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 () {
|
it('Should fail with a wrong account', async function () {
|
||||||
const fields = { account: { id: 'blabla' }, reason: 'my super reason' }
|
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 () {
|
it('Should fail with an unknown account', async function () {
|
||||||
const fields = { account: { id: 42 }, reason: 'my super reason' }
|
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 () {
|
it('Should fail with not account, comment or video', async function () {
|
||||||
const fields = { reason: 'my super reason' }
|
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 () {
|
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 () {
|
it('Should fail with a reason too short', async function () {
|
||||||
const fields = { video: { id: server.video.id }, reason: 'h' }
|
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 () {
|
it('Should fail with a too big reason', async function () {
|
||||||
const fields = { video: { id: server.video.id }, reason: 'super'.repeat(605) }
|
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 () {
|
it('Should succeed with the correct parameters (basic)', async function () {
|
||||||
const fields: AbuseCreate = { video: { id: server.video.id }, reason: 'my super reason' }
|
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
|
abuseId = res.body.abuse.id
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a wrong predefined reason', async function () {
|
it('Should fail with a wrong predefined reason', async function () {
|
||||||
const fields = { video: { id: server.video.id }, reason: 'my super reason', predefinedReasons: [ 'wrongPredefinedReason' ] }
|
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 () {
|
it('Should fail with negative timestamps', async function () {
|
||||||
const fields = { video: { id: server.video.id, startAt: -1 }, reason: 'my super reason' }
|
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 () {
|
it('Should fail mith misordered startAt/endAt', async function () {
|
||||||
const fields = { video: { id: server.video.id, startAt: 5, endAt: 1 }, reason: 'my super reason' }
|
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 () {
|
it('Should succeed with the corret parameters (advanced)', async function () {
|
||||||
|
@ -210,7 +262,7 @@ describe('Test abuses API validators', function () {
|
||||||
predefinedReasons: [ 'serverRules' ]
|
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 () {
|
describe('When deleting a video abuse', function () {
|
||||||
|
|
||||||
it('Should fail with a non authenticated user', async function () {
|
it('Should fail with a non authenticated user', async function () {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import 'mocha'
|
import 'mocha'
|
||||||
import * as chai from 'chai'
|
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 {
|
import {
|
||||||
addVideoCommentThread,
|
addVideoCommentThread,
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
|
@ -10,11 +10,15 @@ import {
|
||||||
deleteAbuse,
|
deleteAbuse,
|
||||||
deleteVideoComment,
|
deleteVideoComment,
|
||||||
flushAndRunMultipleServers,
|
flushAndRunMultipleServers,
|
||||||
getAbusesList,
|
generateUserAccessToken,
|
||||||
|
getAccount,
|
||||||
|
getAdminAbusesList,
|
||||||
|
getUserAbusesList,
|
||||||
getVideoCommentThreads,
|
getVideoCommentThreads,
|
||||||
getVideoIdFromUUID,
|
getVideoIdFromUUID,
|
||||||
getVideosList,
|
getVideosList,
|
||||||
immutableAssign,
|
immutableAssign,
|
||||||
|
removeUser,
|
||||||
removeVideo,
|
removeVideo,
|
||||||
reportAbuse,
|
reportAbuse,
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
|
@ -23,9 +27,9 @@ import {
|
||||||
uploadVideo,
|
uploadVideo,
|
||||||
uploadVideoAndGetId,
|
uploadVideoAndGetId,
|
||||||
userLogin,
|
userLogin,
|
||||||
getAccount,
|
addAbuseMessage,
|
||||||
removeUser,
|
listAbuseMessages,
|
||||||
generateUserAccessToken
|
deleteAbuseMessage
|
||||||
} from '../../../../shared/extra-utils/index'
|
} from '../../../../shared/extra-utils/index'
|
||||||
import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
|
import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
|
||||||
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
||||||
|
@ -40,8 +44,8 @@ const expect = chai.expect
|
||||||
|
|
||||||
describe('Test abuses', function () {
|
describe('Test abuses', function () {
|
||||||
let servers: ServerInfo[] = []
|
let servers: ServerInfo[] = []
|
||||||
let abuseServer1: Abuse
|
let abuseServer1: AdminAbuse
|
||||||
let abuseServer2: Abuse
|
let abuseServer2: AdminAbuse
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
this.timeout(50000)
|
this.timeout(50000)
|
||||||
|
@ -87,7 +91,7 @@ describe('Test abuses', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not have abuses', async 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.total).to.equal(0)
|
||||||
expect(res.body.data).to.be.an('array')
|
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 () {
|
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.total).to.equal(1)
|
||||||
expect(res1.body.data).to.be.an('array')
|
expect(res1.body.data).to.be.an('array')
|
||||||
expect(res1.body.data.length).to.equal(1)
|
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.reason).to.equal('my super bad reason')
|
||||||
|
|
||||||
expect(abuse.reporterAccount.name).to.equal('root')
|
expect(abuse.reporterAccount.name).to.equal('root')
|
||||||
|
@ -131,7 +135,7 @@ describe('Test abuses', function () {
|
||||||
expect(abuse.countReportsForReporter).to.equal(1)
|
expect(abuse.countReportsForReporter).to.equal(1)
|
||||||
expect(abuse.countReportsForReportee).to.equal(1)
|
expect(abuse.countReportsForReportee).to.equal(1)
|
||||||
|
|
||||||
const res2 = await 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.total).to.equal(0)
|
||||||
expect(res2.body.data).to.be.an('array')
|
expect(res2.body.data).to.be.an('array')
|
||||||
expect(res2.body.data.length).to.equal(0)
|
expect(res2.body.data.length).to.equal(0)
|
||||||
|
@ -141,19 +145,20 @@ describe('Test abuses', function () {
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
|
|
||||||
const reason = 'my super bad reason 2'
|
const reason = 'my super bad reason 2'
|
||||||
await 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
|
// We wait requests propagation
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have 2 video abuses on server 1 and 1 on server 2', async function () {
|
it('Should have 2 video abuses on server 1 and 1 on server 2', async function () {
|
||||||
const res1 = await 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.total).to.equal(2)
|
||||||
expect(res1.body.data.length).to.equal(2)
|
expect(res1.body.data.length).to.equal(2)
|
||||||
|
|
||||||
const abuse1: Abuse = res1.body.data[0]
|
const abuse1: AdminAbuse = res1.body.data[0]
|
||||||
expect(abuse1.reason).to.equal('my super bad reason')
|
expect(abuse1.reason).to.equal('my super bad reason')
|
||||||
expect(abuse1.reporterAccount.name).to.equal('root')
|
expect(abuse1.reporterAccount.name).to.equal('root')
|
||||||
expect(abuse1.reporterAccount.host).to.equal(servers[0].host)
|
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.state.label).to.equal('Pending')
|
||||||
expect(abuse1.moderationComment).to.be.null
|
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.reason).to.equal('my super bad reason 2')
|
||||||
|
|
||||||
expect(abuse2.reporterAccount.name).to.equal('root')
|
expect(abuse2.reporterAccount.name).to.equal('root')
|
||||||
|
@ -188,7 +193,7 @@ describe('Test abuses', function () {
|
||||||
expect(abuse2.state.label).to.equal('Pending')
|
expect(abuse2.state.label).to.equal('Pending')
|
||||||
expect(abuse2.moderationComment).to.be.null
|
expect(abuse2.moderationComment).to.be.null
|
||||||
|
|
||||||
const res2 = await 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.total).to.equal(1)
|
||||||
expect(res2.body.data.length).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 reportAbuse({ url: servers[1].url, token: servers[1].accessToken, videoId, reason: 'will mute this' })
|
||||||
await waitJobs(servers)
|
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)
|
expect(res.body.total).to.equal(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +227,7 @@ describe('Test abuses', function () {
|
||||||
{
|
{
|
||||||
await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
|
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)
|
expect(res.body.total).to.equal(2)
|
||||||
|
|
||||||
const abuse = res.body.data.find(a => a.reason === 'will mute this')
|
const abuse = res.body.data.find(a => a.reason === 'will mute this')
|
||||||
|
@ -232,7 +237,7 @@ describe('Test abuses', function () {
|
||||||
{
|
{
|
||||||
await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
|
await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock)
|
||||||
|
|
||||||
const res = await 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)
|
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)
|
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)
|
expect(res.body.total).to.equal(2)
|
||||||
|
|
||||||
const abuse = res.body.data.find(a => a.reason === 'will mute this')
|
const abuse = res.body.data.find(a => a.reason === 'will mute this')
|
||||||
|
@ -253,7 +258,7 @@ describe('Test abuses', function () {
|
||||||
{
|
{
|
||||||
await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, serverToBlock)
|
await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, serverToBlock)
|
||||||
|
|
||||||
const res = await 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)
|
expect(res.body.total).to.equal(3)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -265,11 +270,11 @@ describe('Test abuses', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
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.total).to.equal(2, "wrong number of videos returned")
|
||||||
expect(res.body.data).to.have.lengthOf(2, "wrong number of videos returned")
|
expect(res.body.data).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.id).to.equal(abuseServer2.id, "wrong origin server id for first video")
|
||||||
expect(abuse.video.id).to.equal(abuseServer2.video.id, "wrong video id")
|
expect(abuse.video.id).to.equal(abuseServer2.video.id, "wrong video id")
|
||||||
expect(abuse.video.channel).to.exist
|
expect(abuse.video.channel).to.exist
|
||||||
|
@ -303,8 +308,8 @@ describe('Test abuses', function () {
|
||||||
await reportAbuse({ url: servers[0].url, token: userAccessToken, videoId: servers[0].video.id, reason: reason4 })
|
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 res2 = await getAdminAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
||||||
const abuses = res2.body.data as Abuse[]
|
const abuses = res2.body.data as AdminAbuse[]
|
||||||
|
|
||||||
const abuseVideo3 = res2.body.data.find(a => a.video.id === video3.id)
|
const abuseVideo3 = res2.body.data.find(a => a.video.id === video3.id)
|
||||||
expect(abuseVideo3).to.not.be.undefined
|
expect(abuseVideo3).to.not.be.undefined
|
||||||
|
@ -333,10 +338,10 @@ describe('Test abuses', function () {
|
||||||
endAt: 5
|
endAt: 5
|
||||||
})).body.abuse
|
})).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.reason).to.equals(reason5)
|
||||||
expect(abuse.predefinedReasons).to.deep.equals(predefinedReasons5, "predefined reasons do not match the one reported")
|
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")
|
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)
|
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.total).to.equal(1)
|
||||||
expect(res.body.data.length).to.equal(1)
|
expect(res.body.data.length).to.equal(1)
|
||||||
expect(res.body.data[0].id).to.not.equal(abuseServer2.id)
|
expect(res.body.data[0].id).to.not.equal(abuseServer2.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
const res = await 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)
|
expect(res.body.total).to.equal(6)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -367,7 +372,7 @@ describe('Test abuses', function () {
|
||||||
it('Should list and filter video abuses', async function () {
|
it('Should list and filter video abuses', async function () {
|
||||||
this.timeout(10000)
|
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 = {
|
const options = {
|
||||||
url: servers[0].url,
|
url: servers[0].url,
|
||||||
token: servers[0].accessToken
|
token: servers[0].accessToken
|
||||||
|
@ -375,9 +380,9 @@ describe('Test abuses', function () {
|
||||||
|
|
||||||
Object.assign(options, query)
|
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)
|
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 () {
|
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 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.total).to.equal(1)
|
||||||
expect(res.body.data).to.have.lengthOf(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.reason).to.equal('it is a bad comment')
|
||||||
|
|
||||||
expect(abuse.reporterAccount.name).to.equal('root')
|
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.total).to.equal(0)
|
||||||
expect(res.body.data.length).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 () {
|
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 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.total).to.equal(2)
|
||||||
expect(res1.body.data.length).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.reason).to.equal('it is a bad comment')
|
||||||
expect(abuse.countReportsForReporter).to.equal(6)
|
expect(abuse.countReportsForReporter).to.equal(6)
|
||||||
expect(abuse.countReportsForReportee).to.equal(5)
|
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')
|
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.countReportsForReporter).to.equal(6)
|
||||||
expect(abuse2.countReportsForReportee).to.equal(2)
|
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.total).to.equal(1)
|
||||||
expect(res2.body.data.length).to.equal(1)
|
expect(res2.body.data.length).to.equal(1)
|
||||||
|
|
||||||
|
@ -550,11 +555,11 @@ describe('Test abuses', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
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.total).to.equal(2)
|
||||||
expect(res.body.data).to.have.lengthOf(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).to.not.be.undefined
|
||||||
|
|
||||||
expect(abuse.comment.text).to.be.empty
|
expect(abuse.comment.text).to.be.empty
|
||||||
|
@ -570,36 +575,46 @@ describe('Test abuses', function () {
|
||||||
await waitJobs(servers)
|
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.total).to.equal(0)
|
||||||
expect(res.body.data.length).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)
|
expect(res.body.total).to.equal(2)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should list and filter video abuses', async function () {
|
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)
|
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)
|
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 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).to.have.lengthOf(1)
|
||||||
expect(res1.body.data[0].comment.text).to.be.empty
|
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).to.have.lengthOf(1)
|
||||||
expect(res2.body.data[0].comment.text).to.equal('comment server 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 () {
|
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.total).to.equal(1)
|
||||||
expect(res.body.data).to.have.lengthOf(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.reason).to.equal('it is a bad account')
|
||||||
|
|
||||||
expect(abuse.reporterAccount.name).to.equal('root')
|
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.total).to.equal(0)
|
||||||
expect(res.body.data.length).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 () {
|
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.total).to.equal(2)
|
||||||
expect(res1.body.data.length).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')
|
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.reason).to.equal('it is a really bad account')
|
||||||
|
|
||||||
expect(abuse2.reporterAccount.name).to.equal('root')
|
expect(abuse2.reporterAccount.name).to.equal('root')
|
||||||
|
@ -696,7 +711,7 @@ describe('Test abuses', function () {
|
||||||
|
|
||||||
expect(abuse2.moderationComment).to.be.null
|
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.total).to.equal(1)
|
||||||
expect(res2.body.data.length).to.equal(1)
|
expect(res2.body.data.length).to.equal(1)
|
||||||
|
|
||||||
|
@ -721,11 +736,11 @@ describe('Test abuses', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
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.total).to.equal(2)
|
||||||
expect(res.body.data).to.have.lengthOf(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
|
expect(abuse).to.not.be.undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -737,13 +752,13 @@ describe('Test abuses', function () {
|
||||||
await waitJobs(servers)
|
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.total).to.equal(0)
|
||||||
expect(res.body.data.length).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)
|
expect(res.body.total).to.equal(2)
|
||||||
|
|
||||||
abuseServer1 = res.body.data[0]
|
abuseServer1 = res.body.data[0]
|
||||||
|
@ -757,7 +772,7 @@ describe('Test abuses', function () {
|
||||||
const body = { state: AbuseState.REJECTED }
|
const body = { state: AbuseState.REJECTED }
|
||||||
await updateAbuse(servers[0].url, servers[0].accessToken, abuseServer1.id, body)
|
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)
|
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' }
|
const body = { state: AbuseState.ACCEPTED, moderationComment: 'It is valid' }
|
||||||
await updateAbuse(servers[0].url, servers[0].accessToken, abuseServer1.id, body)
|
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].state.id).to.equal(AbuseState.ACCEPTED)
|
||||||
expect(res.body.data[0].moderationComment).to.equal('It is valid')
|
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 () {
|
after(async function () {
|
||||||
await cleanupTests(servers)
|
await cleanupTests(servers)
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,8 +11,8 @@ import {
|
||||||
createUser,
|
createUser,
|
||||||
deleteMe,
|
deleteMe,
|
||||||
flushAndRunServer,
|
flushAndRunServer,
|
||||||
getAbusesList,
|
|
||||||
getAccountRatings,
|
getAccountRatings,
|
||||||
|
getAdminAbusesList,
|
||||||
getBlacklistedVideosList,
|
getBlacklistedVideosList,
|
||||||
getCustomConfig,
|
getCustomConfig,
|
||||||
getMyUserInformation,
|
getMyUserInformation,
|
||||||
|
@ -928,7 +928,7 @@ describe('Test users', function () {
|
||||||
const reason = 'my super bad reason'
|
const reason = 'my super bad reason'
|
||||||
await reportAbuse({ url: server.url, token: user17AccessToken, videoId, 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 abuseId = res1.body.data[0].id
|
||||||
|
|
||||||
const res2 = await getUserInformation(server.url, server.accessToken, user17Id, true)
|
const res2 = await getUserInformation(server.url, server.accessToken, user17Id, true)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import 'mocha'
|
import 'mocha'
|
||||||
import * as chai from 'chai'
|
import * as chai from 'chai'
|
||||||
import { Abuse, AbusePredefinedReasonsString, AbuseState } from '@shared/models'
|
import { AbusePredefinedReasonsString, AbuseState, AdminAbuse } from '@shared/models'
|
||||||
import {
|
import {
|
||||||
cleanupTests,
|
cleanupTests,
|
||||||
createUser,
|
createUser,
|
||||||
|
@ -33,7 +33,7 @@ const expect = chai.expect
|
||||||
|
|
||||||
describe('Test video abuses', function () {
|
describe('Test video abuses', function () {
|
||||||
let servers: ServerInfo[] = []
|
let servers: ServerInfo[] = []
|
||||||
let abuseServer2: Abuse
|
let abuseServer2: AdminAbuse
|
||||||
|
|
||||||
before(async function () {
|
before(async function () {
|
||||||
this.timeout(50000)
|
this.timeout(50000)
|
||||||
|
@ -97,7 +97,7 @@ describe('Test video abuses', function () {
|
||||||
expect(res1.body.data).to.be.an('array')
|
expect(res1.body.data).to.be.an('array')
|
||||||
expect(res1.body.data.length).to.equal(1)
|
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.reason).to.equal('my super bad reason')
|
||||||
expect(abuse.reporterAccount.name).to.equal('root')
|
expect(abuse.reporterAccount.name).to.equal('root')
|
||||||
expect(abuse.reporterAccount.host).to.equal('localhost:' + servers[0].port)
|
expect(abuse.reporterAccount.host).to.equal('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).to.be.an('array')
|
||||||
expect(res1.body.data.length).to.equal(2)
|
expect(res1.body.data.length).to.equal(2)
|
||||||
|
|
||||||
const abuse1: Abuse = res1.body.data[0]
|
const abuse1: AdminAbuse = res1.body.data[0]
|
||||||
expect(abuse1.reason).to.equal('my super bad reason')
|
expect(abuse1.reason).to.equal('my super bad reason')
|
||||||
expect(abuse1.reporterAccount.name).to.equal('root')
|
expect(abuse1.reporterAccount.name).to.equal('root')
|
||||||
expect(abuse1.reporterAccount.host).to.equal('localhost:' + servers[0].port)
|
expect(abuse1.reporterAccount.host).to.equal('localhost:' + servers[0].port)
|
||||||
|
@ -141,7 +141,7 @@ describe('Test video abuses', function () {
|
||||||
expect(abuse1.video.countReports).to.equal(1)
|
expect(abuse1.video.countReports).to.equal(1)
|
||||||
expect(abuse1.video.nthReport).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.reason).to.equal('my super bad reason 2')
|
||||||
expect(abuse2.reporterAccount.name).to.equal('root')
|
expect(abuse2.reporterAccount.name).to.equal('root')
|
||||||
expect(abuse2.reporterAccount.host).to.equal('localhost:' + servers[0].port)
|
expect(abuse2.reporterAccount.host).to.equal('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.length).to.equal(2, "wrong number of videos returned")
|
||||||
expect(res.body.data[0].id).to.equal(abuseServer2.id, "wrong origin server id for first video")
|
expect(res.body.data[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.id).to.equal(abuseServer2.video.id, "wrong video id")
|
||||||
expect(abuse.video.channel).to.exist
|
expect(abuse.video.channel).to.exist
|
||||||
expect(abuse.video.deleted).to.be.true
|
expect(abuse.video.deleted).to.be.true
|
||||||
|
@ -279,7 +279,7 @@ describe('Test video abuses', function () {
|
||||||
const res2 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken })
|
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) {
|
if (abuse.video.id === video3.id) {
|
||||||
expect(abuse.video.countReports).to.equal(1, "wrong reports count for video 3")
|
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")
|
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 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.reason).to.equals(reason5)
|
||||||
expect(abuse.predefinedReasons).to.deep.equals(predefinedReasons5, "predefined reasons do not match the one reported")
|
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")
|
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)
|
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)
|
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
|
// Format for API or AP object
|
||||||
|
|
||||||
export type MAbuseFormattable =
|
export type MAbuseAdminFormattable =
|
||||||
MAbuse &
|
MAbuse &
|
||||||
Use<'ReporterAccount', MAccountFormattable> &
|
Use<'ReporterAccount', MAccountFormattable> &
|
||||||
Use<'FlaggedAccount', MAccountFormattable> &
|
Use<'FlaggedAccount', MAccountFormattable> &
|
||||||
Use<'VideoAbuse', MVideoAbuseFormattable> &
|
Use<'VideoAbuse', MVideoAbuseFormattable> &
|
||||||
Use<'VideoCommentAbuse', MCommentAbuseFormattable>
|
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'
|
||||||
|
export * from './abuse-message'
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { RegisterServerAuthExternalOptions } from '@server/types'
|
import { RegisterServerAuthExternalOptions } from '@server/types'
|
||||||
import {
|
import {
|
||||||
MAbuse,
|
MAbuse,
|
||||||
|
MAbuseMessage,
|
||||||
MAccountBlocklist,
|
MAccountBlocklist,
|
||||||
MActorUrl,
|
MActorUrl,
|
||||||
MStreamingPlaylist,
|
MStreamingPlaylist,
|
||||||
|
@ -78,6 +79,7 @@ declare module 'express' {
|
||||||
videoCaption?: MVideoCaptionVideo
|
videoCaption?: MVideoCaptionVideo
|
||||||
|
|
||||||
abuse?: MAbuse
|
abuse?: MAbuse
|
||||||
|
abuseMessage?: MAbuseMessage
|
||||||
|
|
||||||
videoStreamingPlaylist?: MStreamingPlaylist
|
videoStreamingPlaylist?: MStreamingPlaylist
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,7 @@ function reportAbuse (options: {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAbusesList (options: {
|
function getAdminAbusesList (options: {
|
||||||
url: string
|
url: string
|
||||||
token: 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 (
|
function updateAbuse (
|
||||||
url: string,
|
url: string,
|
||||||
token: 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 {
|
export {
|
||||||
reportAbuse,
|
reportAbuse,
|
||||||
getAbusesList,
|
getAdminAbusesList,
|
||||||
updateAbuse,
|
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 { VideoConstant } from '../../videos/video-constant.model'
|
||||||
import { VideoChannel } from '../../videos/channel/video-channel.model'
|
import { VideoChannel } from '../../videos/channel/video-channel.model'
|
||||||
|
|
||||||
export interface VideoAbuse {
|
export interface AdminVideoAbuse {
|
||||||
id: number
|
id: number
|
||||||
name: string
|
name: string
|
||||||
uuid: string
|
uuid: string
|
||||||
|
@ -23,7 +23,7 @@ export interface VideoAbuse {
|
||||||
nthReport: number
|
nthReport: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VideoCommentAbuse {
|
export interface AdminVideoCommentAbuse {
|
||||||
id: number
|
id: number
|
||||||
threadId: number
|
threadId: number
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ export interface VideoCommentAbuse {
|
||||||
deleted: boolean
|
deleted: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Abuse {
|
export interface AdminAbuse {
|
||||||
id: number
|
id: number
|
||||||
|
|
||||||
reason: string
|
reason: string
|
||||||
|
@ -50,8 +50,8 @@ export interface Abuse {
|
||||||
state: VideoConstant<AbuseState>
|
state: VideoConstant<AbuseState>
|
||||||
moderationComment?: string
|
moderationComment?: string
|
||||||
|
|
||||||
video?: VideoAbuse
|
video?: AdminVideoAbuse
|
||||||
comment?: VideoCommentAbuse
|
comment?: AdminVideoCommentAbuse
|
||||||
|
|
||||||
createdAt: Date
|
createdAt: Date
|
||||||
updatedAt: Date
|
updatedAt: Date
|
||||||
|
@ -59,6 +59,8 @@ export interface Abuse {
|
||||||
countReportsForReporter?: number
|
countReportsForReporter?: number
|
||||||
countReportsForReportee?: number
|
countReportsForReportee?: number
|
||||||
|
|
||||||
|
countMessages: number
|
||||||
|
|
||||||
// FIXME: deprecated in 2.3, remove the following properties
|
// FIXME: deprecated in 2.3, remove the following properties
|
||||||
|
|
||||||
// @deprecated
|
// @deprecated
|
||||||
|
@ -71,3 +73,10 @@ export interface Abuse {
|
||||||
// @deprecated
|
// @deprecated
|
||||||
nth?: number
|
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-create.model'
|
||||||
export * from './abuse-filter.type'
|
export * from './abuse-filter.type'
|
||||||
|
export * from './abuse-message.model'
|
||||||
export * from './abuse-reason.model'
|
export * from './abuse-reason.model'
|
||||||
export * from './abuse-state.model'
|
export * from './abuse-state.model'
|
||||||
export * from './abuse-update.model'
|
export * from './abuse-update.model'
|
||||||
|
|
Loading…
Reference in New Issue