From 72c7248b6fdcdb2175e726ff51b42e7555f2bd84 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 24 Oct 2017 19:41:09 +0200 Subject: Add video channels --- server/middlewares/validators/index.ts | 1 + server/middlewares/validators/oembed.ts | 11 +- server/middlewares/validators/sort.ts | 3 + server/middlewares/validators/users.ts | 4 +- server/middlewares/validators/video-blacklist.ts | 6 +- server/middlewares/validators/video-channels.ts | 142 +++++++++++++++++++++++ server/middlewares/validators/videos.ts | 33 ++++-- 7 files changed, 182 insertions(+), 18 deletions(-) create mode 100644 server/middlewares/validators/video-channels.ts (limited to 'server/middlewares/validators') diff --git a/server/middlewares/validators/index.ts b/server/middlewares/validators/index.ts index 068c41b24..247f6039e 100644 --- a/server/middlewares/validators/index.ts +++ b/server/middlewares/validators/index.ts @@ -6,3 +6,4 @@ export * from './sort' export * from './users' export * from './videos' export * from './video-blacklist' +export * from './video-channels' diff --git a/server/middlewares/validators/oembed.ts b/server/middlewares/validators/oembed.ts index 4b8c03faf..f8e34d2d4 100644 --- a/server/middlewares/validators/oembed.ts +++ b/server/middlewares/validators/oembed.ts @@ -4,9 +4,12 @@ import { join } from 'path' import { checkErrors } from './utils' import { CONFIG } from '../../initializers' -import { logger } from '../../helpers' -import { checkVideoExists, isVideoIdOrUUIDValid } from '../../helpers/custom-validators/videos' -import { isTestInstance } from '../../helpers/core-utils' +import { + logger, + isTestInstance, + checkVideoExists, + isIdOrUUIDValid +} from '../../helpers' const urlShouldStartWith = CONFIG.WEBSERVER.SCHEME + '://' + join(CONFIG.WEBSERVER.HOST, 'videos', 'watch') + '/' const videoWatchRegex = new RegExp('([^/]+)$') @@ -45,7 +48,7 @@ const oembedValidator = [ } const videoId = matches[1] - if (isVideoIdOrUUIDValid(videoId) === false) { + if (isIdOrUUIDValid(videoId) === false) { return res.status(400) .json({ error: 'Invalid video id.' }) .end() diff --git a/server/middlewares/validators/sort.ts b/server/middlewares/validators/sort.ts index 227f309ad..d23a95537 100644 --- a/server/middlewares/validators/sort.ts +++ b/server/middlewares/validators/sort.ts @@ -11,12 +11,14 @@ const SORTABLE_USERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USERS) const SORTABLE_VIDEO_ABUSES_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEO_ABUSES) const SORTABLE_VIDEOS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEOS) const SORTABLE_BLACKLISTS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.BLACKLISTS) +const SORTABLE_VIDEO_CHANNELS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.VIDEO_CHANNELS) const podsSortValidator = checkSort(SORTABLE_PODS_COLUMNS) const usersSortValidator = checkSort(SORTABLE_USERS_COLUMNS) const videoAbusesSortValidator = checkSort(SORTABLE_VIDEO_ABUSES_COLUMNS) const videosSortValidator = checkSort(SORTABLE_VIDEOS_COLUMNS) const blacklistSortValidator = checkSort(SORTABLE_BLACKLISTS_COLUMNS) +const videoChannelsSortValidator = checkSort(SORTABLE_VIDEO_CHANNELS_COLUMNS) // --------------------------------------------------------------------------- @@ -24,6 +26,7 @@ export { podsSortValidator, usersSortValidator, videoAbusesSortValidator, + videoChannelsSortValidator, videosSortValidator, blacklistSortValidator } diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index ab9d0938c..1a33cfd8c 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts @@ -13,7 +13,7 @@ import { isUserPasswordValid, isUserVideoQuotaValid, isUserDisplayNSFWValid, - isVideoIdOrUUIDValid + isIdOrUUIDValid } from '../../helpers' import { UserInstance, VideoInstance } from '../../models' @@ -109,7 +109,7 @@ const usersGetValidator = [ ] const usersVideoRatingValidator = [ - param('videoId').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), + param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking usersVideoRating parameters', { parameters: req.params }) diff --git a/server/middlewares/validators/video-blacklist.ts b/server/middlewares/validators/video-blacklist.ts index 30c6d4bd9..3c8c31519 100644 --- a/server/middlewares/validators/video-blacklist.ts +++ b/server/middlewares/validators/video-blacklist.ts @@ -3,10 +3,10 @@ import * as express from 'express' import { database as db } from '../../initializers/database' import { checkErrors } from './utils' -import { logger, isVideoIdOrUUIDValid, checkVideoExists } from '../../helpers' +import { logger, isIdOrUUIDValid, checkVideoExists } from '../../helpers' const videosBlacklistRemoveValidator = [ - param('videoId').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), + param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking blacklistRemove parameters.', { parameters: req.params }) @@ -20,7 +20,7 @@ const videosBlacklistRemoveValidator = [ ] const videosBlacklistAddValidator = [ - param('videoId').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), + param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosBlacklist parameters', { parameters: req.params }) diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts new file mode 100644 index 000000000..979fbd34a --- /dev/null +++ b/server/middlewares/validators/video-channels.ts @@ -0,0 +1,142 @@ +import { body, param } from 'express-validator/check' +import * as express from 'express' + +import { checkErrors } from './utils' +import { database as db } from '../../initializers' +import { + logger, + isIdOrUUIDValid, + isVideoChannelDescriptionValid, + isVideoChannelNameValid, + checkVideoChannelExists, + checkVideoAuthorExists +} from '../../helpers' + +const listVideoAuthorChannelsValidator = [ + param('authorId').custom(isIdOrUUIDValid).withMessage('Should have a valid author id'), + + (req: express.Request, res: express.Response, next: express.NextFunction) => { + logger.debug('Checking listVideoAuthorChannelsValidator parameters', { parameters: req.body }) + + checkErrors(req, res, () => { + checkVideoAuthorExists(req.params.authorId, res, next) + }) + } +] + +const videoChannelsAddValidator = [ + body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'), + body('description').custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), + + (req: express.Request, res: express.Response, next: express.NextFunction) => { + logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body }) + + checkErrors(req, res, next) + } +] + +const videoChannelsUpdateValidator = [ + param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), + body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'), + body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), + + (req: express.Request, res: express.Response, next: express.NextFunction) => { + logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body }) + + checkErrors(req, res, () => { + checkVideoChannelExists(req.params.id, res, () => { + // We need to make additional checks + if (res.locals.videoChannel.isOwned() === false) { + return res.status(403) + .json({ error: 'Cannot update video channel of another pod' }) + .end() + } + + if (res.locals.videoChannel.Author.userId !== res.locals.oauth.token.User.id) { + return res.status(403) + .json({ error: 'Cannot update video channel of another user' }) + .end() + } + + next() + }) + }) + } +] + +const videoChannelsRemoveValidator = [ + param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), + + (req: express.Request, res: express.Response, next: express.NextFunction) => { + logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params }) + + checkErrors(req, res, () => { + checkVideoChannelExists(req.params.id, res, () => { + // Check if the user who did the request is able to delete the video + checkUserCanDeleteVideoChannel(res, () => { + checkVideoChannelIsNotTheLastOne(res, next) + }) + }) + }) + } +] + +const videoChannelGetValidator = [ + param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), + + (req: express.Request, res: express.Response, next: express.NextFunction) => { + logger.debug('Checking videoChannelsGet parameters', { parameters: req.params }) + + checkErrors(req, res, () => { + checkVideoChannelExists(req.params.id, res, next) + }) + } +] + +// --------------------------------------------------------------------------- + +export { + listVideoAuthorChannelsValidator, + videoChannelsAddValidator, + videoChannelsUpdateValidator, + videoChannelsRemoveValidator, + videoChannelGetValidator +} + +// --------------------------------------------------------------------------- + +function checkUserCanDeleteVideoChannel (res: express.Response, callback: () => void) { + const user = res.locals.oauth.token.User + + // Retrieve the user who did the request + if (res.locals.videoChannel.isOwned() === false) { + return res.status(403) + .json({ error: 'Cannot remove video channel of another pod.' }) + .end() + } + + // Check if the user can delete the video channel + // The user can delete it if s/he is an admin + // Or if s/he is the video channel's author + if (user.isAdmin() === false && res.locals.videoChannel.Author.userId !== user.id) { + return res.status(403) + .json({ error: 'Cannot remove video channel of another user' }) + .end() + } + + // If we reach this comment, we can delete the video + callback() +} + +function checkVideoChannelIsNotTheLastOne (res: express.Response, callback: () => void) { + db.VideoChannel.countByAuthor(res.locals.oauth.token.User.Author.id) + .then(count => { + if (count <= 1) { + return res.status(409) + .json({ error: 'Cannot remove the last channel of this user' }) + .end() + } + + callback() + }) +} diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index 3f881e1b5..8a9b383b8 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts @@ -15,11 +15,12 @@ import { isVideoLanguageValid, isVideoTagsValid, isVideoNSFWValid, - isVideoIdOrUUIDValid, + isIdOrUUIDValid, isVideoAbuseReasonValid, isVideoRatingTypeValid, getDurationFromVideoFile, - checkVideoExists + checkVideoExists, + isIdValid } from '../../helpers' const videosAddValidator = [ @@ -33,6 +34,7 @@ const videosAddValidator = [ 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('channelId').custom(isIdValid).withMessage('Should have correct video channel id'), body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), (req: express.Request, res: express.Response, next: express.NextFunction) => { @@ -42,7 +44,20 @@ const videosAddValidator = [ const videoFile: Express.Multer.File = req.files['videofile'][0] const user = res.locals.oauth.token.User - user.isAbleToUploadVideo(videoFile) + return db.VideoChannel.loadByIdAndAuthor(req.body.channelId, user.Author.id) + .then(videoChannel => { + if (!videoChannel) { + res.status(400) + .json({ error: 'Unknown video video channel for this author.' }) + .end() + + return undefined + } + + res.locals.videoChannel = videoChannel + + return user.isAbleToUploadVideo(videoFile) + }) .then(isAble => { if (isAble === false) { res.status(403) @@ -88,7 +103,7 @@ const videosAddValidator = [ ] const videosUpdateValidator = [ - param('id').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), + param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), body('name').optional().custom(isVideoNameValid).withMessage('Should have a valid name'), body('category').optional().custom(isVideoCategoryValid).withMessage('Should have a valid category'), body('licence').optional().custom(isVideoLicenceValid).withMessage('Should have a valid licence'), @@ -109,7 +124,7 @@ const videosUpdateValidator = [ .end() } - if (res.locals.video.Author.userId !== res.locals.oauth.token.User.id) { + if (res.locals.video.VideoChannel.Author.userId !== res.locals.oauth.token.User.id) { return res.status(403) .json({ error: 'Cannot update video of another user' }) .end() @@ -122,7 +137,7 @@ const videosUpdateValidator = [ ] const videosGetValidator = [ - param('id').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), + param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosGet parameters', { parameters: req.params }) @@ -134,7 +149,7 @@ const videosGetValidator = [ ] const videosRemoveValidator = [ - param('id').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), + param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosRemove parameters', { parameters: req.params }) @@ -162,7 +177,7 @@ const videosSearchValidator = [ ] const videoAbuseReportValidator = [ - param('id').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), + param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), body('reason').custom(isVideoAbuseReasonValid).withMessage('Should have a valid reason'), (req: express.Request, res: express.Response, next: express.NextFunction) => { @@ -175,7 +190,7 @@ const videoAbuseReportValidator = [ ] const videoRateValidator = [ - param('id').custom(isVideoIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), + param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), body('rating').custom(isVideoRatingTypeValid).withMessage('Should have a valid rate type'), (req: express.Request, res: express.Response, next: express.NextFunction) => { -- cgit v1.2.3