diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2016-05-17 21:03:00 +0200 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2016-05-17 21:03:00 +0200 |
commit | a877d5acc5c52b8667c65f725bbca9a52e40ec48 (patch) | |
tree | 20b5dd56f71c7572360807f894e85e0ab729629f /server | |
parent | 479f229198bdfcfd3a63d02babdddaa8b2209ccb (diff) | |
download | PeerTube-a877d5acc5c52b8667c65f725bbca9a52e40ec48.tar.gz PeerTube-a877d5acc5c52b8667c65f725bbca9a52e40ec48.tar.zst PeerTube-a877d5acc5c52b8667c65f725bbca9a52e40ec48.zip |
Add ability to sort videos list
Diffstat (limited to 'server')
-rw-r--r-- | server/controllers/api/v1/videos.js | 10 | ||||
-rw-r--r-- | server/initializers/constants.js | 6 | ||||
-rw-r--r-- | server/middlewares/index.js | 2 | ||||
-rw-r--r-- | server/middlewares/reqValidators/index.js | 2 | ||||
-rw-r--r-- | server/middlewares/reqValidators/pagination.js | 6 | ||||
-rw-r--r-- | server/middlewares/reqValidators/sort.js | 23 | ||||
-rw-r--r-- | server/middlewares/sort.js | 15 | ||||
-rw-r--r-- | server/models/videos.js | 9 | ||||
-rw-r--r-- | server/tests/api/checkParams.js | 50 | ||||
-rw-r--r-- | server/tests/api/singlePod.js | 33 | ||||
-rw-r--r-- | server/tests/api/utils.js | 26 |
11 files changed, 173 insertions, 9 deletions
diff --git a/server/controllers/api/v1/videos.js b/server/controllers/api/v1/videos.js index c6dbfbaf2..73e496ace 100644 --- a/server/controllers/api/v1/videos.js +++ b/server/controllers/api/v1/videos.js | |||
@@ -15,7 +15,9 @@ const oAuth2 = middlewares.oauth2 | |||
15 | const pagination = middlewares.pagination | 15 | const pagination = middlewares.pagination |
16 | const reqValidator = middlewares.reqValidators | 16 | const reqValidator = middlewares.reqValidators |
17 | const reqValidatorPagination = reqValidator.pagination | 17 | const reqValidatorPagination = reqValidator.pagination |
18 | const reqValidatorSort = reqValidator.sort | ||
18 | const reqValidatorVideos = reqValidator.videos | 19 | const reqValidatorVideos = reqValidator.videos |
20 | const sort = middlewares.sort | ||
19 | const utils = require('../../../helpers/utils') | 21 | const utils = require('../../../helpers/utils') |
20 | const Videos = require('../../../models/videos') // model | 22 | const Videos = require('../../../models/videos') // model |
21 | const videos = require('../../../lib/videos') | 23 | const videos = require('../../../lib/videos') |
@@ -47,6 +49,8 @@ const thumbnailsDir = path.join(__dirname, '..', '..', '..', '..', config.get('s | |||
47 | 49 | ||
48 | router.get('/', | 50 | router.get('/', |
49 | reqValidatorPagination.pagination, | 51 | reqValidatorPagination.pagination, |
52 | reqValidatorSort.videosSort, | ||
53 | sort.setVideosSort, | ||
50 | pagination.setPagination, | 54 | pagination.setPagination, |
51 | listVideos | 55 | listVideos |
52 | ) | 56 | ) |
@@ -68,6 +72,8 @@ router.delete('/:id', | |||
68 | router.get('/search/:name', | 72 | router.get('/search/:name', |
69 | reqValidatorVideos.videosSearch, | 73 | reqValidatorVideos.videosSearch, |
70 | reqValidatorPagination.pagination, | 74 | reqValidatorPagination.pagination, |
75 | reqValidatorSort.videosSort, | ||
76 | sort.setVideosSort, | ||
71 | pagination.setPagination, | 77 | pagination.setPagination, |
72 | searchVideos | 78 | searchVideos |
73 | ) | 79 | ) |
@@ -173,7 +179,7 @@ function getVideos (req, res, next) { | |||
173 | } | 179 | } |
174 | 180 | ||
175 | function listVideos (req, res, next) { | 181 | function listVideos (req, res, next) { |
176 | Videos.list(req.query.start, req.query.count, function (err, videosList) { | 182 | Videos.list(req.query.start, req.query.count, req.query.sort, function (err, videosList) { |
177 | if (err) return next(err) | 183 | if (err) return next(err) |
178 | 184 | ||
179 | res.json(getFormatedVideos(videosList)) | 185 | res.json(getFormatedVideos(videosList)) |
@@ -231,7 +237,7 @@ function removeVideo (req, res, next) { | |||
231 | } | 237 | } |
232 | 238 | ||
233 | function searchVideos (req, res, next) { | 239 | function searchVideos (req, res, next) { |
234 | Videos.search(req.params.name, req.query.start, req.query.count, function (err, videosList) { | 240 | Videos.search(req.params.name, req.query.start, req.query.count, req.query.sort, function (err, videosList) { |
235 | if (err) return next(err) | 241 | if (err) return next(err) |
236 | 242 | ||
237 | res.json(getFormatedVideos(videosList)) | 243 | res.json(getFormatedVideos(videosList)) |
diff --git a/server/initializers/constants.js b/server/initializers/constants.js index 78bee5efe..4350bb892 100644 --- a/server/initializers/constants.js +++ b/server/initializers/constants.js | |||
@@ -26,6 +26,11 @@ const PODS_SCORE = { | |||
26 | // Number of retries we make for the make retry requests (to friends...) | 26 | // Number of retries we make for the make retry requests (to friends...) |
27 | let REQUEST_RETRIES = 10 | 27 | let REQUEST_RETRIES = 10 |
28 | 28 | ||
29 | // Sortable columns per schema | ||
30 | const SORTABLE_COLUMNS = { | ||
31 | VIDEOS: [ 'name', '-name', 'duration', '-duration', 'createdDate', '-createdDate' ] | ||
32 | } | ||
33 | |||
29 | // Videos thumbnail size | 34 | // Videos thumbnail size |
30 | const THUMBNAILS_SIZE = '200x110' | 35 | const THUMBNAILS_SIZE = '200x110' |
31 | 36 | ||
@@ -51,6 +56,7 @@ module.exports = { | |||
51 | PAGINATION_COUNT_DEFAULT: PAGINATION_COUNT_DEFAULT, | 56 | PAGINATION_COUNT_DEFAULT: PAGINATION_COUNT_DEFAULT, |
52 | PODS_SCORE: PODS_SCORE, | 57 | PODS_SCORE: PODS_SCORE, |
53 | REQUEST_RETRIES: REQUEST_RETRIES, | 58 | REQUEST_RETRIES: REQUEST_RETRIES, |
59 | SORTABLE_COLUMNS: SORTABLE_COLUMNS, | ||
54 | THUMBNAILS_SIZE: THUMBNAILS_SIZE, | 60 | THUMBNAILS_SIZE: THUMBNAILS_SIZE, |
55 | THUMBNAILS_STATIC_PATH: THUMBNAILS_STATIC_PATH | 61 | THUMBNAILS_STATIC_PATH: THUMBNAILS_STATIC_PATH |
56 | } | 62 | } |
diff --git a/server/middlewares/index.js b/server/middlewares/index.js index f0fad3418..35858da2c 100644 --- a/server/middlewares/index.js +++ b/server/middlewares/index.js | |||
@@ -3,12 +3,14 @@ | |||
3 | const oauth2 = require('./oauth2') | 3 | const oauth2 = require('./oauth2') |
4 | const pagination = require('./pagination') | 4 | const pagination = require('./pagination') |
5 | const reqValidatorsMiddleware = require('./reqValidators') | 5 | const reqValidatorsMiddleware = require('./reqValidators') |
6 | const sort = require('./sort') | ||
6 | const secureMiddleware = require('./secure') | 7 | const secureMiddleware = require('./secure') |
7 | 8 | ||
8 | const middlewares = { | 9 | const middlewares = { |
9 | oauth2: oauth2, | 10 | oauth2: oauth2, |
10 | pagination: pagination, | 11 | pagination: pagination, |
11 | reqValidators: reqValidatorsMiddleware, | 12 | reqValidators: reqValidatorsMiddleware, |
13 | sort: sort, | ||
12 | secure: secureMiddleware | 14 | secure: secureMiddleware |
13 | } | 15 | } |
14 | 16 | ||
diff --git a/server/middlewares/reqValidators/index.js b/server/middlewares/reqValidators/index.js index b732a27b6..be68f6a29 100644 --- a/server/middlewares/reqValidators/index.js +++ b/server/middlewares/reqValidators/index.js | |||
@@ -3,12 +3,14 @@ | |||
3 | const paginationReqValidators = require('./pagination') | 3 | const paginationReqValidators = require('./pagination') |
4 | const podsReqValidators = require('./pods') | 4 | const podsReqValidators = require('./pods') |
5 | const remoteReqValidators = require('./remote') | 5 | const remoteReqValidators = require('./remote') |
6 | const sortReqValidators = require('./sort') | ||
6 | const videosReqValidators = require('./videos') | 7 | const videosReqValidators = require('./videos') |
7 | 8 | ||
8 | const reqValidators = { | 9 | const reqValidators = { |
9 | pagination: paginationReqValidators, | 10 | pagination: paginationReqValidators, |
10 | pods: podsReqValidators, | 11 | pods: podsReqValidators, |
11 | remote: remoteReqValidators, | 12 | remote: remoteReqValidators, |
13 | sort: sortReqValidators, | ||
12 | videos: videosReqValidators | 14 | videos: videosReqValidators |
13 | } | 15 | } |
14 | 16 | ||
diff --git a/server/middlewares/reqValidators/pagination.js b/server/middlewares/reqValidators/pagination.js index ca8375396..e598f269a 100644 --- a/server/middlewares/reqValidators/pagination.js +++ b/server/middlewares/reqValidators/pagination.js | |||
@@ -8,10 +8,10 @@ const reqValidatorsPagination = { | |||
8 | } | 8 | } |
9 | 9 | ||
10 | function pagination (req, res, next) { | 10 | function pagination (req, res, next) { |
11 | req.checkParams('start', 'Should have a number start').optional().isInt() | 11 | req.checkQuery('start', 'Should have a number start').optional().isInt() |
12 | req.checkParams('count', 'Should have a number count').optional().isInt() | 12 | req.checkQuery('count', 'Should have a number count').optional().isInt() |
13 | 13 | ||
14 | logger.debug('Checking pagination parameters', { parameters: req.params }) | 14 | logger.debug('Checking pagination parameters', { parameters: req.query }) |
15 | 15 | ||
16 | checkErrors(req, res, next) | 16 | checkErrors(req, res, next) |
17 | } | 17 | } |
diff --git a/server/middlewares/reqValidators/sort.js b/server/middlewares/reqValidators/sort.js new file mode 100644 index 000000000..06e680ef4 --- /dev/null +++ b/server/middlewares/reqValidators/sort.js | |||
@@ -0,0 +1,23 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const checkErrors = require('./utils').checkErrors | ||
4 | const constants = require('../../initializers/constants') | ||
5 | const logger = require('../../helpers/logger') | ||
6 | |||
7 | const reqValidatorsSort = { | ||
8 | videosSort: videosSort | ||
9 | } | ||
10 | |||
11 | function videosSort (req, res, next) { | ||
12 | const sortableColumns = constants.SORTABLE_COLUMNS.VIDEOS | ||
13 | |||
14 | req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns) | ||
15 | |||
16 | logger.debug('Checking sort parameters', { parameters: req.query }) | ||
17 | |||
18 | checkErrors(req, res, next) | ||
19 | } | ||
20 | |||
21 | // --------------------------------------------------------------------------- | ||
22 | |||
23 | module.exports = reqValidatorsSort | ||
diff --git a/server/middlewares/sort.js b/server/middlewares/sort.js new file mode 100644 index 000000000..9f52290a6 --- /dev/null +++ b/server/middlewares/sort.js | |||
@@ -0,0 +1,15 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const sortMiddleware = { | ||
4 | setVideosSort: setVideosSort | ||
5 | } | ||
6 | |||
7 | function setVideosSort (req, res, next) { | ||
8 | if (!req.query.sort) req.query.sort = '-createdDate' | ||
9 | |||
10 | return next() | ||
11 | } | ||
12 | |||
13 | // --------------------------------------------------------------------------- | ||
14 | |||
15 | module.exports = sortMiddleware | ||
diff --git a/server/models/videos.js b/server/models/videos.js index 250ad3952..9cac8edda 100644 --- a/server/models/videos.js +++ b/server/models/videos.js | |||
@@ -80,8 +80,9 @@ function get (id, callback) { | |||
80 | }) | 80 | }) |
81 | } | 81 | } |
82 | 82 | ||
83 | function list (start, count, callback) { | 83 | function list (start, count, sort, callback) { |
84 | VideosDB.find({}).skip(start).limit(start + count).exec(function (err, videosList) { | 84 | VideosDB.find({}).skip(start).limit(start + count).sort(sort) |
85 | .exec(function (err, videosList) { | ||
85 | if (err) { | 86 | if (err) { |
86 | logger.error('Cannot get the list of the videos.') | 87 | logger.error('Cannot get the list of the videos.') |
87 | return callback(err) | 88 | return callback(err) |
@@ -129,8 +130,8 @@ function removeByIds (ids, callback) { | |||
129 | VideosDB.remove({ _id: { $in: ids } }, callback) | 130 | VideosDB.remove({ _id: { $in: ids } }, callback) |
130 | } | 131 | } |
131 | 132 | ||
132 | function search (name, start, count, callback) { | 133 | function search (name, start, count, sort, callback) { |
133 | VideosDB.find({ name: new RegExp(name) }).skip(start).limit(start + count) | 134 | VideosDB.find({ name: new RegExp(name) }).skip(start).limit(start + count).sort(sort) |
134 | .exec(function (err, videos) { | 135 | .exec(function (err, videos) { |
135 | if (err) { | 136 | if (err) { |
136 | logger.error('Cannot search the videos.') | 137 | logger.error('Cannot search the videos.') |
diff --git a/server/tests/api/checkParams.js b/server/tests/api/checkParams.js index b63091910..a109aba47 100644 --- a/server/tests/api/checkParams.js +++ b/server/tests/api/checkParams.js | |||
@@ -130,6 +130,32 @@ describe('Test parameters validator', function () { | |||
130 | describe('Of the videos API', function () { | 130 | describe('Of the videos API', function () { |
131 | const path = '/api/v1/videos/' | 131 | const path = '/api/v1/videos/' |
132 | 132 | ||
133 | describe('When listing a video', function () { | ||
134 | it('Should fail with a bad start pagination', function (done) { | ||
135 | request(server.url) | ||
136 | .get(path) | ||
137 | .query({ start: 'hello' }) | ||
138 | .set('Accept', 'application/json') | ||
139 | .expect(400, done) | ||
140 | }) | ||
141 | |||
142 | it('Should fail with a bad count pagination', function (done) { | ||
143 | request(server.url) | ||
144 | .get(path) | ||
145 | .query({ count: 'hello' }) | ||
146 | .set('Accept', 'application/json') | ||
147 | .expect(400, done) | ||
148 | }) | ||
149 | |||
150 | it('Should fail with an incorrect sort', function (done) { | ||
151 | request(server.url) | ||
152 | .get(path) | ||
153 | .query({ sort: 'hello' }) | ||
154 | .set('Accept', 'application/json') | ||
155 | .expect(400, done) | ||
156 | }) | ||
157 | }) | ||
158 | |||
133 | describe('When searching a video', function () { | 159 | describe('When searching a video', function () { |
134 | it('Should fail with nothing', function (done) { | 160 | it('Should fail with nothing', function (done) { |
135 | request(server.url) | 161 | request(server.url) |
@@ -137,6 +163,30 @@ describe('Test parameters validator', function () { | |||
137 | .set('Accept', 'application/json') | 163 | .set('Accept', 'application/json') |
138 | .expect(400, done) | 164 | .expect(400, done) |
139 | }) | 165 | }) |
166 | |||
167 | it('Should fail with a bad start pagination', function (done) { | ||
168 | request(server.url) | ||
169 | .get(pathUtils.join(path, 'search', 'test')) | ||
170 | .query({ start: 'hello' }) | ||
171 | .set('Accept', 'application/json') | ||
172 | .expect(400, done) | ||
173 | }) | ||
174 | |||
175 | it('Should fail with a bad count pagination', function (done) { | ||
176 | request(server.url) | ||
177 | .get(pathUtils.join(path, 'search', 'test')) | ||
178 | .query({ count: 'hello' }) | ||
179 | .set('Accept', 'application/json') | ||
180 | .expect(400, done) | ||
181 | }) | ||
182 | |||
183 | it('Should fail with an incorrect sort', function (done) { | ||
184 | request(server.url) | ||
185 | .get(pathUtils.join(path, 'search', 'test')) | ||
186 | .query({ sort: 'hello' }) | ||
187 | .set('Accept', 'application/json') | ||
188 | .expect(400, done) | ||
189 | }) | ||
140 | }) | 190 | }) |
141 | 191 | ||
142 | describe('When adding a video', function () { | 192 | describe('When adding a video', function () { |
diff --git a/server/tests/api/singlePod.js b/server/tests/api/singlePod.js index 72002b631..1a53ada3a 100644 --- a/server/tests/api/singlePod.js +++ b/server/tests/api/singlePod.js | |||
@@ -314,6 +314,39 @@ describe('Test a single pod', function () { | |||
314 | }) | 314 | }) |
315 | }) | 315 | }) |
316 | 316 | ||
317 | it('Should list and sort by name in descending order', function (done) { | ||
318 | utils.getVideosListSort(server.url, '-name', function (err, res) { | ||
319 | if (err) throw err | ||
320 | |||
321 | const videos = res.body | ||
322 | expect(videos.length).to.equal(6) | ||
323 | expect(videos[5].name === 'video_short.mp4 name') | ||
324 | expect(videos[4].name === 'video_short.ogv name') | ||
325 | expect(videos[3].name === 'video_short.webm name') | ||
326 | expect(videos[2].name === 'video_short1.webm name') | ||
327 | expect(videos[1].name === 'video_short2.webm name') | ||
328 | expect(videos[0].name === 'video_short3.webm name') | ||
329 | |||
330 | done() | ||
331 | }) | ||
332 | }) | ||
333 | |||
334 | it('Should search and sort by name in ascending order', function (done) { | ||
335 | utils.searchVideoWithSort(server.url, 'webm', 'name', function (err, res) { | ||
336 | if (err) throw err | ||
337 | |||
338 | const videos = res.body | ||
339 | expect(videos.length).to.equal(4) | ||
340 | |||
341 | expect(videos[0].name === 'video_short.webm name') | ||
342 | expect(videos[1].name === 'video_short1.webm name') | ||
343 | expect(videos[2].name === 'video_short2.webm name') | ||
344 | expect(videos[3].name === 'video_short3.webm name') | ||
345 | |||
346 | done() | ||
347 | }) | ||
348 | }) | ||
349 | |||
317 | after(function (done) { | 350 | after(function (done) { |
318 | process.kill(-server.app.pid) | 351 | process.kill(-server.app.pid) |
319 | process.kill(-webtorrent.app.pid) | 352 | process.kill(-webtorrent.app.pid) |
diff --git a/server/tests/api/utils.js b/server/tests/api/utils.js index d505cb5d9..ac43946cd 100644 --- a/server/tests/api/utils.js +++ b/server/tests/api/utils.js | |||
@@ -14,6 +14,7 @@ const testUtils = { | |||
14 | getVideo: getVideo, | 14 | getVideo: getVideo, |
15 | getVideosList: getVideosList, | 15 | getVideosList: getVideosList, |
16 | getVideosListPagination: getVideosListPagination, | 16 | getVideosListPagination: getVideosListPagination, |
17 | getVideosListSort: getVideosListSort, | ||
17 | login: login, | 18 | login: login, |
18 | loginAndGetAccessToken: loginAndGetAccessToken, | 19 | loginAndGetAccessToken: loginAndGetAccessToken, |
19 | makeFriends: makeFriends, | 20 | makeFriends: makeFriends, |
@@ -23,6 +24,7 @@ const testUtils = { | |||
23 | runServer: runServer, | 24 | runServer: runServer, |
24 | searchVideo: searchVideo, | 25 | searchVideo: searchVideo, |
25 | searchVideoWithPagination: searchVideoWithPagination, | 26 | searchVideoWithPagination: searchVideoWithPagination, |
27 | searchVideoWithSort: searchVideoWithSort, | ||
26 | testImage: testImage, | 28 | testImage: testImage, |
27 | uploadVideo: uploadVideo | 29 | uploadVideo: uploadVideo |
28 | } | 30 | } |
@@ -89,6 +91,18 @@ function getVideosListPagination (url, start, count, end) { | |||
89 | .end(end) | 91 | .end(end) |
90 | } | 92 | } |
91 | 93 | ||
94 | function getVideosListSort (url, sort, end) { | ||
95 | const path = '/api/v1/videos' | ||
96 | |||
97 | request(url) | ||
98 | .get(path) | ||
99 | .query({ sort: sort }) | ||
100 | .set('Accept', 'application/json') | ||
101 | .expect(200) | ||
102 | .expect('Content-Type', /json/) | ||
103 | .end(end) | ||
104 | } | ||
105 | |||
92 | function login (url, client, user, expectedStatus, end) { | 106 | function login (url, client, user, expectedStatus, end) { |
93 | if (!end) { | 107 | if (!end) { |
94 | end = expectedStatus | 108 | end = expectedStatus |
@@ -300,6 +314,18 @@ function searchVideoWithPagination (url, search, start, count, end) { | |||
300 | .end(end) | 314 | .end(end) |
301 | } | 315 | } |
302 | 316 | ||
317 | function searchVideoWithSort (url, search, sort, end) { | ||
318 | const path = '/api/v1/videos' | ||
319 | |||
320 | request(url) | ||
321 | .get(path + '/search/' + search) | ||
322 | .query({ sort: sort }) | ||
323 | .set('Accept', 'application/json') | ||
324 | .expect(200) | ||
325 | .expect('Content-Type', /json/) | ||
326 | .end(end) | ||
327 | } | ||
328 | |||
303 | function testImage (url, videoName, imagePath, callback) { | 329 | function testImage (url, videoName, imagePath, callback) { |
304 | request(url) | 330 | request(url) |
305 | .get(imagePath) | 331 | .get(imagePath) |