]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/middlewares/validators/videos.ts
Add pod list endpoint with pagination, sort...
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / videos.ts
CommitLineData
b60e5f38 1import { body, param, query } from 'express-validator/check'
69818c93
C
2import * as express from 'express'
3
e02643f3 4import { database as db } from '../../initializers/database'
65fcc311
C
5import { checkErrors } from './utils'
6import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers'
b60e5f38
C
7import {
8 logger,
9 isVideoDurationValid,
10 isVideoFile,
11 isVideoNameValid,
12 isVideoCategoryValid,
13 isVideoLicenceValid,
14 isVideoDescriptionValid,
15 isVideoLanguageValid,
16 isVideoTagsValid,
17 isVideoNSFWValid,
18 isVideoIdOrUUIDValid,
19 isVideoAbuseReasonValid,
14d3270f 20 isVideoRatingTypeValid,
35bf0c83
C
21 getDurationFromVideoFile,
22 checkVideoExists
b60e5f38 23} from '../../helpers'
34ca3b52 24
b60e5f38 25const videosAddValidator = [
8376734e
R
26 body('videofile').custom((value, { req }) => isVideoFile(req.files)).withMessage(
27 'This file is not supported. Are you sure it is of the following type : '
28 + CONSTRAINTS_FIELDS.VIDEOS.EXTNAME
29 ),
b60e5f38
C
30 body('name').custom(isVideoNameValid).withMessage('Should have a valid name'),
31 body('category').custom(isVideoCategoryValid).withMessage('Should have a valid category'),
32 body('licence').custom(isVideoLicenceValid).withMessage('Should have a valid licence'),
33 body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'),
34 body('nsfw').custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'),
35 body('description').custom(isVideoDescriptionValid).withMessage('Should have a valid description'),
36 body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'),
37
38 (req: express.Request, res: express.Response, next: express.NextFunction) => {
39 logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files })
40
41 checkErrors(req, res, () => {
42 const videoFile: Express.Multer.File = req.files['videofile'][0]
43 const user = res.locals.oauth.token.User
44
45 user.isAbleToUploadVideo(videoFile)
46 .then(isAble => {
47 if (isAble === false) {
48 res.status(403)
49 .json({ error: 'The user video quota is exceeded with this video.' })
50 .end()
51
52 return undefined
53 }
54
14d3270f 55 return getDurationFromVideoFile(videoFile.path)
b60e5f38
C
56 .catch(err => {
57 logger.error('Invalid input file in videosAddValidator.', err)
58 res.status(400)
59 .json({ error: 'Invalid input file.' })
60 .end()
61
62 return undefined
63 })
64 })
65 .then(duration => {
66 // Previous test failed, abort
67 if (duration === undefined) return
68
69 if (!isVideoDurationValid('' + duration)) {
70 return res.status(400)
71 .json({
72 error: 'Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).'
73 })
74 .end()
75 }
76
77 videoFile['duration'] = duration
78 next()
79 })
80 .catch(err => {
81 logger.error('Error in video add validator', err)
82 res.sendStatus(500)
b0f9f39e
C
83
84 return undefined
b60e5f38
C
85 })
86 })
87 }
88]
89
90const videosUpdateValidator = [
91 param('id').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
92 body('name').optional().custom(isVideoNameValid).withMessage('Should have a valid name'),
93 body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'),
94 body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'),
95 body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'),
96 body('nsfw').optional().custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'),
97 body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'),
98 body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'),
99
100 (req: express.Request, res: express.Response, next: express.NextFunction) => {
101 logger.debug('Checking videosUpdate parameters', { parameters: req.body })
102
103 checkErrors(req, res, () => {
104 checkVideoExists(req.params.id, res, () => {
105 // We need to make additional checks
106 if (res.locals.video.isOwned() === false) {
107 return res.status(403)
108 .json({ error: 'Cannot update video of another pod' })
109 .end()
b0f9f39e
C
110 }
111
b60e5f38
C
112 if (res.locals.video.Author.userId !== res.locals.oauth.token.User.id) {
113 return res.status(403)
114 .json({ error: 'Cannot update video of another user' })
bfb3a98f 115 .end()
6fcd19ba 116 }
67100f1f 117
6fcd19ba
C
118 next()
119 })
63d00f5d 120 })
b60e5f38
C
121 }
122]
c173e565 123
b60e5f38
C
124const videosGetValidator = [
125 param('id').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
34ca3b52 126
b60e5f38
C
127 (req: express.Request, res: express.Response, next: express.NextFunction) => {
128 logger.debug('Checking videosGet parameters', { parameters: req.params })
7b1f49de 129
b60e5f38
C
130 checkErrors(req, res, () => {
131 checkVideoExists(req.params.id, res, next)
132 })
133 }
134]
34ca3b52 135
b60e5f38
C
136const videosRemoveValidator = [
137 param('id').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
34ca3b52 138
b60e5f38
C
139 (req: express.Request, res: express.Response, next: express.NextFunction) => {
140 logger.debug('Checking videosRemove parameters', { parameters: req.params })
34ca3b52 141
b60e5f38
C
142 checkErrors(req, res, () => {
143 checkVideoExists(req.params.id, res, () => {
144 // Check if the user who did the request is able to delete the video
145 checkUserCanDeleteVideo(res.locals.oauth.token.User.id, res, () => {
146 next()
147 })
198b205c 148 })
34ca3b52 149 })
b60e5f38
C
150 }
151]
34ca3b52 152
b60e5f38
C
153const videosSearchValidator = [
154 param('value').not().isEmpty().withMessage('Should have a valid search'),
155 query('field').optional().isIn(SEARCHABLE_COLUMNS.VIDEOS).withMessage('Should have correct searchable column'),
c45f7f84 156
b60e5f38
C
157 (req: express.Request, res: express.Response, next: express.NextFunction) => {
158 logger.debug('Checking videosSearch parameters', { parameters: req.params })
c45f7f84 159
b60e5f38
C
160 checkErrors(req, res, next)
161 }
162]
c45f7f84 163
b60e5f38
C
164const videoAbuseReportValidator = [
165 param('id').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
166 body('reason').custom(isVideoAbuseReasonValid).withMessage('Should have a valid reason'),
55fa55a9 167
b60e5f38
C
168 (req: express.Request, res: express.Response, next: express.NextFunction) => {
169 logger.debug('Checking videoAbuseReport parameters', { parameters: req.body })
55fa55a9 170
b60e5f38
C
171 checkErrors(req, res, () => {
172 checkVideoExists(req.params.id, res, next)
173 })
174 }
175]
55fa55a9 176
b60e5f38
C
177const videoRateValidator = [
178 param('id').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
179 body('rating').custom(isVideoRatingTypeValid).withMessage('Should have a valid rate type'),
d38b8281 180
b60e5f38
C
181 (req: express.Request, res: express.Response, next: express.NextFunction) => {
182 logger.debug('Checking videoRate parameters', { parameters: req.body })
d38b8281 183
b60e5f38
C
184 checkErrors(req, res, () => {
185 checkVideoExists(req.params.id, res, next)
186 })
187 }
188]
d38b8281 189
9f10b292 190// ---------------------------------------------------------------------------
c45f7f84 191
65fcc311
C
192export {
193 videosAddValidator,
194 videosUpdateValidator,
195 videosGetValidator,
196 videosRemoveValidator,
197 videosSearchValidator,
198
199 videoAbuseReportValidator,
200
35bf0c83 201 videoRateValidator
65fcc311 202}
7b1f49de
C
203
204// ---------------------------------------------------------------------------
205
69818c93 206function checkUserCanDeleteVideo (userId: number, res: express.Response, callback: () => void) {
198b205c 207 // Retrieve the user who did the request
6fcd19ba
C
208 db.User.loadById(userId)
209 .then(user => {
6d33593a 210 if (res.locals.video.isOwned() === false) {
bfb3a98f
C
211 return res.status(403)
212 .json({ error: 'Cannot remove video of another pod, blacklist it' })
213 .end()
6d33593a
C
214 }
215
6fcd19ba
C
216 // Check if the user can delete the video
217 // The user can delete it if s/he is an admin
218 // Or if s/he is the video's author
6d33593a 219 if (user.isAdmin() === false && res.locals.video.Author.userId !== res.locals.oauth.token.User.id) {
bfb3a98f
C
220 return res.status(403)
221 .json({ error: 'Cannot remove video of another user' })
222 .end()
198b205c 223 }
198b205c 224
6fcd19ba
C
225 // If we reach this comment, we can delete the video
226 callback()
227 })
228 .catch(err => {
ad0997ad 229 logger.error('Error in video request validator.', err)
6fcd19ba
C
230 return res.sendStatus(500)
231 })
198b205c 232}