aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/abuse.ts4
-rw-r--r--server/controllers/api/users/my-abuses.ts2
-rw-r--r--server/helpers/middlewares/abuses.ts2
-rw-r--r--server/middlewares/validators/abuse.ts16
-rw-r--r--server/models/abuse/abuse.ts26
-rw-r--r--server/tests/api/check-params/abuses.ts52
-rw-r--r--server/tests/api/moderation/abuses.ts19
-rw-r--r--server/types/models/moderation/abuse.ts6
-rw-r--r--server/typings/express/index.d.ts5
9 files changed, 109 insertions, 23 deletions
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 {
16 asyncMiddleware, 16 asyncMiddleware,
17 asyncRetryTransactionMiddleware, 17 asyncRetryTransactionMiddleware,
18 authenticate, 18 authenticate,
19 checkAbuseValidForMessagesValidator,
19 deleteAbuseMessageValidator, 20 deleteAbuseMessageValidator,
20 ensureUserHasRight, 21 ensureUserHasRight,
21 getAbuseValidator, 22 getAbuseValidator,
@@ -58,12 +59,14 @@ abuseRouter.delete('/:id',
58abuseRouter.get('/:id/messages', 59abuseRouter.get('/:id/messages',
59 authenticate, 60 authenticate,
60 asyncMiddleware(getAbuseValidator), 61 asyncMiddleware(getAbuseValidator),
62 checkAbuseValidForMessagesValidator,
61 asyncRetryTransactionMiddleware(listAbuseMessages) 63 asyncRetryTransactionMiddleware(listAbuseMessages)
62) 64)
63 65
64abuseRouter.post('/:id/messages', 66abuseRouter.post('/:id/messages',
65 authenticate, 67 authenticate,
66 asyncMiddleware(getAbuseValidator), 68 asyncMiddleware(getAbuseValidator),
69 checkAbuseValidForMessagesValidator,
67 addAbuseMessageValidator, 70 addAbuseMessageValidator,
68 asyncRetryTransactionMiddleware(addAbuseMessage) 71 asyncRetryTransactionMiddleware(addAbuseMessage)
69) 72)
@@ -71,6 +74,7 @@ abuseRouter.post('/:id/messages',
71abuseRouter.delete('/:id/messages/:messageId', 74abuseRouter.delete('/:id/messages/:messageId',
72 authenticate, 75 authenticate,
73 asyncMiddleware(getAbuseValidator), 76 asyncMiddleware(getAbuseValidator),
77 checkAbuseValidForMessagesValidator,
74 asyncMiddleware(deleteAbuseMessageValidator), 78 asyncMiddleware(deleteAbuseMessageValidator),
75 asyncRetryTransactionMiddleware(deleteAbuseMessage) 79 asyncRetryTransactionMiddleware(deleteAbuseMessage)
76) 80)
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) {
43 43
44 return res.json({ 44 return res.json({
45 total: resultList.total, 45 total: resultList.total,
46 data: resultList.data.map(d => d.toFormattedAdminJSON()) 46 data: resultList.data.map(d => d.toFormattedUserJSON())
47 }) 47 })
48} 48}
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
26} 26}
27 27
28async function doesAbuseExist (abuseId: number | string, res: Response) { 28async function doesAbuseExist (abuseId: number | string, res: Response) {
29 const abuse = await AbuseModel.loadById(parseInt(abuseId + '', 10)) 29 const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10))
30 30
31 if (!abuse) { 31 if (!abuse) {
32 res.status(404) 32 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 = [
201 } 201 }
202] 202]
203 203
204const checkAbuseValidForMessagesValidator = [
205 (req: express.Request, res: express.Response, next: express.NextFunction) => {
206 logger.debug('Checking checkAbuseValidForMessagesValidator parameters', { parameters: req.body })
207
208 const abuse = res.locals.abuse
209 if (abuse.ReporterAccount.isOwned() === false) {
210 return res.status(400).json({
211 error: 'This abuse was created by a user of your instance.',
212 })
213 }
214
215 return next()
216 }
217]
218
204const addAbuseMessageValidator = [ 219const addAbuseMessageValidator = [
205 body('message').custom(isAbuseMessageValid).not().isEmpty().withMessage('Should have a valid abuse message'), 220 body('message').custom(isAbuseMessageValid).not().isEmpty().withMessage('Should have a valid abuse message'),
206 221
@@ -357,6 +372,7 @@ export {
357 abuseReportValidator, 372 abuseReportValidator,
358 abuseGetValidator, 373 abuseGetValidator,
359 addAbuseMessageValidator, 374 addAbuseMessageValidator,
375 checkAbuseValidForMessagesValidator,
360 abuseUpdateValidator, 376 abuseUpdateValidator,
361 deleteAbuseMessageValidator, 377 deleteAbuseMessageValidator,
362 abuseListForUserValidator, 378 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 {
25 AbusePredefinedReasonsString, 25 AbusePredefinedReasonsString,
26 AbuseState, 26 AbuseState,
27 AbuseVideoIs, 27 AbuseVideoIs,
28 AdminVideoAbuse,
29 AdminAbuse, 28 AdminAbuse,
29 AdminVideoAbuse,
30 AdminVideoCommentAbuse, 30 AdminVideoCommentAbuse,
31 UserAbuse, 31 UserAbuse,
32 UserVideoAbuse 32 UserVideoAbuse
33} from '@shared/models' 33} from '@shared/models'
34import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants' 34import { ABUSE_STATES, CONSTRAINTS_FIELDS } from '../../initializers/constants'
35import { MAbuse, MAbuseAdminFormattable, MAbuseAP, MUserAccountId, MAbuseUserFormattable } from '../../types/models' 35import { MAbuse, MAbuseAdminFormattable, MAbuseAP, MAbuseReporter, MAbuseUserFormattable, MUserAccountId } from '../../types/models'
36import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account' 36import { AccountModel, ScopeNames as AccountScopeNames, SummaryOptions as AccountSummaryOptions } from '../account/account'
37import { getSort, throwIfNotValid } from '../utils' 37import { getSort, throwIfNotValid } from '../utils'
38import { ThumbnailModel } from '../video/thumbnail' 38import { ThumbnailModel } from '../video/thumbnail'
@@ -266,7 +266,7 @@ export class AbuseModel extends Model<AbuseModel> {
266 VideoAbuse: VideoAbuseModel 266 VideoAbuse: VideoAbuseModel
267 267
268 // FIXME: deprecated in 2.3. Remove these validators 268 // FIXME: deprecated in 2.3. Remove these validators
269 static loadByIdAndVideoId (id: number, videoId?: number, uuid?: string): Bluebird<MAbuse> { 269 static loadByIdAndVideoId (id: number, videoId?: number, uuid?: string): Bluebird<MAbuseReporter> {
270 const videoWhere: WhereOptions = {} 270 const videoWhere: WhereOptions = {}
271 271
272 if (videoId) videoWhere.videoId = videoId 272 if (videoId) videoWhere.videoId = videoId
@@ -278,6 +278,10 @@ export class AbuseModel extends Model<AbuseModel> {
278 model: VideoAbuseModel, 278 model: VideoAbuseModel,
279 required: true, 279 required: true,
280 where: videoWhere 280 where: videoWhere
281 },
282 {
283 model: AccountModel,
284 as: 'ReporterAccount'
281 } 285 }
282 ], 286 ],
283 where: { 287 where: {
@@ -287,11 +291,17 @@ export class AbuseModel extends Model<AbuseModel> {
287 return AbuseModel.findOne(query) 291 return AbuseModel.findOne(query)
288 } 292 }
289 293
290 static loadById (id: number): Bluebird<MAbuse> { 294 static loadByIdWithReporter (id: number): Bluebird<MAbuseReporter> {
291 const query = { 295 const query = {
292 where: { 296 where: {
293 id 297 id
294 } 298 },
299 include: [
300 {
301 model: AccountModel,
302 as: 'ReporterAccount'
303 }
304 ]
295 } 305 }
296 306
297 return AbuseModel.findOne(query) 307 return AbuseModel.findOne(query)
@@ -466,8 +476,6 @@ export class AbuseModel extends Model<AbuseModel> {
466 label: AbuseModel.getStateLabel(this.state) 476 label: AbuseModel.getStateLabel(this.state)
467 }, 477 },
468 478
469 moderationComment: this.moderationComment,
470
471 countMessages, 479 countMessages,
472 480
473 createdAt: this.createdAt, 481 createdAt: this.createdAt,
@@ -500,6 +508,8 @@ export class AbuseModel extends Model<AbuseModel> {
500 video, 508 video,
501 comment, 509 comment,
502 510
511 moderationComment: this.moderationComment,
512
503 reporterAccount: this.ReporterAccount 513 reporterAccount: this.ReporterAccount
504 ? this.ReporterAccount.toFormattedJSON() 514 ? this.ReporterAccount.toFormattedJSON()
505 : null, 515 : null,
@@ -519,7 +529,7 @@ export class AbuseModel extends Model<AbuseModel> {
519 const countMessages = this.get('countMessages') as number 529 const countMessages = this.get('countMessages') as number
520 530
521 const video = this.buildBaseVideoAbuse() 531 const video = this.buildBaseVideoAbuse()
522 const comment: AdminVideoCommentAbuse = this.buildBaseVideoCommentAbuse() 532 const comment = this.buildBaseVideoCommentAbuse()
523 const abuse = this.buildBaseAbuse(countMessages || 0) 533 const abuse = this.buildBaseAbuse(countMessages || 0)
524 534
525 return Object.assign(abuse, { 535 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 @@
3import 'mocha' 3import 'mocha'
4import { AbuseCreate, AbuseState } from '@shared/models' 4import { AbuseCreate, AbuseState } from '@shared/models'
5import { 5import {
6 addAbuseMessage,
6 cleanupTests, 7 cleanupTests,
7 createUser, 8 createUser,
8 deleteAbuse, 9 deleteAbuse,
10 deleteAbuseMessage,
11 doubleFollow,
9 flushAndRunServer, 12 flushAndRunServer,
13 generateUserAccessToken,
14 getAdminAbusesList,
15 getVideoIdFromUUID,
16 listAbuseMessages,
10 makeGetRequest, 17 makeGetRequest,
11 makePostBodyRequest, 18 makePostBodyRequest,
19 reportAbuse,
12 ServerInfo, 20 ServerInfo,
13 setAccessTokensToServers, 21 setAccessTokensToServers,
14 updateAbuse, 22 updateAbuse,
15 uploadVideo, 23 uploadVideo,
16 userLogin, 24 userLogin,
17 generateUserAccessToken, 25 waitJobs
18 addAbuseMessage,
19 listAbuseMessages,
20 deleteAbuseMessage
21} from '../../../../shared/extra-utils' 26} from '../../../../shared/extra-utils'
22import { 27import {
23 checkBadCountPagination, 28 checkBadCountPagination,
@@ -29,6 +34,7 @@ describe('Test abuses API validators', function () {
29 const basePath = '/api/v1/abuses/' 34 const basePath = '/api/v1/abuses/'
30 35
31 let server: ServerInfo 36 let server: ServerInfo
37
32 let userAccessToken = '' 38 let userAccessToken = ''
33 let userAccessToken2 = '' 39 let userAccessToken2 = ''
34 let abuseId: number 40 let abuseId: number
@@ -321,7 +327,7 @@ describe('Test abuses API validators', function () {
321 }) 327 })
322 }) 328 })
323 329
324 describe('When listing abuse message', function () { 330 describe('When listing abuse messages', function () {
325 331
326 it('Should fail with an invalid abuse id', async function () { 332 it('Should fail with an invalid abuse id', async function () {
327 await listAbuseMessages(server.url, userAccessToken, 888, 404) 333 await listAbuseMessages(server.url, userAccessToken, 888, 404)
@@ -382,7 +388,43 @@ describe('Test abuses API validators', function () {
382 }) 388 })
383 }) 389 })
384 390
391 describe('When trying to manage messages of a remote abuse', function () {
392 let remoteAbuseId: number
393 let anotherServer: ServerInfo
394
395 before(async function () {
396 this.timeout(20000)
397
398 anotherServer = await flushAndRunServer(2)
399 await setAccessTokensToServers([ anotherServer ])
400
401 await doubleFollow(anotherServer, server)
402
403 const server2VideoId = await getVideoIdFromUUID(anotherServer.url, server.video.uuid)
404 await reportAbuse({
405 url: anotherServer.url,
406 token: anotherServer.accessToken,
407 reason: 'remote server',
408 videoId: server2VideoId
409 })
410
411 await waitJobs([ server, anotherServer ])
412
413 const res = await getAdminAbusesList({ url: server.url, token: server.accessToken, sort: '-createdAt' })
414 remoteAbuseId = res.body.data[0].id
415 })
416
417 it('Should fail when listing abuse messages of a remote abuse', async function () {
418 await listAbuseMessages(server.url, server.accessToken, remoteAbuseId, 400)
419 })
420
421 it('Should fail when creating abuse message of a remote abuse', async function () {
422 await addAbuseMessage(server.url, server.accessToken, remoteAbuseId, 'message', 400)
423 })
424 })
425
385 after(async function () { 426 after(async function () {
386 await cleanupTests([ server ]) 427 await cleanupTests([ server ])
387 }) 428 })
388}) 429})
430
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 @@
2 2
3import 'mocha' 3import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { AbuseFilter, AbusePredefinedReasonsString, AbuseState, Account, AdminAbuse, UserAbuse, VideoComment, AbuseMessage } from '@shared/models'
6import { 5import {
6 AbuseFilter,
7 AbuseMessage,
8 AbusePredefinedReasonsString,
9 AbuseState,
10 Account,
11 AdminAbuse,
12 UserAbuse,
13 VideoComment
14} from '@shared/models'
15import {
16 addAbuseMessage,
7 addVideoCommentThread, 17 addVideoCommentThread,
8 cleanupTests, 18 cleanupTests,
9 createUser, 19 createUser,
10 deleteAbuse, 20 deleteAbuse,
21 deleteAbuseMessage,
11 deleteVideoComment, 22 deleteVideoComment,
12 flushAndRunMultipleServers, 23 flushAndRunMultipleServers,
13 generateUserAccessToken, 24 generateUserAccessToken,
@@ -18,6 +29,7 @@ import {
18 getVideoIdFromUUID, 29 getVideoIdFromUUID,
19 getVideosList, 30 getVideosList,
20 immutableAssign, 31 immutableAssign,
32 listAbuseMessages,
21 removeUser, 33 removeUser,
22 removeVideo, 34 removeVideo,
23 reportAbuse, 35 reportAbuse,
@@ -26,10 +38,7 @@ import {
26 updateAbuse, 38 updateAbuse,
27 uploadVideo, 39 uploadVideo,
28 uploadVideoAndGetId, 40 uploadVideoAndGetId,
29 userLogin, 41 userLogin
30 addAbuseMessage,
31 listAbuseMessages,
32 deleteAbuseMessage
33} from '../../../../shared/extra-utils/index' 42} from '../../../../shared/extra-utils/index'
34import { doubleFollow } from '../../../../shared/extra-utils/server/follows' 43import { doubleFollow } from '../../../../shared/extra-utils/server/follows'
35import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 44import { 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'
2import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse' 2import { VideoCommentAbuseModel } from '@server/models/abuse/video-comment-abuse'
3import { PickWith } from '@shared/core-utils' 3import { PickWith } from '@shared/core-utils'
4import { AbuseModel } from '../../../models/abuse/abuse' 4import { AbuseModel } from '../../../models/abuse/abuse'
5import { MAccountDefault, MAccountFormattable, MAccountLight, MAccountUrl } from '../account' 5import { MAccountDefault, MAccountFormattable, MAccountLight, MAccountUrl, MAccount } from '../account'
6import { MCommentOwner, MCommentUrl, MVideoUrl, MCommentOwnerVideo, MComment, MCommentVideo } from '../video' 6import { MCommentOwner, MCommentUrl, MVideoUrl, MCommentOwnerVideo, MComment, MCommentVideo } from '../video'
7import { MVideo, MVideoAccountLightBlacklistAllFiles } from '../video/video' 7import { MVideo, MVideoAccountLightBlacklistAllFiles } from '../video/video'
8 8
@@ -18,6 +18,10 @@ export type MVideoAbuse = Omit<VideoAbuseModel, 'Abuse' | 'Video'>
18 18
19export type MCommentAbuse = Omit<VideoCommentAbuseModel, 'Abuse' | 'VideoComment'> 19export type MCommentAbuse = Omit<VideoCommentAbuseModel, 'Abuse' | 'VideoComment'>
20 20
21export type MAbuseReporter =
22 MAbuse &
23 Use<'ReporterAccount', MAccountDefault>
24
21// ############################################################################ 25// ############################################################################
22 26
23export type MVideoAbuseVideo = 27export 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 {
9 MVideoFile, 9 MVideoFile,
10 MVideoImmutable, 10 MVideoImmutable,
11 MVideoPlaylistFull, 11 MVideoPlaylistFull,
12 MVideoPlaylistFullSummary 12 MVideoPlaylistFullSummary,
13 MAbuseReporter
13} from '@server/types/models' 14} from '@server/types/models'
14import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token' 15import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token'
15import { MPlugin, MServer, MServerBlocklist } from '@server/types/models/server' 16import { MPlugin, MServer, MServerBlocklist } from '@server/types/models/server'
@@ -78,7 +79,7 @@ declare module 'express' {
78 79
79 videoCaption?: MVideoCaptionVideo 80 videoCaption?: MVideoCaptionVideo
80 81
81 abuse?: MAbuse 82 abuse?: MAbuseReporter
82 abuseMessage?: MAbuseMessage 83 abuseMessage?: MAbuseMessage
83 84
84 videoStreamingPlaylist?: MStreamingPlaylist 85 videoStreamingPlaylist?: MStreamingPlaylist