From 55fa55a9be566cca2ba95322f2ae23b434aed62a Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Wed, 4 Jan 2017 20:59:23 +0100 Subject: [PATCH] Server: add video abuse support --- .../friend-list/friend-list.component.ts | 2 +- .../admin/friends/shared/friend.service.ts | 16 +- config/default.yaml | 4 +- server.js | 3 +- server/controllers/api/pods.js | 17 +- server/controllers/api/remote/videos.js | 68 +++++-- server/controllers/api/users.js | 18 +- server/controllers/api/videos.js | 61 +++++- server/helpers/custom-validators/index.js | 2 + .../helpers/custom-validators/remote/index.js | 11 + .../custom-validators/remote/videos.js | 74 +++++++ server/helpers/custom-validators/videos.js | 66 ++---- server/helpers/utils.js | 16 +- server/initializers/constants.js | 4 + server/lib/friends.js | 39 ++-- server/middlewares/sort.js | 7 + server/middlewares/validators/remote/index.js | 13 ++ .../{remote.js => remote/signature.js} | 17 +- .../middlewares/validators/remote/videos.js | 20 ++ server/middlewares/validators/sort.js | 23 ++- server/middlewares/validators/videos.js | 15 +- .../{requestToPod.js => request-to-pod.js} | 0 server/models/video-abuse.js | 113 +++++++++++ server/models/{videoTag.js => video-tag.js} | 0 server/models/video.js | 8 + server/tests/api/check-params/index.js | 1 + server/tests/api/check-params/remotes.js | 4 + server/tests/api/check-params/video-abuses.js | 180 +++++++++++++++++ server/tests/api/friends-advanced.js | 10 +- server/tests/api/friends-basic.js | 12 +- server/tests/api/video-abuse.js | 191 ++++++++++++++++++ server/tests/utils/video-abuses.js | 73 +++++++ 32 files changed, 917 insertions(+), 171 deletions(-) create mode 100644 server/helpers/custom-validators/remote/index.js create mode 100644 server/helpers/custom-validators/remote/videos.js create mode 100644 server/middlewares/validators/remote/index.js rename server/middlewares/validators/{remote.js => remote/signature.js} (53%) create mode 100644 server/middlewares/validators/remote/videos.js rename server/models/{requestToPod.js => request-to-pod.js} (100%) create mode 100644 server/models/video-abuse.js rename server/models/{videoTag.js => video-tag.js} (100%) create mode 100644 server/tests/api/check-params/video-abuses.js create mode 100644 server/tests/api/video-abuse.js create mode 100644 server/tests/utils/video-abuses.js diff --git a/client/src/app/admin/friends/friend-list/friend-list.component.ts b/client/src/app/admin/friends/friend-list/friend-list.component.ts index 88c4800ee..bec10162c 100644 --- a/client/src/app/admin/friends/friend-list/friend-list.component.ts +++ b/client/src/app/admin/friends/friend-list/friend-list.component.ts @@ -30,7 +30,7 @@ export class FriendListComponent implements OnInit { private getFriends() { this.friendService.getFriends().subscribe( - friends => this.friends = friends, + res => this.friends = res.friends, err => alert(err.text) ); diff --git a/client/src/app/admin/friends/shared/friend.service.ts b/client/src/app/admin/friends/shared/friend.service.ts index 8a1ba6b02..85ac04ba0 100644 --- a/client/src/app/admin/friends/shared/friend.service.ts +++ b/client/src/app/admin/friends/shared/friend.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { Friend } from './friend.model'; -import { AuthHttp, RestExtractor } from '../../../shared'; +import { AuthHttp, RestExtractor, ResultList } from '../../../shared'; @Injectable() export class FriendService { @@ -13,11 +13,10 @@ export class FriendService { private restExtractor: RestExtractor ) {} - getFriends(): Observable { + getFriends() { return this.authHttp.get(FriendService.BASE_FRIEND_URL) - // Not implemented as a data list by the server yet - // .map(this.restExtractor.extractDataList) - .map((res) => res.json()) + .map(this.restExtractor.extractDataList) + .map(this.extractFriends) .catch((res) => this.restExtractor.handleError(res)); } @@ -36,4 +35,11 @@ export class FriendService { .map(res => res.status) .catch((res) => this.restExtractor.handleError(res)); } + + private extractFriends(result: ResultList) { + const friends: Friend[] = result.data; + const totalFriends = result.total; + + return { friends, totalFriends }; + } } diff --git a/config/default.yaml b/config/default.yaml index 2dd5e05f9..0939ae4ba 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -10,8 +10,8 @@ database: hostname: 'localhost' port: 5432 suffix: '_dev' - username: peertube - password: peertube + username: 'peertube' + password: 'peertube' # From the project root directory storage: diff --git a/server.js b/server.js index f4ca53907..7503072af 100644 --- a/server.js +++ b/server.js @@ -57,7 +57,8 @@ app.use(expressValidator({ customValidators.misc, customValidators.pods, customValidators.users, - customValidators.videos + customValidators.videos, + customValidators.remote.videos ) })) diff --git a/server/controllers/api/pods.js b/server/controllers/api/pods.js index d9279f1d9..38702face 100644 --- a/server/controllers/api/pods.js +++ b/server/controllers/api/pods.js @@ -5,6 +5,7 @@ const waterfall = require('async/waterfall') const db = require('../../initializers/database') const logger = require('../../helpers/logger') +const utils = require('../../helpers/utils') const friends = require('../../lib/friends') const middlewares = require('../../middlewares') const admin = middlewares.admin @@ -36,7 +37,7 @@ router.get('/quitfriends', ) // Post because this is a secured request router.post('/remove', - signatureValidator, + signatureValidator.signature, checkSignature, removePods ) @@ -86,7 +87,7 @@ function listPods (req, res, next) { db.Pod.list(function (err, podsList) { if (err) return next(err) - res.json(getFormatedPods(podsList)) + res.json(utils.getFormatedObjects(podsList, podsList.length)) }) } @@ -130,15 +131,3 @@ function quitFriends (req, res, next) { res.type('json').status(204).end() }) } - -// --------------------------------------------------------------------------- - -function getFormatedPods (pods) { - const formatedPods = [] - - pods.forEach(function (pod) { - formatedPods.push(pod.toFormatedJSON()) - }) - - return formatedPods -} diff --git a/server/controllers/api/remote/videos.js b/server/controllers/api/remote/videos.js index 87c49bff9..d02da4463 100644 --- a/server/controllers/api/remote/videos.js +++ b/server/controllers/api/remote/videos.js @@ -7,15 +7,16 @@ const waterfall = require('async/waterfall') const db = require('../../../initializers/database') const middlewares = require('../../../middlewares') const secureMiddleware = middlewares.secure -const validators = middlewares.validators.remote +const videosValidators = middlewares.validators.remote.videos +const signatureValidators = middlewares.validators.remote.signature const logger = require('../../../helpers/logger') const router = express.Router() router.post('/', - validators.signature, + signatureValidators.signature, secureMiddleware.checkSignature, - validators.remoteVideos, + videosValidators.remoteVideos, remoteVideos ) @@ -32,19 +33,23 @@ function remoteVideos (req, res, next) { // We need to process in the same order to keep consistency // TODO: optimization eachSeries(requests, function (request, callbackEach) { - const videoData = request.data + const data = request.data switch (request.type) { case 'add': - addRemoteVideo(videoData, fromPod, callbackEach) + addRemoteVideo(data, fromPod, callbackEach) break case 'update': - updateRemoteVideo(videoData, fromPod, callbackEach) + updateRemoteVideo(data, fromPod, callbackEach) break case 'remove': - removeRemoteVideo(videoData, fromPod, callbackEach) + removeRemoteVideo(data, fromPod, callbackEach) + break + + case 'report-abuse': + reportAbuseRemoteVideo(data, fromPod, callbackEach) break default: @@ -164,13 +169,8 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) { }, function findVideo (t, callback) { - db.Video.loadByHostAndRemoteId(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) { - if (err || !videoInstance) { - logger.error('Cannot load video from host and remote id.', { error: err.message }) - return callback(err) - } - - return callback(null, t, videoInstance) + fetchVideo(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) { + return callback(err, t, videoInstance) }) }, @@ -225,13 +225,45 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) { function removeRemoteVideo (videoToRemoveData, fromPod, callback) { // We need the instance because we have to remove some other stuffs (thumbnail etc) - db.Video.loadByHostAndRemoteId(fromPod.host, videoToRemoveData.remoteId, function (err, video) { + fetchVideo(fromPod.host, videoToRemoveData.remoteId, function (err, video) { + if (err) return callback(err) + + logger.debug('Removing remote video %s.', video.remoteId) + video.destroy().asCallback(callback) + }) +} + +function reportAbuseRemoteVideo (reportData, fromPod, callback) { + db.Video.load(reportData.videoRemoteId, function (err, video) { if (err || !video) { - logger.error('Cannot load video from host and remote id.', { error: err.message }) + if (!err) err = new Error('video not found') + + logger.error('Cannot load video from host and remote id.', { error: err }) return callback(err) } - logger.debug('Removing remote video %s.', video.remoteId) - video.destroy().asCallback(callback) + logger.debug('Reporting remote abuse for video %s.', video.id) + + const videoAbuseData = { + reporterUsername: reportData.reporterUsername, + reason: reportData.reportReason, + reporterPodId: fromPod.id, + videoId: video.id + } + + db.VideoAbuse.create(videoAbuseData).asCallback(callback) + }) +} + +function fetchVideo (podHost, remoteId, callback) { + db.Video.loadByHostAndRemoteId(podHost, remoteId, function (err, video) { + if (err || !video) { + if (!err) err = new Error('video not found') + + logger.error('Cannot load video from host and remote id.', { error: err }) + return callback(err) + } + + return callback(null, video) }) } diff --git a/server/controllers/api/users.js b/server/controllers/api/users.js index 53bf56790..6cd0e84f7 100644 --- a/server/controllers/api/users.js +++ b/server/controllers/api/users.js @@ -6,6 +6,7 @@ const waterfall = require('async/waterfall') const constants = require('../../initializers/constants') const db = require('../../initializers/database') const logger = require('../../helpers/logger') +const utils = require('../../helpers/utils') const middlewares = require('../../middlewares') const admin = middlewares.admin const oAuth = middlewares.oauth @@ -82,7 +83,7 @@ function listUsers (req, res, next) { db.User.listForApi(req.query.start, req.query.count, req.query.sort, function (err, usersList, usersTotal) { if (err) return next(err) - res.json(getFormatedUsers(usersList, usersTotal)) + res.json(utils.getFormatedObjects(usersList, usersTotal)) }) } @@ -121,18 +122,3 @@ function updateUser (req, res, next) { function success (req, res, next) { res.end() } - -// --------------------------------------------------------------------------- - -function getFormatedUsers (users, usersTotal) { - const formatedUsers = [] - - users.forEach(function (user) { - formatedUsers.push(user.toFormatedJSON()) - }) - - return { - total: usersTotal, - data: formatedUsers - } -} diff --git a/server/controllers/api/videos.js b/server/controllers/api/videos.js index 35d6979e5..6829804ec 100644 --- a/server/controllers/api/videos.js +++ b/server/controllers/api/videos.js @@ -11,6 +11,7 @@ const db = require('../../initializers/database') const logger = require('../../helpers/logger') const friends = require('../../lib/friends') const middlewares = require('../../middlewares') +const admin = middlewares.admin const oAuth = middlewares.oauth const pagination = middlewares.pagination const validators = middlewares.validators @@ -43,6 +44,21 @@ const storage = multer.diskStorage({ const reqFiles = multer({ storage: storage }).fields([{ name: 'videofile', maxCount: 1 }]) +router.get('/abuse', + oAuth.authenticate, + admin.ensureIsAdmin, + validatorsPagination.pagination, + validatorsSort.videoAbusesSort, + sort.setVideoAbusesSort, + pagination.setPagination, + listVideoAbuses +) +router.post('/:id/abuse', + oAuth.authenticate, + validatorsVideos.videoAbuseReport, + reportVideoAbuse +) + router.get('/', validatorsPagination.pagination, validatorsSort.videosSort, @@ -283,7 +299,7 @@ function listVideos (req, res, next) { db.Video.listForApi(req.query.start, req.query.count, req.query.sort, function (err, videosList, videosTotal) { if (err) return next(err) - res.json(getFormatedVideos(videosList, videosTotal)) + res.json(utils.getFormatedObjects(videosList, videosTotal)) }) } @@ -306,22 +322,45 @@ function searchVideos (req, res, next) { function (err, videosList, videosTotal) { if (err) return next(err) - res.json(getFormatedVideos(videosList, videosTotal)) + res.json(utils.getFormatedObjects(videosList, videosTotal)) } ) } -// --------------------------------------------------------------------------- - -function getFormatedVideos (videos, videosTotal) { - const formatedVideos = [] +function listVideoAbuses (req, res, next) { + db.VideoAbuse.listForApi(req.query.start, req.query.count, req.query.sort, function (err, abusesList, abusesTotal) { + if (err) return next(err) - videos.forEach(function (video) { - formatedVideos.push(video.toFormatedJSON()) + res.json(utils.getFormatedObjects(abusesList, abusesTotal)) }) +} - return { - total: videosTotal, - data: formatedVideos +function reportVideoAbuse (req, res, next) { + const videoInstance = res.locals.video + const reporterUsername = res.locals.oauth.token.User.username + + const abuse = { + reporterUsername, + reason: req.body.reason, + videoId: videoInstance.id, + reporterPodId: null // This is our pod that reported this abuse } + + db.VideoAbuse.create(abuse).asCallback(function (err) { + if (err) return next(err) + + // We send the information to the destination pod + if (videoInstance.isOwned() === false) { + const reportData = { + reporterUsername, + reportReason: abuse.reason, + videoRemoteId: videoInstance.remoteId + } + + friends.reportAbuseVideoToFriend(reportData, videoInstance) + } + + return res.type('json').status(204).end() + }) } + diff --git a/server/helpers/custom-validators/index.js b/server/helpers/custom-validators/index.js index 96b5b20b9..9383e0304 100644 --- a/server/helpers/custom-validators/index.js +++ b/server/helpers/custom-validators/index.js @@ -2,12 +2,14 @@ const miscValidators = require('./misc') const podsValidators = require('./pods') +const remoteValidators = require('./remote') const usersValidators = require('./users') const videosValidators = require('./videos') const validators = { misc: miscValidators, pods: podsValidators, + remote: remoteValidators, users: usersValidators, videos: videosValidators } diff --git a/server/helpers/custom-validators/remote/index.js b/server/helpers/custom-validators/remote/index.js new file mode 100644 index 000000000..1939a95f4 --- /dev/null +++ b/server/helpers/custom-validators/remote/index.js @@ -0,0 +1,11 @@ +'use strict' + +const remoteVideosValidators = require('./videos') + +const validators = { + videos: remoteVideosValidators +} + +// --------------------------------------------------------------------------- + +module.exports = validators diff --git a/server/helpers/custom-validators/remote/videos.js b/server/helpers/custom-validators/remote/videos.js new file mode 100644 index 000000000..c3ca00e1c --- /dev/null +++ b/server/helpers/custom-validators/remote/videos.js @@ -0,0 +1,74 @@ +'use strict' + +const videosValidators = require('../videos') +const miscValidators = require('../misc') + +const remoteVideosValidators = { + isEachRemoteRequestVideosValid +} + +function isEachRemoteRequestVideosValid (requests) { + return miscValidators.isArray(requests) && + requests.every(function (request) { + const video = request.data + return ( + isRequestTypeAddValid(request.type) && + videosValidators.isVideoAuthorValid(video.author) && + videosValidators.isVideoDateValid(video.createdAt) && + videosValidators.isVideoDateValid(video.updatedAt) && + videosValidators.isVideoDescriptionValid(video.description) && + videosValidators.isVideoDurationValid(video.duration) && + videosValidators.isVideoInfoHashValid(video.infoHash) && + videosValidators.isVideoNameValid(video.name) && + videosValidators.isVideoTagsValid(video.tags) && + videosValidators.isVideoThumbnailDataValid(video.thumbnailData) && + videosValidators.isVideoRemoteIdValid(video.remoteId) && + videosValidators.isVideoExtnameValid(video.extname) + ) || + ( + isRequestTypeUpdateValid(request.type) && + videosValidators.isVideoDateValid(video.createdAt) && + videosValidators.isVideoDateValid(video.updatedAt) && + videosValidators.isVideoDescriptionValid(video.description) && + videosValidators.isVideoDurationValid(video.duration) && + videosValidators.isVideoInfoHashValid(video.infoHash) && + videosValidators.isVideoNameValid(video.name) && + videosValidators.isVideoTagsValid(video.tags) && + videosValidators.isVideoRemoteIdValid(video.remoteId) && + videosValidators.isVideoExtnameValid(video.extname) + ) || + ( + isRequestTypeRemoveValid(request.type) && + videosValidators.isVideoNameValid(video.name) && + videosValidators.isVideoRemoteIdValid(video.remoteId) + ) || + ( + isRequestTypeReportAbuseValid(request.type) && + videosValidators.isVideoRemoteIdValid(request.data.videoRemoteId) && + videosValidators.isVideoAbuseReasonValid(request.data.reportReason) && + videosValidators.isVideoAbuseReporterUsernameValid(request.data.reporterUsername) + ) + }) +} + +// --------------------------------------------------------------------------- + +module.exports = remoteVideosValidators + +// --------------------------------------------------------------------------- + +function isRequestTypeAddValid (value) { + return value === 'add' +} + +function isRequestTypeUpdateValid (value) { + return value === 'update' +} + +function isRequestTypeRemoveValid (value) { + return value === 'remove' +} + +function isRequestTypeReportAbuseValid (value) { + return value === 'report-abuse' +} diff --git a/server/helpers/custom-validators/videos.js b/server/helpers/custom-validators/videos.js index 8448386d9..7f727854d 100644 --- a/server/helpers/custom-validators/videos.js +++ b/server/helpers/custom-validators/videos.js @@ -6,9 +6,9 @@ const constants = require('../../initializers/constants') const usersValidators = require('./users') const miscValidators = require('./misc') const VIDEOS_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEOS +const VIDEO_ABUSES_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEO_ABUSES const videosValidators = { - isEachRemoteVideosValid, isVideoAuthorValid, isVideoDateValid, isVideoDescriptionValid, @@ -17,45 +17,11 @@ const videosValidators = { isVideoNameValid, isVideoTagsValid, isVideoThumbnailValid, - isVideoThumbnailDataValid -} - -function isEachRemoteVideosValid (requests) { - return miscValidators.isArray(requests) && - requests.every(function (request) { - const video = request.data - return ( - isRequestTypeAddValid(request.type) && - isVideoAuthorValid(video.author) && - isVideoDateValid(video.createdAt) && - isVideoDateValid(video.updatedAt) && - isVideoDescriptionValid(video.description) && - isVideoDurationValid(video.duration) && - isVideoInfoHashValid(video.infoHash) && - isVideoNameValid(video.name) && - isVideoTagsValid(video.tags) && - isVideoThumbnailDataValid(video.thumbnailData) && - isVideoRemoteIdValid(video.remoteId) && - isVideoExtnameValid(video.extname) - ) || - ( - isRequestTypeUpdateValid(request.type) && - isVideoDateValid(video.createdAt) && - isVideoDateValid(video.updatedAt) && - isVideoDescriptionValid(video.description) && - isVideoDurationValid(video.duration) && - isVideoInfoHashValid(video.infoHash) && - isVideoNameValid(video.name) && - isVideoTagsValid(video.tags) && - isVideoRemoteIdValid(video.remoteId) && - isVideoExtnameValid(video.extname) - ) || - ( - isRequestTypeRemoveValid(request.type) && - isVideoNameValid(video.name) && - isVideoRemoteIdValid(video.remoteId) - ) - }) + isVideoThumbnailDataValid, + isVideoExtnameValid, + isVideoRemoteIdValid, + isVideoAbuseReasonValid, + isVideoAbuseReporterUsernameValid } function isVideoAuthorValid (value) { @@ -107,20 +73,14 @@ function isVideoRemoteIdValid (value) { return validator.isUUID(value, 4) } -// --------------------------------------------------------------------------- - -module.exports = videosValidators - -// --------------------------------------------------------------------------- - -function isRequestTypeAddValid (value) { - return value === 'add' +function isVideoAbuseReasonValid (value) { + return validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON) } -function isRequestTypeUpdateValid (value) { - return value === 'update' +function isVideoAbuseReporterUsernameValid (value) { + return usersValidators.isUserUsernameValid(value) } -function isRequestTypeRemoveValid (value) { - return value === 'remove' -} +// --------------------------------------------------------------------------- + +module.exports = videosValidators diff --git a/server/helpers/utils.js b/server/helpers/utils.js index 7e0c9823c..9f4b14582 100644 --- a/server/helpers/utils.js +++ b/server/helpers/utils.js @@ -8,7 +8,8 @@ const utils = { badRequest, cleanForExit, generateRandomString, - isTestInstance + isTestInstance, + getFormatedObjects } function badRequest (req, res, next) { @@ -32,6 +33,19 @@ function isTestInstance () { return (process.env.NODE_ENV === 'test') } +function getFormatedObjects (objects, objectsTotal) { + const formatedObjects = [] + + objects.forEach(function (object) { + formatedObjects.push(object.toFormatedJSON()) + }) + + return { + total: objectsTotal, + data: formatedObjects + } +} + // --------------------------------------------------------------------------- module.exports = utils diff --git a/server/initializers/constants.js b/server/initializers/constants.js index 474a37277..6ba8a9da0 100644 --- a/server/initializers/constants.js +++ b/server/initializers/constants.js @@ -19,6 +19,7 @@ const SEARCHABLE_COLUMNS = { // Sortable columns per schema const SORTABLE_COLUMNS = { USERS: [ 'username', '-username', 'createdAt', '-createdAt' ], + VIDEO_ABUSES: [ 'createdAt', '-createdAt' ], VIDEOS: [ 'name', '-name', 'duration', '-duration', 'createdAt', '-createdAt' ] } @@ -65,6 +66,9 @@ const CONSTRAINTS_FIELDS = { USERNAME: { min: 3, max: 20 }, // Length PASSWORD: { min: 6, max: 255 } // Length }, + VIDEO_ABUSES: { + REASON: { min: 2, max: 300 } // Length + }, VIDEOS: { NAME: { min: 3, max: 50 }, // Length DESCRIPTION: { min: 3, max: 250 }, // Length diff --git a/server/lib/friends.js b/server/lib/friends.js index 589b79660..4afb91b8b 100644 --- a/server/lib/friends.js +++ b/server/lib/friends.js @@ -15,6 +15,7 @@ const requests = require('../helpers/requests') const friends = { addVideoToFriends, updateVideoToFriends, + reportAbuseVideoToFriend, hasFriends, getMyCertificate, makeFriends, @@ -23,12 +24,20 @@ const friends = { sendOwnedVideosToPod } -function addVideoToFriends (video) { - createRequest('add', constants.REQUEST_ENDPOINTS.VIDEOS, video) +function addVideoToFriends (videoData) { + createRequest('add', constants.REQUEST_ENDPOINTS.VIDEOS, videoData) } -function updateVideoToFriends (video) { - createRequest('update', constants.REQUEST_ENDPOINTS.VIDEOS, video) +function updateVideoToFriends (videoData) { + createRequest('update', constants.REQUEST_ENDPOINTS.VIDEOS, videoData) +} + +function removeVideoToFriends (videoParams) { + createRequest('remove', constants.REQUEST_ENDPOINTS.VIDEOS, videoParams) +} + +function reportAbuseVideoToFriend (reportData, video) { + createRequest('report-abuse', constants.REQUEST_ENDPOINTS.VIDEOS, reportData, [ video.Author.podId ]) } function hasFriends (callback) { @@ -120,10 +129,6 @@ function quitFriends (callback) { }) } -function removeVideoToFriends (videoParams) { - createRequest('remove', constants.REQUEST_ENDPOINTS.VIDEOS, videoParams) -} - function sendOwnedVideosToPod (podId) { db.Video.listOwnedAndPopulateAuthorAndTags(function (err, videosList) { if (err) { @@ -152,10 +157,10 @@ module.exports = friends // --------------------------------------------------------------------------- function computeForeignPodsList (host, podsScore, callback) { - getForeignPodsList(host, function (err, foreignPodsList) { + getForeignPodsList(host, function (err, res) { if (err) return callback(err) - if (!foreignPodsList) foreignPodsList = [] + const foreignPodsList = res.data // Let's give 1 point to the pod we ask the friends list foreignPodsList.push({ host }) @@ -252,11 +257,11 @@ function makeRequestsToWinningPods (cert, podsList, callback) { }) } -// Wrapper that populate "to" argument with all our friends if it is not specified -function createRequest (type, endpoint, data, to) { - if (to) return _createRequest(type, endpoint, data, to) +// Wrapper that populate "toIds" argument with all our friends if it is not specified +function createRequest (type, endpoint, data, toIds) { + if (toIds) return _createRequest(type, endpoint, data, toIds) - // If the "to" pods is not specified, we send the request to all our friends + // If the "toIds" pods is not specified, we send the request to all our friends db.Pod.listAllIds(function (err, podIds) { if (err) { logger.error('Cannot get pod ids', { error: err }) @@ -267,13 +272,13 @@ function createRequest (type, endpoint, data, to) { }) } -function _createRequest (type, endpoint, data, to) { +function _createRequest (type, endpoint, data, toIds) { const pods = [] // If there are no destination pods abort - if (to.length === 0) return + if (toIds.length === 0) return - to.forEach(function (toPod) { + toIds.forEach(function (toPod) { pods.push(db.Pod.build({ id: toPod })) }) diff --git a/server/middlewares/sort.js b/server/middlewares/sort.js index 477e10571..39e167265 100644 --- a/server/middlewares/sort.js +++ b/server/middlewares/sort.js @@ -2,6 +2,7 @@ const sortMiddleware = { setUsersSort, + setVideoAbusesSort, setVideosSort } @@ -11,6 +12,12 @@ function setUsersSort (req, res, next) { return next() } +function setVideoAbusesSort (req, res, next) { + if (!req.query.sort) req.query.sort = '-createdAt' + + return next() +} + function setVideosSort (req, res, next) { if (!req.query.sort) req.query.sort = '-createdAt' diff --git a/server/middlewares/validators/remote/index.js b/server/middlewares/validators/remote/index.js new file mode 100644 index 000000000..022a2fe50 --- /dev/null +++ b/server/middlewares/validators/remote/index.js @@ -0,0 +1,13 @@ +'use strict' + +const remoteSignatureValidators = require('./signature') +const remoteVideosValidators = require('./videos') + +const validators = { + signature: remoteSignatureValidators, + videos: remoteVideosValidators +} + +// --------------------------------------------------------------------------- + +module.exports = validators diff --git a/server/middlewares/validators/remote.js b/server/middlewares/validators/remote/signature.js similarity index 53% rename from server/middlewares/validators/remote.js rename to server/middlewares/validators/remote/signature.js index 858d193cc..5880a2c2c 100644 --- a/server/middlewares/validators/remote.js +++ b/server/middlewares/validators/remote/signature.js @@ -1,21 +1,12 @@ 'use strict' -const checkErrors = require('./utils').checkErrors -const logger = require('../../helpers/logger') +const checkErrors = require('../utils').checkErrors +const logger = require('../../../helpers/logger') -const validatorsRemote = { - remoteVideos, +const validatorsRemoteSignature = { signature } -function remoteVideos (req, res, next) { - req.checkBody('data').isEachRemoteVideosValid() - - logger.debug('Checking remoteVideos parameters', { parameters: req.body }) - - checkErrors(req, res, next) -} - function signature (req, res, next) { req.checkBody('signature.host', 'Should have a signature host').isURL() req.checkBody('signature.signature', 'Should have a signature').notEmpty() @@ -27,4 +18,4 @@ function signature (req, res, next) { // --------------------------------------------------------------------------- -module.exports = validatorsRemote +module.exports = validatorsRemoteSignature diff --git a/server/middlewares/validators/remote/videos.js b/server/middlewares/validators/remote/videos.js new file mode 100644 index 000000000..cf9925b6c --- /dev/null +++ b/server/middlewares/validators/remote/videos.js @@ -0,0 +1,20 @@ +'use strict' + +const checkErrors = require('../utils').checkErrors +const logger = require('../../../helpers/logger') + +const validatorsRemoteVideos = { + remoteVideos +} + +function remoteVideos (req, res, next) { + req.checkBody('data').isEachRemoteRequestVideosValid() + + logger.debug('Checking remoteVideos parameters', { parameters: req.body }) + + checkErrors(req, res, next) +} + +// --------------------------------------------------------------------------- + +module.exports = validatorsRemoteVideos diff --git a/server/middlewares/validators/sort.js b/server/middlewares/validators/sort.js index 431d3fffd..b7eec0316 100644 --- a/server/middlewares/validators/sort.js +++ b/server/middlewares/validators/sort.js @@ -6,29 +6,38 @@ const logger = require('../../helpers/logger') const validatorsSort = { usersSort, + videoAbusesSort, videosSort } function usersSort (req, res, next) { const sortableColumns = constants.SORTABLE_COLUMNS.USERS - req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns) + checkSort(req, res, next, sortableColumns) +} - logger.debug('Checking sort parameters', { parameters: req.query }) +function videoAbusesSort (req, res, next) { + const sortableColumns = constants.SORTABLE_COLUMNS.VIDEO_ABUSES - checkErrors(req, res, next) + checkSort(req, res, next, sortableColumns) } function videosSort (req, res, next) { const sortableColumns = constants.SORTABLE_COLUMNS.VIDEOS + checkSort(req, res, next, sortableColumns) +} + +// --------------------------------------------------------------------------- + +module.exports = validatorsSort + +// --------------------------------------------------------------------------- + +function checkSort (req, res, next, sortableColumns) { req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns) logger.debug('Checking sort parameters', { parameters: req.query }) checkErrors(req, res, next) } - -// --------------------------------------------------------------------------- - -module.exports = validatorsSort diff --git a/server/middlewares/validators/videos.js b/server/middlewares/validators/videos.js index 295ed05fa..ff18a99c2 100644 --- a/server/middlewares/validators/videos.js +++ b/server/middlewares/validators/videos.js @@ -11,7 +11,9 @@ const validatorsVideos = { videosUpdate, videosGet, videosRemove, - videosSearch + videosSearch, + + videoAbuseReport } function videosAdd (req, res, next) { @@ -97,6 +99,17 @@ function videosSearch (req, res, next) { checkErrors(req, res, next) } +function videoAbuseReport (req, res, next) { + req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4) + req.checkBody('reason', 'Should have a valid reason').isVideoAbuseReasonValid() + + logger.debug('Checking videoAbuseReport parameters', { parameters: req.body }) + + checkErrors(req, res, function () { + checkVideoExists(req.params.id, res, next) + }) +} + // --------------------------------------------------------------------------- module.exports = validatorsVideos diff --git a/server/models/requestToPod.js b/server/models/request-to-pod.js similarity index 100% rename from server/models/requestToPod.js rename to server/models/request-to-pod.js diff --git a/server/models/video-abuse.js b/server/models/video-abuse.js new file mode 100644 index 000000000..766a7568d --- /dev/null +++ b/server/models/video-abuse.js @@ -0,0 +1,113 @@ +'use strict' + +const constants = require('../initializers/constants') +const modelUtils = require('./utils') +const customVideosValidators = require('../helpers/custom-validators').videos + +module.exports = function (sequelize, DataTypes) { + const VideoAbuse = sequelize.define('VideoAbuse', + { + reporterUsername: { + type: DataTypes.STRING, + allowNull: false, + validate: { + reporterUsernameValid: function (value) { + const res = customVideosValidators.isVideoAbuseReporterUsernameValid(value) + if (res === false) throw new Error('Video abuse reporter username is not valid.') + } + } + }, + reason: { + type: DataTypes.STRING, + allowNull: false, + validate: { + reasonValid: function (value) { + const res = customVideosValidators.isVideoAbuseReasonValid(value) + if (res === false) throw new Error('Video abuse reason is not valid.') + } + } + } + }, + { + indexes: [ + { + fields: [ 'videoId' ] + }, + { + fields: [ 'reporterPodId' ] + } + ], + classMethods: { + associate, + + listForApi + }, + instanceMethods: { + toFormatedJSON + } + } + ) + + return VideoAbuse +} + +// --------------------------------------------------------------------------- + +function associate (models) { + this.belongsTo(models.Pod, { + foreignKey: { + name: 'reporterPodId', + allowNull: true + }, + onDelete: 'cascade' + }) + + this.belongsTo(models.Video, { + foreignKey: { + name: 'videoId', + allowNull: false + }, + onDelete: 'cascade' + }) +} + +function listForApi (start, count, sort, callback) { + const query = { + offset: start, + limit: count, + order: [ modelUtils.getSort(sort) ], + include: [ + { + model: this.sequelize.models.Pod, + required: false + } + ] + } + + return this.findAndCountAll(query).asCallback(function (err, result) { + if (err) return callback(err) + + return callback(null, result.rows, result.count) + }) +} + +function toFormatedJSON () { + let reporterPodHost + + if (this.Pod) { + reporterPodHost = this.Pod.host + } else { + // It means it's our video + reporterPodHost = constants.CONFIG.WEBSERVER.HOST + } + + const json = { + id: this.id, + reporterPodHost, + reason: this.reason, + reporterUsername: this.reporterUsername, + videoId: this.videoId + } + + return json +} diff --git a/server/models/videoTag.js b/server/models/video-tag.js similarity index 100% rename from server/models/videoTag.js rename to server/models/video-tag.js diff --git a/server/models/video.js b/server/models/video.js index 3fe8368c7..4c197a835 100644 --- a/server/models/video.js +++ b/server/models/video.js @@ -248,6 +248,14 @@ function associate (models) { through: models.VideoTag, onDelete: 'cascade' }) + + this.hasMany(models.VideoAbuse, { + foreignKey: { + name: 'videoId', + allowNull: false + }, + onDelete: 'cascade' + }) } function generateMagnetUri () { diff --git a/server/tests/api/check-params/index.js b/server/tests/api/check-params/index.js index 3d6f09267..d0824f08a 100644 --- a/server/tests/api/check-params/index.js +++ b/server/tests/api/check-params/index.js @@ -6,3 +6,4 @@ require('./remotes') require('./users') require('./requests') require('./videos') +require('./video-abuses') diff --git a/server/tests/api/check-params/remotes.js b/server/tests/api/check-params/remotes.js index 30ba3b697..c1ab9fb2b 100644 --- a/server/tests/api/check-params/remotes.js +++ b/server/tests/api/check-params/remotes.js @@ -47,6 +47,10 @@ describe('Test remote videos API validators', function () { it('Should check when removing a video') }) + describe('When reporting abuse on a video', function () { + it('Should check when reporting a video abuse') + }) + after(function (done) { process.kill(-server.app.pid) diff --git a/server/tests/api/check-params/video-abuses.js b/server/tests/api/check-params/video-abuses.js new file mode 100644 index 000000000..8cb4ccdc1 --- /dev/null +++ b/server/tests/api/check-params/video-abuses.js @@ -0,0 +1,180 @@ +'use strict' + +const request = require('supertest') +const series = require('async/series') + +const loginUtils = require('../../utils/login') +const requestsUtils = require('../../utils/requests') +const serversUtils = require('../../utils/servers') +const usersUtils = require('../../utils/users') +const videosUtils = require('../../utils/videos') + +describe('Test video abuses API validators', function () { + let server = null + let userAccessToken = null + + // --------------------------------------------------------------- + + before(function (done) { + this.timeout(20000) + + series([ + function (next) { + serversUtils.flushTests(next) + }, + function (next) { + serversUtils.runServer(1, function (server1) { + server = server1 + + next() + }) + }, + function (next) { + loginUtils.loginAndGetAccessToken(server, function (err, token) { + if (err) throw err + server.accessToken = token + + next() + }) + }, + function (next) { + const username = 'user1' + const password = 'my super password' + + usersUtils.createUser(server.url, server.accessToken, username, password, next) + }, + function (next) { + const user = { + username: 'user1', + password: 'my super password' + } + + loginUtils.getUserAccessToken(server, user, function (err, accessToken) { + if (err) throw err + + userAccessToken = accessToken + + next() + }) + }, + // Upload some videos on each pods + function (next) { + const name = 'my super name for pod' + const description = 'my super description for pod' + const tags = [ 'tag' ] + const file = 'video_short2.webm' + videosUtils.uploadVideo(server.url, server.accessToken, name, description, tags, file, next) + }, + function (next) { + videosUtils.getVideosList(server.url, function (err, res) { + if (err) throw err + + const videos = res.body.data + server.video = videos[0] + + next() + }) + } + ], done) + }) + + describe('When listing video abuses', function () { + const path = '/api/v1/videos/abuse' + + it('Should fail with a bad start pagination', function (done) { + request(server.url) + .get(path) + .query({ start: 'hello' }) + .set('Authorization', 'Bearer ' + server.accessToken) + .set('Accept', 'application/json') + .expect(400, done) + }) + + it('Should fail with a bad count pagination', function (done) { + request(server.url) + .get(path) + .query({ count: 'hello' }) + .set('Accept', 'application/json') + .set('Authorization', 'Bearer ' + server.accessToken) + .expect(400, done) + }) + + it('Should fail with an incorrect sort', function (done) { + request(server.url) + .get(path) + .query({ sort: 'hello' }) + .set('Accept', 'application/json') + .set('Authorization', 'Bearer ' + server.accessToken) + .expect(400, done) + }) + + it('Should fail with a non authenticated user', function (done) { + request(server.url) + .get(path) + .query({ sort: 'hello' }) + .set('Accept', 'application/json') + .expect(401, done) + }) + + it('Should fail with a non admin user', function (done) { + request(server.url) + .get(path) + .query({ sort: 'hello' }) + .set('Accept', 'application/json') + .set('Authorization', 'Bearer ' + userAccessToken) + .expect(403, done) + }) + }) + + describe('When reporting a video abuse', function () { + const basePath = '/api/v1/videos/' + + it('Should fail with nothing', function (done) { + const path = basePath + server.video + '/abuse' + const data = {} + requestsUtils.makePostBodyRequest(server.url, path, server.accessToken, data, done) + }) + + it('Should fail with a wrong video', function (done) { + const wrongPath = '/api/v1/videos/blabla/abuse' + const data = {} + requestsUtils.makePostBodyRequest(server.url, wrongPath, server.accessToken, data, done) + }) + + it('Should fail with a non authenticated user', function (done) { + const data = {} + const path = basePath + server.video + '/abuse' + requestsUtils.makePostBodyRequest(server.url, path, 'hello', data, done, 401) + }) + + it('Should fail with a reason too short', function (done) { + const data = { + reason: 'h' + } + const path = basePath + server.video + '/abuse' + requestsUtils.makePostBodyRequest(server.url, path, server.accessToken, data, done) + }) + + it('Should fail with a reason too big', function (done) { + const data = { + reason: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef' + + '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef' + + '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef' + + '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef' + } + const path = basePath + server.video + '/abuse' + requestsUtils.makePostBodyRequest(server.url, path, server.accessToken, data, done) + }) + }) + + after(function (done) { + process.kill(-server.app.pid) + + // Keep the logs if the test failed + if (this.ok) { + serversUtils.flushTests(done) + } else { + done() + } + }) +}) diff --git a/server/tests/api/friends-advanced.js b/server/tests/api/friends-advanced.js index 0a2d58d82..708138bc9 100644 --- a/server/tests/api/friends-advanced.js +++ b/server/tests/api/friends-advanced.js @@ -86,7 +86,7 @@ describe('Test advanced friends', function () { getFriendsList(5, function (err, res) { if (err) throw err - expect(res.body.length).to.equal(0) + expect(res.body.data.length).to.equal(0) done() }) @@ -111,7 +111,7 @@ describe('Test advanced friends', function () { getFriendsList(i, function (err, res) { if (err) throw err - expect(res.body.length).to.equal(0) + expect(res.body.data.length).to.equal(0) callback() }) @@ -140,7 +140,7 @@ describe('Test advanced friends', function () { getFriendsList(i, function (err, res) { if (err) throw err - expect(res.body.length).to.equal(3) + expect(res.body.data.length).to.equal(3) callback() }) @@ -182,7 +182,7 @@ describe('Test advanced friends', function () { if (err) throw err // Pod 4 didn't know pod 1 and 2 removed it - expect(res.body.length).to.equal(3) + expect(res.body.data.length).to.equal(3) next() }) }, @@ -200,7 +200,7 @@ describe('Test advanced friends', function () { if (err) throw err // Pod 4 should not be our friend - const result = res.body + const result = res.body.data expect(result.length).to.equal(3) for (const pod of result) { expect(pod.host).not.equal(servers[3].host) diff --git a/server/tests/api/friends-basic.js b/server/tests/api/friends-basic.js index 3a904dbd7..6f37ff291 100644 --- a/server/tests/api/friends-basic.js +++ b/server/tests/api/friends-basic.js @@ -28,7 +28,7 @@ describe('Test basic friends', function () { podsUtils.getFriendsList(serverToTest.url, function (err, res) { if (err) throw err - const result = res.body + const result = res.body.data expect(result).to.be.an('array') expect(result.length).to.equal(2) @@ -65,7 +65,7 @@ describe('Test basic friends', function () { podsUtils.getFriendsList(server.url, function (err, res) { if (err) throw err - const result = res.body + const result = res.body.data expect(result).to.be.an('array') expect(result.length).to.equal(0) callback() @@ -90,7 +90,7 @@ describe('Test basic friends', function () { podsUtils.getFriendsList(servers[1].url, function (err, res) { if (err) throw err - const result = res.body + const result = res.body.data expect(result).to.be.an('array') expect(result.length).to.equal(1) @@ -107,7 +107,7 @@ describe('Test basic friends', function () { podsUtils.getFriendsList(servers[2].url, function (err, res) { if (err) throw err - const result = res.body + const result = res.body.data expect(result).to.be.an('array') expect(result.length).to.equal(1) @@ -154,7 +154,7 @@ describe('Test basic friends', function () { podsUtils.getFriendsList(servers[1].url, function (err, res) { if (err) throw err - const result = res.body + const result = res.body.data expect(result).to.be.an('array') expect(result.length).to.equal(0) @@ -167,7 +167,7 @@ describe('Test basic friends', function () { podsUtils.getFriendsList(url, function (err, res) { if (err) throw err - const result = res.body + const result = res.body.data expect(result).to.be.an('array') expect(result.length).to.equal(1) expect(result[0].host).not.to.be.equal(servers[1].host) diff --git a/server/tests/api/video-abuse.js b/server/tests/api/video-abuse.js new file mode 100644 index 000000000..58db17c42 --- /dev/null +++ b/server/tests/api/video-abuse.js @@ -0,0 +1,191 @@ +'use strict' + +const chai = require('chai') +const each = require('async/each') +const expect = chai.expect +const series = require('async/series') + +const loginUtils = require('../utils/login') +const podsUtils = require('../utils/pods') +const serversUtils = require('../utils/servers') +const videosUtils = require('../utils/videos') +const videoAbusesUtils = require('../utils/video-abuses') + +describe('Test video abuses', function () { + let servers = [] + + before(function (done) { + this.timeout(30000) + + series([ + // Run servers + function (next) { + serversUtils.flushAndRunMultipleServers(2, function (serversRun) { + servers = serversRun + next() + }) + }, + // Get the access tokens + function (next) { + each(servers, function (server, callbackEach) { + loginUtils.loginAndGetAccessToken(server, function (err, accessToken) { + if (err) return callbackEach(err) + + server.accessToken = accessToken + callbackEach() + }) + }, next) + }, + // Pod 1 make friends too + function (next) { + const server = servers[0] + podsUtils.makeFriends(server.url, server.accessToken, next) + }, + // Upload some videos on each pods + function (next) { + const name = 'my super name for pod 1' + const description = 'my super description for pod 1' + const tags = [ 'tag' ] + const file = 'video_short2.webm' + videosUtils.uploadVideo(servers[0].url, servers[0].accessToken, name, description, tags, file, next) + }, + function (next) { + const name = 'my super name for pod 2' + const description = 'my super description for pod 2' + const tags = [ 'tag' ] + const file = 'video_short2.webm' + videosUtils.uploadVideo(servers[1].url, servers[1].accessToken, name, description, tags, file, next) + }, + // Wait videos propagation + function (next) { + setTimeout(next, 11000) + }, + function (next) { + videosUtils.getVideosList(servers[0].url, function (err, res) { + if (err) throw err + + const videos = res.body.data + + expect(videos.length).to.equal(2) + + servers[0].video = videos.find(function (video) { return video.name === 'my super name for pod 1' }) + servers[1].video = videos.find(function (video) { return video.name === 'my super name for pod 2' }) + + next() + }) + } + ], done) + }) + + it('Should not have video abuses', function (done) { + videoAbusesUtils.getVideoAbusesList(servers[0].url, servers[0].accessToken, function (err, res) { + if (err) throw err + + expect(res.body.total).to.equal(0) + expect(res.body.data).to.be.an('array') + expect(res.body.data.length).to.equal(0) + + done() + }) + }) + + it('Should report abuse on a local video', function (done) { + this.timeout(15000) + + const reason = 'my super bad reason' + videoAbusesUtils.reportVideoAbuse(servers[0].url, servers[0].accessToken, servers[0].video.id, reason, function (err) { + if (err) throw err + + // We wait requests propagation, even if the pod 1 is not supposed to make a request to pod 2 + setTimeout(done, 11000) + }) + }) + + it('Should have 1 video abuses on pod 1 and 0 on pod 2', function (done) { + videoAbusesUtils.getVideoAbusesList(servers[0].url, servers[0].accessToken, function (err, res) { + if (err) throw err + + expect(res.body.total).to.equal(1) + expect(res.body.data).to.be.an('array') + expect(res.body.data.length).to.equal(1) + + const abuse = res.body.data[0] + expect(abuse.reason).to.equal('my super bad reason') + expect(abuse.reporterUsername).to.equal('root') + expect(abuse.reporterPodHost).to.equal('localhost:9001') + expect(abuse.videoId).to.equal(servers[0].video.id) + + videoAbusesUtils.getVideoAbusesList(servers[1].url, servers[1].accessToken, function (err, res) { + if (err) throw err + + expect(res.body.total).to.equal(0) + expect(res.body.data).to.be.an('array') + expect(res.body.data.length).to.equal(0) + + done() + }) + }) + }) + + it('Should report abuse on a remote video', function (done) { + this.timeout(15000) + + const reason = 'my super bad reason 2' + videoAbusesUtils.reportVideoAbuse(servers[0].url, servers[0].accessToken, servers[1].video.id, reason, function (err) { + if (err) throw err + + // We wait requests propagation + setTimeout(done, 11000) + }) + }) + + it('Should have 2 video abuse on pod 1 and 1 on pod 2', function (done) { + videoAbusesUtils.getVideoAbusesList(servers[0].url, servers[0].accessToken, function (err, res) { + if (err) throw err + + expect(res.body.total).to.equal(2) + expect(res.body.data).to.be.an('array') + expect(res.body.data.length).to.equal(2) + + let abuse = res.body.data[0] + expect(abuse.reason).to.equal('my super bad reason') + expect(abuse.reporterUsername).to.equal('root') + expect(abuse.reporterPodHost).to.equal('localhost:9001') + expect(abuse.videoId).to.equal(servers[0].video.id) + + abuse = res.body.data[1] + expect(abuse.reason).to.equal('my super bad reason 2') + expect(abuse.reporterUsername).to.equal('root') + expect(abuse.reporterPodHost).to.equal('localhost:9001') + expect(abuse.videoId).to.equal(servers[1].video.id) + + videoAbusesUtils.getVideoAbusesList(servers[1].url, servers[1].accessToken, function (err, res) { + if (err) throw err + + expect(res.body.total).to.equal(1) + expect(res.body.data).to.be.an('array') + expect(res.body.data.length).to.equal(1) + + let abuse = res.body.data[0] + expect(abuse.reason).to.equal('my super bad reason 2') + expect(abuse.reporterUsername).to.equal('root') + expect(abuse.reporterPodHost).to.equal('localhost:9001') + + done() + }) + }) + }) + + after(function (done) { + servers.forEach(function (server) { + process.kill(-server.app.pid) + }) + + // Keep the logs if the test failed + if (this.ok) { + serversUtils.flushTests(done) + } else { + done() + } + }) +}) diff --git a/server/tests/utils/video-abuses.js b/server/tests/utils/video-abuses.js new file mode 100644 index 000000000..596c824b3 --- /dev/null +++ b/server/tests/utils/video-abuses.js @@ -0,0 +1,73 @@ +'use strict' + +const request = require('supertest') + +const videosUtils = { + getVideoAbusesList, + getVideoAbusesListPagination, + getVideoAbusesListSort, + reportVideoAbuse +} + +// ---------------------- Export functions -------------------- + +function reportVideoAbuse (url, token, videoId, reason, specialStatus, end) { + if (!end) { + end = specialStatus + specialStatus = 204 + } + + const path = '/api/v1/videos/' + videoId + '/abuse' + + request(url) + .post(path) + .set('Accept', 'application/json') + .set('Authorization', 'Bearer ' + token) + .send({ reason }) + .expect(specialStatus) + .end(end) +} + +function getVideoAbusesList (url, token, end) { + const path = '/api/v1/videos/abuse' + + request(url) + .get(path) + .query({ sort: 'createdAt' }) + .set('Accept', 'application/json') + .set('Authorization', 'Bearer ' + token) + .expect(200) + .expect('Content-Type', /json/) + .end(end) +} + +function getVideoAbusesListPagination (url, token, start, count, end) { + const path = '/api/v1/videos/abuse' + + request(url) + .get(path) + .query({ start: start }) + .query({ count: count }) + .set('Accept', 'application/json') + .set('Authorization', 'Bearer ' + token) + .expect(200) + .expect('Content-Type', /json/) + .end(end) +} + +function getVideoAbusesListSort (url, token, sort, end) { + const path = '/api/v1/videos/abuse' + + request(url) + .get(path) + .query({ sort: sort }) + .set('Accept', 'application/json') + .set('Authorization', 'Bearer ' + token) + .expect(200) + .expect('Content-Type', /json/) + .end(end) +} + +// --------------------------------------------------------------------------- + +module.exports = videosUtils -- 2.25.1