X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;ds=sidebyside;f=server%2Fmiddlewares%2Fvalidators%2Fvideos.ts;h=a365ed217e8e6a7c2224b117bdd389c880d15548;hb=81ebea48bfba2d81e62dd7a0f01a0cadf41d2607;hp=52b4475ce314c68e33ba32c81073c53af75cf393;hpb=c60774b05b12d262ed27d8efeb0905ac283eeebb;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index 52b4475ce..a365ed217 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts @@ -1,27 +1,19 @@ import * as express from 'express' +import 'express-validator' import { body, param, query } from 'express-validator/check' import { UserRight, VideoPrivacy } from '../../../shared' -import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc' +import { isBooleanValid, isIdOrUUIDValid, isIdValid, isUUIDValid } from '../../helpers/custom-validators/misc' import { - isVideoAbuseReasonValid, - isVideoCategoryValid, - isVideoDescriptionValid, - isVideoExist, - isVideoFile, - isVideoLanguageValid, - isVideoLicenceValid, - isVideoNameValid, - isVideoNSFWValid, - isVideoPrivacyValid, - isVideoRatingTypeValid, - isVideoTagsValid + isVideoAbuseReasonValid, isVideoCategoryValid, isVideoDescriptionValid, isVideoExist, isVideoFile, isVideoLanguageValid, + isVideoLicenceValid, isVideoNameValid, isVideoPrivacyValid, isVideoRatingTypeValid, isVideoTagsValid } from '../../helpers/custom-validators/videos' import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' import { logger } from '../../helpers/logger' -import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers' -import { database as db } from '../../initializers/database' -import { UserInstance } from '../../models/account/user-interface' -import { VideoInstance } from '../../models/video/video-interface' +import { CONSTRAINTS_FIELDS } from '../../initializers' +import { UserModel } from '../../models/account/user' +import { VideoModel } from '../../models/video/video' +import { VideoChannelModel } from '../../models/video/video-channel' +import { VideoShareModel } from '../../models/video/video-share' import { authenticate } from '../oauth' import { areValidationErrors } from './utils' @@ -31,14 +23,15 @@ const videosAddValidator = [ + CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') ), body('name').custom(isVideoNameValid).withMessage('Should have a valid name'), - body('category').custom(isVideoCategoryValid).withMessage('Should have a valid category'), - body('licence').custom(isVideoLicenceValid).withMessage('Should have a valid licence'), + body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'), + body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), - body('nsfw').custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'), - body('description').custom(isVideoDescriptionValid).withMessage('Should have a valid description'), + body('nsfw').custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), + body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), body('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), + body('commentsEnabled').custom(isBooleanValid).withMessage('Should have comments enabled boolean'), async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) @@ -48,7 +41,7 @@ const videosAddValidator = [ const videoFile: Express.Multer.File = req.files['videofile'][0] const user = res.locals.oauth.token.User - const videoChannel = await db.VideoChannel.loadByIdAndAccount(req.body.channelId, user.Account.id) + const videoChannel = await VideoChannelModel.loadByIdAndAccount(req.body.channelId, user.Account.id) if (!videoChannel) { res.status(400) .json({ error: 'Unknown video video channel for this account.' }) @@ -93,10 +86,11 @@ const videosUpdateValidator = [ body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'), body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), body('language').optional().custom(isVideoLanguageValid).withMessage('Should have a valid language'), - body('nsfw').optional().custom(isVideoNSFWValid).withMessage('Should have a valid NSFW attribute'), + body('nsfw').optional().custom(isBooleanValid).withMessage('Should have a valid NSFW attribute'), body('privacy').optional().custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), + body('commentsEnabled').optional().custom(isBooleanValid).withMessage('Should have comments enabled boolean'), async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosUpdate parameters', { parameters: req.body }) @@ -140,9 +134,18 @@ const videosGetValidator = [ const video = res.locals.video - // Video is not private, anyone can access it - if (video.privacy !== VideoPrivacy.PRIVATE) return next() + // Video is public, anyone can access it + if (video.privacy === VideoPrivacy.PUBLIC) return next() + + // Video is unlisted, check we used the uuid to fetch it + if (video.privacy === VideoPrivacy.UNLISTED) { + if (isUUIDValid(req.params.id)) return next() + + // Don't leak this unlisted video + return res.status(404).end() + } + // Video is private, check the user authenticate(req, res, () => { if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) { return res.status(403) @@ -172,8 +175,7 @@ const videosRemoveValidator = [ ] const videosSearchValidator = [ - param('value').not().isEmpty().withMessage('Should have a valid search'), - query('field').optional().isIn(SEARCHABLE_COLUMNS.VIDEOS).withMessage('Should have correct searchable column'), + query('search').not().isEmpty().withMessage('Should have a valid search'), (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosSearch parameters', { parameters: req.params }) @@ -222,7 +224,7 @@ const videosShareValidator = [ if (areValidationErrors(req, res)) return if (!await isVideoExist(req.params.id, res)) return - const share = await db.VideoShare.load(req.params.accountId, res.locals.video.id) + const share = await VideoShareModel.load(req.params.accountId, res.locals.video.id, undefined) if (!share) { return res.status(404) .end() @@ -250,7 +252,7 @@ export { // --------------------------------------------------------------------------- -function checkUserCanDeleteVideo (user: UserInstance, video: VideoInstance, res: express.Response) { +function checkUserCanDeleteVideo (user: UserModel, video: VideoModel, res: express.Response) { // Retrieve the user who did the request if (video.isOwned() === false) { res.status(403) @@ -260,7 +262,7 @@ function checkUserCanDeleteVideo (user: UserInstance, video: VideoInstance, res: } // Check if the user can delete the video - // The user can delete it if s/he is an admin + // The user can delete it if he has the right // Or if s/he is the video's account const account = video.VideoChannel.Account if (user.hasRight(UserRight.REMOVE_ANY_VIDEO) === false && account.userId !== user.id) {