aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/middlewares/validators/videos/videos.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/middlewares/validators/videos/videos.ts')
-rw-r--r--server/middlewares/validators/videos/videos.ts105
1 files changed, 62 insertions, 43 deletions
diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts
index 8864be269..dfd472400 100644
--- a/server/middlewares/validators/videos/videos.ts
+++ b/server/middlewares/validators/videos/videos.ts
@@ -73,6 +73,7 @@ const videosAddLegacyValidator = getCommonVideoEditAttributes().concat([
73 .custom(isIdValid).withMessage('Should have correct video channel id'), 73 .custom(isIdValid).withMessage('Should have correct video channel id'),
74 74
75 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 75 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
76 res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadLegacy"
76 logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) 77 logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files })
77 78
78 if (areValidationErrors(req, res)) return cleanUpReqFiles(req) 79 if (areValidationErrors(req, res)) return cleanUpReqFiles(req)
@@ -88,9 +89,11 @@ const videosAddLegacyValidator = getCommonVideoEditAttributes().concat([
88 if (!videoFile.duration) await addDurationToVideo(videoFile) 89 if (!videoFile.duration) await addDurationToVideo(videoFile)
89 } catch (err) { 90 } catch (err) {
90 logger.error('Invalid input file in videosAddLegacyValidator.', { err }) 91 logger.error('Invalid input file in videosAddLegacyValidator.', { err })
91 res.status(HttpStatusCode.UNPROCESSABLE_ENTITY_422)
92 .json({ error: 'Video file unreadable.' })
93 92
93 res.fail({
94 status: HttpStatusCode.UNPROCESSABLE_ENTITY_422,
95 message: 'Video file unreadable.'
96 })
94 return cleanUpReqFiles(req) 97 return cleanUpReqFiles(req)
95 } 98 }
96 99
@@ -105,6 +108,7 @@ const videosAddLegacyValidator = getCommonVideoEditAttributes().concat([
105 */ 108 */
106const videosAddResumableValidator = [ 109const videosAddResumableValidator = [
107 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 110 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
111 res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadResumable"
108 const user = res.locals.oauth.token.User 112 const user = res.locals.oauth.token.User
109 113
110 const body: express.CustomUploadXFile<express.UploadXFileMetadata> = req.body 114 const body: express.CustomUploadXFile<express.UploadXFileMetadata> = req.body
@@ -118,9 +122,11 @@ const videosAddResumableValidator = [
118 if (!file.duration) await addDurationToVideo(file) 122 if (!file.duration) await addDurationToVideo(file)
119 } catch (err) { 123 } catch (err) {
120 logger.error('Invalid input file in videosAddResumableValidator.', { err }) 124 logger.error('Invalid input file in videosAddResumableValidator.', { err })
121 res.status(HttpStatusCode.UNPROCESSABLE_ENTITY_422)
122 .json({ error: 'Video file unreadable.' })
123 125
126 res.fail({
127 status: HttpStatusCode.UNPROCESSABLE_ENTITY_422,
128 message: 'Video file unreadable.'
129 })
124 return cleanup() 130 return cleanup()
125 } 131 }
126 132
@@ -164,6 +170,7 @@ const videosAddResumableInitValidator = getCommonVideoEditAttributes().concat([
164 .withMessage('Should specify the file mimetype'), 170 .withMessage('Should specify the file mimetype'),
165 171
166 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 172 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
173 res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/uploadResumableInit"
167 const videoFileMetadata = { 174 const videoFileMetadata = {
168 mimetype: req.headers['x-upload-content-type'] as string, 175 mimetype: req.headers['x-upload-content-type'] as string,
169 size: +req.headers['x-upload-content-length'], 176 size: +req.headers['x-upload-content-length'],
@@ -207,6 +214,7 @@ const videosUpdateValidator = getCommonVideoEditAttributes().concat([
207 .custom(isIdValid).withMessage('Should have correct video channel id'), 214 .custom(isIdValid).withMessage('Should have correct video channel id'),
208 215
209 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 216 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
217 res.docs = 'https://docs.joinpeertube.org/api-rest-reference.html#operation/putVideo'
210 logger.debug('Checking videosUpdate parameters', { parameters: req.body }) 218 logger.debug('Checking videosUpdate parameters', { parameters: req.body })
211 219
212 if (areValidationErrors(req, res)) return cleanUpReqFiles(req) 220 if (areValidationErrors(req, res)) return cleanUpReqFiles(req)
@@ -242,12 +250,14 @@ async function checkVideoFollowConstraints (req: express.Request, res: express.R
242 const serverActor = await getServerActor() 250 const serverActor = await getServerActor()
243 if (await VideoModel.checkVideoHasInstanceFollow(video.id, serverActor.id) === true) return next() 251 if (await VideoModel.checkVideoHasInstanceFollow(video.id, serverActor.id) === true) return next()
244 252
245 return res.status(HttpStatusCode.FORBIDDEN_403) 253 return res.fail({
246 .json({ 254 status: HttpStatusCode.FORBIDDEN_403,
247 errorCode: ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS, 255 message: 'Cannot get this video regarding follow constraints.',
248 error: 'Cannot get this video regarding follow constraints.', 256 type: ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS.toString(),
249 originUrl: video.url 257 data: {
250 }) 258 originUrl: video.url
259 }
260 })
251} 261}
252 262
253const videosCustomGetValidator = ( 263const videosCustomGetValidator = (
@@ -258,6 +268,7 @@ const videosCustomGetValidator = (
258 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 268 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
259 269
260 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 270 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
271 res.docs = 'https://docs.joinpeertube.org/api-rest-reference.html#operation/getVideo'
261 logger.debug('Checking videosGet parameters', { parameters: req.params }) 272 logger.debug('Checking videosGet parameters', { parameters: req.params })
262 273
263 if (areValidationErrors(req, res)) return 274 if (areValidationErrors(req, res)) return
@@ -276,8 +287,10 @@ const videosCustomGetValidator = (
276 287
277 // Only the owner or a user that have blacklist rights can see the video 288 // Only the owner or a user that have blacklist rights can see the video
278 if (!user || !user.canGetVideo(video)) { 289 if (!user || !user.canGetVideo(video)) {
279 return res.status(HttpStatusCode.FORBIDDEN_403) 290 return res.fail({
280 .json({ error: 'Cannot get this private/internal or blacklisted video.' }) 291 status: HttpStatusCode.FORBIDDEN_403,
292 message: 'Cannot get this private/internal or blacklisted video.'
293 })
281 } 294 }
282 295
283 return next() 296 return next()
@@ -291,7 +304,10 @@ const videosCustomGetValidator = (
291 if (isUUIDValid(req.params.id)) return next() 304 if (isUUIDValid(req.params.id)) return next()
292 305
293 // Don't leak this unlisted video 306 // Don't leak this unlisted video
294 return res.status(HttpStatusCode.NOT_FOUND_404).end() 307 return res.fail({
308 status: HttpStatusCode.NOT_FOUND_404,
309 message: 'Video not found'
310 })
295 } 311 }
296 } 312 }
297 ] 313 ]
@@ -318,6 +334,7 @@ const videosRemoveValidator = [
318 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 334 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
319 335
320 async (req: express.Request, res: express.Response, next: express.NextFunction) => { 336 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
337 res.docs = "https://docs.joinpeertube.org/api-rest-reference.html#operation/delVideo"
321 logger.debug('Checking videosRemove parameters', { parameters: req.params }) 338 logger.debug('Checking videosRemove parameters', { parameters: req.params })
322 339
323 if (areValidationErrors(req, res)) return 340 if (areValidationErrors(req, res)) return
@@ -344,13 +361,11 @@ const videosChangeOwnershipValidator = [
344 361
345 const nextOwner = await AccountModel.loadLocalByName(req.body.username) 362 const nextOwner = await AccountModel.loadLocalByName(req.body.username)
346 if (!nextOwner) { 363 if (!nextOwner) {
347 res.status(HttpStatusCode.BAD_REQUEST_400) 364 res.fail({ message: 'Changing video ownership to a remote account is not supported yet' })
348 .json({ error: 'Changing video ownership to a remote account is not supported yet' })
349
350 return 365 return
351 } 366 }
352 res.locals.nextOwner = nextOwner
353 367
368 res.locals.nextOwner = nextOwner
354 return next() 369 return next()
355 } 370 }
356] 371]
@@ -370,8 +385,10 @@ const videosTerminateChangeOwnershipValidator = [
370 const videoChangeOwnership = res.locals.videoChangeOwnership 385 const videoChangeOwnership = res.locals.videoChangeOwnership
371 386
372 if (videoChangeOwnership.status !== VideoChangeOwnershipStatus.WAITING) { 387 if (videoChangeOwnership.status !== VideoChangeOwnershipStatus.WAITING) {
373 res.status(HttpStatusCode.FORBIDDEN_403) 388 res.fail({
374 .json({ error: 'Ownership already accepted or refused' }) 389 status: HttpStatusCode.FORBIDDEN_403,
390 message: 'Ownership already accepted or refused'
391 })
375 return 392 return
376 } 393 }
377 394
@@ -388,9 +405,10 @@ const videosAcceptChangeOwnershipValidator = [
388 const videoChangeOwnership = res.locals.videoChangeOwnership 405 const videoChangeOwnership = res.locals.videoChangeOwnership
389 const isAble = await isAbleToUploadVideo(user.id, videoChangeOwnership.Video.getMaxQualityFile().size) 406 const isAble = await isAbleToUploadVideo(user.id, videoChangeOwnership.Video.getMaxQualityFile().size)
390 if (isAble === false) { 407 if (isAble === false) {
391 res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413) 408 res.fail({
392 .json({ error: 'The user video quota is exceeded with this video.' }) 409 status: HttpStatusCode.PAYLOAD_TOO_LARGE_413,
393 410 message: 'The user video quota is exceeded with this video.'
411 })
394 return 412 return
395 } 413 }
396 414
@@ -538,9 +556,10 @@ const commonVideosFiltersValidator = [
538 (req.query.filter === 'all-local' || req.query.filter === 'all') && 556 (req.query.filter === 'all-local' || req.query.filter === 'all') &&
539 (!user || user.hasRight(UserRight.SEE_ALL_VIDEOS) === false) 557 (!user || user.hasRight(UserRight.SEE_ALL_VIDEOS) === false)
540 ) { 558 ) {
541 res.status(HttpStatusCode.UNAUTHORIZED_401) 559 res.fail({
542 .json({ error: 'You are not allowed to see all local videos.' }) 560 status: HttpStatusCode.UNAUTHORIZED_401,
543 561 message: 'You are not allowed to see all local videos.'
562 })
544 return 563 return
545 } 564 }
546 565
@@ -581,9 +600,7 @@ function areErrorsInScheduleUpdate (req: express.Request, res: express.Response)
581 if (!req.body.scheduleUpdate.updateAt) { 600 if (!req.body.scheduleUpdate.updateAt) {
582 logger.warn('Invalid parameters: scheduleUpdate.updateAt is mandatory.') 601 logger.warn('Invalid parameters: scheduleUpdate.updateAt is mandatory.')
583 602
584 res.status(HttpStatusCode.BAD_REQUEST_400) 603 res.fail({ message: 'Schedule update at is mandatory.' })
585 .json({ error: 'Schedule update at is mandatory.' })
586
587 return true 604 return true
588 } 605 }
589 } 606 }
@@ -605,26 +622,27 @@ async function commonVideoChecksPass (parameters: {
605 if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return false 622 if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return false
606 623
607 if (!isVideoFileMimeTypeValid(files)) { 624 if (!isVideoFileMimeTypeValid(files)) {
608 res.status(HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415) 625 res.fail({
609 .json({ 626 status: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415,
610 error: 'This file is not supported. Please, make sure it is of the following type: ' + 627 message: 'This file is not supported. Please, make sure it is of the following type: ' +
611 CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') 628 CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ')
612 }) 629 })
613
614 return false 630 return false
615 } 631 }
616 632
617 if (!isVideoFileSizeValid(videoFileSize.toString())) { 633 if (!isVideoFileSizeValid(videoFileSize.toString())) {
618 res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413) 634 res.fail({
619 .json({ error: 'This file is too large. It exceeds the maximum file size authorized.' }) 635 status: HttpStatusCode.PAYLOAD_TOO_LARGE_413,
620 636 message: 'This file is too large. It exceeds the maximum file size authorized.'
637 })
621 return false 638 return false
622 } 639 }
623 640
624 if (await isAbleToUploadVideo(user.id, videoFileSize) === false) { 641 if (await isAbleToUploadVideo(user.id, videoFileSize) === false) {
625 res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413) 642 res.fail({
626 .json({ error: 'The user video quota is exceeded with this video.' }) 643 status: HttpStatusCode.PAYLOAD_TOO_LARGE_413,
627 644 message: 'The user video quota is exceeded with this video.'
645 })
628 return false 646 return false
629 } 647 }
630 648
@@ -650,9 +668,10 @@ export async function isVideoAccepted (
650 668
651 if (!acceptedResult || acceptedResult.accepted !== true) { 669 if (!acceptedResult || acceptedResult.accepted !== true) {
652 logger.info('Refused local video.', { acceptedResult, acceptParameters }) 670 logger.info('Refused local video.', { acceptedResult, acceptParameters })
653 res.status(HttpStatusCode.FORBIDDEN_403) 671 res.fail({
654 .json({ error: acceptedResult.errorMessage || 'Refused local video' }) 672 status: HttpStatusCode.FORBIDDEN_403,
655 673 message: acceptedResult.errorMessage || 'Refused local video'
674 })
656 return false 675 return false
657 } 676 }
658 677