diff options
-rw-r--r-- | client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts | 4 | ||||
-rw-r--r-- | server/controllers/api/abuse.ts | 8 | ||||
-rw-r--r-- | server/controllers/api/videos/abuse.ts | 114 | ||||
-rw-r--r-- | server/controllers/api/videos/index.ts | 4 | ||||
-rw-r--r-- | server/helpers/middlewares/abuses.ts | 27 | ||||
-rw-r--r-- | server/middlewares/validators/abuse.ts | 119 | ||||
-rw-r--r-- | server/models/abuse/abuse.ts | 36 | ||||
-rw-r--r-- | server/tests/api/check-params/index.ts | 1 | ||||
-rw-r--r-- | server/tests/api/check-params/video-abuses.ts | 216 | ||||
-rw-r--r-- | server/tests/api/moderation/index.ts | 1 | ||||
-rw-r--r-- | server/tests/api/moderation/video-abuse.ts | 386 | ||||
-rw-r--r-- | shared/extra-utils/index.ts | 1 | ||||
-rw-r--r-- | shared/extra-utils/videos/video-abuses.ts | 114 | ||||
-rw-r--r-- | shared/models/moderation/abuse/abuse-create.model.ts | 8 | ||||
-rw-r--r-- | shared/models/moderation/abuse/abuse.model.ts | 12 |
15 files changed, 10 insertions, 1041 deletions
diff --git a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts index 20be94d6e..3bc527684 100644 --- a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts +++ b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts | |||
@@ -144,8 +144,8 @@ export class AbuseListTableComponent extends RestTable implements OnInit, AfterV | |||
144 | baseUrl: `${environment.embedUrl}/videos/embed/${abuse.video.uuid}`, | 144 | baseUrl: `${environment.embedUrl}/videos/embed/${abuse.video.uuid}`, |
145 | title: false, | 145 | title: false, |
146 | warningTitle: false, | 146 | warningTitle: false, |
147 | startTime: abuse.startAt, | 147 | startTime: abuse.video.startAt, |
148 | stopTime: abuse.endAt | 148 | stopTime: abuse.video.endAt |
149 | }) | 149 | }) |
150 | ) | 150 | ) |
151 | } | 151 | } |
diff --git a/server/controllers/api/abuse.ts b/server/controllers/api/abuse.ts index b97b99f16..25d6e2ab0 100644 --- a/server/controllers/api/abuse.ts +++ b/server/controllers/api/abuse.ts | |||
@@ -85,13 +85,7 @@ abuseRouter.delete('/:id/messages/:messageId', | |||
85 | // --------------------------------------------------------------------------- | 85 | // --------------------------------------------------------------------------- |
86 | 86 | ||
87 | export { | 87 | export { |
88 | abuseRouter, | 88 | abuseRouter |
89 | |||
90 | // FIXME: deprecated in 2.3. Remove these exports | ||
91 | listAbusesForAdmins, | ||
92 | updateAbuse, | ||
93 | deleteAbuse, | ||
94 | reportAbuse | ||
95 | } | 89 | } |
96 | 90 | ||
97 | // --------------------------------------------------------------------------- | 91 | // --------------------------------------------------------------------------- |
diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts deleted file mode 100644 index 9c4d00849..000000000 --- a/server/controllers/api/videos/abuse.ts +++ /dev/null | |||
@@ -1,114 +0,0 @@ | |||
1 | import * as express from 'express' | ||
2 | import { AbuseModel } from '@server/models/abuse/abuse' | ||
3 | import { getServerActor } from '@server/models/application/application' | ||
4 | import { AbuseCreate, UserRight, VideoAbuseCreate } from '../../../../shared' | ||
5 | import { | ||
6 | abusesSortValidator, | ||
7 | asyncMiddleware, | ||
8 | asyncRetryTransactionMiddleware, | ||
9 | authenticate, | ||
10 | ensureUserHasRight, | ||
11 | paginationValidator, | ||
12 | setDefaultPagination, | ||
13 | setDefaultSort, | ||
14 | videoAbuseGetValidator, | ||
15 | videoAbuseListValidator, | ||
16 | videoAbuseReportValidator, | ||
17 | videoAbuseUpdateValidator | ||
18 | } from '../../../middlewares' | ||
19 | import { deleteAbuse, reportAbuse, updateAbuse } from '../abuse' | ||
20 | |||
21 | // FIXME: deprecated in 2.3. Remove this controller | ||
22 | |||
23 | const abuseVideoRouter = express.Router() | ||
24 | |||
25 | abuseVideoRouter.get('/abuse', | ||
26 | authenticate, | ||
27 | ensureUserHasRight(UserRight.MANAGE_ABUSES), | ||
28 | paginationValidator, | ||
29 | abusesSortValidator, | ||
30 | setDefaultSort, | ||
31 | setDefaultPagination, | ||
32 | videoAbuseListValidator, | ||
33 | asyncMiddleware(listVideoAbuses) | ||
34 | ) | ||
35 | abuseVideoRouter.put('/:videoId/abuse/:id', | ||
36 | authenticate, | ||
37 | ensureUserHasRight(UserRight.MANAGE_ABUSES), | ||
38 | asyncMiddleware(videoAbuseUpdateValidator), | ||
39 | asyncRetryTransactionMiddleware(updateVideoAbuse) | ||
40 | ) | ||
41 | abuseVideoRouter.post('/:videoId/abuse', | ||
42 | authenticate, | ||
43 | asyncMiddleware(videoAbuseReportValidator), | ||
44 | asyncRetryTransactionMiddleware(reportVideoAbuse) | ||
45 | ) | ||
46 | abuseVideoRouter.delete('/:videoId/abuse/:id', | ||
47 | authenticate, | ||
48 | ensureUserHasRight(UserRight.MANAGE_ABUSES), | ||
49 | asyncMiddleware(videoAbuseGetValidator), | ||
50 | asyncRetryTransactionMiddleware(deleteVideoAbuse) | ||
51 | ) | ||
52 | |||
53 | // --------------------------------------------------------------------------- | ||
54 | |||
55 | export { | ||
56 | abuseVideoRouter | ||
57 | } | ||
58 | |||
59 | // --------------------------------------------------------------------------- | ||
60 | |||
61 | async function listVideoAbuses (req: express.Request, res: express.Response) { | ||
62 | const user = res.locals.oauth.token.user | ||
63 | const serverActor = await getServerActor() | ||
64 | |||
65 | const resultList = await AbuseModel.listForAdminApi({ | ||
66 | start: req.query.start, | ||
67 | count: req.query.count, | ||
68 | sort: req.query.sort, | ||
69 | id: req.query.id, | ||
70 | filter: 'video', | ||
71 | predefinedReason: req.query.predefinedReason, | ||
72 | search: req.query.search, | ||
73 | state: req.query.state, | ||
74 | videoIs: req.query.videoIs, | ||
75 | searchReporter: req.query.searchReporter, | ||
76 | searchReportee: req.query.searchReportee, | ||
77 | searchVideo: req.query.searchVideo, | ||
78 | searchVideoChannel: req.query.searchVideoChannel, | ||
79 | serverAccountId: serverActor.Account.id, | ||
80 | user | ||
81 | }) | ||
82 | |||
83 | return res.json({ | ||
84 | total: resultList.total, | ||
85 | data: resultList.data.map(d => d.toFormattedAdminJSON()) | ||
86 | }) | ||
87 | } | ||
88 | |||
89 | async function updateVideoAbuse (req: express.Request, res: express.Response) { | ||
90 | return updateAbuse(req, res) | ||
91 | } | ||
92 | |||
93 | async function deleteVideoAbuse (req: express.Request, res: express.Response) { | ||
94 | return deleteAbuse(req, res) | ||
95 | } | ||
96 | |||
97 | async function reportVideoAbuse (req: express.Request, res: express.Response) { | ||
98 | const oldBody = req.body as VideoAbuseCreate | ||
99 | |||
100 | req.body = { | ||
101 | accountId: res.locals.videoAll.VideoChannel.accountId, | ||
102 | |||
103 | reason: oldBody.reason, | ||
104 | predefinedReasons: oldBody.predefinedReasons, | ||
105 | |||
106 | video: { | ||
107 | id: res.locals.videoAll.id, | ||
108 | startAt: oldBody.startAt, | ||
109 | endAt: oldBody.endAt | ||
110 | } | ||
111 | } as AbuseCreate | ||
112 | |||
113 | return reportAbuse(req, res) | ||
114 | } | ||
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 3f96f142c..bfebc54ed 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -6,6 +6,7 @@ import { addOptimizeOrMergeAudioJob } from '@server/helpers/video' | |||
6 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' | 6 | import { createTorrentAndSetInfoHash } from '@server/helpers/webtorrent' |
7 | import { changeVideoChannelShare } from '@server/lib/activitypub/share' | 7 | import { changeVideoChannelShare } from '@server/lib/activitypub/share' |
8 | import { getVideoActivityPubUrl } from '@server/lib/activitypub/url' | 8 | import { getVideoActivityPubUrl } from '@server/lib/activitypub/url' |
9 | import { LiveManager } from '@server/lib/live-manager' | ||
9 | import { buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' | 10 | import { buildLocalVideoFromReq, buildVideoThumbnailsFromReq, setVideoTags } from '@server/lib/video' |
10 | import { getVideoFilePath } from '@server/lib/video-paths' | 11 | import { getVideoFilePath } from '@server/lib/video-paths' |
11 | import { getServerActor } from '@server/models/application/application' | 12 | import { getServerActor } from '@server/models/application/application' |
@@ -57,7 +58,6 @@ import { | |||
57 | import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' | 58 | import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' |
58 | import { VideoModel } from '../../../models/video/video' | 59 | import { VideoModel } from '../../../models/video/video' |
59 | import { VideoFileModel } from '../../../models/video/video-file' | 60 | import { VideoFileModel } from '../../../models/video/video-file' |
60 | import { abuseVideoRouter } from './abuse' | ||
61 | import { blacklistRouter } from './blacklist' | 61 | import { blacklistRouter } from './blacklist' |
62 | import { videoCaptionsRouter } from './captions' | 62 | import { videoCaptionsRouter } from './captions' |
63 | import { videoCommentRouter } from './comment' | 63 | import { videoCommentRouter } from './comment' |
@@ -66,7 +66,6 @@ import { liveRouter } from './live' | |||
66 | import { ownershipVideoRouter } from './ownership' | 66 | import { ownershipVideoRouter } from './ownership' |
67 | import { rateVideoRouter } from './rate' | 67 | import { rateVideoRouter } from './rate' |
68 | import { watchingRouter } from './watching' | 68 | import { watchingRouter } from './watching' |
69 | import { LiveManager } from '@server/lib/live-manager' | ||
70 | 69 | ||
71 | const auditLogger = auditLoggerFactory('videos') | 70 | const auditLogger = auditLoggerFactory('videos') |
72 | const videosRouter = express.Router() | 71 | const videosRouter = express.Router() |
@@ -89,7 +88,6 @@ const reqVideoFileUpdate = createReqFiles( | |||
89 | } | 88 | } |
90 | ) | 89 | ) |
91 | 90 | ||
92 | videosRouter.use('/', abuseVideoRouter) | ||
93 | videosRouter.use('/', blacklistRouter) | 91 | videosRouter.use('/', blacklistRouter) |
94 | videosRouter.use('/', rateVideoRouter) | 92 | videosRouter.use('/', rateVideoRouter) |
95 | videosRouter.use('/', videoCommentRouter) | 93 | videosRouter.use('/', videoCommentRouter) |
diff --git a/server/helpers/middlewares/abuses.ts b/server/helpers/middlewares/abuses.ts index 659ad8939..59ba0d3ed 100644 --- a/server/helpers/middlewares/abuses.ts +++ b/server/helpers/middlewares/abuses.ts | |||
@@ -1,29 +1,5 @@ | |||
1 | import { Response } from 'express' | 1 | import { Response } from 'express' |
2 | import { AbuseModel } from '../../models/abuse/abuse' | 2 | import { AbuseModel } from '../../models/abuse/abuse' |
3 | import { fetchVideo } from '../video' | ||
4 | |||
5 | // FIXME: deprecated in 2.3. Remove this function | ||
6 | async function doesVideoAbuseExist (abuseIdArg: number | string, videoUUID: string, res: Response) { | ||
7 | const abuseId = parseInt(abuseIdArg + '', 10) | ||
8 | let abuse = await AbuseModel.loadByIdAndVideoId(abuseId, null, videoUUID) | ||
9 | |||
10 | if (!abuse) { | ||
11 | const userId = res.locals.oauth?.token.User.id | ||
12 | const video = await fetchVideo(videoUUID, 'all', userId) | ||
13 | |||
14 | if (video) abuse = await AbuseModel.loadByIdAndVideoId(abuseId, video.id) | ||
15 | } | ||
16 | |||
17 | if (abuse === null) { | ||
18 | res.status(404) | ||
19 | .json({ error: 'Video abuse not found' }) | ||
20 | |||
21 | return false | ||
22 | } | ||
23 | |||
24 | res.locals.abuse = abuse | ||
25 | return true | ||
26 | } | ||
27 | 3 | ||
28 | async function doesAbuseExist (abuseId: number | string, res: Response) { | 4 | async function doesAbuseExist (abuseId: number | string, res: Response) { |
29 | const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10)) | 5 | const abuse = await AbuseModel.loadByIdWithReporter(parseInt(abuseId + '', 10)) |
@@ -42,6 +18,5 @@ async function doesAbuseExist (abuseId: number | string, res: Response) { | |||
42 | // --------------------------------------------------------------------------- | 18 | // --------------------------------------------------------------------------- |
43 | 19 | ||
44 | export { | 20 | export { |
45 | doesAbuseExist, | 21 | doesAbuseExist |
46 | doesVideoAbuseExist | ||
47 | } | 22 | } |
diff --git a/server/middlewares/validators/abuse.ts b/server/middlewares/validators/abuse.ts index f99d850a5..99403ca40 100644 --- a/server/middlewares/validators/abuse.ts +++ b/server/middlewares/validators/abuse.ts | |||
@@ -1,10 +1,10 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { body, param, query } from 'express-validator' | 2 | import { body, param, query } from 'express-validator' |
3 | import { | 3 | import { |
4 | areAbusePredefinedReasonsValid, | ||
4 | isAbuseFilterValid, | 5 | isAbuseFilterValid, |
5 | isAbuseMessageValid, | 6 | isAbuseMessageValid, |
6 | isAbuseModerationCommentValid, | 7 | isAbuseModerationCommentValid, |
7 | areAbusePredefinedReasonsValid, | ||
8 | isAbusePredefinedReasonValid, | 8 | isAbusePredefinedReasonValid, |
9 | isAbuseReasonValid, | 9 | isAbuseReasonValid, |
10 | isAbuseStateValid, | 10 | isAbuseStateValid, |
@@ -15,7 +15,7 @@ import { | |||
15 | import { exists, isIdOrUUIDValid, isIdValid, toIntOrNull } from '@server/helpers/custom-validators/misc' | 15 | import { exists, isIdOrUUIDValid, isIdValid, toIntOrNull } from '@server/helpers/custom-validators/misc' |
16 | import { doesCommentIdExist } from '@server/helpers/custom-validators/video-comments' | 16 | import { doesCommentIdExist } from '@server/helpers/custom-validators/video-comments' |
17 | import { logger } from '@server/helpers/logger' | 17 | import { logger } from '@server/helpers/logger' |
18 | import { doesAbuseExist, doesAccountIdExist, doesVideoAbuseExist, doesVideoExist } from '@server/helpers/middlewares' | 18 | import { doesAbuseExist, doesAccountIdExist, doesVideoExist } from '@server/helpers/middlewares' |
19 | import { AbuseMessageModel } from '@server/models/abuse/abuse-message' | 19 | import { AbuseMessageModel } from '@server/models/abuse/abuse-message' |
20 | import { AbuseCreate, UserRight } from '@shared/models' | 20 | import { AbuseCreate, UserRight } from '@shared/models' |
21 | import { areValidationErrors } from './utils' | 21 | import { areValidationErrors } from './utils' |
@@ -256,115 +256,6 @@ const deleteAbuseMessageValidator = [ | |||
256 | } | 256 | } |
257 | ] | 257 | ] |
258 | 258 | ||
259 | // FIXME: deprecated in 2.3. Remove these validators | ||
260 | |||
261 | const videoAbuseReportValidator = [ | ||
262 | param('videoId') | ||
263 | .custom(isIdOrUUIDValid) | ||
264 | .not() | ||
265 | .isEmpty() | ||
266 | .withMessage('Should have a valid videoId'), | ||
267 | body('reason') | ||
268 | .custom(isAbuseReasonValid) | ||
269 | .withMessage('Should have a valid reason'), | ||
270 | body('predefinedReasons') | ||
271 | .optional() | ||
272 | .custom(areAbusePredefinedReasonsValid) | ||
273 | .withMessage('Should have a valid list of predefined reasons'), | ||
274 | body('startAt') | ||
275 | .optional() | ||
276 | .customSanitizer(toIntOrNull) | ||
277 | .custom(isAbuseTimestampValid) | ||
278 | .withMessage('Should have valid starting time value'), | ||
279 | body('endAt') | ||
280 | .optional() | ||
281 | .customSanitizer(toIntOrNull) | ||
282 | .custom(isAbuseTimestampValid) | ||
283 | .withMessage('Should have valid ending time value'), | ||
284 | |||
285 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
286 | logger.debug('Checking videoAbuseReport parameters', { parameters: req.body }) | ||
287 | |||
288 | if (areValidationErrors(req, res)) return | ||
289 | if (!await doesVideoExist(req.params.videoId, res)) return | ||
290 | |||
291 | return next() | ||
292 | } | ||
293 | ] | ||
294 | |||
295 | const videoAbuseGetValidator = [ | ||
296 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), | ||
297 | param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'), | ||
298 | |||
299 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
300 | logger.debug('Checking videoAbuseGetValidator parameters', { parameters: req.body }) | ||
301 | |||
302 | if (areValidationErrors(req, res)) return | ||
303 | if (!await doesVideoAbuseExist(req.params.id, req.params.videoId, res)) return | ||
304 | |||
305 | return next() | ||
306 | } | ||
307 | ] | ||
308 | |||
309 | const videoAbuseUpdateValidator = [ | ||
310 | param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), | ||
311 | param('id').custom(isIdValid).not().isEmpty().withMessage('Should have a valid id'), | ||
312 | body('state') | ||
313 | .optional() | ||
314 | .custom(isAbuseStateValid).withMessage('Should have a valid video abuse state'), | ||
315 | body('moderationComment') | ||
316 | .optional() | ||
317 | .custom(isAbuseModerationCommentValid).withMessage('Should have a valid video moderation comment'), | ||
318 | |||
319 | async (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
320 | logger.debug('Checking videoAbuseUpdateValidator parameters', { parameters: req.body }) | ||
321 | |||
322 | if (areValidationErrors(req, res)) return | ||
323 | if (!await doesVideoAbuseExist(req.params.id, req.params.videoId, res)) return | ||
324 | |||
325 | return next() | ||
326 | } | ||
327 | ] | ||
328 | |||
329 | const videoAbuseListValidator = [ | ||
330 | query('id') | ||
331 | .optional() | ||
332 | .custom(isIdValid).withMessage('Should have a valid id'), | ||
333 | query('predefinedReason') | ||
334 | .optional() | ||
335 | .custom(isAbusePredefinedReasonValid) | ||
336 | .withMessage('Should have a valid predefinedReason'), | ||
337 | query('search') | ||
338 | .optional() | ||
339 | .custom(exists).withMessage('Should have a valid search'), | ||
340 | query('state') | ||
341 | .optional() | ||
342 | .custom(isAbuseStateValid).withMessage('Should have a valid video abuse state'), | ||
343 | query('videoIs') | ||
344 | .optional() | ||
345 | .custom(isAbuseVideoIsValid).withMessage('Should have a valid "video is" attribute'), | ||
346 | query('searchReporter') | ||
347 | .optional() | ||
348 | .custom(exists).withMessage('Should have a valid reporter search'), | ||
349 | query('searchReportee') | ||
350 | .optional() | ||
351 | .custom(exists).withMessage('Should have a valid reportee search'), | ||
352 | query('searchVideo') | ||
353 | .optional() | ||
354 | .custom(exists).withMessage('Should have a valid video search'), | ||
355 | query('searchVideoChannel') | ||
356 | .optional() | ||
357 | .custom(exists).withMessage('Should have a valid video channel search'), | ||
358 | |||
359 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
360 | logger.debug('Checking videoAbuseListValidator parameters', { parameters: req.body }) | ||
361 | |||
362 | if (areValidationErrors(req, res)) return | ||
363 | |||
364 | return next() | ||
365 | } | ||
366 | ] | ||
367 | |||
368 | // --------------------------------------------------------------------------- | 259 | // --------------------------------------------------------------------------- |
369 | 260 | ||
370 | export { | 261 | export { |
@@ -376,9 +267,5 @@ export { | |||
376 | abuseUpdateValidator, | 267 | abuseUpdateValidator, |
377 | deleteAbuseMessageValidator, | 268 | deleteAbuseMessageValidator, |
378 | abuseListForUserValidator, | 269 | abuseListForUserValidator, |
379 | getAbuseValidator, | 270 | getAbuseValidator |
380 | videoAbuseReportValidator, | ||
381 | videoAbuseGetValidator, | ||
382 | videoAbuseUpdateValidator, | ||
383 | videoAbuseListValidator | ||
384 | } | 271 | } |
diff --git a/server/models/abuse/abuse.ts b/server/models/abuse/abuse.ts index 2a407c3d2..290270fe2 100644 --- a/server/models/abuse/abuse.ts +++ b/server/models/abuse/abuse.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import { invert } from 'lodash' | 2 | import { invert } from 'lodash' |
3 | import { literal, Op, QueryTypes, WhereOptions } from 'sequelize' | 3 | import { literal, Op, QueryTypes } from 'sequelize' |
4 | import { | 4 | import { |
5 | AllowNull, | 5 | AllowNull, |
6 | BelongsTo, | 6 | BelongsTo, |
@@ -265,32 +265,6 @@ export class AbuseModel extends Model<AbuseModel> { | |||
265 | }) | 265 | }) |
266 | VideoAbuse: VideoAbuseModel | 266 | VideoAbuse: VideoAbuseModel |
267 | 267 | ||
268 | // FIXME: deprecated in 2.3. Remove these validators | ||
269 | static loadByIdAndVideoId (id: number, videoId?: number, uuid?: string): Bluebird<MAbuseReporter> { | ||
270 | const videoWhere: WhereOptions = {} | ||
271 | |||
272 | if (videoId) videoWhere.videoId = videoId | ||
273 | if (uuid) videoWhere.deletedVideo = { uuid } | ||
274 | |||
275 | const query = { | ||
276 | include: [ | ||
277 | { | ||
278 | model: VideoAbuseModel, | ||
279 | required: true, | ||
280 | where: videoWhere | ||
281 | }, | ||
282 | { | ||
283 | model: AccountModel, | ||
284 | as: 'ReporterAccount' | ||
285 | } | ||
286 | ], | ||
287 | where: { | ||
288 | id | ||
289 | } | ||
290 | } | ||
291 | return AbuseModel.findOne(query) | ||
292 | } | ||
293 | |||
294 | static loadByIdWithReporter (id: number): Bluebird<MAbuseReporter> { | 268 | static loadByIdWithReporter (id: number): Bluebird<MAbuseReporter> { |
295 | const query = { | 269 | const query = { |
296 | where: { | 270 | where: { |
@@ -561,13 +535,7 @@ export class AbuseModel extends Model<AbuseModel> { | |||
561 | : null, | 535 | : null, |
562 | 536 | ||
563 | countReportsForReporter: (countReportsForReporter || 0), | 537 | countReportsForReporter: (countReportsForReporter || 0), |
564 | countReportsForReportee: (countReportsForReportee || 0), | 538 | countReportsForReportee: (countReportsForReportee || 0) |
565 | |||
566 | // FIXME: deprecated in 2.3, remove this | ||
567 | startAt: null, | ||
568 | endAt: null, | ||
569 | count: countReportsForVideo || 0, | ||
570 | nth: nthReportForVideo || 0 | ||
571 | }) | 539 | }) |
572 | } | 540 | } |
573 | 541 | ||
diff --git a/server/tests/api/check-params/index.ts b/server/tests/api/check-params/index.ts index b5f0d07be..d0b0b9c21 100644 --- a/server/tests/api/check-params/index.ts +++ b/server/tests/api/check-params/index.ts | |||
@@ -16,7 +16,6 @@ import './services' | |||
16 | import './user-notifications' | 16 | import './user-notifications' |
17 | import './user-subscriptions' | 17 | import './user-subscriptions' |
18 | import './users' | 18 | import './users' |
19 | import './video-abuses' | ||
20 | import './video-blacklist' | 19 | import './video-blacklist' |
21 | import './video-captions' | 20 | import './video-captions' |
22 | import './video-channels' | 21 | import './video-channels' |
diff --git a/server/tests/api/check-params/video-abuses.ts b/server/tests/api/check-params/video-abuses.ts deleted file mode 100644 index 3b361ca79..000000000 --- a/server/tests/api/check-params/video-abuses.ts +++ /dev/null | |||
@@ -1,216 +0,0 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import { AbuseState, VideoAbuseCreate } from '@shared/models' | ||
5 | import { | ||
6 | cleanupTests, | ||
7 | createUser, | ||
8 | deleteVideoAbuse, | ||
9 | flushAndRunServer, | ||
10 | makeGetRequest, | ||
11 | makePostBodyRequest, | ||
12 | ServerInfo, | ||
13 | setAccessTokensToServers, | ||
14 | updateVideoAbuse, | ||
15 | uploadVideo, | ||
16 | userLogin | ||
17 | } from '../../../../shared/extra-utils' | ||
18 | import { | ||
19 | checkBadCountPagination, | ||
20 | checkBadSortPagination, | ||
21 | checkBadStartPagination | ||
22 | } from '../../../../shared/extra-utils/requests/check-api-params' | ||
23 | |||
24 | // FIXME: deprecated in 2.3. Remove this controller | ||
25 | |||
26 | describe('Test video abuses API validators', function () { | ||
27 | let server: ServerInfo | ||
28 | let userAccessToken = '' | ||
29 | let videoAbuseId: number | ||
30 | |||
31 | // --------------------------------------------------------------- | ||
32 | |||
33 | before(async function () { | ||
34 | this.timeout(30000) | ||
35 | |||
36 | server = await flushAndRunServer(1) | ||
37 | |||
38 | await setAccessTokensToServers([ server ]) | ||
39 | |||
40 | const username = 'user1' | ||
41 | const password = 'my super password' | ||
42 | await createUser({ url: server.url, accessToken: server.accessToken, username: username, password: password }) | ||
43 | userAccessToken = await userLogin(server, { username, password }) | ||
44 | |||
45 | const res = await uploadVideo(server.url, server.accessToken, {}) | ||
46 | server.video = res.body.video | ||
47 | }) | ||
48 | |||
49 | describe('When listing video abuses', function () { | ||
50 | const path = '/api/v1/videos/abuse' | ||
51 | |||
52 | it('Should fail with a bad start pagination', async function () { | ||
53 | await checkBadStartPagination(server.url, path, server.accessToken) | ||
54 | }) | ||
55 | |||
56 | it('Should fail with a bad count pagination', async function () { | ||
57 | await checkBadCountPagination(server.url, path, server.accessToken) | ||
58 | }) | ||
59 | |||
60 | it('Should fail with an incorrect sort', async function () { | ||
61 | await checkBadSortPagination(server.url, path, server.accessToken) | ||
62 | }) | ||
63 | |||
64 | it('Should fail with a non authenticated user', async function () { | ||
65 | await makeGetRequest({ | ||
66 | url: server.url, | ||
67 | path, | ||
68 | statusCodeExpected: 401 | ||
69 | }) | ||
70 | }) | ||
71 | |||
72 | it('Should fail with a non admin user', async function () { | ||
73 | await makeGetRequest({ | ||
74 | url: server.url, | ||
75 | path, | ||
76 | token: userAccessToken, | ||
77 | statusCodeExpected: 403 | ||
78 | }) | ||
79 | }) | ||
80 | |||
81 | it('Should fail with a bad id filter', async function () { | ||
82 | await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { id: 'toto' } }) | ||
83 | }) | ||
84 | |||
85 | it('Should fail with a bad state filter', async function () { | ||
86 | await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { state: 'toto' } }) | ||
87 | }) | ||
88 | |||
89 | it('Should fail with a bad videoIs filter', async function () { | ||
90 | await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { videoIs: 'toto' } }) | ||
91 | }) | ||
92 | |||
93 | it('Should succeed with the correct params', async function () { | ||
94 | await makeGetRequest({ url: server.url, path, token: server.accessToken, query: { id: 13 }, statusCodeExpected: 200 }) | ||
95 | }) | ||
96 | }) | ||
97 | |||
98 | describe('When reporting a video abuse', function () { | ||
99 | const basePath = '/api/v1/videos/' | ||
100 | let path: string | ||
101 | |||
102 | before(() => { | ||
103 | path = basePath + server.video.id + '/abuse' | ||
104 | }) | ||
105 | |||
106 | it('Should fail with nothing', async function () { | ||
107 | const fields = {} | ||
108 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
109 | }) | ||
110 | |||
111 | it('Should fail with a wrong video', async function () { | ||
112 | const wrongPath = '/api/v1/videos/blabla/abuse' | ||
113 | const fields = { reason: 'my super reason' } | ||
114 | |||
115 | await makePostBodyRequest({ url: server.url, path: wrongPath, token: server.accessToken, fields }) | ||
116 | }) | ||
117 | |||
118 | it('Should fail with a non authenticated user', async function () { | ||
119 | const fields = { reason: 'my super reason' } | ||
120 | |||
121 | await makePostBodyRequest({ url: server.url, path, token: 'hello', fields, statusCodeExpected: 401 }) | ||
122 | }) | ||
123 | |||
124 | it('Should fail with a reason too short', async function () { | ||
125 | const fields = { reason: 'h' } | ||
126 | |||
127 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
128 | }) | ||
129 | |||
130 | it('Should fail with a too big reason', async function () { | ||
131 | const fields = { reason: 'super'.repeat(605) } | ||
132 | |||
133 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
134 | }) | ||
135 | |||
136 | it('Should succeed with the correct parameters (basic)', async function () { | ||
137 | const fields = { reason: 'my super reason' } | ||
138 | |||
139 | const res = await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 200 }) | ||
140 | videoAbuseId = res.body.abuse.id | ||
141 | }) | ||
142 | |||
143 | it('Should fail with a wrong predefined reason', async function () { | ||
144 | const fields = { reason: 'my super reason', predefinedReasons: [ 'wrongPredefinedReason' ] } | ||
145 | |||
146 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
147 | }) | ||
148 | |||
149 | it('Should fail with negative timestamps', async function () { | ||
150 | const fields = { reason: 'my super reason', startAt: -1 } | ||
151 | |||
152 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields }) | ||
153 | }) | ||
154 | |||
155 | it('Should succeed with the corret parameters (advanced)', async function () { | ||
156 | const fields: VideoAbuseCreate = { reason: 'my super reason', predefinedReasons: [ 'serverRules' ], startAt: 1, endAt: 5 } | ||
157 | |||
158 | await makePostBodyRequest({ url: server.url, path, token: server.accessToken, fields, statusCodeExpected: 200 }) | ||
159 | }) | ||
160 | }) | ||
161 | |||
162 | describe('When updating a video abuse', function () { | ||
163 | |||
164 | it('Should fail with a non authenticated user', async function () { | ||
165 | await updateVideoAbuse(server.url, 'blabla', server.video.uuid, videoAbuseId, {}, 401) | ||
166 | }) | ||
167 | |||
168 | it('Should fail with a non admin user', async function () { | ||
169 | await updateVideoAbuse(server.url, userAccessToken, server.video.uuid, videoAbuseId, {}, 403) | ||
170 | }) | ||
171 | |||
172 | it('Should fail with a bad video id or bad video abuse id', async function () { | ||
173 | await updateVideoAbuse(server.url, server.accessToken, server.video.uuid, 45, {}, 404) | ||
174 | await updateVideoAbuse(server.url, server.accessToken, 52, videoAbuseId, {}, 404) | ||
175 | }) | ||
176 | |||
177 | it('Should fail with a bad state', async function () { | ||
178 | const body = { state: 5 } | ||
179 | await updateVideoAbuse(server.url, server.accessToken, server.video.uuid, videoAbuseId, body, 400) | ||
180 | }) | ||
181 | |||
182 | it('Should fail with a bad moderation comment', async function () { | ||
183 | const body = { moderationComment: 'b'.repeat(3001) } | ||
184 | await updateVideoAbuse(server.url, server.accessToken, server.video.uuid, videoAbuseId, body, 400) | ||
185 | }) | ||
186 | |||
187 | it('Should succeed with the correct params', async function () { | ||
188 | const body = { state: AbuseState.ACCEPTED } | ||
189 | await updateVideoAbuse(server.url, server.accessToken, server.video.uuid, videoAbuseId, body) | ||
190 | }) | ||
191 | }) | ||
192 | |||
193 | describe('When deleting a video abuse', function () { | ||
194 | |||
195 | it('Should fail with a non authenticated user', async function () { | ||
196 | await deleteVideoAbuse(server.url, 'blabla', server.video.uuid, videoAbuseId, 401) | ||
197 | }) | ||
198 | |||
199 | it('Should fail with a non admin user', async function () { | ||
200 | await deleteVideoAbuse(server.url, userAccessToken, server.video.uuid, videoAbuseId, 403) | ||
201 | }) | ||
202 | |||
203 | it('Should fail with a bad video id or bad video abuse id', async function () { | ||
204 | await deleteVideoAbuse(server.url, server.accessToken, server.video.uuid, 45, 404) | ||
205 | await deleteVideoAbuse(server.url, server.accessToken, 52, videoAbuseId, 404) | ||
206 | }) | ||
207 | |||
208 | it('Should succeed with the correct params', async function () { | ||
209 | await deleteVideoAbuse(server.url, server.accessToken, server.video.uuid, videoAbuseId) | ||
210 | }) | ||
211 | }) | ||
212 | |||
213 | after(async function () { | ||
214 | await cleanupTests([ server ]) | ||
215 | }) | ||
216 | }) | ||
diff --git a/server/tests/api/moderation/index.ts b/server/tests/api/moderation/index.ts index ceb223003..6593c001f 100644 --- a/server/tests/api/moderation/index.ts +++ b/server/tests/api/moderation/index.ts | |||
@@ -1,4 +1,3 @@ | |||
1 | export * from './abuses' | 1 | export * from './abuses' |
2 | export * from './blocklist' | 2 | export * from './blocklist' |
3 | export * from './video-abuse' | ||
4 | export * from './video-blacklist' | 3 | export * from './video-blacklist' |
diff --git a/server/tests/api/moderation/video-abuse.ts b/server/tests/api/moderation/video-abuse.ts deleted file mode 100644 index 0b6a0e8ae..000000000 --- a/server/tests/api/moderation/video-abuse.ts +++ /dev/null | |||
@@ -1,386 +0,0 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | ||
2 | |||
3 | import 'mocha' | ||
4 | import * as chai from 'chai' | ||
5 | import { AbusePredefinedReasonsString, AbuseState, AdminAbuse } from '@shared/models' | ||
6 | import { | ||
7 | cleanupTests, | ||
8 | createUser, | ||
9 | deleteVideoAbuse, | ||
10 | flushAndRunMultipleServers, | ||
11 | getVideoAbusesList, | ||
12 | getVideosList, | ||
13 | removeVideo, | ||
14 | reportVideoAbuse, | ||
15 | ServerInfo, | ||
16 | setAccessTokensToServers, | ||
17 | updateVideoAbuse, | ||
18 | uploadVideo, | ||
19 | userLogin | ||
20 | } from '../../../../shared/extra-utils/index' | ||
21 | import { doubleFollow } from '../../../../shared/extra-utils/server/follows' | ||
22 | import { waitJobs } from '../../../../shared/extra-utils/server/jobs' | ||
23 | import { | ||
24 | addAccountToServerBlocklist, | ||
25 | addServerToServerBlocklist, | ||
26 | removeAccountFromServerBlocklist, | ||
27 | removeServerFromServerBlocklist | ||
28 | } from '../../../../shared/extra-utils/users/blocklist' | ||
29 | |||
30 | const expect = chai.expect | ||
31 | |||
32 | // FIXME: deprecated in 2.3. Remove this controller | ||
33 | |||
34 | describe('Test video abuses', function () { | ||
35 | let servers: ServerInfo[] = [] | ||
36 | let abuseServer2: AdminAbuse | ||
37 | |||
38 | before(async function () { | ||
39 | this.timeout(50000) | ||
40 | |||
41 | // Run servers | ||
42 | servers = await flushAndRunMultipleServers(2) | ||
43 | |||
44 | // Get the access tokens | ||
45 | await setAccessTokensToServers(servers) | ||
46 | |||
47 | // Server 1 and server 2 follow each other | ||
48 | await doubleFollow(servers[0], servers[1]) | ||
49 | |||
50 | // Upload some videos on each servers | ||
51 | const video1Attributes = { | ||
52 | name: 'my super name for server 1', | ||
53 | description: 'my super description for server 1' | ||
54 | } | ||
55 | await uploadVideo(servers[0].url, servers[0].accessToken, video1Attributes) | ||
56 | |||
57 | const video2Attributes = { | ||
58 | name: 'my super name for server 2', | ||
59 | description: 'my super description for server 2' | ||
60 | } | ||
61 | await uploadVideo(servers[1].url, servers[1].accessToken, video2Attributes) | ||
62 | |||
63 | // Wait videos propagation, server 2 has transcoding enabled | ||
64 | await waitJobs(servers) | ||
65 | |||
66 | const res = await getVideosList(servers[0].url) | ||
67 | const videos = res.body.data | ||
68 | |||
69 | expect(videos.length).to.equal(2) | ||
70 | |||
71 | servers[0].video = videos.find(video => video.name === 'my super name for server 1') | ||
72 | servers[1].video = videos.find(video => video.name === 'my super name for server 2') | ||
73 | }) | ||
74 | |||
75 | it('Should not have video abuses', async function () { | ||
76 | const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
77 | |||
78 | expect(res.body.total).to.equal(0) | ||
79 | expect(res.body.data).to.be.an('array') | ||
80 | expect(res.body.data.length).to.equal(0) | ||
81 | }) | ||
82 | |||
83 | it('Should report abuse on a local video', async function () { | ||
84 | this.timeout(15000) | ||
85 | |||
86 | const reason = 'my super bad reason' | ||
87 | await reportVideoAbuse(servers[0].url, servers[0].accessToken, servers[0].video.id, reason) | ||
88 | |||
89 | // We wait requests propagation, even if the server 1 is not supposed to make a request to server 2 | ||
90 | await waitJobs(servers) | ||
91 | }) | ||
92 | |||
93 | it('Should have 1 video abuses on server 1 and 0 on server 2', async function () { | ||
94 | const res1 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
95 | |||
96 | expect(res1.body.total).to.equal(1) | ||
97 | expect(res1.body.data).to.be.an('array') | ||
98 | expect(res1.body.data.length).to.equal(1) | ||
99 | |||
100 | const abuse: AdminAbuse = res1.body.data[0] | ||
101 | expect(abuse.reason).to.equal('my super bad reason') | ||
102 | expect(abuse.reporterAccount.name).to.equal('root') | ||
103 | expect(abuse.reporterAccount.host).to.equal('localhost:' + servers[0].port) | ||
104 | expect(abuse.video.id).to.equal(servers[0].video.id) | ||
105 | expect(abuse.video.channel).to.exist | ||
106 | expect(abuse.video.countReports).to.equal(1) | ||
107 | expect(abuse.video.nthReport).to.equal(1) | ||
108 | expect(abuse.countReportsForReporter).to.equal(1) | ||
109 | expect(abuse.countReportsForReportee).to.equal(1) | ||
110 | |||
111 | const res2 = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken }) | ||
112 | expect(res2.body.total).to.equal(0) | ||
113 | expect(res2.body.data).to.be.an('array') | ||
114 | expect(res2.body.data.length).to.equal(0) | ||
115 | }) | ||
116 | |||
117 | it('Should report abuse on a remote video', async function () { | ||
118 | this.timeout(10000) | ||
119 | |||
120 | const reason = 'my super bad reason 2' | ||
121 | await reportVideoAbuse(servers[0].url, servers[0].accessToken, servers[1].video.id, reason) | ||
122 | |||
123 | // We wait requests propagation | ||
124 | await waitJobs(servers) | ||
125 | }) | ||
126 | |||
127 | it('Should have 2 video abuses on server 1 and 1 on server 2', async function () { | ||
128 | const res1 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
129 | expect(res1.body.total).to.equal(2) | ||
130 | expect(res1.body.data).to.be.an('array') | ||
131 | expect(res1.body.data.length).to.equal(2) | ||
132 | |||
133 | const abuse1: AdminAbuse = res1.body.data[0] | ||
134 | expect(abuse1.reason).to.equal('my super bad reason') | ||
135 | expect(abuse1.reporterAccount.name).to.equal('root') | ||
136 | expect(abuse1.reporterAccount.host).to.equal('localhost:' + servers[0].port) | ||
137 | expect(abuse1.video.id).to.equal(servers[0].video.id) | ||
138 | expect(abuse1.state.id).to.equal(AbuseState.PENDING) | ||
139 | expect(abuse1.state.label).to.equal('Pending') | ||
140 | expect(abuse1.moderationComment).to.be.null | ||
141 | expect(abuse1.video.countReports).to.equal(1) | ||
142 | expect(abuse1.video.nthReport).to.equal(1) | ||
143 | |||
144 | const abuse2: AdminAbuse = res1.body.data[1] | ||
145 | expect(abuse2.reason).to.equal('my super bad reason 2') | ||
146 | expect(abuse2.reporterAccount.name).to.equal('root') | ||
147 | expect(abuse2.reporterAccount.host).to.equal('localhost:' + servers[0].port) | ||
148 | expect(abuse2.video.id).to.equal(servers[1].video.id) | ||
149 | expect(abuse2.state.id).to.equal(AbuseState.PENDING) | ||
150 | expect(abuse2.state.label).to.equal('Pending') | ||
151 | expect(abuse2.moderationComment).to.be.null | ||
152 | |||
153 | const res2 = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken }) | ||
154 | expect(res2.body.total).to.equal(1) | ||
155 | expect(res2.body.data).to.be.an('array') | ||
156 | expect(res2.body.data.length).to.equal(1) | ||
157 | |||
158 | abuseServer2 = res2.body.data[0] | ||
159 | expect(abuseServer2.reason).to.equal('my super bad reason 2') | ||
160 | expect(abuseServer2.reporterAccount.name).to.equal('root') | ||
161 | expect(abuseServer2.reporterAccount.host).to.equal('localhost:' + servers[0].port) | ||
162 | expect(abuseServer2.state.id).to.equal(AbuseState.PENDING) | ||
163 | expect(abuseServer2.state.label).to.equal('Pending') | ||
164 | expect(abuseServer2.moderationComment).to.be.null | ||
165 | }) | ||
166 | |||
167 | it('Should update the state of a video abuse', async function () { | ||
168 | const body = { state: AbuseState.REJECTED } | ||
169 | await updateVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id, body) | ||
170 | |||
171 | const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken }) | ||
172 | expect(res.body.data[0].state.id).to.equal(AbuseState.REJECTED) | ||
173 | }) | ||
174 | |||
175 | it('Should add a moderation comment', async function () { | ||
176 | const body = { state: AbuseState.ACCEPTED, moderationComment: 'It is valid' } | ||
177 | await updateVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id, body) | ||
178 | |||
179 | const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken }) | ||
180 | expect(res.body.data[0].state.id).to.equal(AbuseState.ACCEPTED) | ||
181 | expect(res.body.data[0].moderationComment).to.equal('It is valid') | ||
182 | }) | ||
183 | |||
184 | it('Should hide video abuses from blocked accounts', async function () { | ||
185 | this.timeout(10000) | ||
186 | |||
187 | { | ||
188 | await reportVideoAbuse(servers[1].url, servers[1].accessToken, servers[0].video.uuid, 'will mute this') | ||
189 | await waitJobs(servers) | ||
190 | |||
191 | const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
192 | expect(res.body.total).to.equal(3) | ||
193 | } | ||
194 | |||
195 | const accountToBlock = 'root@localhost:' + servers[1].port | ||
196 | |||
197 | { | ||
198 | await addAccountToServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock) | ||
199 | |||
200 | const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
201 | expect(res.body.total).to.equal(2) | ||
202 | |||
203 | const abuse = res.body.data.find(a => a.reason === 'will mute this') | ||
204 | expect(abuse).to.be.undefined | ||
205 | } | ||
206 | |||
207 | { | ||
208 | await removeAccountFromServerBlocklist(servers[0].url, servers[0].accessToken, accountToBlock) | ||
209 | |||
210 | const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
211 | expect(res.body.total).to.equal(3) | ||
212 | } | ||
213 | }) | ||
214 | |||
215 | it('Should hide video abuses from blocked servers', async function () { | ||
216 | const serverToBlock = servers[1].host | ||
217 | |||
218 | { | ||
219 | await addServerToServerBlocklist(servers[0].url, servers[0].accessToken, servers[1].host) | ||
220 | |||
221 | const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
222 | expect(res.body.total).to.equal(2) | ||
223 | |||
224 | const abuse = res.body.data.find(a => a.reason === 'will mute this') | ||
225 | expect(abuse).to.be.undefined | ||
226 | } | ||
227 | |||
228 | { | ||
229 | await removeServerFromServerBlocklist(servers[0].url, servers[0].accessToken, serverToBlock) | ||
230 | |||
231 | const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
232 | expect(res.body.total).to.equal(3) | ||
233 | } | ||
234 | }) | ||
235 | |||
236 | it('Should keep the video abuse when deleting the video', async function () { | ||
237 | this.timeout(10000) | ||
238 | |||
239 | await removeVideo(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid) | ||
240 | |||
241 | await waitJobs(servers) | ||
242 | |||
243 | const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken }) | ||
244 | expect(res.body.total).to.equal(2, "wrong number of videos returned") | ||
245 | expect(res.body.data.length).to.equal(2, "wrong number of videos returned") | ||
246 | expect(res.body.data[0].id).to.equal(abuseServer2.id, "wrong origin server id for first video") | ||
247 | |||
248 | const abuse: AdminAbuse = res.body.data[0] | ||
249 | expect(abuse.video.id).to.equal(abuseServer2.video.id, "wrong video id") | ||
250 | expect(abuse.video.channel).to.exist | ||
251 | expect(abuse.video.deleted).to.be.true | ||
252 | }) | ||
253 | |||
254 | it('Should include counts of reports from reporter and reportee', async function () { | ||
255 | this.timeout(10000) | ||
256 | |||
257 | // register a second user to have two reporters/reportees | ||
258 | const user = { username: 'user2', password: 'password' } | ||
259 | await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, ...user }) | ||
260 | const userAccessToken = await userLogin(servers[0], user) | ||
261 | |||
262 | // upload a third video via this user | ||
263 | const video3Attributes = { | ||
264 | name: 'my second super name for server 1', | ||
265 | description: 'my second super description for server 1' | ||
266 | } | ||
267 | await uploadVideo(servers[0].url, userAccessToken, video3Attributes) | ||
268 | |||
269 | const res1 = await getVideosList(servers[0].url) | ||
270 | const videos = res1.body.data | ||
271 | const video3 = videos.find(video => video.name === 'my second super name for server 1') | ||
272 | |||
273 | // resume with the test | ||
274 | const reason3 = 'my super bad reason 3' | ||
275 | await reportVideoAbuse(servers[0].url, servers[0].accessToken, video3.id, reason3) | ||
276 | const reason4 = 'my super bad reason 4' | ||
277 | await reportVideoAbuse(servers[0].url, userAccessToken, servers[0].video.id, reason4) | ||
278 | |||
279 | const res2 = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
280 | |||
281 | { | ||
282 | for (const abuse of res2.body.data as AdminAbuse[]) { | ||
283 | if (abuse.video.id === video3.id) { | ||
284 | expect(abuse.video.countReports).to.equal(1, "wrong reports count for video 3") | ||
285 | expect(abuse.video.nthReport).to.equal(1, "wrong report position in report list for video 3") | ||
286 | expect(abuse.countReportsForReportee).to.equal(1, "wrong reports count for reporter on video 3 abuse") | ||
287 | expect(abuse.countReportsForReporter).to.equal(3, "wrong reports count for reportee on video 3 abuse") | ||
288 | } | ||
289 | if (abuse.video.id === servers[0].video.id) { | ||
290 | expect(abuse.countReportsForReportee).to.equal(3, "wrong reports count for reporter on video 1 abuse") | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | }) | ||
295 | |||
296 | it('Should list predefined reasons as well as timestamps for the reported video', async function () { | ||
297 | this.timeout(10000) | ||
298 | |||
299 | const reason5 = 'my super bad reason 5' | ||
300 | const predefinedReasons5: AbusePredefinedReasonsString[] = [ 'violentOrRepulsive', 'captions' ] | ||
301 | const createdAbuse = (await reportVideoAbuse( | ||
302 | servers[0].url, | ||
303 | servers[0].accessToken, | ||
304 | servers[0].video.id, | ||
305 | reason5, | ||
306 | predefinedReasons5, | ||
307 | 1, | ||
308 | 5 | ||
309 | )).body.abuse | ||
310 | |||
311 | const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
312 | |||
313 | { | ||
314 | const abuse = (res.body.data as AdminAbuse[]).find(a => a.id === createdAbuse.id) | ||
315 | expect(abuse.reason).to.equals(reason5) | ||
316 | expect(abuse.predefinedReasons).to.deep.equals(predefinedReasons5, "predefined reasons do not match the one reported") | ||
317 | expect(abuse.video.startAt).to.equal(1, "starting timestamp doesn't match the one reported") | ||
318 | expect(abuse.video.endAt).to.equal(5, "ending timestamp doesn't match the one reported") | ||
319 | } | ||
320 | }) | ||
321 | |||
322 | it('Should delete the video abuse', async function () { | ||
323 | this.timeout(10000) | ||
324 | |||
325 | await deleteVideoAbuse(servers[1].url, servers[1].accessToken, abuseServer2.video.uuid, abuseServer2.id) | ||
326 | |||
327 | await waitJobs(servers) | ||
328 | |||
329 | { | ||
330 | const res = await getVideoAbusesList({ url: servers[1].url, token: servers[1].accessToken }) | ||
331 | expect(res.body.total).to.equal(1) | ||
332 | expect(res.body.data.length).to.equal(1) | ||
333 | expect(res.body.data[0].id).to.not.equal(abuseServer2.id) | ||
334 | } | ||
335 | |||
336 | { | ||
337 | const res = await getVideoAbusesList({ url: servers[0].url, token: servers[0].accessToken }) | ||
338 | expect(res.body.total).to.equal(6) | ||
339 | } | ||
340 | }) | ||
341 | |||
342 | it('Should list and filter video abuses', async function () { | ||
343 | async function list (query: Omit<Parameters<typeof getVideoAbusesList>[0], 'url' | 'token'>) { | ||
344 | const options = { | ||
345 | url: servers[0].url, | ||
346 | token: servers[0].accessToken | ||
347 | } | ||
348 | |||
349 | Object.assign(options, query) | ||
350 | |||
351 | const res = await getVideoAbusesList(options) | ||
352 | |||
353 | return res.body.data as AdminAbuse[] | ||
354 | } | ||
355 | |||
356 | expect(await list({ id: 56 })).to.have.lengthOf(0) | ||
357 | expect(await list({ id: 1 })).to.have.lengthOf(1) | ||
358 | |||
359 | expect(await list({ search: 'my super name for server 1' })).to.have.lengthOf(4) | ||
360 | expect(await list({ search: 'aaaaaaaaaaaaaaaaaaaaaaaaaa' })).to.have.lengthOf(0) | ||
361 | |||
362 | expect(await list({ searchVideo: 'my second super name for server 1' })).to.have.lengthOf(1) | ||
363 | |||
364 | expect(await list({ searchVideoChannel: 'root' })).to.have.lengthOf(4) | ||
365 | expect(await list({ searchVideoChannel: 'aaaa' })).to.have.lengthOf(0) | ||
366 | |||
367 | expect(await list({ searchReporter: 'user2' })).to.have.lengthOf(1) | ||
368 | expect(await list({ searchReporter: 'root' })).to.have.lengthOf(5) | ||
369 | |||
370 | expect(await list({ searchReportee: 'root' })).to.have.lengthOf(5) | ||
371 | expect(await list({ searchReportee: 'aaaa' })).to.have.lengthOf(0) | ||
372 | |||
373 | expect(await list({ videoIs: 'deleted' })).to.have.lengthOf(1) | ||
374 | expect(await list({ videoIs: 'blacklisted' })).to.have.lengthOf(0) | ||
375 | |||
376 | expect(await list({ state: AbuseState.ACCEPTED })).to.have.lengthOf(0) | ||
377 | expect(await list({ state: AbuseState.PENDING })).to.have.lengthOf(6) | ||
378 | |||
379 | expect(await list({ predefinedReason: 'violentOrRepulsive' })).to.have.lengthOf(1) | ||
380 | expect(await list({ predefinedReason: 'serverRules' })).to.have.lengthOf(0) | ||
381 | }) | ||
382 | |||
383 | after(async function () { | ||
384 | await cleanupTests(servers) | ||
385 | }) | ||
386 | }) | ||
diff --git a/shared/extra-utils/index.ts b/shared/extra-utils/index.ts index d118b12d2..8f5c709ff 100644 --- a/shared/extra-utils/index.ts +++ b/shared/extra-utils/index.ts | |||
@@ -19,7 +19,6 @@ export * from './users/accounts' | |||
19 | export * from './moderation/abuses' | 19 | export * from './moderation/abuses' |
20 | export * from './videos/services' | 20 | export * from './videos/services' |
21 | export * from './videos/live' | 21 | export * from './videos/live' |
22 | export * from './videos/video-abuses' | ||
23 | export * from './videos/video-blacklist' | 22 | export * from './videos/video-blacklist' |
24 | export * from './videos/video-captions' | 23 | export * from './videos/video-captions' |
25 | export * from './videos/video-channels' | 24 | export * from './videos/video-channels' |
diff --git a/shared/extra-utils/videos/video-abuses.ts b/shared/extra-utils/videos/video-abuses.ts deleted file mode 100644 index 8827b8196..000000000 --- a/shared/extra-utils/videos/video-abuses.ts +++ /dev/null | |||
@@ -1,114 +0,0 @@ | |||
1 | import * as request from 'supertest' | ||
2 | import { AbusePredefinedReasonsString, AbuseState, AbuseUpdate, AbuseVideoIs } from '@shared/models' | ||
3 | import { makeDeleteRequest, makeGetRequest, makePutBodyRequest } from '../requests/requests' | ||
4 | |||
5 | // FIXME: deprecated in 2.3. Remove this file | ||
6 | |||
7 | function reportVideoAbuse ( | ||
8 | url: string, | ||
9 | token: string, | ||
10 | videoId: number | string, | ||
11 | reason: string, | ||
12 | predefinedReasons?: AbusePredefinedReasonsString[], | ||
13 | startAt?: number, | ||
14 | endAt?: number, | ||
15 | specialStatus = 200 | ||
16 | ) { | ||
17 | const path = '/api/v1/videos/' + videoId + '/abuse' | ||
18 | |||
19 | return request(url) | ||
20 | .post(path) | ||
21 | .set('Accept', 'application/json') | ||
22 | .set('Authorization', 'Bearer ' + token) | ||
23 | .send({ reason, predefinedReasons, startAt, endAt }) | ||
24 | .expect(specialStatus) | ||
25 | } | ||
26 | |||
27 | function getVideoAbusesList (options: { | ||
28 | url: string | ||
29 | token: string | ||
30 | id?: number | ||
31 | predefinedReason?: AbusePredefinedReasonsString | ||
32 | search?: string | ||
33 | state?: AbuseState | ||
34 | videoIs?: AbuseVideoIs | ||
35 | searchReporter?: string | ||
36 | searchReportee?: string | ||
37 | searchVideo?: string | ||
38 | searchVideoChannel?: string | ||
39 | }) { | ||
40 | const { | ||
41 | url, | ||
42 | token, | ||
43 | id, | ||
44 | predefinedReason, | ||
45 | search, | ||
46 | state, | ||
47 | videoIs, | ||
48 | searchReporter, | ||
49 | searchReportee, | ||
50 | searchVideo, | ||
51 | searchVideoChannel | ||
52 | } = options | ||
53 | const path = '/api/v1/videos/abuse' | ||
54 | |||
55 | const query = { | ||
56 | sort: 'createdAt', | ||
57 | id, | ||
58 | predefinedReason, | ||
59 | search, | ||
60 | state, | ||
61 | videoIs, | ||
62 | searchReporter, | ||
63 | searchReportee, | ||
64 | searchVideo, | ||
65 | searchVideoChannel | ||
66 | } | ||
67 | |||
68 | return makeGetRequest({ | ||
69 | url, | ||
70 | path, | ||
71 | token, | ||
72 | query, | ||
73 | statusCodeExpected: 200 | ||
74 | }) | ||
75 | } | ||
76 | |||
77 | function updateVideoAbuse ( | ||
78 | url: string, | ||
79 | token: string, | ||
80 | videoId: string | number, | ||
81 | videoAbuseId: number, | ||
82 | body: AbuseUpdate, | ||
83 | statusCodeExpected = 204 | ||
84 | ) { | ||
85 | const path = '/api/v1/videos/' + videoId + '/abuse/' + videoAbuseId | ||
86 | |||
87 | return makePutBodyRequest({ | ||
88 | url, | ||
89 | token, | ||
90 | path, | ||
91 | fields: body, | ||
92 | statusCodeExpected | ||
93 | }) | ||
94 | } | ||
95 | |||
96 | function deleteVideoAbuse (url: string, token: string, videoId: string | number, videoAbuseId: number, statusCodeExpected = 204) { | ||
97 | const path = '/api/v1/videos/' + videoId + '/abuse/' + videoAbuseId | ||
98 | |||
99 | return makeDeleteRequest({ | ||
100 | url, | ||
101 | token, | ||
102 | path, | ||
103 | statusCodeExpected | ||
104 | }) | ||
105 | } | ||
106 | |||
107 | // --------------------------------------------------------------------------- | ||
108 | |||
109 | export { | ||
110 | reportVideoAbuse, | ||
111 | getVideoAbusesList, | ||
112 | updateVideoAbuse, | ||
113 | deleteVideoAbuse | ||
114 | } | ||
diff --git a/shared/models/moderation/abuse/abuse-create.model.ts b/shared/models/moderation/abuse/abuse-create.model.ts index b0358dbb9..0e7e9587f 100644 --- a/shared/models/moderation/abuse/abuse-create.model.ts +++ b/shared/models/moderation/abuse/abuse-create.model.ts | |||
@@ -19,11 +19,3 @@ export interface AbuseCreate { | |||
19 | id: number | 19 | id: number |
20 | } | 20 | } |
21 | } | 21 | } |
22 | |||
23 | // FIXME: deprecated in 2.3. Remove it | ||
24 | export interface VideoAbuseCreate { | ||
25 | reason: string | ||
26 | predefinedReasons?: AbusePredefinedReasonsString[] | ||
27 | startAt?: number | ||
28 | endAt?: number | ||
29 | } | ||
diff --git a/shared/models/moderation/abuse/abuse.model.ts b/shared/models/moderation/abuse/abuse.model.ts index 781870b1a..6048777ff 100644 --- a/shared/models/moderation/abuse/abuse.model.ts +++ b/shared/models/moderation/abuse/abuse.model.ts | |||
@@ -60,18 +60,6 @@ export interface AdminAbuse { | |||
60 | countReportsForReportee?: number | 60 | countReportsForReportee?: number |
61 | 61 | ||
62 | countMessages: number | 62 | countMessages: number |
63 | |||
64 | // FIXME: deprecated in 2.3, remove the following properties | ||
65 | |||
66 | // @deprecated | ||
67 | startAt?: null | ||
68 | // @deprecated | ||
69 | endAt?: null | ||
70 | |||
71 | // @deprecated | ||
72 | count?: number | ||
73 | // @deprecated | ||
74 | nth?: number | ||
75 | } | 63 | } |
76 | 64 | ||
77 | export type UserVideoAbuse = Omit<AdminVideoAbuse, 'countReports' | 'nthReport'> | 65 | export type UserVideoAbuse = Omit<AdminVideoAbuse, 'countReports' | 'nthReport'> |