diff options
-rw-r--r-- | server/controllers/api/v1/videos.js | 7 | ||||
-rw-r--r-- | server/initializers/constants.js | 6 | ||||
-rw-r--r-- | server/middlewares/index.js | 2 | ||||
-rw-r--r-- | server/middlewares/reqValidators/videos.js | 4 | ||||
-rw-r--r-- | server/middlewares/search.js | 15 | ||||
-rw-r--r-- | server/models/videos.js | 11 | ||||
-rw-r--r-- | server/tests/api/singlePod.js | 99 | ||||
-rw-r--r-- | server/tests/api/utils.js | 25 |
8 files changed, 149 insertions, 20 deletions
diff --git a/server/controllers/api/v1/videos.js b/server/controllers/api/v1/videos.js index f7aeea453..7f59dd232 100644 --- a/server/controllers/api/v1/videos.js +++ b/server/controllers/api/v1/videos.js | |||
@@ -17,6 +17,7 @@ const reqValidator = middlewares.reqValidators | |||
17 | const reqValidatorPagination = reqValidator.pagination | 17 | const reqValidatorPagination = reqValidator.pagination |
18 | const reqValidatorSort = reqValidator.sort | 18 | const reqValidatorSort = reqValidator.sort |
19 | const reqValidatorVideos = reqValidator.videos | 19 | const reqValidatorVideos = reqValidator.videos |
20 | const search = middlewares.search | ||
20 | const sort = middlewares.sort | 21 | const sort = middlewares.sort |
21 | const utils = require('../../../helpers/utils') | 22 | const utils = require('../../../helpers/utils') |
22 | const Videos = require('../../../models/videos') // model | 23 | const Videos = require('../../../models/videos') // model |
@@ -69,12 +70,13 @@ router.delete('/:id', | |||
69 | reqValidatorVideos.videosRemove, | 70 | reqValidatorVideos.videosRemove, |
70 | removeVideo | 71 | removeVideo |
71 | ) | 72 | ) |
72 | router.get('/search/:name', | 73 | router.get('/search/:value', |
73 | reqValidatorVideos.videosSearch, | 74 | reqValidatorVideos.videosSearch, |
74 | reqValidatorPagination.pagination, | 75 | reqValidatorPagination.pagination, |
75 | reqValidatorSort.videosSort, | 76 | reqValidatorSort.videosSort, |
76 | sort.setVideosSort, | 77 | sort.setVideosSort, |
77 | pagination.setPagination, | 78 | pagination.setPagination, |
79 | search.setVideosSearch, | ||
78 | searchVideos | 80 | searchVideos |
79 | ) | 81 | ) |
80 | 82 | ||
@@ -237,7 +239,8 @@ function removeVideo (req, res, next) { | |||
237 | } | 239 | } |
238 | 240 | ||
239 | function searchVideos (req, res, next) { | 241 | function searchVideos (req, res, next) { |
240 | Videos.search(req.params.name, req.query.start, req.query.count, req.query.sort, function (err, videosList, totalVideos) { | 242 | Videos.search(req.params.value, req.query.field, req.query.start, req.query.count, req.query.sort, |
243 | function (err, videosList, totalVideos) { | ||
241 | if (err) return next(err) | 244 | if (err) return next(err) |
242 | 245 | ||
243 | res.json(getFormatedVideos(videosList, totalVideos)) | 246 | res.json(getFormatedVideos(videosList, totalVideos)) |
diff --git a/server/initializers/constants.js b/server/initializers/constants.js index 4350bb892..c190ab506 100644 --- a/server/initializers/constants.js +++ b/server/initializers/constants.js | |||
@@ -27,6 +27,11 @@ const PODS_SCORE = { | |||
27 | let REQUEST_RETRIES = 10 | 27 | let REQUEST_RETRIES = 10 |
28 | 28 | ||
29 | // Sortable columns per schema | 29 | // Sortable columns per schema |
30 | const SEARCHABLE_COLUMNS = { | ||
31 | VIDEOS: [ 'name', 'magnetUri', 'podUrl', 'author' ] | ||
32 | } | ||
33 | |||
34 | // Sortable columns per schema | ||
30 | const SORTABLE_COLUMNS = { | 35 | const SORTABLE_COLUMNS = { |
31 | VIDEOS: [ 'name', '-name', 'duration', '-duration', 'createdDate', '-createdDate' ] | 36 | VIDEOS: [ 'name', '-name', 'duration', '-duration', 'createdDate', '-createdDate' ] |
32 | } | 37 | } |
@@ -56,6 +61,7 @@ module.exports = { | |||
56 | PAGINATION_COUNT_DEFAULT: PAGINATION_COUNT_DEFAULT, | 61 | PAGINATION_COUNT_DEFAULT: PAGINATION_COUNT_DEFAULT, |
57 | PODS_SCORE: PODS_SCORE, | 62 | PODS_SCORE: PODS_SCORE, |
58 | REQUEST_RETRIES: REQUEST_RETRIES, | 63 | REQUEST_RETRIES: REQUEST_RETRIES, |
64 | SEARCHABLE_COLUMNS: SEARCHABLE_COLUMNS, | ||
59 | SORTABLE_COLUMNS: SORTABLE_COLUMNS, | 65 | SORTABLE_COLUMNS: SORTABLE_COLUMNS, |
60 | THUMBNAILS_SIZE: THUMBNAILS_SIZE, | 66 | THUMBNAILS_SIZE: THUMBNAILS_SIZE, |
61 | THUMBNAILS_STATIC_PATH: THUMBNAILS_STATIC_PATH | 67 | THUMBNAILS_STATIC_PATH: THUMBNAILS_STATIC_PATH |
diff --git a/server/middlewares/index.js b/server/middlewares/index.js index 35858da2c..b30a7be56 100644 --- a/server/middlewares/index.js +++ b/server/middlewares/index.js | |||
@@ -3,6 +3,7 @@ | |||
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 search = require('./search') | ||
6 | const sort = require('./sort') | 7 | const sort = require('./sort') |
7 | const secureMiddleware = require('./secure') | 8 | const secureMiddleware = require('./secure') |
8 | 9 | ||
@@ -10,6 +11,7 @@ const middlewares = { | |||
10 | oauth2: oauth2, | 11 | oauth2: oauth2, |
11 | pagination: pagination, | 12 | pagination: pagination, |
12 | reqValidators: reqValidatorsMiddleware, | 13 | reqValidators: reqValidatorsMiddleware, |
14 | search: search, | ||
13 | sort: sort, | 15 | sort: sort, |
14 | secure: secureMiddleware | 16 | secure: secureMiddleware |
15 | } | 17 | } |
diff --git a/server/middlewares/reqValidators/videos.js b/server/middlewares/reqValidators/videos.js index d4dec1a59..d444c9f0a 100644 --- a/server/middlewares/reqValidators/videos.js +++ b/server/middlewares/reqValidators/videos.js | |||
@@ -81,7 +81,9 @@ function videosRemove (req, res, next) { | |||
81 | } | 81 | } |
82 | 82 | ||
83 | function videosSearch (req, res, next) { | 83 | function videosSearch (req, res, next) { |
84 | req.checkParams('name', 'Should have a name').notEmpty() | 84 | const searchableColumns = constants.SEARCHABLE_COLUMNS.VIDEOS |
85 | req.checkParams('value', 'Should have a name').notEmpty() | ||
86 | req.checkQuery('field', 'Should have correct searchable column').optional().isIn(searchableColumns) | ||
85 | 87 | ||
86 | logger.debug('Checking videosSearch parameters', { parameters: req.params }) | 88 | logger.debug('Checking videosSearch parameters', { parameters: req.params }) |
87 | 89 | ||
diff --git a/server/middlewares/search.js b/server/middlewares/search.js new file mode 100644 index 000000000..89302a564 --- /dev/null +++ b/server/middlewares/search.js | |||
@@ -0,0 +1,15 @@ | |||
1 | 'use strict' | ||
2 | |||
3 | const searchMiddleware = { | ||
4 | setVideosSearch: setVideosSearch | ||
5 | } | ||
6 | |||
7 | function setVideosSearch (req, res, next) { | ||
8 | if (!req.query.field) req.query.field = 'name' | ||
9 | |||
10 | return next() | ||
11 | } | ||
12 | |||
13 | // --------------------------------------------------------------------------- | ||
14 | |||
15 | module.exports = searchMiddleware | ||
diff --git a/server/models/videos.js b/server/models/videos.js index 9521e63e3..7bd41f7ee 100644 --- a/server/models/videos.js +++ b/server/models/videos.js | |||
@@ -124,8 +124,15 @@ function removeByIds (ids, callback) { | |||
124 | VideosDB.remove({ _id: { $in: ids } }, callback) | 124 | VideosDB.remove({ _id: { $in: ids } }, callback) |
125 | } | 125 | } |
126 | 126 | ||
127 | function search (name, start, count, sort, callback) { | 127 | function search (value, field, start, count, sort, callback) { |
128 | const query = { name: new RegExp(name) } | 128 | const query = {} |
129 | // Make an exact search with the magnet | ||
130 | if (field === 'magnetUri') { | ||
131 | query[field] = value | ||
132 | } else { | ||
133 | query[field] = new RegExp(value) | ||
134 | } | ||
135 | |||
129 | findWithCount(query, start, count, sort, callback) | 136 | findWithCount(query, start, count, sort, callback) |
130 | } | 137 | } |
131 | 138 | ||
diff --git a/server/tests/api/singlePod.js b/server/tests/api/singlePod.js index 884a83032..296dd0aa4 100644 --- a/server/tests/api/singlePod.js +++ b/server/tests/api/singlePod.js | |||
@@ -129,7 +129,7 @@ describe('Test a single pod', function () { | |||
129 | }) | 129 | }) |
130 | }) | 130 | }) |
131 | 131 | ||
132 | it('Should search the video', function (done) { | 132 | it('Should search the video by name by default', function (done) { |
133 | utils.searchVideo(server.url, 'my', function (err, res) { | 133 | utils.searchVideo(server.url, 'my', function (err, res) { |
134 | if (err) throw err | 134 | if (err) throw err |
135 | 135 | ||
@@ -154,7 +154,32 @@ describe('Test a single pod', function () { | |||
154 | }) | 154 | }) |
155 | }) | 155 | }) |
156 | 156 | ||
157 | it('Should not find a search', function (done) { | 157 | it('Should search the video by podUrl', function (done) { |
158 | utils.searchVideo(server.url, '9001', 'podUrl', function (err, res) { | ||
159 | if (err) throw err | ||
160 | |||
161 | expect(res.body.total).to.equal(1) | ||
162 | expect(res.body.data).to.be.an('array') | ||
163 | expect(res.body.data.length).to.equal(1) | ||
164 | |||
165 | const video = res.body.data[0] | ||
166 | expect(video.name).to.equal('my super name') | ||
167 | expect(video.description).to.equal('my super description') | ||
168 | expect(video.podUrl).to.equal('localhost:9001') | ||
169 | expect(video.author).to.equal('root') | ||
170 | expect(video.isLocal).to.be.true | ||
171 | expect(utils.dateIsValid(video.createdDate)).to.be.true | ||
172 | |||
173 | utils.testImage(server.url, 'video_short.webm', video.thumbnailPath, function (err, test) { | ||
174 | if (err) throw err | ||
175 | expect(test).to.equal(true) | ||
176 | |||
177 | done() | ||
178 | }) | ||
179 | }) | ||
180 | }) | ||
181 | |||
182 | it('Should not find a search by name by default', function (done) { | ||
158 | utils.searchVideo(server.url, 'hello', function (err, res) { | 183 | utils.searchVideo(server.url, 'hello', function (err, res) { |
159 | if (err) throw err | 184 | if (err) throw err |
160 | 185 | ||
@@ -166,6 +191,18 @@ describe('Test a single pod', function () { | |||
166 | }) | 191 | }) |
167 | }) | 192 | }) |
168 | 193 | ||
194 | it('Should not find a search by author', function (done) { | ||
195 | utils.searchVideo(server.url, 'hello', 'author', function (err, res) { | ||
196 | if (err) throw err | ||
197 | |||
198 | expect(res.body.total).to.equal(0) | ||
199 | expect(res.body.data).to.be.an('array') | ||
200 | expect(res.body.data.length).to.equal(0) | ||
201 | |||
202 | done() | ||
203 | }) | ||
204 | }) | ||
205 | |||
169 | it('Should remove the video', function (done) { | 206 | it('Should remove the video', function (done) { |
170 | utils.removeVideo(server.url, server.accessToken, videoId, function (err) { | 207 | utils.removeVideo(server.url, server.accessToken, videoId, function (err) { |
171 | if (err) throw err | 208 | if (err) throw err |
@@ -288,7 +325,7 @@ describe('Test a single pod', function () { | |||
288 | }) | 325 | }) |
289 | 326 | ||
290 | it('Should search the first video', function (done) { | 327 | it('Should search the first video', function (done) { |
291 | utils.searchVideoWithPagination(server.url, 'webm', 0, 1, function (err, res) { | 328 | utils.searchVideoWithPagination(server.url, 'webm', 'name', 0, 1, function (err, res) { |
292 | if (err) throw err | 329 | if (err) throw err |
293 | 330 | ||
294 | const videos = res.body.data | 331 | const videos = res.body.data |
@@ -301,7 +338,7 @@ describe('Test a single pod', function () { | |||
301 | }) | 338 | }) |
302 | 339 | ||
303 | it('Should search the last two videos', function (done) { | 340 | it('Should search the last two videos', function (done) { |
304 | utils.searchVideoWithPagination(server.url, 'webm', 2, 2, function (err, res) { | 341 | utils.searchVideoWithPagination(server.url, 'webm', 'name', 2, 2, function (err, res) { |
305 | if (err) throw err | 342 | if (err) throw err |
306 | 343 | ||
307 | const videos = res.body.data | 344 | const videos = res.body.data |
@@ -314,8 +351,8 @@ describe('Test a single pod', function () { | |||
314 | }) | 351 | }) |
315 | }) | 352 | }) |
316 | 353 | ||
317 | it('Should search all the videos', function (done) { | 354 | it('Should search all the webm videos', function (done) { |
318 | utils.searchVideoWithPagination(server.url, 'webm', 0, 15, function (err, res) { | 355 | utils.searchVideoWithPagination(server.url, 'webm', 'name', 0, 15, function (err, res) { |
319 | if (err) throw err | 356 | if (err) throw err |
320 | 357 | ||
321 | const videos = res.body.data | 358 | const videos = res.body.data |
@@ -326,6 +363,56 @@ describe('Test a single pod', function () { | |||
326 | }) | 363 | }) |
327 | }) | 364 | }) |
328 | 365 | ||
366 | it('Should search all the root author videos', function (done) { | ||
367 | utils.searchVideoWithPagination(server.url, 'root', 'author', 0, 15, function (err, res) { | ||
368 | if (err) throw err | ||
369 | |||
370 | const videos = res.body.data | ||
371 | expect(res.body.total).to.equal(6) | ||
372 | expect(videos.length).to.equal(6) | ||
373 | |||
374 | done() | ||
375 | }) | ||
376 | }) | ||
377 | |||
378 | it('Should search all the 9001 port videos', function (done) { | ||
379 | utils.searchVideoWithPagination(server.url, '9001', 'podUrl', 0, 15, function (err, res) { | ||
380 | if (err) throw err | ||
381 | |||
382 | const videos = res.body.data | ||
383 | expect(res.body.total).to.equal(6) | ||
384 | expect(videos.length).to.equal(6) | ||
385 | |||
386 | done() | ||
387 | }) | ||
388 | }) | ||
389 | |||
390 | it('Should search all the localhost videos', function (done) { | ||
391 | utils.searchVideoWithPagination(server.url, 'localhost', 'podUrl', 0, 15, function (err, res) { | ||
392 | if (err) throw err | ||
393 | |||
394 | const videos = res.body.data | ||
395 | expect(res.body.total).to.equal(6) | ||
396 | expect(videos.length).to.equal(6) | ||
397 | |||
398 | done() | ||
399 | }) | ||
400 | }) | ||
401 | |||
402 | it('Should search the good magnetUri video', function (done) { | ||
403 | const video = videosListBase[0] | ||
404 | utils.searchVideoWithPagination(server.url, encodeURIComponent(video.magnetUri), 'magnetUri', 0, 15, function (err, res) { | ||
405 | if (err) throw err | ||
406 | |||
407 | const videos = res.body.data | ||
408 | expect(res.body.total).to.equal(1) | ||
409 | expect(videos.length).to.equal(1) | ||
410 | expect(videos[0].name).to.equal(video.name) | ||
411 | |||
412 | done() | ||
413 | }) | ||
414 | }) | ||
415 | |||
329 | it('Should list and sort by name in descending order', function (done) { | 416 | it('Should list and sort by name in descending order', function (done) { |
330 | utils.getVideosListSort(server.url, '-name', function (err, res) { | 417 | utils.getVideosListSort(server.url, '-name', function (err, res) { |
331 | if (err) throw err | 418 | if (err) throw err |
diff --git a/server/tests/api/utils.js b/server/tests/api/utils.js index 218b46157..c6430c930 100644 --- a/server/tests/api/utils.js +++ b/server/tests/api/utils.js | |||
@@ -291,24 +291,31 @@ function runServer (number, callback) { | |||
291 | }) | 291 | }) |
292 | } | 292 | } |
293 | 293 | ||
294 | function searchVideo (url, search, end) { | 294 | function searchVideo (url, search, field, end) { |
295 | const path = '/api/v1/videos' | 295 | if (!end) { |
296 | end = field | ||
297 | field = null | ||
298 | } | ||
296 | 299 | ||
297 | request(url) | 300 | const path = '/api/v1/videos' |
298 | .get(path + '/search/' + search) | 301 | const req = request(url) |
299 | .set('Accept', 'application/json') | 302 | .get(path + '/search/' + search) |
300 | .expect(200) | 303 | .set('Accept', 'application/json') |
301 | .expect('Content-Type', /json/) | 304 | |
302 | .end(end) | 305 | if (field) req.query({ field: field }) |
306 | req.expect(200) | ||
307 | .expect('Content-Type', /json/) | ||
308 | .end(end) | ||
303 | } | 309 | } |
304 | 310 | ||
305 | function searchVideoWithPagination (url, search, start, count, end) { | 311 | function searchVideoWithPagination (url, search, field, start, count, end) { |
306 | const path = '/api/v1/videos' | 312 | const path = '/api/v1/videos' |
307 | 313 | ||
308 | request(url) | 314 | request(url) |
309 | .get(path + '/search/' + search) | 315 | .get(path + '/search/' + search) |
310 | .query({ start: start }) | 316 | .query({ start: start }) |
311 | .query({ count: count }) | 317 | .query({ count: count }) |
318 | .query({ field: field }) | ||
312 | .set('Accept', 'application/json') | 319 | .set('Accept', 'application/json') |
313 | .expect(200) | 320 | .expect(200) |
314 | .expect('Content-Type', /json/) | 321 | .expect('Content-Type', /json/) |