From: Chocobozzz Date: Tue, 17 May 2016 19:03:00 +0000 (+0200) Subject: Add ability to sort videos list X-Git-Tag: v0.0.1-alpha~918 X-Git-Url: https://git.immae.eu/?a=commitdiff_plain;h=a877d5acc5c52b8667c65f725bbca9a52e40ec48;p=github%2FChocobozzz%2FPeerTube.git Add ability to sort videos list --- 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 const pagination = middlewares.pagination const reqValidator = middlewares.reqValidators const reqValidatorPagination = reqValidator.pagination +const reqValidatorSort = reqValidator.sort const reqValidatorVideos = reqValidator.videos +const sort = middlewares.sort const utils = require('../../../helpers/utils') const Videos = require('../../../models/videos') // model const videos = require('../../../lib/videos') @@ -47,6 +49,8 @@ const thumbnailsDir = path.join(__dirname, '..', '..', '..', '..', config.get('s router.get('/', reqValidatorPagination.pagination, + reqValidatorSort.videosSort, + sort.setVideosSort, pagination.setPagination, listVideos ) @@ -68,6 +72,8 @@ router.delete('/:id', router.get('/search/:name', reqValidatorVideos.videosSearch, reqValidatorPagination.pagination, + reqValidatorSort.videosSort, + sort.setVideosSort, pagination.setPagination, searchVideos ) @@ -173,7 +179,7 @@ function getVideos (req, res, next) { } function listVideos (req, res, next) { - Videos.list(req.query.start, req.query.count, function (err, videosList) { + Videos.list(req.query.start, req.query.count, req.query.sort, function (err, videosList) { if (err) return next(err) res.json(getFormatedVideos(videosList)) @@ -231,7 +237,7 @@ function removeVideo (req, res, next) { } function searchVideos (req, res, next) { - Videos.search(req.params.name, req.query.start, req.query.count, function (err, videosList) { + Videos.search(req.params.name, req.query.start, req.query.count, req.query.sort, function (err, videosList) { if (err) return next(err) 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 = { // Number of retries we make for the make retry requests (to friends...) let REQUEST_RETRIES = 10 +// Sortable columns per schema +const SORTABLE_COLUMNS = { + VIDEOS: [ 'name', '-name', 'duration', '-duration', 'createdDate', '-createdDate' ] +} + // Videos thumbnail size const THUMBNAILS_SIZE = '200x110' @@ -51,6 +56,7 @@ module.exports = { PAGINATION_COUNT_DEFAULT: PAGINATION_COUNT_DEFAULT, PODS_SCORE: PODS_SCORE, REQUEST_RETRIES: REQUEST_RETRIES, + SORTABLE_COLUMNS: SORTABLE_COLUMNS, THUMBNAILS_SIZE: THUMBNAILS_SIZE, THUMBNAILS_STATIC_PATH: THUMBNAILS_STATIC_PATH } 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 @@ const oauth2 = require('./oauth2') const pagination = require('./pagination') const reqValidatorsMiddleware = require('./reqValidators') +const sort = require('./sort') const secureMiddleware = require('./secure') const middlewares = { oauth2: oauth2, pagination: pagination, reqValidators: reqValidatorsMiddleware, + sort: sort, secure: secureMiddleware } 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 @@ const paginationReqValidators = require('./pagination') const podsReqValidators = require('./pods') const remoteReqValidators = require('./remote') +const sortReqValidators = require('./sort') const videosReqValidators = require('./videos') const reqValidators = { pagination: paginationReqValidators, pods: podsReqValidators, remote: remoteReqValidators, + sort: sortReqValidators, videos: videosReqValidators } 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 = { } function pagination (req, res, next) { - req.checkParams('start', 'Should have a number start').optional().isInt() - req.checkParams('count', 'Should have a number count').optional().isInt() + req.checkQuery('start', 'Should have a number start').optional().isInt() + req.checkQuery('count', 'Should have a number count').optional().isInt() - logger.debug('Checking pagination parameters', { parameters: req.params }) + logger.debug('Checking pagination parameters', { parameters: req.query }) checkErrors(req, res, next) } 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 @@ +'use strict' + +const checkErrors = require('./utils').checkErrors +const constants = require('../../initializers/constants') +const logger = require('../../helpers/logger') + +const reqValidatorsSort = { + videosSort: videosSort +} + +function videosSort (req, res, next) { + const sortableColumns = constants.SORTABLE_COLUMNS.VIDEOS + + 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 = 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 @@ +'use strict' + +const sortMiddleware = { + setVideosSort: setVideosSort +} + +function setVideosSort (req, res, next) { + if (!req.query.sort) req.query.sort = '-createdDate' + + return next() +} + +// --------------------------------------------------------------------------- + +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) { }) } -function list (start, count, callback) { - VideosDB.find({}).skip(start).limit(start + count).exec(function (err, videosList) { +function list (start, count, sort, callback) { + VideosDB.find({}).skip(start).limit(start + count).sort(sort) + .exec(function (err, videosList) { if (err) { logger.error('Cannot get the list of the videos.') return callback(err) @@ -129,8 +130,8 @@ function removeByIds (ids, callback) { VideosDB.remove({ _id: { $in: ids } }, callback) } -function search (name, start, count, callback) { - VideosDB.find({ name: new RegExp(name) }).skip(start).limit(start + count) +function search (name, start, count, sort, callback) { + VideosDB.find({ name: new RegExp(name) }).skip(start).limit(start + count).sort(sort) .exec(function (err, videos) { if (err) { 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 () { describe('Of the videos API', function () { const path = '/api/v1/videos/' + describe('When listing a video', function () { + it('Should fail with a bad start pagination', function (done) { + request(server.url) + .get(path) + .query({ start: 'hello' }) + .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') + .expect(400, done) + }) + + it('Should fail with an incorrect sort', function (done) { + request(server.url) + .get(path) + .query({ sort: 'hello' }) + .set('Accept', 'application/json') + .expect(400, done) + }) + }) + describe('When searching a video', function () { it('Should fail with nothing', function (done) { request(server.url) @@ -137,6 +163,30 @@ describe('Test parameters validator', function () { .set('Accept', 'application/json') .expect(400, done) }) + + it('Should fail with a bad start pagination', function (done) { + request(server.url) + .get(pathUtils.join(path, 'search', 'test')) + .query({ start: 'hello' }) + .set('Accept', 'application/json') + .expect(400, done) + }) + + it('Should fail with a bad count pagination', function (done) { + request(server.url) + .get(pathUtils.join(path, 'search', 'test')) + .query({ count: 'hello' }) + .set('Accept', 'application/json') + .expect(400, done) + }) + + it('Should fail with an incorrect sort', function (done) { + request(server.url) + .get(pathUtils.join(path, 'search', 'test')) + .query({ sort: 'hello' }) + .set('Accept', 'application/json') + .expect(400, done) + }) }) 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 () { }) }) + it('Should list and sort by name in descending order', function (done) { + utils.getVideosListSort(server.url, '-name', function (err, res) { + if (err) throw err + + const videos = res.body + expect(videos.length).to.equal(6) + expect(videos[5].name === 'video_short.mp4 name') + expect(videos[4].name === 'video_short.ogv name') + expect(videos[3].name === 'video_short.webm name') + expect(videos[2].name === 'video_short1.webm name') + expect(videos[1].name === 'video_short2.webm name') + expect(videos[0].name === 'video_short3.webm name') + + done() + }) + }) + + it('Should search and sort by name in ascending order', function (done) { + utils.searchVideoWithSort(server.url, 'webm', 'name', function (err, res) { + if (err) throw err + + const videos = res.body + expect(videos.length).to.equal(4) + + expect(videos[0].name === 'video_short.webm name') + expect(videos[1].name === 'video_short1.webm name') + expect(videos[2].name === 'video_short2.webm name') + expect(videos[3].name === 'video_short3.webm name') + + done() + }) + }) + after(function (done) { process.kill(-server.app.pid) 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 = { getVideo: getVideo, getVideosList: getVideosList, getVideosListPagination: getVideosListPagination, + getVideosListSort: getVideosListSort, login: login, loginAndGetAccessToken: loginAndGetAccessToken, makeFriends: makeFriends, @@ -23,6 +24,7 @@ const testUtils = { runServer: runServer, searchVideo: searchVideo, searchVideoWithPagination: searchVideoWithPagination, + searchVideoWithSort: searchVideoWithSort, testImage: testImage, uploadVideo: uploadVideo } @@ -89,6 +91,18 @@ function getVideosListPagination (url, start, count, end) { .end(end) } +function getVideosListSort (url, sort, end) { + const path = '/api/v1/videos' + + request(url) + .get(path) + .query({ sort: sort }) + .set('Accept', 'application/json') + .expect(200) + .expect('Content-Type', /json/) + .end(end) +} + function login (url, client, user, expectedStatus, end) { if (!end) { end = expectedStatus @@ -300,6 +314,18 @@ function searchVideoWithPagination (url, search, start, count, end) { .end(end) } +function searchVideoWithSort (url, search, sort, end) { + const path = '/api/v1/videos' + + request(url) + .get(path + '/search/' + search) + .query({ sort: sort }) + .set('Accept', 'application/json') + .expect(200) + .expect('Content-Type', /json/) + .end(end) +} + function testImage (url, videoName, imagePath, callback) { request(url) .get(imagePath)