diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-01-04 20:59:23 +0100 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-01-04 21:05:13 +0100 |
commit | 55fa55a9be566cca2ba95322f2ae23b434aed62a (patch) | |
tree | f51ef35c120ce8a928917a659418079538cdb8dc | |
parent | a6fd2b30bf717eec14972a2175354781f5f43e77 (diff) | |
download | PeerTube-55fa55a9be566cca2ba95322f2ae23b434aed62a.tar.gz PeerTube-55fa55a9be566cca2ba95322f2ae23b434aed62a.tar.zst PeerTube-55fa55a9be566cca2ba95322f2ae23b434aed62a.zip |
Server: add video abuse support
32 files changed, 917 insertions, 171 deletions
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 { | |||
30 | 30 | ||
31 | private getFriends() { | 31 | private getFriends() { |
32 | this.friendService.getFriends().subscribe( | 32 | this.friendService.getFriends().subscribe( |
33 | friends => this.friends = friends, | 33 | res => this.friends = res.friends, |
34 | 34 | ||
35 | err => alert(err.text) | 35 | err => alert(err.text) |
36 | ); | 36 | ); |
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'; | |||
2 | import { Observable } from 'rxjs/Observable'; | 2 | import { Observable } from 'rxjs/Observable'; |
3 | 3 | ||
4 | import { Friend } from './friend.model'; | 4 | import { Friend } from './friend.model'; |
5 | import { AuthHttp, RestExtractor } from '../../../shared'; | 5 | import { AuthHttp, RestExtractor, ResultList } from '../../../shared'; |
6 | 6 | ||
7 | @Injectable() | 7 | @Injectable() |
8 | export class FriendService { | 8 | export class FriendService { |
@@ -13,11 +13,10 @@ export class FriendService { | |||
13 | private restExtractor: RestExtractor | 13 | private restExtractor: RestExtractor |
14 | ) {} | 14 | ) {} |
15 | 15 | ||
16 | getFriends(): Observable<Friend[]> { | 16 | getFriends() { |
17 | return this.authHttp.get(FriendService.BASE_FRIEND_URL) | 17 | return this.authHttp.get(FriendService.BASE_FRIEND_URL) |
18 | // Not implemented as a data list by the server yet | 18 | .map(this.restExtractor.extractDataList) |
19 | // .map(this.restExtractor.extractDataList) | 19 | .map(this.extractFriends) |
20 | .map((res) => res.json()) | ||
21 | .catch((res) => this.restExtractor.handleError(res)); | 20 | .catch((res) => this.restExtractor.handleError(res)); |
22 | } | 21 | } |
23 | 22 | ||
@@ -36,4 +35,11 @@ export class FriendService { | |||
36 | .map(res => res.status) | 35 | .map(res => res.status) |
37 | .catch((res) => this.restExtractor.handleError(res)); | 36 | .catch((res) => this.restExtractor.handleError(res)); |
38 | } | 37 | } |
38 | |||
39 | private extractFriends(result: ResultList) { | ||
40 | const friends: Friend[] = result.data; | ||
41 | const totalFriends = result.total; | ||
42 | |||
43 | return { friends, totalFriends }; | ||
44 | } | ||
39 | } | 45 | } |
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: | |||
10 | hostname: 'localhost' | 10 | hostname: 'localhost' |
11 | port: 5432 | 11 | port: 5432 |
12 | suffix: '_dev' | 12 | suffix: '_dev' |
13 | username: peertube | 13 | username: 'peertube' |
14 | password: peertube | 14 | password: 'peertube' |
15 | 15 | ||
16 | # From the project root directory | 16 | # From the project root directory |
17 | storage: | 17 | storage: |
@@ -57,7 +57,8 @@ app.use(expressValidator({ | |||
57 | customValidators.misc, | 57 | customValidators.misc, |
58 | customValidators.pods, | 58 | customValidators.pods, |
59 | customValidators.users, | 59 | customValidators.users, |
60 | customValidators.videos | 60 | customValidators.videos, |
61 | customValidators.remote.videos | ||
61 | ) | 62 | ) |
62 | })) | 63 | })) |
63 | 64 | ||
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') | |||
5 | 5 | ||
6 | const db = require('../../initializers/database') | 6 | const db = require('../../initializers/database') |
7 | const logger = require('../../helpers/logger') | 7 | const logger = require('../../helpers/logger') |
8 | const utils = require('../../helpers/utils') | ||
8 | const friends = require('../../lib/friends') | 9 | const friends = require('../../lib/friends') |
9 | const middlewares = require('../../middlewares') | 10 | const middlewares = require('../../middlewares') |
10 | const admin = middlewares.admin | 11 | const admin = middlewares.admin |
@@ -36,7 +37,7 @@ router.get('/quitfriends', | |||
36 | ) | 37 | ) |
37 | // Post because this is a secured request | 38 | // Post because this is a secured request |
38 | router.post('/remove', | 39 | router.post('/remove', |
39 | signatureValidator, | 40 | signatureValidator.signature, |
40 | checkSignature, | 41 | checkSignature, |
41 | removePods | 42 | removePods |
42 | ) | 43 | ) |
@@ -86,7 +87,7 @@ function listPods (req, res, next) { | |||
86 | db.Pod.list(function (err, podsList) { | 87 | db.Pod.list(function (err, podsList) { |
87 | if (err) return next(err) | 88 | if (err) return next(err) |
88 | 89 | ||
89 | res.json(getFormatedPods(podsList)) | 90 | res.json(utils.getFormatedObjects(podsList, podsList.length)) |
90 | }) | 91 | }) |
91 | } | 92 | } |
92 | 93 | ||
@@ -130,15 +131,3 @@ function quitFriends (req, res, next) { | |||
130 | res.type('json').status(204).end() | 131 | res.type('json').status(204).end() |
131 | }) | 132 | }) |
132 | } | 133 | } |
133 | |||
134 | // --------------------------------------------------------------------------- | ||
135 | |||
136 | function getFormatedPods (pods) { | ||
137 | const formatedPods = [] | ||
138 | |||
139 | pods.forEach(function (pod) { | ||
140 | formatedPods.push(pod.toFormatedJSON()) | ||
141 | }) | ||
142 | |||
143 | return formatedPods | ||
144 | } | ||
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') | |||
7 | const db = require('../../../initializers/database') | 7 | const db = require('../../../initializers/database') |
8 | const middlewares = require('../../../middlewares') | 8 | const middlewares = require('../../../middlewares') |
9 | const secureMiddleware = middlewares.secure | 9 | const secureMiddleware = middlewares.secure |
10 | const validators = middlewares.validators.remote | 10 | const videosValidators = middlewares.validators.remote.videos |
11 | const signatureValidators = middlewares.validators.remote.signature | ||
11 | const logger = require('../../../helpers/logger') | 12 | const logger = require('../../../helpers/logger') |
12 | 13 | ||
13 | const router = express.Router() | 14 | const router = express.Router() |
14 | 15 | ||
15 | router.post('/', | 16 | router.post('/', |
16 | validators.signature, | 17 | signatureValidators.signature, |
17 | secureMiddleware.checkSignature, | 18 | secureMiddleware.checkSignature, |
18 | validators.remoteVideos, | 19 | videosValidators.remoteVideos, |
19 | remoteVideos | 20 | remoteVideos |
20 | ) | 21 | ) |
21 | 22 | ||
@@ -32,19 +33,23 @@ function remoteVideos (req, res, next) { | |||
32 | // We need to process in the same order to keep consistency | 33 | // We need to process in the same order to keep consistency |
33 | // TODO: optimization | 34 | // TODO: optimization |
34 | eachSeries(requests, function (request, callbackEach) { | 35 | eachSeries(requests, function (request, callbackEach) { |
35 | const videoData = request.data | 36 | const data = request.data |
36 | 37 | ||
37 | switch (request.type) { | 38 | switch (request.type) { |
38 | case 'add': | 39 | case 'add': |
39 | addRemoteVideo(videoData, fromPod, callbackEach) | 40 | addRemoteVideo(data, fromPod, callbackEach) |
40 | break | 41 | break |
41 | 42 | ||
42 | case 'update': | 43 | case 'update': |
43 | updateRemoteVideo(videoData, fromPod, callbackEach) | 44 | updateRemoteVideo(data, fromPod, callbackEach) |
44 | break | 45 | break |
45 | 46 | ||
46 | case 'remove': | 47 | case 'remove': |
47 | removeRemoteVideo(videoData, fromPod, callbackEach) | 48 | removeRemoteVideo(data, fromPod, callbackEach) |
49 | break | ||
50 | |||
51 | case 'report-abuse': | ||
52 | reportAbuseRemoteVideo(data, fromPod, callbackEach) | ||
48 | break | 53 | break |
49 | 54 | ||
50 | default: | 55 | default: |
@@ -164,13 +169,8 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) { | |||
164 | }, | 169 | }, |
165 | 170 | ||
166 | function findVideo (t, callback) { | 171 | function findVideo (t, callback) { |
167 | db.Video.loadByHostAndRemoteId(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) { | 172 | fetchVideo(fromPod.host, videoAttributesToUpdate.remoteId, function (err, videoInstance) { |
168 | if (err || !videoInstance) { | 173 | return callback(err, t, videoInstance) |
169 | logger.error('Cannot load video from host and remote id.', { error: err.message }) | ||
170 | return callback(err) | ||
171 | } | ||
172 | |||
173 | return callback(null, t, videoInstance) | ||
174 | }) | 174 | }) |
175 | }, | 175 | }, |
176 | 176 | ||
@@ -225,13 +225,45 @@ function updateRemoteVideo (videoAttributesToUpdate, fromPod, finalCallback) { | |||
225 | 225 | ||
226 | function removeRemoteVideo (videoToRemoveData, fromPod, callback) { | 226 | function removeRemoteVideo (videoToRemoveData, fromPod, callback) { |
227 | // We need the instance because we have to remove some other stuffs (thumbnail etc) | 227 | // We need the instance because we have to remove some other stuffs (thumbnail etc) |
228 | db.Video.loadByHostAndRemoteId(fromPod.host, videoToRemoveData.remoteId, function (err, video) { | 228 | fetchVideo(fromPod.host, videoToRemoveData.remoteId, function (err, video) { |
229 | if (err) return callback(err) | ||
230 | |||
231 | logger.debug('Removing remote video %s.', video.remoteId) | ||
232 | video.destroy().asCallback(callback) | ||
233 | }) | ||
234 | } | ||
235 | |||
236 | function reportAbuseRemoteVideo (reportData, fromPod, callback) { | ||
237 | db.Video.load(reportData.videoRemoteId, function (err, video) { | ||
229 | if (err || !video) { | 238 | if (err || !video) { |
230 | logger.error('Cannot load video from host and remote id.', { error: err.message }) | 239 | if (!err) err = new Error('video not found') |
240 | |||
241 | logger.error('Cannot load video from host and remote id.', { error: err }) | ||
231 | return callback(err) | 242 | return callback(err) |
232 | } | 243 | } |
233 | 244 | ||
234 | logger.debug('Removing remote video %s.', video.remoteId) | 245 | logger.debug('Reporting remote abuse for video %s.', video.id) |
235 | video.destroy().asCallback(callback) | 246 | |
247 | const videoAbuseData = { | ||
248 | reporterUsername: reportData.reporterUsername, | ||
249 | reason: reportData.reportReason, | ||
250 | reporterPodId: fromPod.id, | ||
251 | videoId: video.id | ||
252 | } | ||
253 | |||
254 | db.VideoAbuse.create(videoAbuseData).asCallback(callback) | ||
255 | }) | ||
256 | } | ||
257 | |||
258 | function fetchVideo (podHost, remoteId, callback) { | ||
259 | db.Video.loadByHostAndRemoteId(podHost, remoteId, function (err, video) { | ||
260 | if (err || !video) { | ||
261 | if (!err) err = new Error('video not found') | ||
262 | |||
263 | logger.error('Cannot load video from host and remote id.', { error: err }) | ||
264 | return callback(err) | ||
265 | } | ||
266 | |||
267 | return callback(null, video) | ||
236 | }) | 268 | }) |
237 | } | 269 | } |
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') | |||
6 | const constants = require('../../initializers/constants') | 6 | const constants = require('../../initializers/constants') |
7 | const db = require('../../initializers/database') | 7 | const db = require('../../initializers/database') |
8 | const logger = require('../../helpers/logger') | 8 | const logger = require('../../helpers/logger') |
9 | const utils = require('../../helpers/utils') | ||
9 | const middlewares = require('../../middlewares') | 10 | const middlewares = require('../../middlewares') |
10 | const admin = middlewares.admin | 11 | const admin = middlewares.admin |
11 | const oAuth = middlewares.oauth | 12 | const oAuth = middlewares.oauth |
@@ -82,7 +83,7 @@ function listUsers (req, res, next) { | |||
82 | db.User.listForApi(req.query.start, req.query.count, req.query.sort, function (err, usersList, usersTotal) { | 83 | db.User.listForApi(req.query.start, req.query.count, req.query.sort, function (err, usersList, usersTotal) { |
83 | if (err) return next(err) | 84 | if (err) return next(err) |
84 | 85 | ||
85 | res.json(getFormatedUsers(usersList, usersTotal)) | 86 | res.json(utils.getFormatedObjects(usersList, usersTotal)) |
86 | }) | 87 | }) |
87 | } | 88 | } |
88 | 89 | ||
@@ -121,18 +122,3 @@ function updateUser (req, res, next) { | |||
121 | function success (req, res, next) { | 122 | function success (req, res, next) { |
122 | res.end() | 123 | res.end() |
123 | } | 124 | } |
124 | |||
125 | // --------------------------------------------------------------------------- | ||
126 | |||
127 | function getFormatedUsers (users, usersTotal) { | ||
128 | const formatedUsers = [] | ||
129 | |||
130 | users.forEach(function (user) { | ||
131 | formatedUsers.push(user.toFormatedJSON()) | ||
132 | }) | ||
133 | |||
134 | return { | ||
135 | total: usersTotal, | ||
136 | data: formatedUsers | ||
137 | } | ||
138 | } | ||
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') | |||
11 | const logger = require('../../helpers/logger') | 11 | const logger = require('../../helpers/logger') |
12 | const friends = require('../../lib/friends') | 12 | const friends = require('../../lib/friends') |
13 | const middlewares = require('../../middlewares') | 13 | const middlewares = require('../../middlewares') |
14 | const admin = middlewares.admin | ||
14 | const oAuth = middlewares.oauth | 15 | const oAuth = middlewares.oauth |
15 | const pagination = middlewares.pagination | 16 | const pagination = middlewares.pagination |
16 | const validators = middlewares.validators | 17 | const validators = middlewares.validators |
@@ -43,6 +44,21 @@ const storage = multer.diskStorage({ | |||
43 | 44 | ||
44 | const reqFiles = multer({ storage: storage }).fields([{ name: 'videofile', maxCount: 1 }]) | 45 | const reqFiles = multer({ storage: storage }).fields([{ name: 'videofile', maxCount: 1 }]) |
45 | 46 | ||
47 | router.get('/abuse', | ||
48 | oAuth.authenticate, | ||
49 | admin.ensureIsAdmin, | ||
50 | validatorsPagination.pagination, | ||
51 | validatorsSort.videoAbusesSort, | ||
52 | sort.setVideoAbusesSort, | ||
53 | pagination.setPagination, | ||
54 | listVideoAbuses | ||
55 | ) | ||
56 | router.post('/:id/abuse', | ||
57 | oAuth.authenticate, | ||
58 | validatorsVideos.videoAbuseReport, | ||
59 | reportVideoAbuse | ||
60 | ) | ||
61 | |||
46 | router.get('/', | 62 | router.get('/', |
47 | validatorsPagination.pagination, | 63 | validatorsPagination.pagination, |
48 | validatorsSort.videosSort, | 64 | validatorsSort.videosSort, |
@@ -283,7 +299,7 @@ function listVideos (req, res, next) { | |||
283 | db.Video.listForApi(req.query.start, req.query.count, req.query.sort, function (err, videosList, videosTotal) { | 299 | db.Video.listForApi(req.query.start, req.query.count, req.query.sort, function (err, videosList, videosTotal) { |
284 | if (err) return next(err) | 300 | if (err) return next(err) |
285 | 301 | ||
286 | res.json(getFormatedVideos(videosList, videosTotal)) | 302 | res.json(utils.getFormatedObjects(videosList, videosTotal)) |
287 | }) | 303 | }) |
288 | } | 304 | } |
289 | 305 | ||
@@ -306,22 +322,45 @@ function searchVideos (req, res, next) { | |||
306 | function (err, videosList, videosTotal) { | 322 | function (err, videosList, videosTotal) { |
307 | if (err) return next(err) | 323 | if (err) return next(err) |
308 | 324 | ||
309 | res.json(getFormatedVideos(videosList, videosTotal)) | 325 | res.json(utils.getFormatedObjects(videosList, videosTotal)) |
310 | } | 326 | } |
311 | ) | 327 | ) |
312 | } | 328 | } |
313 | 329 | ||
314 | // --------------------------------------------------------------------------- | 330 | function listVideoAbuses (req, res, next) { |
315 | 331 | db.VideoAbuse.listForApi(req.query.start, req.query.count, req.query.sort, function (err, abusesList, abusesTotal) { | |
316 | function getFormatedVideos (videos, videosTotal) { | 332 | if (err) return next(err) |
317 | const formatedVideos = [] | ||
318 | 333 | ||
319 | videos.forEach(function (video) { | 334 | res.json(utils.getFormatedObjects(abusesList, abusesTotal)) |
320 | formatedVideos.push(video.toFormatedJSON()) | ||
321 | }) | 335 | }) |
336 | } | ||
322 | 337 | ||
323 | return { | 338 | function reportVideoAbuse (req, res, next) { |
324 | total: videosTotal, | 339 | const videoInstance = res.locals.video |
325 | data: formatedVideos | 340 | const reporterUsername = res.locals.oauth.token.User.username |
341 | |||
342 | const abuse = { | ||
343 | reporterUsername, | ||
344 | reason: req.body.reason, | ||
345 | videoId: videoInstance.id, | ||
346 | reporterPodId: null // This is our pod that reported this abuse | ||
326 | } | 347 | } |
348 | |||
349 | db.VideoAbuse.create(abuse).asCallback(function (err) { | ||
350 | if (err) return next(err) | ||
351 | |||
352 | // We send the information to the destination pod | ||
353 | if (videoInstance.isOwned() === false) { | ||
354 | const reportData = { | ||
355 | reporterUsername, | ||
356 | reportReason: abuse.reason, | ||
357 | videoRemoteId: videoInstance.remoteId | ||
358 | } | ||
359 | |||
360 | friends.reportAbuseVideoToFriend(reportData, videoInstance) | ||
361 | } | ||
362 | |||
363 | return res.type('json').status(204).end() | ||
364 | }) | ||
327 | } | 365 | } |
366 | |||
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 @@ | |||
2 | 2 | ||
3 | const miscValidators = require('./misc') | 3 | const miscValidators = require('./misc') |
4 | const podsValidators = require('./pods') | 4 | const podsValidators = require('./pods') |
5 | const remoteValidators = require('./remote') | ||
5 | const usersValidators = require('./users') | 6 | const usersValidators = require('./users') |
6 | const videosValidators = require('./videos') | 7 | const videosValidators = require('./videos') |
7 | 8 | ||
8 | const validators = { | 9 | const validators = { |
9 | misc: miscValidators, | 10 | misc: miscValidators, |
10 | pods: podsValidators, | 11 | pods: podsValidators, |
12 | remote: remoteValidators, | ||
11 | users: usersValidators, | 13 | users: usersValidators, |
12 | videos: videosValidators | 14 | videos: videosValidators |
13 | } | 15 | } |
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 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const remoteVideosValidators = require('./videos') | ||
4 | |||
5 | const validators = { | ||
6 | videos: remoteVideosValidators | ||
7 | } | ||
8 | |||
9 | // --------------------------------------------------------------------------- | ||
10 | |||
11 | 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 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const videosValidators = require('../videos') | ||
4 | const miscValidators = require('../misc') | ||
5 | |||
6 | const remoteVideosValidators = { | ||
7 | isEachRemoteRequestVideosValid | ||
8 | } | ||
9 | |||
10 | function isEachRemoteRequestVideosValid (requests) { | ||
11 | return miscValidators.isArray(requests) && | ||
12 | requests.every(function (request) { | ||
13 | const video = request.data | ||
14 | return ( | ||
15 | isRequestTypeAddValid(request.type) && | ||
16 | videosValidators.isVideoAuthorValid(video.author) && | ||
17 | videosValidators.isVideoDateValid(video.createdAt) && | ||
18 | videosValidators.isVideoDateValid(video.updatedAt) && | ||
19 | videosValidators.isVideoDescriptionValid(video.description) && | ||
20 | videosValidators.isVideoDurationValid(video.duration) && | ||
21 | videosValidators.isVideoInfoHashValid(video.infoHash) && | ||
22 | videosValidators.isVideoNameValid(video.name) && | ||
23 | videosValidators.isVideoTagsValid(video.tags) && | ||
24 | videosValidators.isVideoThumbnailDataValid(video.thumbnailData) && | ||
25 | videosValidators.isVideoRemoteIdValid(video.remoteId) && | ||
26 | videosValidators.isVideoExtnameValid(video.extname) | ||
27 | ) || | ||
28 | ( | ||
29 | isRequestTypeUpdateValid(request.type) && | ||
30 | videosValidators.isVideoDateValid(video.createdAt) && | ||
31 | videosValidators.isVideoDateValid(video.updatedAt) && | ||
32 | videosValidators.isVideoDescriptionValid(video.description) && | ||
33 | videosValidators.isVideoDurationValid(video.duration) && | ||
34 | videosValidators.isVideoInfoHashValid(video.infoHash) && | ||
35 | videosValidators.isVideoNameValid(video.name) && | ||
36 | videosValidators.isVideoTagsValid(video.tags) && | ||
37 | videosValidators.isVideoRemoteIdValid(video.remoteId) && | ||
38 | videosValidators.isVideoExtnameValid(video.extname) | ||
39 | ) || | ||
40 | ( | ||
41 | isRequestTypeRemoveValid(request.type) && | ||
42 | videosValidators.isVideoNameValid(video.name) && | ||
43 | videosValidators.isVideoRemoteIdValid(video.remoteId) | ||
44 | ) || | ||
45 | ( | ||
46 | isRequestTypeReportAbuseValid(request.type) && | ||
47 | videosValidators.isVideoRemoteIdValid(request.data.videoRemoteId) && | ||
48 | videosValidators.isVideoAbuseReasonValid(request.data.reportReason) && | ||
49 | videosValidators.isVideoAbuseReporterUsernameValid(request.data.reporterUsername) | ||
50 | ) | ||
51 | }) | ||
52 | } | ||
53 | |||
54 | // --------------------------------------------------------------------------- | ||
55 | |||
56 | module.exports = remoteVideosValidators | ||
57 | |||
58 | // --------------------------------------------------------------------------- | ||
59 | |||
60 | function isRequestTypeAddValid (value) { | ||
61 | return value === 'add' | ||
62 | } | ||
63 | |||
64 | function isRequestTypeUpdateValid (value) { | ||
65 | return value === 'update' | ||
66 | } | ||
67 | |||
68 | function isRequestTypeRemoveValid (value) { | ||
69 | return value === 'remove' | ||
70 | } | ||
71 | |||
72 | function isRequestTypeReportAbuseValid (value) { | ||
73 | return value === 'report-abuse' | ||
74 | } | ||
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') | |||
6 | const usersValidators = require('./users') | 6 | const usersValidators = require('./users') |
7 | const miscValidators = require('./misc') | 7 | const miscValidators = require('./misc') |
8 | const VIDEOS_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEOS | 8 | const VIDEOS_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEOS |
9 | const VIDEO_ABUSES_CONSTRAINTS_FIELDS = constants.CONSTRAINTS_FIELDS.VIDEO_ABUSES | ||
9 | 10 | ||
10 | const videosValidators = { | 11 | const videosValidators = { |
11 | isEachRemoteVideosValid, | ||
12 | isVideoAuthorValid, | 12 | isVideoAuthorValid, |
13 | isVideoDateValid, | 13 | isVideoDateValid, |
14 | isVideoDescriptionValid, | 14 | isVideoDescriptionValid, |
@@ -17,45 +17,11 @@ const videosValidators = { | |||
17 | isVideoNameValid, | 17 | isVideoNameValid, |
18 | isVideoTagsValid, | 18 | isVideoTagsValid, |
19 | isVideoThumbnailValid, | 19 | isVideoThumbnailValid, |
20 | isVideoThumbnailDataValid | 20 | isVideoThumbnailDataValid, |
21 | } | 21 | isVideoExtnameValid, |
22 | 22 | isVideoRemoteIdValid, | |
23 | function isEachRemoteVideosValid (requests) { | 23 | isVideoAbuseReasonValid, |
24 | return miscValidators.isArray(requests) && | 24 | isVideoAbuseReporterUsernameValid |
25 | requests.every(function (request) { | ||
26 | const video = request.data | ||
27 | return ( | ||
28 | isRequestTypeAddValid(request.type) && | ||
29 | isVideoAuthorValid(video.author) && | ||
30 | isVideoDateValid(video.createdAt) && | ||
31 | isVideoDateValid(video.updatedAt) && | ||
32 | isVideoDescriptionValid(video.description) && | ||
33 | isVideoDurationValid(video.duration) && | ||
34 | isVideoInfoHashValid(video.infoHash) && | ||
35 | isVideoNameValid(video.name) && | ||
36 | isVideoTagsValid(video.tags) && | ||
37 | isVideoThumbnailDataValid(video.thumbnailData) && | ||
38 | isVideoRemoteIdValid(video.remoteId) && | ||
39 | isVideoExtnameValid(video.extname) | ||
40 | ) || | ||
41 | ( | ||
42 | isRequestTypeUpdateValid(request.type) && | ||
43 | isVideoDateValid(video.createdAt) && | ||
44 | isVideoDateValid(video.updatedAt) && | ||
45 | isVideoDescriptionValid(video.description) && | ||
46 | isVideoDurationValid(video.duration) && | ||
47 | isVideoInfoHashValid(video.infoHash) && | ||
48 | isVideoNameValid(video.name) && | ||
49 | isVideoTagsValid(video.tags) && | ||
50 | isVideoRemoteIdValid(video.remoteId) && | ||
51 | isVideoExtnameValid(video.extname) | ||
52 | ) || | ||
53 | ( | ||
54 | isRequestTypeRemoveValid(request.type) && | ||
55 | isVideoNameValid(video.name) && | ||
56 | isVideoRemoteIdValid(video.remoteId) | ||
57 | ) | ||
58 | }) | ||
59 | } | 25 | } |
60 | 26 | ||
61 | function isVideoAuthorValid (value) { | 27 | function isVideoAuthorValid (value) { |
@@ -107,20 +73,14 @@ function isVideoRemoteIdValid (value) { | |||
107 | return validator.isUUID(value, 4) | 73 | return validator.isUUID(value, 4) |
108 | } | 74 | } |
109 | 75 | ||
110 | // --------------------------------------------------------------------------- | 76 | function isVideoAbuseReasonValid (value) { |
111 | 77 | return validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON) | |
112 | module.exports = videosValidators | ||
113 | |||
114 | // --------------------------------------------------------------------------- | ||
115 | |||
116 | function isRequestTypeAddValid (value) { | ||
117 | return value === 'add' | ||
118 | } | 78 | } |
119 | 79 | ||
120 | function isRequestTypeUpdateValid (value) { | 80 | function isVideoAbuseReporterUsernameValid (value) { |
121 | return value === 'update' | 81 | return usersValidators.isUserUsernameValid(value) |
122 | } | 82 | } |
123 | 83 | ||
124 | function isRequestTypeRemoveValid (value) { | 84 | // --------------------------------------------------------------------------- |
125 | return value === 'remove' | 85 | |
126 | } | 86 | 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 = { | |||
8 | badRequest, | 8 | badRequest, |
9 | cleanForExit, | 9 | cleanForExit, |
10 | generateRandomString, | 10 | generateRandomString, |
11 | isTestInstance | 11 | isTestInstance, |
12 | getFormatedObjects | ||
12 | } | 13 | } |
13 | 14 | ||
14 | function badRequest (req, res, next) { | 15 | function badRequest (req, res, next) { |
@@ -32,6 +33,19 @@ function isTestInstance () { | |||
32 | return (process.env.NODE_ENV === 'test') | 33 | return (process.env.NODE_ENV === 'test') |
33 | } | 34 | } |
34 | 35 | ||
36 | function getFormatedObjects (objects, objectsTotal) { | ||
37 | const formatedObjects = [] | ||
38 | |||
39 | objects.forEach(function (object) { | ||
40 | formatedObjects.push(object.toFormatedJSON()) | ||
41 | }) | ||
42 | |||
43 | return { | ||
44 | total: objectsTotal, | ||
45 | data: formatedObjects | ||
46 | } | ||
47 | } | ||
48 | |||
35 | // --------------------------------------------------------------------------- | 49 | // --------------------------------------------------------------------------- |
36 | 50 | ||
37 | module.exports = utils | 51 | 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 = { | |||
19 | // Sortable columns per schema | 19 | // Sortable columns per schema |
20 | const SORTABLE_COLUMNS = { | 20 | const SORTABLE_COLUMNS = { |
21 | USERS: [ 'username', '-username', 'createdAt', '-createdAt' ], | 21 | USERS: [ 'username', '-username', 'createdAt', '-createdAt' ], |
22 | VIDEO_ABUSES: [ 'createdAt', '-createdAt' ], | ||
22 | VIDEOS: [ 'name', '-name', 'duration', '-duration', 'createdAt', '-createdAt' ] | 23 | VIDEOS: [ 'name', '-name', 'duration', '-duration', 'createdAt', '-createdAt' ] |
23 | } | 24 | } |
24 | 25 | ||
@@ -65,6 +66,9 @@ const CONSTRAINTS_FIELDS = { | |||
65 | USERNAME: { min: 3, max: 20 }, // Length | 66 | USERNAME: { min: 3, max: 20 }, // Length |
66 | PASSWORD: { min: 6, max: 255 } // Length | 67 | PASSWORD: { min: 6, max: 255 } // Length |
67 | }, | 68 | }, |
69 | VIDEO_ABUSES: { | ||
70 | REASON: { min: 2, max: 300 } // Length | ||
71 | }, | ||
68 | VIDEOS: { | 72 | VIDEOS: { |
69 | NAME: { min: 3, max: 50 }, // Length | 73 | NAME: { min: 3, max: 50 }, // Length |
70 | DESCRIPTION: { min: 3, max: 250 }, // Length | 74 | 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') | |||
15 | const friends = { | 15 | const friends = { |
16 | addVideoToFriends, | 16 | addVideoToFriends, |
17 | updateVideoToFriends, | 17 | updateVideoToFriends, |
18 | reportAbuseVideoToFriend, | ||
18 | hasFriends, | 19 | hasFriends, |
19 | getMyCertificate, | 20 | getMyCertificate, |
20 | makeFriends, | 21 | makeFriends, |
@@ -23,12 +24,20 @@ const friends = { | |||
23 | sendOwnedVideosToPod | 24 | sendOwnedVideosToPod |
24 | } | 25 | } |
25 | 26 | ||
26 | function addVideoToFriends (video) { | 27 | function addVideoToFriends (videoData) { |
27 | createRequest('add', constants.REQUEST_ENDPOINTS.VIDEOS, video) | 28 | createRequest('add', constants.REQUEST_ENDPOINTS.VIDEOS, videoData) |
28 | } | 29 | } |
29 | 30 | ||
30 | function updateVideoToFriends (video) { | 31 | function updateVideoToFriends (videoData) { |
31 | createRequest('update', constants.REQUEST_ENDPOINTS.VIDEOS, video) | 32 | createRequest('update', constants.REQUEST_ENDPOINTS.VIDEOS, videoData) |
33 | } | ||
34 | |||
35 | function removeVideoToFriends (videoParams) { | ||
36 | createRequest('remove', constants.REQUEST_ENDPOINTS.VIDEOS, videoParams) | ||
37 | } | ||
38 | |||
39 | function reportAbuseVideoToFriend (reportData, video) { | ||
40 | createRequest('report-abuse', constants.REQUEST_ENDPOINTS.VIDEOS, reportData, [ video.Author.podId ]) | ||
32 | } | 41 | } |
33 | 42 | ||
34 | function hasFriends (callback) { | 43 | function hasFriends (callback) { |
@@ -120,10 +129,6 @@ function quitFriends (callback) { | |||
120 | }) | 129 | }) |
121 | } | 130 | } |
122 | 131 | ||
123 | function removeVideoToFriends (videoParams) { | ||
124 | createRequest('remove', constants.REQUEST_ENDPOINTS.VIDEOS, videoParams) | ||
125 | } | ||
126 | |||
127 | function sendOwnedVideosToPod (podId) { | 132 | function sendOwnedVideosToPod (podId) { |
128 | db.Video.listOwnedAndPopulateAuthorAndTags(function (err, videosList) { | 133 | db.Video.listOwnedAndPopulateAuthorAndTags(function (err, videosList) { |
129 | if (err) { | 134 | if (err) { |
@@ -152,10 +157,10 @@ module.exports = friends | |||
152 | // --------------------------------------------------------------------------- | 157 | // --------------------------------------------------------------------------- |
153 | 158 | ||
154 | function computeForeignPodsList (host, podsScore, callback) { | 159 | function computeForeignPodsList (host, podsScore, callback) { |
155 | getForeignPodsList(host, function (err, foreignPodsList) { | 160 | getForeignPodsList(host, function (err, res) { |
156 | if (err) return callback(err) | 161 | if (err) return callback(err) |
157 | 162 | ||
158 | if (!foreignPodsList) foreignPodsList = [] | 163 | const foreignPodsList = res.data |
159 | 164 | ||
160 | // Let's give 1 point to the pod we ask the friends list | 165 | // Let's give 1 point to the pod we ask the friends list |
161 | foreignPodsList.push({ host }) | 166 | foreignPodsList.push({ host }) |
@@ -252,11 +257,11 @@ function makeRequestsToWinningPods (cert, podsList, callback) { | |||
252 | }) | 257 | }) |
253 | } | 258 | } |
254 | 259 | ||
255 | // Wrapper that populate "to" argument with all our friends if it is not specified | 260 | // Wrapper that populate "toIds" argument with all our friends if it is not specified |
256 | function createRequest (type, endpoint, data, to) { | 261 | function createRequest (type, endpoint, data, toIds) { |
257 | if (to) return _createRequest(type, endpoint, data, to) | 262 | if (toIds) return _createRequest(type, endpoint, data, toIds) |
258 | 263 | ||
259 | // If the "to" pods is not specified, we send the request to all our friends | 264 | // If the "toIds" pods is not specified, we send the request to all our friends |
260 | db.Pod.listAllIds(function (err, podIds) { | 265 | db.Pod.listAllIds(function (err, podIds) { |
261 | if (err) { | 266 | if (err) { |
262 | logger.error('Cannot get pod ids', { error: err }) | 267 | logger.error('Cannot get pod ids', { error: err }) |
@@ -267,13 +272,13 @@ function createRequest (type, endpoint, data, to) { | |||
267 | }) | 272 | }) |
268 | } | 273 | } |
269 | 274 | ||
270 | function _createRequest (type, endpoint, data, to) { | 275 | function _createRequest (type, endpoint, data, toIds) { |
271 | const pods = [] | 276 | const pods = [] |
272 | 277 | ||
273 | // If there are no destination pods abort | 278 | // If there are no destination pods abort |
274 | if (to.length === 0) return | 279 | if (toIds.length === 0) return |
275 | 280 | ||
276 | to.forEach(function (toPod) { | 281 | toIds.forEach(function (toPod) { |
277 | pods.push(db.Pod.build({ id: toPod })) | 282 | pods.push(db.Pod.build({ id: toPod })) |
278 | }) | 283 | }) |
279 | 284 | ||
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 @@ | |||
2 | 2 | ||
3 | const sortMiddleware = { | 3 | const sortMiddleware = { |
4 | setUsersSort, | 4 | setUsersSort, |
5 | setVideoAbusesSort, | ||
5 | setVideosSort | 6 | setVideosSort |
6 | } | 7 | } |
7 | 8 | ||
@@ -11,6 +12,12 @@ function setUsersSort (req, res, next) { | |||
11 | return next() | 12 | return next() |
12 | } | 13 | } |
13 | 14 | ||
15 | function setVideoAbusesSort (req, res, next) { | ||
16 | if (!req.query.sort) req.query.sort = '-createdAt' | ||
17 | |||
18 | return next() | ||
19 | } | ||
20 | |||
14 | function setVideosSort (req, res, next) { | 21 | function setVideosSort (req, res, next) { |
15 | if (!req.query.sort) req.query.sort = '-createdAt' | 22 | if (!req.query.sort) req.query.sort = '-createdAt' |
16 | 23 | ||
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 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const remoteSignatureValidators = require('./signature') | ||
4 | const remoteVideosValidators = require('./videos') | ||
5 | |||
6 | const validators = { | ||
7 | signature: remoteSignatureValidators, | ||
8 | videos: remoteVideosValidators | ||
9 | } | ||
10 | |||
11 | // --------------------------------------------------------------------------- | ||
12 | |||
13 | module.exports = validators | ||
diff --git a/server/middlewares/validators/remote.js b/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 @@ | |||
1 | 'use strict' | 1 | 'use strict' |
2 | 2 | ||
3 | const checkErrors = require('./utils').checkErrors | 3 | const checkErrors = require('../utils').checkErrors |
4 | const logger = require('../../helpers/logger') | 4 | const logger = require('../../../helpers/logger') |
5 | 5 | ||
6 | const validatorsRemote = { | 6 | const validatorsRemoteSignature = { |
7 | remoteVideos, | ||
8 | signature | 7 | signature |
9 | } | 8 | } |
10 | 9 | ||
11 | function remoteVideos (req, res, next) { | ||
12 | req.checkBody('data').isEachRemoteVideosValid() | ||
13 | |||
14 | logger.debug('Checking remoteVideos parameters', { parameters: req.body }) | ||
15 | |||
16 | checkErrors(req, res, next) | ||
17 | } | ||
18 | |||
19 | function signature (req, res, next) { | 10 | function signature (req, res, next) { |
20 | req.checkBody('signature.host', 'Should have a signature host').isURL() | 11 | req.checkBody('signature.host', 'Should have a signature host').isURL() |
21 | req.checkBody('signature.signature', 'Should have a signature').notEmpty() | 12 | req.checkBody('signature.signature', 'Should have a signature').notEmpty() |
@@ -27,4 +18,4 @@ function signature (req, res, next) { | |||
27 | 18 | ||
28 | // --------------------------------------------------------------------------- | 19 | // --------------------------------------------------------------------------- |
29 | 20 | ||
30 | module.exports = validatorsRemote | 21 | 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 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const checkErrors = require('../utils').checkErrors | ||
4 | const logger = require('../../../helpers/logger') | ||
5 | |||
6 | const validatorsRemoteVideos = { | ||
7 | remoteVideos | ||
8 | } | ||
9 | |||
10 | function remoteVideos (req, res, next) { | ||
11 | req.checkBody('data').isEachRemoteRequestVideosValid() | ||
12 | |||
13 | logger.debug('Checking remoteVideos parameters', { parameters: req.body }) | ||
14 | |||
15 | checkErrors(req, res, next) | ||
16 | } | ||
17 | |||
18 | // --------------------------------------------------------------------------- | ||
19 | |||
20 | 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') | |||
6 | 6 | ||
7 | const validatorsSort = { | 7 | const validatorsSort = { |
8 | usersSort, | 8 | usersSort, |
9 | videoAbusesSort, | ||
9 | videosSort | 10 | videosSort |
10 | } | 11 | } |
11 | 12 | ||
12 | function usersSort (req, res, next) { | 13 | function usersSort (req, res, next) { |
13 | const sortableColumns = constants.SORTABLE_COLUMNS.USERS | 14 | const sortableColumns = constants.SORTABLE_COLUMNS.USERS |
14 | 15 | ||
15 | req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns) | 16 | checkSort(req, res, next, sortableColumns) |
17 | } | ||
16 | 18 | ||
17 | logger.debug('Checking sort parameters', { parameters: req.query }) | 19 | function videoAbusesSort (req, res, next) { |
20 | const sortableColumns = constants.SORTABLE_COLUMNS.VIDEO_ABUSES | ||
18 | 21 | ||
19 | checkErrors(req, res, next) | 22 | checkSort(req, res, next, sortableColumns) |
20 | } | 23 | } |
21 | 24 | ||
22 | function videosSort (req, res, next) { | 25 | function videosSort (req, res, next) { |
23 | const sortableColumns = constants.SORTABLE_COLUMNS.VIDEOS | 26 | const sortableColumns = constants.SORTABLE_COLUMNS.VIDEOS |
24 | 27 | ||
28 | checkSort(req, res, next, sortableColumns) | ||
29 | } | ||
30 | |||
31 | // --------------------------------------------------------------------------- | ||
32 | |||
33 | module.exports = validatorsSort | ||
34 | |||
35 | // --------------------------------------------------------------------------- | ||
36 | |||
37 | function checkSort (req, res, next, sortableColumns) { | ||
25 | req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns) | 38 | req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns) |
26 | 39 | ||
27 | logger.debug('Checking sort parameters', { parameters: req.query }) | 40 | logger.debug('Checking sort parameters', { parameters: req.query }) |
28 | 41 | ||
29 | checkErrors(req, res, next) | 42 | checkErrors(req, res, next) |
30 | } | 43 | } |
31 | |||
32 | // --------------------------------------------------------------------------- | ||
33 | |||
34 | 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 = { | |||
11 | videosUpdate, | 11 | videosUpdate, |
12 | videosGet, | 12 | videosGet, |
13 | videosRemove, | 13 | videosRemove, |
14 | videosSearch | 14 | videosSearch, |
15 | |||
16 | videoAbuseReport | ||
15 | } | 17 | } |
16 | 18 | ||
17 | function videosAdd (req, res, next) { | 19 | function videosAdd (req, res, next) { |
@@ -97,6 +99,17 @@ function videosSearch (req, res, next) { | |||
97 | checkErrors(req, res, next) | 99 | checkErrors(req, res, next) |
98 | } | 100 | } |
99 | 101 | ||
102 | function videoAbuseReport (req, res, next) { | ||
103 | req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4) | ||
104 | req.checkBody('reason', 'Should have a valid reason').isVideoAbuseReasonValid() | ||
105 | |||
106 | logger.debug('Checking videoAbuseReport parameters', { parameters: req.body }) | ||
107 | |||
108 | checkErrors(req, res, function () { | ||
109 | checkVideoExists(req.params.id, res, next) | ||
110 | }) | ||
111 | } | ||
112 | |||
100 | // --------------------------------------------------------------------------- | 113 | // --------------------------------------------------------------------------- |
101 | 114 | ||
102 | module.exports = validatorsVideos | 115 | module.exports = validatorsVideos |
diff --git a/server/models/requestToPod.js b/server/models/request-to-pod.js index f42a53458..f42a53458 100644 --- a/server/models/requestToPod.js +++ b/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 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const constants = require('../initializers/constants') | ||
4 | const modelUtils = require('./utils') | ||
5 | const customVideosValidators = require('../helpers/custom-validators').videos | ||
6 | |||
7 | module.exports = function (sequelize, DataTypes) { | ||
8 | const VideoAbuse = sequelize.define('VideoAbuse', | ||
9 | { | ||
10 | reporterUsername: { | ||
11 | type: DataTypes.STRING, | ||
12 | allowNull: false, | ||
13 | validate: { | ||
14 | reporterUsernameValid: function (value) { | ||
15 | const res = customVideosValidators.isVideoAbuseReporterUsernameValid(value) | ||
16 | if (res === false) throw new Error('Video abuse reporter username is not valid.') | ||
17 | } | ||
18 | } | ||
19 | }, | ||
20 | reason: { | ||
21 | type: DataTypes.STRING, | ||
22 | allowNull: false, | ||
23 | validate: { | ||
24 | reasonValid: function (value) { | ||
25 | const res = customVideosValidators.isVideoAbuseReasonValid(value) | ||
26 | if (res === false) throw new Error('Video abuse reason is not valid.') | ||
27 | } | ||
28 | } | ||
29 | } | ||
30 | }, | ||
31 | { | ||
32 | indexes: [ | ||
33 | { | ||
34 | fields: [ 'videoId' ] | ||
35 | }, | ||
36 | { | ||
37 | fields: [ 'reporterPodId' ] | ||
38 | } | ||
39 | ], | ||
40 | classMethods: { | ||
41 | associate, | ||
42 | |||
43 | listForApi | ||
44 | }, | ||
45 | instanceMethods: { | ||
46 | toFormatedJSON | ||
47 | } | ||
48 | } | ||
49 | ) | ||
50 | |||
51 | return VideoAbuse | ||
52 | } | ||
53 | |||
54 | // --------------------------------------------------------------------------- | ||
55 | |||
56 | function associate (models) { | ||
57 | this.belongsTo(models.Pod, { | ||
58 | foreignKey: { | ||
59 | name: 'reporterPodId', | ||
60 | allowNull: true | ||
61 | }, | ||
62 | onDelete: 'cascade' | ||
63 | }) | ||
64 | |||
65 | this.belongsTo(models.Video, { | ||
66 | foreignKey: { | ||
67 | name: 'videoId', | ||
68 | allowNull: false | ||
69 | }, | ||
70 | onDelete: 'cascade' | ||
71 | }) | ||
72 | } | ||
73 | |||
74 | function listForApi (start, count, sort, callback) { | ||
75 | const query = { | ||
76 | offset: start, | ||
77 | limit: count, | ||
78 | order: [ modelUtils.getSort(sort) ], | ||
79 | include: [ | ||
80 | { | ||
81 | model: this.sequelize.models.Pod, | ||
82 | required: false | ||
83 | } | ||
84 | ] | ||
85 | } | ||
86 | |||
87 | return this.findAndCountAll(query).asCallback(function (err, result) { | ||
88 | if (err) return callback(err) | ||
89 | |||
90 | return callback(null, result.rows, result.count) | ||
91 | }) | ||
92 | } | ||
93 | |||
94 | function toFormatedJSON () { | ||
95 | let reporterPodHost | ||
96 | |||
97 | if (this.Pod) { | ||
98 | reporterPodHost = this.Pod.host | ||
99 | } else { | ||
100 | // It means it's our video | ||
101 | reporterPodHost = constants.CONFIG.WEBSERVER.HOST | ||
102 | } | ||
103 | |||
104 | const json = { | ||
105 | id: this.id, | ||
106 | reporterPodHost, | ||
107 | reason: this.reason, | ||
108 | reporterUsername: this.reporterUsername, | ||
109 | videoId: this.videoId | ||
110 | } | ||
111 | |||
112 | return json | ||
113 | } | ||
diff --git a/server/models/videoTag.js b/server/models/video-tag.js index cd9277a6e..cd9277a6e 100644 --- a/server/models/videoTag.js +++ b/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) { | |||
248 | through: models.VideoTag, | 248 | through: models.VideoTag, |
249 | onDelete: 'cascade' | 249 | onDelete: 'cascade' |
250 | }) | 250 | }) |
251 | |||
252 | this.hasMany(models.VideoAbuse, { | ||
253 | foreignKey: { | ||
254 | name: 'videoId', | ||
255 | allowNull: false | ||
256 | }, | ||
257 | onDelete: 'cascade' | ||
258 | }) | ||
251 | } | 259 | } |
252 | 260 | ||
253 | function generateMagnetUri () { | 261 | 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') | |||
6 | require('./users') | 6 | require('./users') |
7 | require('./requests') | 7 | require('./requests') |
8 | require('./videos') | 8 | require('./videos') |
9 | 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 () { | |||
47 | it('Should check when removing a video') | 47 | it('Should check when removing a video') |
48 | }) | 48 | }) |
49 | 49 | ||
50 | describe('When reporting abuse on a video', function () { | ||
51 | it('Should check when reporting a video abuse') | ||
52 | }) | ||
53 | |||
50 | after(function (done) { | 54 | after(function (done) { |
51 | process.kill(-server.app.pid) | 55 | process.kill(-server.app.pid) |
52 | 56 | ||
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 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const request = require('supertest') | ||
4 | const series = require('async/series') | ||
5 | |||
6 | const loginUtils = require('../../utils/login') | ||
7 | const requestsUtils = require('../../utils/requests') | ||
8 | const serversUtils = require('../../utils/servers') | ||
9 | const usersUtils = require('../../utils/users') | ||
10 | const videosUtils = require('../../utils/videos') | ||
11 | |||
12 | describe('Test video abuses API validators', function () { | ||
13 | let server = null | ||
14 | let userAccessToken = null | ||
15 | |||
16 | // --------------------------------------------------------------- | ||
17 | |||
18 | before(function (done) { | ||
19 | this.timeout(20000) | ||
20 | |||
21 | series([ | ||
22 | function (next) { | ||
23 | serversUtils.flushTests(next) | ||
24 | }, | ||
25 | function (next) { | ||
26 | serversUtils.runServer(1, function (server1) { | ||
27 | server = server1 | ||
28 | |||
29 | next() | ||
30 | }) | ||
31 | }, | ||
32 | function (next) { | ||
33 | loginUtils.loginAndGetAccessToken(server, function (err, token) { | ||
34 | if (err) throw err | ||
35 | server.accessToken = token | ||
36 | |||
37 | next() | ||
38 | }) | ||
39 | }, | ||
40 | function (next) { | ||
41 | const username = 'user1' | ||
42 | const password = 'my super password' | ||
43 | |||
44 | usersUtils.createUser(server.url, server.accessToken, username, password, next) | ||
45 | }, | ||
46 | function (next) { | ||
47 | const user = { | ||
48 | username: 'user1', | ||
49 | password: 'my super password' | ||
50 | } | ||
51 | |||
52 | loginUtils.getUserAccessToken(server, user, function (err, accessToken) { | ||
53 | if (err) throw err | ||
54 | |||
55 | userAccessToken = accessToken | ||
56 | |||
57 | next() | ||
58 | }) | ||
59 | }, | ||
60 | // Upload some videos on each pods | ||
61 | function (next) { | ||
62 | const name = 'my super name for pod' | ||
63 | const description = 'my super description for pod' | ||
64 | const tags = [ 'tag' ] | ||
65 | const file = 'video_short2.webm' | ||
66 | videosUtils.uploadVideo(server.url, server.accessToken, name, description, tags, file, next) | ||
67 | }, | ||
68 | function (next) { | ||
69 | videosUtils.getVideosList(server.url, function (err, res) { | ||
70 | if (err) throw err | ||
71 | |||
72 | const videos = res.body.data | ||
73 | server.video = videos[0] | ||
74 | |||
75 | next() | ||
76 | }) | ||
77 | } | ||
78 | ], done) | ||
79 | }) | ||
80 | |||
81 | describe('When listing video abuses', function () { | ||
82 | const path = '/api/v1/videos/abuse' | ||
83 | |||
84 | it('Should fail with a bad start pagination', function (done) { | ||
85 | request(server.url) | ||
86 | .get(path) | ||
87 | .query({ start: 'hello' }) | ||
88 | .set('Authorization', 'Bearer ' + server.accessToken) | ||
89 | .set('Accept', 'application/json') | ||
90 | .expect(400, done) | ||
91 | }) | ||
92 | |||
93 | it('Should fail with a bad count pagination', function (done) { | ||
94 | request(server.url) | ||
95 | .get(path) | ||
96 | .query({ count: 'hello' }) | ||
97 | .set('Accept', 'application/json') | ||
98 | .set('Authorization', 'Bearer ' + server.accessToken) | ||
99 | .expect(400, done) | ||
100 | }) | ||
101 | |||
102 | it('Should fail with an incorrect sort', function (done) { | ||
103 | request(server.url) | ||
104 | .get(path) | ||
105 | .query({ sort: 'hello' }) | ||
106 | .set('Accept', 'application/json') | ||
107 | .set('Authorization', 'Bearer ' + server.accessToken) | ||
108 | .expect(400, done) | ||
109 | }) | ||
110 | |||
111 | it('Should fail with a non authenticated user', function (done) { | ||
112 | request(server.url) | ||
113 | .get(path) | ||
114 | .query({ sort: 'hello' }) | ||
115 | .set('Accept', 'application/json') | ||
116 | .expect(401, done) | ||
117 | }) | ||
118 | |||
119 | it('Should fail with a non admin user', function (done) { | ||
120 | request(server.url) | ||
121 | .get(path) | ||
122 | .query({ sort: 'hello' }) | ||
123 | .set('Accept', 'application/json') | ||
124 | .set('Authorization', 'Bearer ' + userAccessToken) | ||
125 | .expect(403, done) | ||
126 | }) | ||
127 | }) | ||
128 | |||
129 | describe('When reporting a video abuse', function () { | ||
130 | const basePath = '/api/v1/videos/' | ||
131 | |||
132 | it('Should fail with nothing', function (done) { | ||
133 | const path = basePath + server.video + '/abuse' | ||
134 | const data = {} | ||
135 | requestsUtils.makePostBodyRequest(server.url, path, server.accessToken, data, done) | ||
136 | }) | ||
137 | |||
138 | it('Should fail with a wrong video', function (done) { | ||
139 | const wrongPath = '/api/v1/videos/blabla/abuse' | ||
140 | const data = {} | ||
141 | requestsUtils.makePostBodyRequest(server.url, wrongPath, server.accessToken, data, done) | ||
142 | }) | ||
143 | |||
144 | it('Should fail with a non authenticated user', function (done) { | ||
145 | const data = {} | ||
146 | const path = basePath + server.video + '/abuse' | ||
147 | requestsUtils.makePostBodyRequest(server.url, path, 'hello', data, done, 401) | ||
148 | }) | ||
149 | |||
150 | it('Should fail with a reason too short', function (done) { | ||
151 | const data = { | ||
152 | reason: 'h' | ||
153 | } | ||
154 | const path = basePath + server.video + '/abuse' | ||
155 | requestsUtils.makePostBodyRequest(server.url, path, server.accessToken, data, done) | ||
156 | }) | ||
157 | |||
158 | it('Should fail with a reason too big', function (done) { | ||
159 | const data = { | ||
160 | reason: '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef' + | ||
161 | '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef' + | ||
162 | '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef' + | ||
163 | '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef' | ||
164 | } | ||
165 | const path = basePath + server.video + '/abuse' | ||
166 | requestsUtils.makePostBodyRequest(server.url, path, server.accessToken, data, done) | ||
167 | }) | ||
168 | }) | ||
169 | |||
170 | after(function (done) { | ||
171 | process.kill(-server.app.pid) | ||
172 | |||
173 | // Keep the logs if the test failed | ||
174 | if (this.ok) { | ||
175 | serversUtils.flushTests(done) | ||
176 | } else { | ||
177 | done() | ||
178 | } | ||
179 | }) | ||
180 | }) | ||
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 () { | |||
86 | getFriendsList(5, function (err, res) { | 86 | getFriendsList(5, function (err, res) { |
87 | if (err) throw err | 87 | if (err) throw err |
88 | 88 | ||
89 | expect(res.body.length).to.equal(0) | 89 | expect(res.body.data.length).to.equal(0) |
90 | 90 | ||
91 | done() | 91 | done() |
92 | }) | 92 | }) |
@@ -111,7 +111,7 @@ describe('Test advanced friends', function () { | |||
111 | getFriendsList(i, function (err, res) { | 111 | getFriendsList(i, function (err, res) { |
112 | if (err) throw err | 112 | if (err) throw err |
113 | 113 | ||
114 | expect(res.body.length).to.equal(0) | 114 | expect(res.body.data.length).to.equal(0) |
115 | 115 | ||
116 | callback() | 116 | callback() |
117 | }) | 117 | }) |
@@ -140,7 +140,7 @@ describe('Test advanced friends', function () { | |||
140 | getFriendsList(i, function (err, res) { | 140 | getFriendsList(i, function (err, res) { |
141 | if (err) throw err | 141 | if (err) throw err |
142 | 142 | ||
143 | expect(res.body.length).to.equal(3) | 143 | expect(res.body.data.length).to.equal(3) |
144 | 144 | ||
145 | callback() | 145 | callback() |
146 | }) | 146 | }) |
@@ -182,7 +182,7 @@ describe('Test advanced friends', function () { | |||
182 | if (err) throw err | 182 | if (err) throw err |
183 | 183 | ||
184 | // Pod 4 didn't know pod 1 and 2 removed it | 184 | // Pod 4 didn't know pod 1 and 2 removed it |
185 | expect(res.body.length).to.equal(3) | 185 | expect(res.body.data.length).to.equal(3) |
186 | next() | 186 | next() |
187 | }) | 187 | }) |
188 | }, | 188 | }, |
@@ -200,7 +200,7 @@ describe('Test advanced friends', function () { | |||
200 | if (err) throw err | 200 | if (err) throw err |
201 | 201 | ||
202 | // Pod 4 should not be our friend | 202 | // Pod 4 should not be our friend |
203 | const result = res.body | 203 | const result = res.body.data |
204 | expect(result.length).to.equal(3) | 204 | expect(result.length).to.equal(3) |
205 | for (const pod of result) { | 205 | for (const pod of result) { |
206 | expect(pod.host).not.equal(servers[3].host) | 206 | 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 () { | |||
28 | podsUtils.getFriendsList(serverToTest.url, function (err, res) { | 28 | podsUtils.getFriendsList(serverToTest.url, function (err, res) { |
29 | if (err) throw err | 29 | if (err) throw err |
30 | 30 | ||
31 | const result = res.body | 31 | const result = res.body.data |
32 | expect(result).to.be.an('array') | 32 | expect(result).to.be.an('array') |
33 | expect(result.length).to.equal(2) | 33 | expect(result.length).to.equal(2) |
34 | 34 | ||
@@ -65,7 +65,7 @@ describe('Test basic friends', function () { | |||
65 | podsUtils.getFriendsList(server.url, function (err, res) { | 65 | podsUtils.getFriendsList(server.url, function (err, res) { |
66 | if (err) throw err | 66 | if (err) throw err |
67 | 67 | ||
68 | const result = res.body | 68 | const result = res.body.data |
69 | expect(result).to.be.an('array') | 69 | expect(result).to.be.an('array') |
70 | expect(result.length).to.equal(0) | 70 | expect(result.length).to.equal(0) |
71 | callback() | 71 | callback() |
@@ -90,7 +90,7 @@ describe('Test basic friends', function () { | |||
90 | podsUtils.getFriendsList(servers[1].url, function (err, res) { | 90 | podsUtils.getFriendsList(servers[1].url, function (err, res) { |
91 | if (err) throw err | 91 | if (err) throw err |
92 | 92 | ||
93 | const result = res.body | 93 | const result = res.body.data |
94 | expect(result).to.be.an('array') | 94 | expect(result).to.be.an('array') |
95 | expect(result.length).to.equal(1) | 95 | expect(result.length).to.equal(1) |
96 | 96 | ||
@@ -107,7 +107,7 @@ describe('Test basic friends', function () { | |||
107 | podsUtils.getFriendsList(servers[2].url, function (err, res) { | 107 | podsUtils.getFriendsList(servers[2].url, function (err, res) { |
108 | if (err) throw err | 108 | if (err) throw err |
109 | 109 | ||
110 | const result = res.body | 110 | const result = res.body.data |
111 | expect(result).to.be.an('array') | 111 | expect(result).to.be.an('array') |
112 | expect(result.length).to.equal(1) | 112 | expect(result.length).to.equal(1) |
113 | 113 | ||
@@ -154,7 +154,7 @@ describe('Test basic friends', function () { | |||
154 | podsUtils.getFriendsList(servers[1].url, function (err, res) { | 154 | podsUtils.getFriendsList(servers[1].url, function (err, res) { |
155 | if (err) throw err | 155 | if (err) throw err |
156 | 156 | ||
157 | const result = res.body | 157 | const result = res.body.data |
158 | expect(result).to.be.an('array') | 158 | expect(result).to.be.an('array') |
159 | expect(result.length).to.equal(0) | 159 | expect(result.length).to.equal(0) |
160 | 160 | ||
@@ -167,7 +167,7 @@ describe('Test basic friends', function () { | |||
167 | podsUtils.getFriendsList(url, function (err, res) { | 167 | podsUtils.getFriendsList(url, function (err, res) { |
168 | if (err) throw err | 168 | if (err) throw err |
169 | 169 | ||
170 | const result = res.body | 170 | const result = res.body.data |
171 | expect(result).to.be.an('array') | 171 | expect(result).to.be.an('array') |
172 | expect(result.length).to.equal(1) | 172 | expect(result.length).to.equal(1) |
173 | expect(result[0].host).not.to.be.equal(servers[1].host) | 173 | 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 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const chai = require('chai') | ||
4 | const each = require('async/each') | ||
5 | const expect = chai.expect | ||
6 | const series = require('async/series') | ||
7 | |||
8 | const loginUtils = require('../utils/login') | ||
9 | const podsUtils = require('../utils/pods') | ||
10 | const serversUtils = require('../utils/servers') | ||
11 | const videosUtils = require('../utils/videos') | ||
12 | const videoAbusesUtils = require('../utils/video-abuses') | ||
13 | |||
14 | describe('Test video abuses', function () { | ||
15 | let servers = [] | ||
16 | |||
17 | before(function (done) { | ||
18 | this.timeout(30000) | ||
19 | |||
20 | series([ | ||
21 | // Run servers | ||
22 | function (next) { | ||
23 | serversUtils.flushAndRunMultipleServers(2, function (serversRun) { | ||
24 | servers = serversRun | ||
25 | next() | ||
26 | }) | ||
27 | }, | ||
28 | // Get the access tokens | ||
29 | function (next) { | ||
30 | each(servers, function (server, callbackEach) { | ||
31 | loginUtils.loginAndGetAccessToken(server, function (err, accessToken) { | ||
32 | if (err) return callbackEach(err) | ||
33 | |||
34 | server.accessToken = accessToken | ||
35 | callbackEach() | ||
36 | }) | ||
37 | }, next) | ||
38 | }, | ||
39 | // Pod 1 make friends too | ||
40 | function (next) { | ||
41 | const server = servers[0] | ||
42 | podsUtils.makeFriends(server.url, server.accessToken, next) | ||
43 | }, | ||
44 | // Upload some videos on each pods | ||
45 | function (next) { | ||
46 | const name = 'my super name for pod 1' | ||
47 | const description = 'my super description for pod 1' | ||
48 | const tags = [ 'tag' ] | ||
49 | const file = 'video_short2.webm' | ||
50 | videosUtils.uploadVideo(servers[0].url, servers[0].accessToken, name, description, tags, file, next) | ||
51 | }, | ||
52 | function (next) { | ||
53 | const name = 'my super name for pod 2' | ||
54 | const description = 'my super description for pod 2' | ||
55 | const tags = [ 'tag' ] | ||
56 | const file = 'video_short2.webm' | ||
57 | videosUtils.uploadVideo(servers[1].url, servers[1].accessToken, name, description, tags, file, next) | ||
58 | }, | ||
59 | // Wait videos propagation | ||
60 | function (next) { | ||
61 | setTimeout(next, 11000) | ||
62 | }, | ||
63 | function (next) { | ||
64 | videosUtils.getVideosList(servers[0].url, function (err, res) { | ||
65 | if (err) throw err | ||
66 | |||
67 | const videos = res.body.data | ||
68 | |||
69 | expect(videos.length).to.equal(2) | ||
70 | |||
71 | servers[0].video = videos.find(function (video) { return video.name === 'my super name for pod 1' }) | ||
72 | servers[1].video = videos.find(function (video) { return video.name === 'my super name for pod 2' }) | ||
73 | |||
74 | next() | ||
75 | }) | ||
76 | } | ||
77 | ], done) | ||
78 | }) | ||
79 | |||
80 | it('Should not have video abuses', function (done) { | ||
81 | videoAbusesUtils.getVideoAbusesList(servers[0].url, servers[0].accessToken, function (err, res) { | ||
82 | if (err) throw err | ||
83 | |||
84 | expect(res.body.total).to.equal(0) | ||
85 | expect(res.body.data).to.be.an('array') | ||
86 | expect(res.body.data.length).to.equal(0) | ||
87 | |||
88 | done() | ||
89 | }) | ||
90 | }) | ||
91 | |||
92 | it('Should report abuse on a local video', function (done) { | ||
93 | this.timeout(15000) | ||
94 | |||
95 | const reason = 'my super bad reason' | ||
96 | videoAbusesUtils.reportVideoAbuse(servers[0].url, servers[0].accessToken, servers[0].video.id, reason, function (err) { | ||
97 | if (err) throw err | ||
98 | |||
99 | // We wait requests propagation, even if the pod 1 is not supposed to make a request to pod 2 | ||
100 | setTimeout(done, 11000) | ||
101 | }) | ||
102 | }) | ||
103 | |||
104 | it('Should have 1 video abuses on pod 1 and 0 on pod 2', function (done) { | ||
105 | videoAbusesUtils.getVideoAbusesList(servers[0].url, servers[0].accessToken, function (err, res) { | ||
106 | if (err) throw err | ||
107 | |||
108 | expect(res.body.total).to.equal(1) | ||
109 | expect(res.body.data).to.be.an('array') | ||
110 | expect(res.body.data.length).to.equal(1) | ||
111 | |||
112 | const abuse = res.body.data[0] | ||
113 | expect(abuse.reason).to.equal('my super bad reason') | ||
114 | expect(abuse.reporterUsername).to.equal('root') | ||
115 | expect(abuse.reporterPodHost).to.equal('localhost:9001') | ||
116 | expect(abuse.videoId).to.equal(servers[0].video.id) | ||
117 | |||
118 | videoAbusesUtils.getVideoAbusesList(servers[1].url, servers[1].accessToken, function (err, res) { | ||
119 | if (err) throw err | ||
120 | |||
121 | expect(res.body.total).to.equal(0) | ||
122 | expect(res.body.data).to.be.an('array') | ||
123 | expect(res.body.data.length).to.equal(0) | ||
124 | |||
125 | done() | ||
126 | }) | ||
127 | }) | ||
128 | }) | ||
129 | |||
130 | it('Should report abuse on a remote video', function (done) { | ||
131 | this.timeout(15000) | ||
132 | |||
133 | const reason = 'my super bad reason 2' | ||
134 | videoAbusesUtils.reportVideoAbuse(servers[0].url, servers[0].accessToken, servers[1].video.id, reason, function (err) { | ||
135 | if (err) throw err | ||
136 | |||
137 | // We wait requests propagation | ||
138 | setTimeout(done, 11000) | ||
139 | }) | ||
140 | }) | ||
141 | |||
142 | it('Should have 2 video abuse on pod 1 and 1 on pod 2', function (done) { | ||
143 | videoAbusesUtils.getVideoAbusesList(servers[0].url, servers[0].accessToken, function (err, res) { | ||
144 | if (err) throw err | ||
145 | |||
146 | expect(res.body.total).to.equal(2) | ||
147 | expect(res.body.data).to.be.an('array') | ||
148 | expect(res.body.data.length).to.equal(2) | ||
149 | |||
150 | let abuse = res.body.data[0] | ||
151 | expect(abuse.reason).to.equal('my super bad reason') | ||
152 | expect(abuse.reporterUsername).to.equal('root') | ||
153 | expect(abuse.reporterPodHost).to.equal('localhost:9001') | ||
154 | expect(abuse.videoId).to.equal(servers[0].video.id) | ||
155 | |||
156 | abuse = res.body.data[1] | ||
157 | expect(abuse.reason).to.equal('my super bad reason 2') | ||
158 | expect(abuse.reporterUsername).to.equal('root') | ||
159 | expect(abuse.reporterPodHost).to.equal('localhost:9001') | ||
160 | expect(abuse.videoId).to.equal(servers[1].video.id) | ||
161 | |||
162 | videoAbusesUtils.getVideoAbusesList(servers[1].url, servers[1].accessToken, function (err, res) { | ||
163 | if (err) throw err | ||
164 | |||
165 | expect(res.body.total).to.equal(1) | ||
166 | expect(res.body.data).to.be.an('array') | ||
167 | expect(res.body.data.length).to.equal(1) | ||
168 | |||
169 | let abuse = res.body.data[0] | ||
170 | expect(abuse.reason).to.equal('my super bad reason 2') | ||
171 | expect(abuse.reporterUsername).to.equal('root') | ||
172 | expect(abuse.reporterPodHost).to.equal('localhost:9001') | ||
173 | |||
174 | done() | ||
175 | }) | ||
176 | }) | ||
177 | }) | ||
178 | |||
179 | after(function (done) { | ||
180 | servers.forEach(function (server) { | ||
181 | process.kill(-server.app.pid) | ||
182 | }) | ||
183 | |||
184 | // Keep the logs if the test failed | ||
185 | if (this.ok) { | ||
186 | serversUtils.flushTests(done) | ||
187 | } else { | ||
188 | done() | ||
189 | } | ||
190 | }) | ||
191 | }) | ||
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 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const request = require('supertest') | ||
4 | |||
5 | const videosUtils = { | ||
6 | getVideoAbusesList, | ||
7 | getVideoAbusesListPagination, | ||
8 | getVideoAbusesListSort, | ||
9 | reportVideoAbuse | ||
10 | } | ||
11 | |||
12 | // ---------------------- Export functions -------------------- | ||
13 | |||
14 | function reportVideoAbuse (url, token, videoId, reason, specialStatus, end) { | ||
15 | if (!end) { | ||
16 | end = specialStatus | ||
17 | specialStatus = 204 | ||
18 | } | ||
19 | |||
20 | const path = '/api/v1/videos/' + videoId + '/abuse' | ||
21 | |||
22 | request(url) | ||
23 | .post(path) | ||
24 | .set('Accept', 'application/json') | ||
25 | .set('Authorization', 'Bearer ' + token) | ||
26 | .send({ reason }) | ||
27 | .expect(specialStatus) | ||
28 | .end(end) | ||
29 | } | ||
30 | |||
31 | function getVideoAbusesList (url, token, end) { | ||
32 | const path = '/api/v1/videos/abuse' | ||
33 | |||
34 | request(url) | ||
35 | .get(path) | ||
36 | .query({ sort: 'createdAt' }) | ||
37 | .set('Accept', 'application/json') | ||
38 | .set('Authorization', 'Bearer ' + token) | ||
39 | .expect(200) | ||
40 | .expect('Content-Type', /json/) | ||
41 | .end(end) | ||
42 | } | ||
43 | |||
44 | function getVideoAbusesListPagination (url, token, start, count, end) { | ||
45 | const path = '/api/v1/videos/abuse' | ||
46 | |||
47 | request(url) | ||
48 | .get(path) | ||
49 | .query({ start: start }) | ||
50 | .query({ count: count }) | ||
51 | .set('Accept', 'application/json') | ||
52 | .set('Authorization', 'Bearer ' + token) | ||
53 | .expect(200) | ||
54 | .expect('Content-Type', /json/) | ||
55 | .end(end) | ||
56 | } | ||
57 | |||
58 | function getVideoAbusesListSort (url, token, sort, end) { | ||
59 | const path = '/api/v1/videos/abuse' | ||
60 | |||
61 | request(url) | ||
62 | .get(path) | ||
63 | .query({ sort: sort }) | ||
64 | .set('Accept', 'application/json') | ||
65 | .set('Authorization', 'Bearer ' + token) | ||
66 | .expect(200) | ||
67 | .expect('Content-Type', /json/) | ||
68 | .end(end) | ||
69 | } | ||
70 | |||
71 | // --------------------------------------------------------------------------- | ||
72 | |||
73 | module.exports = videosUtils | ||