aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2016-12-29 19:07:05 +0100
committerChocobozzz <florian.bigard@gmail.com>2016-12-29 19:07:05 +0100
commit7b1f49de22c40ae121ddb3c399b2540ba56fd414 (patch)
tree269e5dc7c2ebe4147319f1ee8e8b7f3c74549149
parent4ff0d86208dafbdd07beb6286fd93c795db8a95f (diff)
downloadPeerTube-7b1f49de22c40ae121ddb3c399b2540ba56fd414.tar.gz
PeerTube-7b1f49de22c40ae121ddb3c399b2540ba56fd414.tar.zst
PeerTube-7b1f49de22c40ae121ddb3c399b2540ba56fd414.zip
Server: add ability to update a video
-rw-r--r--server/controllers/api/videos.js85
-rw-r--r--server/lib/friends.js7
-rw-r--r--server/middlewares/validators/videos.js41
-rw-r--r--server/models/video.js21
-rw-r--r--server/tests/api/check-params.js101
-rw-r--r--server/tests/api/single-pod.js76
-rw-r--r--server/tests/utils/videos.js28
7 files changed, 344 insertions, 15 deletions
diff --git a/server/controllers/api/videos.js b/server/controllers/api/videos.js
index f29edac74..1b306d1cf 100644
--- a/server/controllers/api/videos.js
+++ b/server/controllers/api/videos.js
@@ -50,6 +50,12 @@ router.get('/',
50 pagination.setPagination, 50 pagination.setPagination,
51 listVideos 51 listVideos
52) 52)
53router.put('/:id',
54 oAuth.authenticate,
55 reqFiles,
56 validatorsVideos.videosUpdate,
57 updateVideo
58)
53router.post('/', 59router.post('/',
54 oAuth.authenticate, 60 oAuth.authenticate,
55 reqFiles, 61 reqFiles,
@@ -165,7 +171,7 @@ function addVideo (req, res, next) {
165 }, 171 },
166 172
167 function sendToFriends (t, video, callback) { 173 function sendToFriends (t, video, callback) {
168 video.toRemoteJSON(function (err, remoteVideo) { 174 video.toAddRemoteJSON(function (err, remoteVideo) {
169 if (err) return callback(err) 175 if (err) return callback(err)
170 176
171 // Now we'll add the video's meta data to our friends 177 // Now we'll add the video's meta data to our friends
@@ -193,6 +199,83 @@ function addVideo (req, res, next) {
193 }) 199 })
194} 200}
195 201
202function updateVideo (req, res, next) {
203 let videoInstance = res.locals.video
204 const videoInfosToUpdate = req.body
205
206 waterfall([
207
208 function startTransaction (callback) {
209 db.sequelize.transaction().asCallback(function (err, t) {
210 return callback(err, t)
211 })
212 },
213
214 function findOrCreateTags (t, callback) {
215 if (videoInfosToUpdate.tags) {
216 db.Tag.findOrCreateTags(videoInfosToUpdate.tags, t, function (err, tagInstances) {
217 return callback(err, t, tagInstances)
218 })
219 } else {
220 return callback(null, t, null)
221 }
222 },
223
224 function updateVideoIntoDB (t, tagInstances, callback) {
225 const options = { transaction: t }
226
227 if (videoInfosToUpdate.name) videoInstance.set('name', videoInfosToUpdate.name)
228 if (videoInfosToUpdate.description) videoInstance.set('description', videoInfosToUpdate.description)
229
230 // Add tags association
231 videoInstance.save(options).asCallback(function (err) {
232 if (err) return callback(err)
233
234 return callback(err, t, tagInstances)
235 })
236 },
237
238 function associateTagsToVideo (t, tagInstances, callback) {
239 if (tagInstances) {
240 const options = { transaction: t }
241
242 videoInstance.setTags(tagInstances, options).asCallback(function (err) {
243 videoInstance.Tags = tagInstances
244
245 return callback(err, t)
246 })
247 } else {
248 return callback(null, t)
249 }
250 },
251
252 function sendToFriends (t, callback) {
253 const json = videoInstance.toUpdateRemoteJSON()
254
255 // Now we'll update the video's meta data to our friends
256 friends.updateVideoToFriends(json)
257
258 return callback(null, t)
259 }
260
261 ], function andFinally (err, t) {
262 if (err) {
263 logger.error('Cannot insert the video.')
264
265 // Abort transaction?
266 if (t) t.rollback()
267
268 return next(err)
269 }
270
271 // Commit transaction
272 t.commit()
273
274 // TODO : include Location of the new video -> 201
275 return res.type('json').status(204).end()
276 })
277}
278
196function getVideo (req, res, next) { 279function getVideo (req, res, next) {
197 db.Video.loadAndPopulateAuthorAndPodAndTags(req.params.id, function (err, video) { 280 db.Video.loadAndPopulateAuthorAndPodAndTags(req.params.id, function (err, video) {
198 if (err) return next(err) 281 if (err) return next(err)
diff --git a/server/lib/friends.js b/server/lib/friends.js
index ad9e4fdae..589b79660 100644
--- a/server/lib/friends.js
+++ b/server/lib/friends.js
@@ -14,6 +14,7 @@ const requests = require('../helpers/requests')
14 14
15const friends = { 15const friends = {
16 addVideoToFriends, 16 addVideoToFriends,
17 updateVideoToFriends,
17 hasFriends, 18 hasFriends,
18 getMyCertificate, 19 getMyCertificate,
19 makeFriends, 20 makeFriends,
@@ -26,6 +27,10 @@ function addVideoToFriends (video) {
26 createRequest('add', constants.REQUEST_ENDPOINTS.VIDEOS, video) 27 createRequest('add', constants.REQUEST_ENDPOINTS.VIDEOS, video)
27} 28}
28 29
30function updateVideoToFriends (video) {
31 createRequest('update', constants.REQUEST_ENDPOINTS.VIDEOS, video)
32}
33
29function hasFriends (callback) { 34function hasFriends (callback) {
30 db.Pod.countAll(function (err, count) { 35 db.Pod.countAll(function (err, count) {
31 if (err) return callback(err) 36 if (err) return callback(err)
@@ -127,7 +132,7 @@ function sendOwnedVideosToPod (podId) {
127 } 132 }
128 133
129 videosList.forEach(function (video) { 134 videosList.forEach(function (video) {
130 video.toRemoteJSON(function (err, remoteVideo) { 135 video.toAddRemoteJSON(function (err, remoteVideo) {
131 if (err) { 136 if (err) {
132 logger.error('Cannot convert video to remote.', { error: err }) 137 logger.error('Cannot convert video to remote.', { error: err })
133 // Don't break the process 138 // Don't break the process
diff --git a/server/middlewares/validators/videos.js b/server/middlewares/validators/videos.js
index 7e90ca047..09a188c76 100644
--- a/server/middlewares/validators/videos.js
+++ b/server/middlewares/validators/videos.js
@@ -8,6 +8,7 @@ const logger = require('../../helpers/logger')
8 8
9const validatorsVideos = { 9const validatorsVideos = {
10 videosAdd, 10 videosAdd,
11 videosUpdate,
11 videosGet, 12 videosGet,
12 videosRemove, 13 videosRemove,
13 videosSearch 14 videosSearch
@@ -41,22 +42,26 @@ function videosAdd (req, res, next) {
41 }) 42 })
42} 43}
43 44
44function videosGet (req, res, next) { 45function videosUpdate (req, res, next) {
45 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4) 46 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
47 req.checkBody('name', 'Should have a valid name').optional().isVideoNameValid()
48 req.checkBody('description', 'Should have a valid description').optional().isVideoDescriptionValid()
49 req.checkBody('tags', 'Should have correct tags').optional().isVideoTagsValid()
46 50
47 logger.debug('Checking videosGet parameters', { parameters: req.params }) 51 logger.debug('Checking videosUpdate parameters', { parameters: req.body })
48 52
49 checkErrors(req, res, function () { 53 checkErrors(req, res, function () {
50 db.Video.load(req.params.id, function (err, video) { 54 checkVideoExists(req.params.id, res, next)
51 if (err) { 55 })
52 logger.error('Error in videosGet request validator.', { error: err }) 56}
53 return res.sendStatus(500)
54 }
55 57
56 if (!video) return res.status(404).send('Video not found') 58function videosGet (req, res, next) {
59 req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
57 60
58 next() 61 logger.debug('Checking videosGet parameters', { parameters: req.params })
59 }) 62
63 checkErrors(req, res, function () {
64 checkVideoExists(req.params.id, res, next)
60 }) 65 })
61} 66}
62 67
@@ -94,3 +99,19 @@ function videosSearch (req, res, next) {
94// --------------------------------------------------------------------------- 99// ---------------------------------------------------------------------------
95 100
96module.exports = validatorsVideos 101module.exports = validatorsVideos
102
103// ---------------------------------------------------------------------------
104
105function checkVideoExists (id, res, callback) {
106 db.Video.loadAndPopulateAuthorAndPodAndTags(id, function (err, video) {
107 if (err) {
108 logger.error('Error in video request validator.', { error: err })
109 return res.sendStatus(500)
110 }
111
112 if (!video) return res.status(404).send('Video not found')
113
114 res.locals.video = video
115 callback()
116 })
117}
diff --git a/server/models/video.js b/server/models/video.js
index 0e84e8986..14fbe2f71 100644
--- a/server/models/video.js
+++ b/server/models/video.js
@@ -127,7 +127,8 @@ module.exports = function (sequelize, DataTypes) {
127 getTorrentName, 127 getTorrentName,
128 isOwned, 128 isOwned,
129 toFormatedJSON, 129 toFormatedJSON,
130 toRemoteJSON 130 toAddRemoteJSON,
131 toUpdateRemoteJSON
131 }, 132 },
132 hooks: { 133 hooks: {
133 beforeValidate, 134 beforeValidate,
@@ -334,7 +335,7 @@ function toFormatedJSON () {
334 return json 335 return json
335} 336}
336 337
337function toRemoteJSON (callback) { 338function toAddRemoteJSON (callback) {
338 const self = this 339 const self = this
339 340
340 // Get thumbnail data to send to the other pod 341 // Get thumbnail data to send to the other pod
@@ -362,6 +363,22 @@ function toRemoteJSON (callback) {
362 }) 363 })
363} 364}
364 365
366function toUpdateRemoteJSON (callback) {
367 const json = {
368 name: this.name,
369 description: this.description,
370 infoHash: this.infoHash,
371 remoteId: this.id,
372 author: this.Author.name,
373 duration: this.duration,
374 tags: map(this.Tags, 'name'),
375 createdAt: this.createdAt,
376 extname: this.extname
377 }
378
379 return json
380}
381
365// ------------------------------ STATICS ------------------------------ 382// ------------------------------ STATICS ------------------------------
366 383
367function generateThumbnailFromData (video, thumbnailData, callback) { 384function generateThumbnailFromData (video, thumbnailData, callback) {
diff --git a/server/tests/api/check-params.js b/server/tests/api/check-params.js
index 9aecc3720..e8f2aa821 100644
--- a/server/tests/api/check-params.js
+++ b/server/tests/api/check-params.js
@@ -10,6 +10,7 @@ const loginUtils = require('../utils/login')
10const requestsUtils = require('../utils/requests') 10const requestsUtils = require('../utils/requests')
11const serversUtils = require('../utils/servers') 11const serversUtils = require('../utils/servers')
12const usersUtils = require('../utils/users') 12const usersUtils = require('../utils/users')
13const videosUtils = require('../utils/videos')
13 14
14describe('Test parameters validator', function () { 15describe('Test parameters validator', function () {
15 let server = null 16 let server = null
@@ -439,6 +440,106 @@ describe('Test parameters validator', function () {
439 }) 440 })
440 }) 441 })
441 442
443 describe('When updating a video', function () {
444 let videoId
445
446 before(function (done) {
447 videosUtils.getVideosList(server.url, function (err, res) {
448 if (err) throw err
449
450 videoId = res.body.data[0].id
451
452 return done()
453 })
454 })
455
456 it('Should fail with nothing', function (done) {
457 const data = {}
458 requestsUtils.makePutBodyRequest(server.url, path + videoId, server.accessToken, data, done)
459 })
460
461 it('Should fail without a valid uuid', function (done) {
462 const data = {
463 description: 'my super description',
464 tags: [ 'tag1', 'tag2' ]
465 }
466 requestsUtils.makePutBodyRequest(server.url, path + 'blabla', server.accessToken, data, done)
467 })
468
469 it('Should fail with an unknown id', function (done) {
470 const data = {
471 description: 'my super description',
472 tags: [ 'tag1', 'tag2' ]
473 }
474 requestsUtils.makePutBodyRequest(server.url, path + '4da6fde3-88f7-4d16-b119-108df5630b06', server.accessToken, data, done)
475 })
476
477 it('Should fail with a long name', function (done) {
478 const data = {
479 name: 'My very very very very very very very very very very very very very very very very long name',
480 description: 'my super description',
481 tags: [ 'tag1', 'tag2' ]
482 }
483 requestsUtils.makePutBodyRequest(server.url, path + videoId, server.accessToken, data, done)
484 })
485
486 it('Should fail with a long description', function (done) {
487 const data = {
488 name: 'my super name',
489 description: 'my super description which is very very very very very very very very very very very very very very' +
490 'very very very very very very very very very very very very very very very very very very very very very' +
491 'very very very very very very very very very very very very very very very long',
492 tags: [ 'tag1', 'tag2' ]
493 }
494 requestsUtils.makePutBodyRequest(server.url, path + videoId, server.accessToken, data, done)
495 })
496
497 it('Should fail with too many tags', function (done) {
498 const data = {
499 name: 'my super name',
500 description: 'my super description',
501 tags: [ 'tag1', 'tag2', 'tag3', 'tag4' ]
502 }
503 requestsUtils.makePutBodyRequest(server.url, path + videoId, server.accessToken, data, done)
504 })
505
506 it('Should fail with not enough tags', function (done) {
507 const data = {
508 name: 'my super name',
509 description: 'my super description',
510 tags: [ ]
511 }
512 requestsUtils.makePutBodyRequest(server.url, path + videoId, server.accessToken, data, done)
513 })
514
515 it('Should fail with a tag length too low', function (done) {
516 const data = {
517 name: 'my super name',
518 description: 'my super description',
519 tags: [ 'tag1', 't' ]
520 }
521 requestsUtils.makePutBodyRequest(server.url, path + videoId, server.accessToken, data, done)
522 })
523
524 it('Should fail with a tag length too big', function (done) {
525 const data = {
526 name: 'my super name',
527 description: 'my super description',
528 tags: [ 'mysupertagtoolong', 'tag1' ]
529 }
530 requestsUtils.makePutBodyRequest(server.url, path + videoId, server.accessToken, data, done)
531 })
532
533 it('Should fail with malformed tags', function (done) {
534 const data = {
535 name: 'my super name',
536 description: 'my super description',
537 tags: [ 'my tag' ]
538 }
539 requestsUtils.makePutBodyRequest(server.url, path + videoId, server.accessToken, data, done)
540 })
541 })
542
442 describe('When getting a video', function () { 543 describe('When getting a video', function () {
443 it('Should return the list of the videos with nothing', function (done) { 544 it('Should return the list of the videos with nothing', function (done) {
444 request(server.url) 545 request(server.url)
diff --git a/server/tests/api/single-pod.js b/server/tests/api/single-pod.js
index 66b762f82..57146900d 100644
--- a/server/tests/api/single-pod.js
+++ b/server/tests/api/single-pod.js
@@ -495,10 +495,86 @@ describe('Test a single pod', function () {
495 expect(videos[2].name === 'video_short2.webm name') 495 expect(videos[2].name === 'video_short2.webm name')
496 expect(videos[3].name === 'video_short3.webm name') 496 expect(videos[3].name === 'video_short3.webm name')
497 497
498 videoId = videos[3].id
499
498 done() 500 done()
499 }) 501 })
500 }) 502 })
501 503
504 it('Should update a video', function (done) {
505 const name = 'my super video updated'
506 const description = 'my super description updated'
507 const tags = [ 'tagup1', 'tagup2' ]
508
509 videosUtils.updateVideo(server.url, server.accessToken, videoId, name, description, tags, done)
510 })
511
512 it('Should have the video updated', function (done) {
513 videosUtils.getVideo(server.url, videoId, function (err, res) {
514 if (err) throw err
515
516 const video = res.body
517
518 expect(video.name).to.equal('my super video updated')
519 expect(video.description).to.equal('my super description updated')
520 expect(video.podHost).to.equal('localhost:9001')
521 expect(video.author).to.equal('root')
522 expect(video.isLocal).to.be.true
523 expect(video.tags).to.deep.equal([ 'tagup1', 'tagup2' ])
524 expect(miscsUtils.dateIsValid(video.createdAt)).to.be.true
525
526 done()
527 })
528 })
529
530 it('Should update only the tags of a video', function (done) {
531 const tags = [ 'tag1', 'tag2', 'supertag' ]
532
533 videosUtils.updateVideo(server.url, server.accessToken, videoId, null, null, tags, function (err) {
534 if (err) throw err
535
536 videosUtils.getVideo(server.url, videoId, function (err, res) {
537 if (err) throw err
538
539 const video = res.body
540
541 expect(video.name).to.equal('my super video updated')
542 expect(video.description).to.equal('my super description updated')
543 expect(video.podHost).to.equal('localhost:9001')
544 expect(video.author).to.equal('root')
545 expect(video.isLocal).to.be.true
546 expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'supertag' ])
547 expect(miscsUtils.dateIsValid(video.createdAt)).to.be.true
548
549 done()
550 })
551 })
552 })
553
554 it('Should update only the description of a video', function (done) {
555 const description = 'hello everybody'
556
557 videosUtils.updateVideo(server.url, server.accessToken, videoId, null, description, null, function (err) {
558 if (err) throw err
559
560 videosUtils.getVideo(server.url, videoId, function (err, res) {
561 if (err) throw err
562
563 const video = res.body
564
565 expect(video.name).to.equal('my super video updated')
566 expect(video.description).to.equal('hello everybody')
567 expect(video.podHost).to.equal('localhost:9001')
568 expect(video.author).to.equal('root')
569 expect(video.isLocal).to.be.true
570 expect(video.tags).to.deep.equal([ 'tag1', 'tag2', 'supertag' ])
571 expect(miscsUtils.dateIsValid(video.createdAt)).to.be.true
572
573 done()
574 })
575 })
576 })
577
502 after(function (done) { 578 after(function (done) {
503 process.kill(-server.app.pid) 579 process.kill(-server.app.pid)
504 580
diff --git a/server/tests/utils/videos.js b/server/tests/utils/videos.js
index 5c120597f..beafd3cf5 100644
--- a/server/tests/utils/videos.js
+++ b/server/tests/utils/videos.js
@@ -15,7 +15,8 @@ const videosUtils = {
15 searchVideoWithPagination, 15 searchVideoWithPagination,
16 searchVideoWithSort, 16 searchVideoWithSort,
17 testVideoImage, 17 testVideoImage,
18 uploadVideo 18 uploadVideo,
19 updateVideo
19} 20}
20 21
21// ---------------------- Export functions -------------------- 22// ---------------------- Export functions --------------------
@@ -194,6 +195,31 @@ function uploadVideo (url, accessToken, name, description, tags, fixture, specia
194 .end(end) 195 .end(end)
195} 196}
196 197
198function updateVideo (url, accessToken, id, name, description, tags, specialStatus, end) {
199 if (!end) {
200 end = specialStatus
201 specialStatus = 204
202 }
203
204 const path = '/api/v1/videos/' + id
205
206 const req = request(url)
207 .put(path)
208 .set('Accept', 'application/json')
209 .set('Authorization', 'Bearer ' + accessToken)
210
211 if (name) req.field('name', name)
212 if (description) req.field('description', description)
213
214 if (tags) {
215 for (let i = 0; i < tags.length; i++) {
216 req.field('tags[' + i + ']', tags[i])
217 }
218 }
219
220 req.expect(specialStatus).end(end)
221}
222
197// --------------------------------------------------------------------------- 223// ---------------------------------------------------------------------------
198 224
199module.exports = videosUtils 225module.exports = videosUtils