From 94148c9028829b5576a5dcbfba2c7fb9cf6443d3 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 27 Jul 2020 11:40:30 +0200 Subject: Add abuse messages management in my account --- server/controllers/api/abuse.ts | 4 +++ server/controllers/api/users/my-abuses.ts | 2 +- server/helpers/middlewares/abuses.ts | 2 +- server/middlewares/validators/abuse.ts | 16 ++++++++++ server/models/abuse/abuse.ts | 26 +++++++++++----- server/tests/api/check-params/abuses.ts | 52 ++++++++++++++++++++++++++++--- server/tests/api/moderation/abuses.ts | 19 ++++++++--- server/types/models/moderation/abuse.ts | 6 +++- server/typings/express/index.d.ts | 5 +-- 9 files changed, 109 insertions(+), 23 deletions(-) (limited to 'server') diff --git a/server/controllers/api/abuse.ts b/server/controllers/api/abuse.ts index 50d068157..72e62fc0b 100644 --- a/server/controllers/api/abuse.ts +++ b/server/controllers/api/abuse.ts @@ -16,6 +16,7 @@ import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, + checkAbuseValidForMessagesValidator, deleteAbuseMessageValidator, ensureUserHasRight, getAbuseValidator, @@ -58,12 +59,14 @@ abuseRouter.delete('/:id', abuseRouter.get('/:id/messages', authenticate, asyncMiddleware(getAbuseValidator), + checkAbuseValidForMessagesValidator, asyncRetryTransactionMiddleware(listAbuseMessages) ) abuseRouter.post('/:id/messages', authenticate, asyncMiddleware(getAbuseValidator), + checkAbuseValidForMessagesValidator, addAbuseMessageValidator, asyncRetryTransactionMiddleware(addAbuseMessage) ) @@ -71,6 +74,7 @@ abuseRouter.post('/:id/messages', abuseRouter.delete('/:id/messages/:messageId', authenticate, asyncMiddleware(getAbuseValidator), + checkAbuseValidForMessagesValidator, asyncMiddleware(deleteAbuseMessageValidator), asyncRetryTransactionMiddleware(deleteAbuseMessage) ) diff --git a/server/controllers/api/users/my-abuses.ts b/server/controllers/api/users/my-abuses.ts index e43fc483e..fcd0ce3fc 100644 --- a/server/controllers/api/users/my-abuses.ts +++ b/server/controllers/api/users/my-abuses.ts @@ -43,6 +43,6 @@ async function listMyAbuses (req: express.Request, res: express.Response) { return res.json({ total: resultList.total, - data: resultList.data.map(d => d.toFormattedAdminJSON()) + data: resultList.data.map(d => d.toFormattedUserJSON()) }) } diff --git a/server/helpers/middlewares/abuses.ts b/server/helpers/middlewares/abuses.ts index be8c8b449..659ad8939 100644 --- a/server/helpers/middlewares/abuses.ts +++ b/server/helpers/middlewares/abuses.ts @@ -26,7 +26,7 @@ async function doesVideoAbuseExist (abuseIdArg: number | string, videoUUID: stri } async function doesAbuseExist (abuseId: number | string, res: Response) { - const abuse = await AbuseModel.loadById(parseInt(abuseId + '', 10)) + const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10)) if (!abuse) { res.status(404) diff --git a/server/middlewares/validators/abuse.ts b/server/middlewares/validators/abuse.ts index cb0bc658a..2a096e0af 100644 --- a/server/middlewares/validators/abuse.ts +++ b/server/middlewares/validators/abuse.ts @@ -201,6 +201,21 @@ const getAbuseValidator = [ } ] +const checkAbuseValidForMessagesValidator = [ + (req: express.Request, res: express.Response, next: express.NextFunction) => { + logger.debug('Checking checkAbuseValidForMessagesValidator parameters', { parameters: req.body }) + + const abuse = res.locals.abuse + if (abuse.ReporterAccount.isOwned() === false) { + return res.status(400).json({ + error: 'This abuse was created by a user of your instance.', + }) + } + + return next() + } +] + const addAbuseMessageValidator = [ body('message').custom(isAbuseMessageValid).not().isEmpty().withMessage('Should have a valid abuse message'), @@ -357,6 +372,7 @@ export { abuseReportValidator, abuseGetValidator, addAbuseMessageValidator, + checkAbuseValidForMessagesValidator, abuseUpdateValidator, deleteAbuseMessageValidator, abuseListForUserValidator, diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts index 7002502d5..3353e9e41 100644 --- a/server/models/abuse/abuse.ts +++ b/server/models/abuse/abuse.ts @@ -25,14 +25,14 @@ import { AbusePredefinedReasonsString, AbuseState, AbuseVideoIs, - AdminVideoAbuse, AdminAbuse, + AdminVideoAbuse, AdminVideoCommentAbuse, UserAbuse, UserVideoAbuse } from '@shared/models' import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants' -import { MAbuse, MAbuseAdminFormattable, MAbuseAP, MUserAccountId, MAbuseUserFormattable } from '../../types/models' +import { MAbuse, MAbuseAdminFormattable, MAbuseAP, MAbuseReporter, MAbuseUserFormattable, MUserAccountId } from '../../types/models' import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' import { getSort, throwIfNotValid } from '../utils' import { ThumbnailModel } from '../video/thumbnail' @@ -266,7 +266,7 @@ export class AbuseModel extends Model { VideoAbuse: VideoAbuseModel // FIXME: deprecated in 2.3. Remove these validators - static loadByIdAndVideoId (id: number, videoId?: number, uuid?: string): Bluebird { + static loadByIdAndVideoId (id: number, videoId?: number, uuid?: string): Bluebird { const videoWhere: WhereOptions = {} if (videoId) videoWhere.videoId = videoId @@ -278,6 +278,10 @@ export class AbuseModel extends Model { model: VideoAbuseModel, required: true, where: videoWhere + }, + { + model: AccountModel, + as: 'ReporterAccount' } ], where: { @@ -287,11 +291,17 @@ export class AbuseModel extends Model { return AbuseModel.findOne(query) } - static loadById (id: number): Bluebird { + static loadByIdWithReporter (id: number): Bluebird { const query = { where: { id - } + }, + include: [ + { + model: AccountModel, + as: 'ReporterAccount' + } + ] } return AbuseModel.findOne(query) @@ -466,8 +476,6 @@ export class AbuseModel extends Model { label: AbuseModel.getStateLabel(this.state) }, - moderationComment: this.moderationComment, - countMessages, createdAt: this.createdAt, @@ -500,6 +508,8 @@ export class AbuseModel extends Model { video, comment, + moderationComment: this.moderationComment, + reporterAccount: this.ReporterAccount ? this.ReporterAccount.toFormattedJSON() : null, @@ -519,7 +529,7 @@ export class AbuseModel extends Model { const countMessages = this.get('countMessages') as number const video = this.buildBaseVideoAbuse() - const comment: AdminVideoCommentAbuse = this.buildBaseVideoCommentAbuse() + const comment = this.buildBaseVideoCommentAbuse() const abuse = this.buildBaseAbuse(countMessages || 0) return Object.assign(abuse, { diff --git a/server/tests/api/check-params/abuses.ts b/server/tests/api/check-params/abuses.ts index 5e1d66c25..0ef8f6cac 100644 --- a/server/tests/api/check-params/abuses.ts +++ b/server/tests/api/check-params/abuses.ts @@ -3,21 +3,26 @@ import 'mocha' import { AbuseCreate, AbuseState } from '@shared/models' import { + addAbuseMessage, cleanupTests, createUser, deleteAbuse, + deleteAbuseMessage, + doubleFollow, flushAndRunServer, + generateUserAccessToken, + getAdminAbusesList, + getVideoIdFromUUID, + listAbuseMessages, makeGetRequest, makePostBodyRequest, + reportAbuse, ServerInfo, setAccessTokensToServers, updateAbuse, uploadVideo, userLogin, - generateUserAccessToken, - addAbuseMessage, - listAbuseMessages, - deleteAbuseMessage + waitJobs } from '../../../../shared/extra-utils' import { checkBadCountPagination, @@ -29,6 +34,7 @@ describe('Test abuses API validators', function () { const basePath = '/api/v1/abuses/' let server: ServerInfo + let userAccessToken = '' let userAccessToken2 = '' let abuseId: number @@ -321,7 +327,7 @@ describe('Test abuses API validators', function () { }) }) - describe('When listing abuse message', function () { + describe('When listing abuse messages', function () { it('Should fail with an invalid abuse id', async function () { await listAbuseMessages(server.url, userAccessToken, 888, 404) @@ -382,7 +388,43 @@ describe('Test abuses API validators', function () { }) }) + describe('When trying to manage messages of a remote abuse', function () { + let remoteAbuseId: number + let anotherServer: ServerInfo + + before(async function () { + this.timeout(20000) + + anotherServer = await flushAndRunServer(2) + await setAccessTokensToServers([ anotherServer ]) + + await doubleFollow(anotherServer, server) + + const server2VideoId = await getVideoIdFromUUID(anotherServer.url, server.video.uuid) + await reportAbuse({ + url: anotherServer.url, + token: anotherServer.accessToken, + reason: 'remote server', + videoId: server2VideoId + }) + + await waitJobs([ server, anotherServer ]) + + const res = await getAdminAbusesList({ url: server.url, token: server.accessToken, sort: '-createdAt' }) + remoteAbuseId = res.body.data[0].id + }) + + it('Should fail when listing abuse messages of a remote abuse', async function () { + await listAbuseMessages(server.url, server.accessToken, remoteAbuseId, 400) + }) + + it('Should fail when creating abuse message of a remote abuse', async function () { + await addAbuseMessage(server.url, server.accessToken, remoteAbuseId, 'message', 400) + }) + }) + after(async function () { await cleanupTests([ server ]) }) }) + diff --git a/server/tests/api/moderation/abuses.ts b/server/tests/api/moderation/abuses.ts index 601125fdf..fb765e7e3 100644 --- a/server/tests/api/moderation/abuses.ts +++ b/server/tests/api/moderation/abuses.ts @@ -2,12 +2,23 @@ import 'mocha' import * as chai from 'chai' -import { AbuseFilter, AbusePredefinedReasonsString, AbuseState, Account, AdminAbuse, UserAbuse, VideoComment, AbuseMessage } from '@shared/models' import { + AbuseFilter, + AbuseMessage, + AbusePredefinedReasonsString, + AbuseState, + Account, + AdminAbuse, + UserAbuse, + VideoComment +} from '@shared/models' +import { + addAbuseMessage, addVideoCommentThread, cleanupTests, createUser, deleteAbuse, + deleteAbuseMessage, deleteVideoComment, flushAndRunMultipleServers, generateUserAccessToken, @@ -18,6 +29,7 @@ import { getVideoIdFromUUID, getVideosList, immutableAssign, + listAbuseMessages, removeUser, removeVideo, reportAbuse, @@ -26,10 +38,7 @@ import { updateAbuse, uploadVideo, uploadVideoAndGetId, - userLogin, - addAbuseMessage, - listAbuseMessages, - deleteAbuseMessage + userLogin } from '../../../../shared/extra-utils/index' import { doubleFollow } from '../../../../shared/extra-utils/server/follows' import { waitJobs } from '../../../../shared/extra-utils/server/jobs' diff --git a/server/types/models/moderation/abuse.ts b/server/types/models/moderation/abuse.ts index 39ef50771..d793a720f 100644 --- a/server/types/models/moderation/abuse.ts +++ b/server/types/models/moderation/abuse.ts @@ -2,7 +2,7 @@ import { VideoAbuseModel } from '@server/models/abuse/video-abuse' import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse' import { PickWith } from '@shared/core-utils' import { AbuseModel } from '../../../models/abuse/abuse' -import { MAccountDefault, MAccountFormattable, MAccountLight, MAccountUrl } from '../account' +import { MAccountDefault, MAccountFormattable, MAccountLight, MAccountUrl, MAccount } from '../account' import { MCommentOwner, MCommentUrl, MVideoUrl, MCommentOwnerVideo, MComment, MCommentVideo } from '../video' import { MVideo, MVideoAccountLightBlacklistAllFiles } from '../video/video' @@ -18,6 +18,10 @@ export type MVideoAbuse = Omit export type MCommentAbuse = Omit +export type MAbuseReporter = + MAbuse & + Use<'ReporterAccount', MAccountDefault> + // ############################################################################ export type MVideoAbuseVideo = diff --git a/server/typings/express/index.d.ts b/server/typings/express/index.d.ts index 452c6e1a0..d95b8925d 100644 --- a/server/typings/express/index.d.ts +++ b/server/typings/express/index.d.ts @@ -9,7 +9,8 @@ import { MVideoFile, MVideoImmutable, MVideoPlaylistFull, - MVideoPlaylistFullSummary + MVideoPlaylistFullSummary, + MAbuseReporter } from '@server/types/models' import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' import { MPlugin, MServer, MServerBlocklist } from '@server/types/models/server' @@ -78,7 +79,7 @@ declare module 'express' { videoCaption?: MVideoCaptionVideo - abuse?: MAbuse + abuse?: MAbuseReporter abuseMessage?: MAbuseMessage videoStreamingPlaylist?: MStreamingPlaylist -- cgit v1.2.3