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