Relax on tags (accept any characters and not required anymore)
[oweals/peertube.git] / server / middlewares / validators / videos.js
1 'use strict'
2
3 const checkErrors = require('./utils').checkErrors
4 const constants = require('../../initializers/constants')
5 const customVideosValidators = require('../../helpers/custom-validators').videos
6 const db = require('../../initializers/database')
7 const logger = require('../../helpers/logger')
8
9 const validatorsVideos = {
10   videosAdd,
11   videosUpdate,
12   videosGet,
13   videosRemove,
14   videosSearch,
15
16   videoAbuseReport,
17
18   videoRate
19 }
20
21 function videosAdd (req, res, next) {
22   req.checkBody('videofile', 'Should have a valid file').isVideoFile(req.files)
23   req.checkBody('name', 'Should have a valid name').isVideoNameValid()
24   req.checkBody('category', 'Should have a valid category').isVideoCategoryValid()
25   req.checkBody('description', 'Should have a valid description').isVideoDescriptionValid()
26   req.checkBody('tags', 'Should have correct tags').optional().isVideoTagsValid()
27
28   logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files })
29
30   checkErrors(req, res, function () {
31     const videoFile = req.files.videofile[0]
32
33     db.Video.getDurationFromFile(videoFile.path, function (err, duration) {
34       if (err) {
35         return res.status(400).send('Cannot retrieve metadata of the file.')
36       }
37
38       if (!customVideosValidators.isVideoDurationValid(duration)) {
39         return res.status(400).send('Duration of the video file is too big (max: ' + constants.CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).')
40       }
41
42       videoFile.duration = duration
43       next()
44     })
45   })
46 }
47
48 function videosUpdate (req, res, next) {
49   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
50   req.checkBody('name', 'Should have a valid name').optional().isVideoNameValid()
51   req.checkBody('category', 'Should have a valid category').optional().isVideoCategoryValid()
52   req.checkBody('description', 'Should have a valid description').optional().isVideoDescriptionValid()
53   req.checkBody('tags', 'Should have correct tags').optional().isVideoTagsValid()
54
55   logger.debug('Checking videosUpdate parameters', { parameters: req.body })
56
57   checkErrors(req, res, function () {
58     checkVideoExists(req.params.id, res, function () {
59       // We need to make additional checks
60       if (res.locals.video.isOwned() === false) {
61         return res.status(403).send('Cannot update video of another pod')
62       }
63
64       if (res.locals.video.Author.userId !== res.locals.oauth.token.User.id) {
65         return res.status(403).send('Cannot update video of another user')
66       }
67
68       next()
69     })
70   })
71 }
72
73 function videosGet (req, res, next) {
74   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
75
76   logger.debug('Checking videosGet parameters', { parameters: req.params })
77
78   checkErrors(req, res, function () {
79     checkVideoExists(req.params.id, res, next)
80   })
81 }
82
83 function videosRemove (req, res, next) {
84   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
85
86   logger.debug('Checking videosRemove parameters', { parameters: req.params })
87
88   checkErrors(req, res, function () {
89     checkVideoExists(req.params.id, res, function () {
90       // We need to make additional checks
91
92       if (res.locals.video.isOwned() === false) {
93         return res.status(403).send('Cannot remove video of another pod')
94       }
95
96       if (res.locals.video.Author.userId !== res.locals.oauth.token.User.id) {
97         return res.status(403).send('Cannot remove video of another user')
98       }
99
100       next()
101     })
102   })
103 }
104
105 function videosSearch (req, res, next) {
106   const searchableColumns = constants.SEARCHABLE_COLUMNS.VIDEOS
107   req.checkParams('value', 'Should have a valid search').notEmpty()
108   req.checkQuery('field', 'Should have correct searchable column').optional().isIn(searchableColumns)
109
110   logger.debug('Checking videosSearch parameters', { parameters: req.params })
111
112   checkErrors(req, res, next)
113 }
114
115 function videoAbuseReport (req, res, next) {
116   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
117   req.checkBody('reason', 'Should have a valid reason').isVideoAbuseReasonValid()
118
119   logger.debug('Checking videoAbuseReport parameters', { parameters: req.body })
120
121   checkErrors(req, res, function () {
122     checkVideoExists(req.params.id, res, next)
123   })
124 }
125
126 function videoRate (req, res, next) {
127   req.checkParams('id', 'Should have a valid id').notEmpty().isUUID(4)
128   req.checkBody('rating', 'Should have a valid rate type').isVideoRatingTypeValid()
129
130   logger.debug('Checking videoRate parameters', { parameters: req.body })
131
132   checkErrors(req, res, function () {
133     checkVideoExists(req.params.id, res, next)
134   })
135 }
136
137 // ---------------------------------------------------------------------------
138
139 module.exports = validatorsVideos
140
141 // ---------------------------------------------------------------------------
142
143 function checkVideoExists (id, res, callback) {
144   db.Video.loadAndPopulateAuthorAndPodAndTags(id, function (err, video) {
145     if (err) {
146       logger.error('Error in video request validator.', { error: err })
147       return res.sendStatus(500)
148     }
149
150     if (!video) return res.status(404).send('Video not found')
151
152     res.locals.video = video
153     callback()
154   })
155 }