From a2431b7dcbc72c05101dcdbe631ff84a823aeb51 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Mon, 27 Nov 2017 17:30:46 +0100 Subject: [PATCH] Refractor validators --- server/controllers/activitypub/client.ts | 10 +- server/controllers/api/server/follows.ts | 2 +- server/controllers/api/users.ts | 16 +- server/controllers/api/videos/abuse.ts | 2 +- server/controllers/api/videos/blacklist.ts | 4 +- server/controllers/api/videos/channel.ts | 12 +- server/controllers/api/videos/index.ts | 8 +- server/controllers/api/videos/rate.ts | 2 +- server/controllers/services.ts | 8 +- server/controllers/webfinger.ts | 3 +- server/helpers/custom-validators/accounts.ts | 44 ++-- .../custom-validators/activitypub/account.ts | 63 +---- .../custom-validators/activitypub/videos.ts | 13 +- .../custom-validators/video-channels.ts | 38 +-- server/helpers/custom-validators/videos.ts | 39 +-- server/middlewares/async.ts | 7 +- server/middlewares/validators/account.ts | 15 +- .../validators/activitypub/activity.ts | 6 +- .../validators/activitypub/signature.ts | 17 +- server/middlewares/validators/follows.ts | 32 ++- server/middlewares/validators/oembed.ts | 59 +++-- server/middlewares/validators/pagination.ts | 9 +- server/middlewares/validators/sort.ts | 6 +- server/middlewares/validators/users.ts | 190 +++++++-------- server/middlewares/validators/utils.ts | 14 +- .../middlewares/validators/video-blacklist.ts | 63 ++--- .../middlewares/validators/video-channels.ts | 123 +++++----- server/middlewares/validators/videos.ts | 228 +++++++++--------- server/middlewares/validators/webfinger.ts | 38 ++- server/models/account/account.ts | 19 +- server/models/video/video-channel.ts | 4 +- server/models/video/video.ts | 23 +- support/doc/server/code.md | 4 +- 33 files changed, 478 insertions(+), 643 deletions(-) diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts index 41272bca0..62cde1fc7 100644 --- a/server/controllers/activitypub/client.ts +++ b/server/controllers/activitypub/client.ts @@ -19,22 +19,22 @@ import { VideoShareInstance } from '../../models/video/video-share-interface' const activityPubClientRouter = express.Router() activityPubClientRouter.get('/account/:name', - executeIfActivityPub(localAccountValidator), + executeIfActivityPub(asyncMiddleware(localAccountValidator)), executeIfActivityPub(accountController) ) activityPubClientRouter.get('/account/:name/followers', - executeIfActivityPub(localAccountValidator), + executeIfActivityPub(asyncMiddleware(localAccountValidator)), executeIfActivityPub(asyncMiddleware(accountFollowersController)) ) activityPubClientRouter.get('/account/:name/following', - executeIfActivityPub(localAccountValidator), + executeIfActivityPub(asyncMiddleware(localAccountValidator)), executeIfActivityPub(asyncMiddleware(accountFollowingController)) ) activityPubClientRouter.get('/videos/watch/:id', - executeIfActivityPub(videosGetValidator), + executeIfActivityPub(asyncMiddleware(videosGetValidator)), executeIfActivityPub(videoController) ) @@ -44,7 +44,7 @@ activityPubClientRouter.get('/videos/watch/:id/announces/:accountId', ) activityPubClientRouter.get('/video-channels/:id', - executeIfActivityPub(videoChannelsGetValidator), + executeIfActivityPub(asyncMiddleware(videoChannelsGetValidator)), executeIfActivityPub(asyncMiddleware(videoChannelController)) ) diff --git a/server/controllers/api/server/follows.ts b/server/controllers/api/server/follows.ts index 535d530f7..c2fb37c39 100644 --- a/server/controllers/api/server/follows.ts +++ b/server/controllers/api/server/follows.ts @@ -41,7 +41,7 @@ serverFollowsRouter.post('/following', serverFollowsRouter.delete('/following/:accountId', authenticate, ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW), - removeFollowingValidator, + asyncMiddleware(removeFollowingValidator), asyncMiddleware(removeFollow) ) diff --git a/server/controllers/api/users.ts b/server/controllers/api/users.ts index ac7c87517..721b23301 100644 --- a/server/controllers/api/users.ts +++ b/server/controllers/api/users.ts @@ -43,7 +43,7 @@ usersRouter.get('/me/videos', usersRouter.get('/me/videos/:videoId/rating', authenticate, - usersVideoRatingValidator, + asyncMiddleware(usersVideoRatingValidator), asyncMiddleware(getUserVideoRating) ) @@ -56,20 +56,20 @@ usersRouter.get('/', ) usersRouter.get('/:id', - usersGetValidator, + asyncMiddleware(usersGetValidator), getUser ) usersRouter.post('/', authenticate, ensureUserHasRight(UserRight.MANAGE_USERS), - usersAddValidator, - createUserRetryWrapper + asyncMiddleware(usersAddValidator), + asyncMiddleware(createUserRetryWrapper) ) usersRouter.post('/register', - ensureUserRegistrationAllowed, - usersRegisterValidator, + asyncMiddleware(ensureUserRegistrationAllowed), + asyncMiddleware(usersRegisterValidator), asyncMiddleware(registerUserRetryWrapper) ) @@ -82,14 +82,14 @@ usersRouter.put('/me', usersRouter.put('/:id', authenticate, ensureUserHasRight(UserRight.MANAGE_USERS), - usersUpdateValidator, + asyncMiddleware(usersUpdateValidator), asyncMiddleware(updateUser) ) usersRouter.delete('/:id', authenticate, ensureUserHasRight(UserRight.MANAGE_USERS), - usersRemoveValidator, + asyncMiddleware(usersRemoveValidator), asyncMiddleware(removeUser) ) diff --git a/server/controllers/api/videos/abuse.ts b/server/controllers/api/videos/abuse.ts index 88b3d538d..29e1175c5 100644 --- a/server/controllers/api/videos/abuse.ts +++ b/server/controllers/api/videos/abuse.ts @@ -33,7 +33,7 @@ abuseVideoRouter.get('/abuse', ) abuseVideoRouter.post('/:id/abuse', authenticate, - videoAbuseReportValidator, + asyncMiddleware(videoAbuseReportValidator), asyncMiddleware(reportVideoAbuseRetryWrapper) ) diff --git a/server/controllers/api/videos/blacklist.ts b/server/controllers/api/videos/blacklist.ts index be7cf6ea4..06333c271 100644 --- a/server/controllers/api/videos/blacklist.ts +++ b/server/controllers/api/videos/blacklist.ts @@ -21,7 +21,7 @@ const blacklistRouter = express.Router() blacklistRouter.post('/:videoId/blacklist', authenticate, ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST), - videosBlacklistAddValidator, + asyncMiddleware(videosBlacklistAddValidator), asyncMiddleware(addVideoToBlacklist) ) @@ -38,7 +38,7 @@ blacklistRouter.get('/blacklist', blacklistRouter.delete('/:videoId/blacklist', authenticate, ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST), - videosBlacklistRemoveValidator, + asyncMiddleware(videosBlacklistRemoveValidator), asyncMiddleware(removeVideoFromBlacklistController) ) diff --git a/server/controllers/api/videos/channel.ts b/server/controllers/api/videos/channel.ts index ce2656e71..d99f47c32 100644 --- a/server/controllers/api/videos/channel.ts +++ b/server/controllers/api/videos/channel.ts @@ -3,6 +3,7 @@ import { VideoChannelCreate, VideoChannelUpdate } from '../../../../shared' import { getFormattedObjects, logger, resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers' import { database as db } from '../../../initializers' import { createVideoChannel } from '../../../lib' +import { sendUpdateVideoChannel } from '../../../lib/activitypub/send/send-update' import { asyncMiddleware, authenticate, @@ -10,14 +11,13 @@ import { paginationValidator, setPagination, setVideoChannelsSort, - videoChannelsGetValidator, videoChannelsAddValidator, + videoChannelsGetValidator, videoChannelsRemoveValidator, videoChannelsSortValidator, videoChannelsUpdateValidator } from '../../../middlewares' import { AccountInstance, VideoChannelInstance } from '../../../models' -import { sendUpdateVideoChannel } from '../../../lib/activitypub/send/send-update' const videoChannelRouter = express.Router() @@ -30,7 +30,7 @@ videoChannelRouter.get('/channels', ) videoChannelRouter.get('/accounts/:accountId/channels', - listVideoAccountChannelsValidator, + asyncMiddleware(listVideoAccountChannelsValidator), asyncMiddleware(listVideoAccountChannels) ) @@ -42,18 +42,18 @@ videoChannelRouter.post('/channels', videoChannelRouter.put('/channels/:id', authenticate, - videoChannelsUpdateValidator, + asyncMiddleware(videoChannelsUpdateValidator), updateVideoChannelRetryWrapper ) videoChannelRouter.delete('/channels/:id', authenticate, - videoChannelsRemoveValidator, + asyncMiddleware(videoChannelsRemoveValidator), asyncMiddleware(removeVideoChannelRetryWrapper) ) videoChannelRouter.get('/channels/:id', - videoChannelsGetValidator, + asyncMiddleware(videoChannelsGetValidator), asyncMiddleware(getVideoChannel) ) diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 2b5afd632..244d91914 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts @@ -86,7 +86,7 @@ videosRouter.get('/', ) videosRouter.put('/:id', authenticate, - videosUpdateValidator, + asyncMiddleware(videosUpdateValidator), asyncMiddleware(updateVideoRetryWrapper) ) videosRouter.post('/upload', @@ -97,17 +97,17 @@ videosRouter.post('/upload', ) videosRouter.get('/:id/description', - videosGetValidator, + asyncMiddleware(videosGetValidator), asyncMiddleware(getVideoDescription) ) videosRouter.get('/:id', - videosGetValidator, + asyncMiddleware(videosGetValidator), getVideo ) videosRouter.delete('/:id', authenticate, - videosRemoveValidator, + asyncMiddleware(videosRemoveValidator), asyncMiddleware(removeVideoRetryWrapper) ) diff --git a/server/controllers/api/videos/rate.ts b/server/controllers/api/videos/rate.ts index 134284df7..0c6a988cf 100644 --- a/server/controllers/api/videos/rate.ts +++ b/server/controllers/api/videos/rate.ts @@ -12,7 +12,7 @@ const rateVideoRouter = express.Router() rateVideoRouter.put('/:id/rate', authenticate, - videoRateValidator, + asyncMiddleware(videoRateValidator), asyncMiddleware(rateVideoRetryWrapper) ) diff --git a/server/controllers/services.ts b/server/controllers/services.ts index 0db6e5498..0c325678c 100644 --- a/server/controllers/services.ts +++ b/server/controllers/services.ts @@ -1,12 +1,16 @@ import * as express from 'express' -import { CONFIG, PREVIEWS_SIZE, EMBED_SIZE } from '../initializers' +import { CONFIG, EMBED_SIZE, PREVIEWS_SIZE } from '../initializers' import { oembedValidator } from '../middlewares' +import { asyncMiddleware } from '../middlewares/async' import { VideoInstance } from '../models' const servicesRouter = express.Router() -servicesRouter.use('/oembed', oembedValidator, generateOEmbed) +servicesRouter.use('/oembed', + asyncMiddleware(oembedValidator), + generateOEmbed +) // --------------------------------------------------------------------------- diff --git a/server/controllers/webfinger.ts b/server/controllers/webfinger.ts index cc28a8909..1cea513a1 100644 --- a/server/controllers/webfinger.ts +++ b/server/controllers/webfinger.ts @@ -1,11 +1,12 @@ import * as express from 'express' +import { asyncMiddleware } from '../middlewares/async' import { webfingerValidator } from '../middlewares/validators/webfinger' import { AccountInstance } from '../models/account/account-interface' const webfingerRouter = express.Router() webfingerRouter.get('/.well-known/webfinger', - webfingerValidator, + asyncMiddleware(webfingerValidator), webfingerController ) diff --git a/server/helpers/custom-validators/accounts.ts b/server/helpers/custom-validators/accounts.ts index a6d7f2b82..e3c477414 100644 --- a/server/helpers/custom-validators/accounts.ts +++ b/server/helpers/custom-validators/accounts.ts @@ -1,17 +1,16 @@ import * as Bluebird from 'bluebird' -import * as express from 'express' +import { Response } from 'express' import 'express-validator' import * as validator from 'validator' import { database as db } from '../../initializers' import { AccountInstance } from '../../models' -import { logger } from '../logger' import { isUserUsernameValid } from './users' function isAccountNameValid (value: string) { return isUserUsernameValid(value) } -function checkAccountIdExists (id: number | string, res: express.Response, callback: (err: Error, account: AccountInstance) => any) { +function isAccountIdExist (id: number | string, res: Response) { let promise: Bluebird if (validator.isInt('' + id)) { @@ -20,36 +19,35 @@ function checkAccountIdExists (id: number | string, res: express.Response, callb promise = db.Account.loadByUUID('' + id) } - return checkAccountExists(promise, res, callback) + return isAccountExist(promise, res) } -function checkLocalAccountNameExists (name: string, res: express.Response, callback: (err: Error, account: AccountInstance) => any) { - const p = db.Account.loadLocalByName(name) +function isLocalAccountNameExist (name: string, res: Response) { + const promise = db.Account.loadLocalByName(name) - return checkAccountExists(p, res, callback) + return isAccountExist(promise, res) } -function checkAccountExists (p: Bluebird, res: express.Response, callback: (err: Error, account: AccountInstance) => any) { - p.then(account => { - if (!account) { - return res.status(404) - .send({ error: 'Account not found' }) - .end() - } +async function isAccountExist (p: Bluebird, res: Response) { + const account = await p - res.locals.account = account - return callback(null, account) - }) - .catch(err => { - logger.error('Error in account request validator.', err) - return res.sendStatus(500) - }) + if (!account) { + res.status(404) + .send({ error: 'Account not found' }) + .end() + + return false + } + + res.locals.account = account + + return true } // --------------------------------------------------------------------------- export { - checkAccountIdExists, - checkLocalAccountNameExists, + isAccountIdExist, + isLocalAccountNameExist, isAccountNameValid } diff --git a/server/helpers/custom-validators/activitypub/account.ts b/server/helpers/custom-validators/activitypub/account.ts index 645f55a5a..cab39a654 100644 --- a/server/helpers/custom-validators/activitypub/account.ts +++ b/server/helpers/custom-validators/activitypub/account.ts @@ -5,31 +5,19 @@ import { exists, isUUIDValid } from '../misc' import { isActivityPubUrlValid, isBaseActivityValid } from './misc' function isAccountEndpointsObjectValid (endpointObject: any) { - return isAccountSharedInboxValid(endpointObject.sharedInbox) -} - -function isAccountSharedInboxValid (sharedInbox: string) { - return isActivityPubUrlValid(sharedInbox) + return isActivityPubUrlValid(endpointObject.sharedInbox) } function isAccountPublicKeyObjectValid (publicKeyObject: any) { - return isAccountPublicKeyIdValid(publicKeyObject.id) && - isAccountPublicKeyOwnerValid(publicKeyObject.owner) && + return isActivityPubUrlValid(publicKeyObject.id) && + isActivityPubUrlValid(publicKeyObject.owner) && isAccountPublicKeyValid(publicKeyObject.publicKeyPem) } -function isAccountPublicKeyIdValid (id: string) { - return isActivityPubUrlValid(id) -} - function isAccountTypeValid (type: string) { return type === 'Person' || type === 'Application' } -function isAccountPublicKeyOwnerValid (owner: string) { - return isActivityPubUrlValid(owner) -} - function isAccountPublicKeyValid (publicKey: string) { return exists(publicKey) && typeof publicKey === 'string' && @@ -38,34 +26,10 @@ function isAccountPublicKeyValid (publicKey: string) { validator.isLength(publicKey, CONSTRAINTS_FIELDS.ACCOUNTS.PUBLIC_KEY) } -function isAccountIdValid (id: string) { - return isActivityPubUrlValid(id) -} - -function isAccountFollowingValid (id: string) { - return isActivityPubUrlValid(id) -} - -function isAccountFollowersValid (id: string) { - return isActivityPubUrlValid(id) -} - -function isAccountInboxValid (inbox: string) { - return isActivityPubUrlValid(inbox) -} - -function isAccountOutboxValid (outbox: string) { - return isActivityPubUrlValid(outbox) -} - function isAccountPreferredUsernameValid (preferredUsername: string) { return isAccountNameValid(preferredUsername) } -function isAccountUrlValid (url: string) { - return isActivityPubUrlValid(url) -} - function isAccountPrivateKeyValid (privateKey: string) { return exists(privateKey) && typeof privateKey === 'string' && @@ -75,15 +39,15 @@ function isAccountPrivateKeyValid (privateKey: string) { } function isRemoteAccountValid (remoteAccount: any) { - return isAccountIdValid(remoteAccount.id) && + return isActivityPubUrlValid(remoteAccount.id) && isUUIDValid(remoteAccount.uuid) && isAccountTypeValid(remoteAccount.type) && - isAccountFollowingValid(remoteAccount.following) && - isAccountFollowersValid(remoteAccount.followers) && - isAccountInboxValid(remoteAccount.inbox) && - isAccountOutboxValid(remoteAccount.outbox) && + isActivityPubUrlValid(remoteAccount.following) && + isActivityPubUrlValid(remoteAccount.followers) && + isActivityPubUrlValid(remoteAccount.inbox) && + isActivityPubUrlValid(remoteAccount.outbox) && isAccountPreferredUsernameValid(remoteAccount.preferredUsername) && - isAccountUrlValid(remoteAccount.url) && + isActivityPubUrlValid(remoteAccount.url) && isAccountPublicKeyObjectValid(remoteAccount.publicKey) && isAccountEndpointsObjectValid(remoteAccount.endpoints) } @@ -113,19 +77,10 @@ function isAccountAcceptActivityValid (activity: any) { export { isAccountEndpointsObjectValid, - isAccountSharedInboxValid, isAccountPublicKeyObjectValid, - isAccountPublicKeyIdValid, isAccountTypeValid, - isAccountPublicKeyOwnerValid, isAccountPublicKeyValid, - isAccountIdValid, - isAccountFollowingValid, - isAccountFollowersValid, - isAccountInboxValid, - isAccountOutboxValid, isAccountPreferredUsernameValid, - isAccountUrlValid, isAccountPrivateKeyValid, isRemoteAccountValid, isAccountFollowingCountValid, diff --git a/server/helpers/custom-validators/activitypub/videos.ts b/server/helpers/custom-validators/activitypub/videos.ts index 55e79c4e8..12c672fd2 100644 --- a/server/helpers/custom-validators/activitypub/videos.ts +++ b/server/helpers/custom-validators/activitypub/videos.ts @@ -8,7 +8,6 @@ import { isVideoNSFWValid, isVideoTagValid, isVideoTruncatedDescriptionValid, - isVideoUrlValid, isVideoViewsValid } from '../videos' import { isActivityPubUrlValid, isBaseActivityValid } from './misc' @@ -77,12 +76,11 @@ export { function setValidRemoteTags (video: any) { if (Array.isArray(video.tag) === false) return false - const newTag = video.tag.filter(t => { + video.tag = video.tag.filter(t => { return t.type === 'Hashtag' && isVideoTagValid(t.name) }) - video.tag = newTag return true } @@ -96,7 +94,7 @@ function isRemoteVideoContentValid (mediaType: string, content: string) { function isRemoteVideoIconValid (icon: any) { return icon.type === 'Image' && - isVideoUrlValid(icon.url) && + isActivityPubUrlValid(icon.url) && icon.mediaType === 'image/jpeg' && validator.isInt(icon.width + '', { min: 0 }) && validator.isInt(icon.height + '', { min: 0 }) @@ -105,8 +103,7 @@ function isRemoteVideoIconValid (icon: any) { function setValidRemoteVideoUrls (video: any) { if (Array.isArray(video.url) === false) return false - const newUrl = video.url.filter(u => isRemoteVideoUrlValid(u)) - video.url = newUrl + video.url = video.url.filter(u => isRemoteVideoUrlValid(u)) return true } @@ -115,13 +112,13 @@ function isRemoteVideoUrlValid (url: any) { return url.type === 'Link' && ( ACTIVITY_PUB.URL_MIME_TYPES.VIDEO.indexOf(url.mimeType) !== -1 && - isVideoUrlValid(url.url) && + isActivityPubUrlValid(url.url) && validator.isInt(url.width + '', { min: 0 }) && validator.isInt(url.size + '', { min: 0 }) ) || ( ACTIVITY_PUB.URL_MIME_TYPES.TORRENT.indexOf(url.mimeType) !== -1 && - isVideoUrlValid(url.url) && + isActivityPubUrlValid(url.url) && validator.isInt(url.width + '', { min: 0 }) ) || ( diff --git a/server/helpers/custom-validators/video-channels.ts b/server/helpers/custom-validators/video-channels.ts index 267d987fc..3de9f041b 100644 --- a/server/helpers/custom-validators/video-channels.ts +++ b/server/helpers/custom-validators/video-channels.ts @@ -1,21 +1,13 @@ -import * as Bluebird from 'bluebird' import * as express from 'express' import 'express-validator' import 'multer' import * as validator from 'validator' - import { CONSTRAINTS_FIELDS, database as db } from '../../initializers' import { VideoChannelInstance } from '../../models' -import { logger } from '../logger' -import { isActivityPubUrlValid } from './index' import { exists } from './misc' const VIDEO_CHANNELS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_CHANNELS -function isVideoChannelUrlValid (value: string) { - return isActivityPubUrlValid(value) -} - function isVideoChannelDescriptionValid (value: string) { return value === null || validator.isLength(value, VIDEO_CHANNELS_CONSTRAINTS_FIELDS.DESCRIPTION) } @@ -24,31 +16,7 @@ function isVideoChannelNameValid (value: string) { return exists(value) && validator.isLength(value, VIDEO_CHANNELS_CONSTRAINTS_FIELDS.NAME) } -function checkVideoChannelExists (id: string, res: express.Response, callback: () => void) { - let promise: Bluebird - if (validator.isInt(id)) { - promise = db.VideoChannel.loadAndPopulateAccount(+id) - } else { // UUID - promise = db.VideoChannel.loadByUUIDAndPopulateAccount(id) - } - - promise.then(videoChannel => { - if (!videoChannel) { - return res.status(404) - .json({ error: 'Video channel not found' }) - .end() - } - - res.locals.videoChannel = videoChannel - callback() - }) - .catch(err => { - logger.error('Error in video channel request validator.', err) - return res.sendStatus(500) - }) -} - -async function isVideoChannelExistsPromise (id: string, res: express.Response) { +async function isVideoChannelExist (id: string, res: express.Response) { let videoChannel: VideoChannelInstance if (validator.isInt(id)) { videoChannel = await db.VideoChannel.loadAndPopulateAccount(+id) @@ -72,8 +40,6 @@ async function isVideoChannelExistsPromise (id: string, res: express.Response) { export { isVideoChannelDescriptionValid, - checkVideoChannelExists, isVideoChannelNameValid, - isVideoChannelExistsPromise, - isVideoChannelUrlValid + isVideoChannelExist } diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index 276354626..f13178c54 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts @@ -1,4 +1,3 @@ -import * as Bluebird from 'bluebird' import { Response } from 'express' import 'express-validator' import { values } from 'lodash' @@ -6,12 +5,10 @@ import 'multer' import * as validator from 'validator' import { VideoRateType } from '../../../shared' import { CONSTRAINTS_FIELDS, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_RATE_TYPES } from '../../initializers' +import { VIDEO_PRIVACIES } from '../../initializers/constants' import { database as db } from '../../initializers/database' import { VideoInstance } from '../../models/video/video-interface' -import { logger } from '../logger' -import { isActivityPubUrlValid } from './activitypub/misc' import { exists, isArray } from './misc' -import { VIDEO_PRIVACIES } from '../../initializers/constants' const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES @@ -20,10 +17,6 @@ function isVideoCategoryValid (value: number) { return VIDEO_CATEGORIES[value] !== undefined } -function isVideoUrlValid (value: string) { - return isActivityPubUrlValid(value) -} - function isVideoLicenceValid (value: number) { return VIDEO_LICENCES[value] !== undefined } @@ -106,31 +99,7 @@ function isVideoFileSizeValid (value: string) { return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE) } -function checkVideoExists (id: string, res: Response, callback: () => void) { - let promise: Bluebird - if (validator.isInt(id)) { - promise = db.Video.loadAndPopulateAccountAndServerAndTags(+id) - } else { // UUID - promise = db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(id) - } - - promise.then(video => { - if (!video) { - return res.status(404) - .json({ error: 'Video not found' }) - .end() - } - - res.locals.video = video - callback() - }) - .catch(err => { - logger.error('Error in video request validator.', err) - return res.sendStatus(500) - }) -} - -async function isVideoExistsPromise (id: string, res: Response) { +async function isVideoExist (id: string, res: Response) { let video: VideoInstance if (validator.isInt(id)) { @@ -169,10 +138,8 @@ export { isVideoRatingTypeValid, isVideoDurationValid, isVideoTagValid, - isVideoUrlValid, isVideoPrivacyValid, isVideoFileResolutionValid, isVideoFileSizeValid, - checkVideoExists, - isVideoExistsPromise + isVideoExist } diff --git a/server/middlewares/async.ts b/server/middlewares/async.ts index 9692f9be7..534891899 100644 --- a/server/middlewares/async.ts +++ b/server/middlewares/async.ts @@ -1,9 +1,12 @@ -import { Request, Response, NextFunction, RequestHandler } from 'express' import { eachSeries } from 'async' +import { NextFunction, Request, RequestHandler, Response } from 'express' // Syntactic sugar to avoid try/catch in express controllers // Thanks: https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016 -function asyncMiddleware (fun: RequestHandler | RequestHandler[]) { + +export type RequestPromiseHandler = (req: Request, res: Response, next: NextFunction) => Promise + +function asyncMiddleware (fun: RequestPromiseHandler | RequestPromiseHandler[]) { return (req: Request, res: Response, next: NextFunction) => { if (Array.isArray(fun) === true) { return eachSeries(fun as RequestHandler[], (f, cb) => { diff --git a/server/middlewares/validators/account.ts b/server/middlewares/validators/account.ts index 47ed6a7bb..70f4e4d3b 100644 --- a/server/middlewares/validators/account.ts +++ b/server/middlewares/validators/account.ts @@ -1,18 +1,19 @@ import * as express from 'express' import { param } from 'express-validator/check' -import { logger } from '../../helpers' -import { checkLocalAccountNameExists, isAccountNameValid } from '../../helpers/custom-validators/accounts' -import { checkErrors } from './utils' +import { logger, isLocalAccountNameExist } from '../../helpers' +import { isAccountNameValid } from '../../helpers/custom-validators/accounts' +import { areValidationErrors } from './utils' const localAccountValidator = [ param('name').custom(isAccountNameValid).withMessage('Should have a valid account name'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking localAccountValidator parameters', { parameters: req.params }) - checkErrors(req, res, () => { - checkLocalAccountNameExists(req.params.name, res, next) - }) + if (areValidationErrors(req, res)) return + if (!await isLocalAccountNameExist(req.params.name, res)) return + + return next() } ] diff --git a/server/middlewares/validators/activitypub/activity.ts b/server/middlewares/validators/activitypub/activity.ts index 0de8b2d85..8aa82298c 100644 --- a/server/middlewares/validators/activitypub/activity.ts +++ b/server/middlewares/validators/activitypub/activity.ts @@ -1,7 +1,7 @@ import * as express from 'express' import { body } from 'express-validator/check' import { isRootActivityValid, logger } from '../../../helpers' -import { checkErrors } from '../utils' +import { areValidationErrors } from '../utils' const activityPubValidator = [ body('').custom((value, { req }) => isRootActivityValid(req.body)), @@ -9,7 +9,9 @@ const activityPubValidator = [ (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking activity pub parameters', { parameters: req.body }) - checkErrors(req, res, next) + if (areValidationErrors(req, res)) return + + return next() } ] diff --git a/server/middlewares/validators/activitypub/signature.ts b/server/middlewares/validators/activitypub/signature.ts index 0ce15c1f6..360685512 100644 --- a/server/middlewares/validators/activitypub/signature.ts +++ b/server/middlewares/validators/activitypub/signature.ts @@ -1,14 +1,7 @@ -import { body } from 'express-validator/check' import * as express from 'express' - -import { - logger, - isDateValid, - isSignatureTypeValid, - isSignatureCreatorValid, - isSignatureValueValid -} from '../../../helpers' -import { checkErrors } from '../utils' +import { body } from 'express-validator/check' +import { isDateValid, isSignatureCreatorValid, isSignatureTypeValid, isSignatureValueValid, logger } from '../../../helpers' +import { areValidationErrors } from '../utils' const signatureValidator = [ body('signature.type').custom(isSignatureTypeValid).withMessage('Should have a valid signature type'), @@ -19,7 +12,9 @@ const signatureValidator = [ (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking activitypub signature parameter', { parameters: { signature: req.body.signature } }) - checkErrors(req, res, next) + if (areValidationErrors(req, res)) return + + return next() } ] diff --git a/server/middlewares/validators/follows.ts b/server/middlewares/validators/follows.ts index ddc4c1de1..605872ecf 100644 --- a/server/middlewares/validators/follows.ts +++ b/server/middlewares/validators/follows.ts @@ -4,7 +4,7 @@ import { isTestInstance } from '../../helpers/core-utils' import { isEachUniqueHostValid } from '../../helpers/custom-validators/servers' import { logger } from '../../helpers/logger' import { CONFIG, database as db } from '../../initializers' -import { checkErrors } from './utils' +import { areValidationErrors } from './utils' import { getServerAccount } from '../../helpers/utils' import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' @@ -23,34 +23,30 @@ const followValidator = [ logger.debug('Checking follow parameters', { parameters: req.body }) - checkErrors(req, res, next) + if (areValidationErrors(req, res)) return + + return next() } ] const removeFollowingValidator = [ param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking unfollow parameters', { parameters: req.params }) - checkErrors(req, res, async () => { - try { - const serverAccount = await getServerAccount() - const follow = await db.AccountFollow.loadByAccountAndTarget(serverAccount.id, req.params.accountId) + if (areValidationErrors(req, res)) return - if (!follow) { - return res.status(404) - .end() - } + const serverAccount = await getServerAccount() + const follow = await db.AccountFollow.loadByAccountAndTarget(serverAccount.id, req.params.accountId) - res.locals.follow = follow + if (!follow) { + return res.status(404) + .end() + } - return next() - } catch (err) { - logger.error('Error in remove following validator.', err) - return res.sendStatus(500) - } - }) + res.locals.follow = follow + return next() } ] diff --git a/server/middlewares/validators/oembed.ts b/server/middlewares/validators/oembed.ts index f8e34d2d4..31f06dc65 100644 --- a/server/middlewares/validators/oembed.ts +++ b/server/middlewares/validators/oembed.ts @@ -1,15 +1,10 @@ -import { query } from 'express-validator/check' import * as express from 'express' +import { query } from 'express-validator/check' import { join } from 'path' - -import { checkErrors } from './utils' +import { isIdOrUUIDValid, isTestInstance, logger } from '../../helpers' import { CONFIG } from '../../initializers' -import { - logger, - isTestInstance, - checkVideoExists, - isIdOrUUIDValid -} from '../../helpers' +import { areValidationErrors } from './utils' +import { isVideoExist } from '../../helpers/custom-validators/videos' const urlShouldStartWith = CONFIG.WEBSERVER.SCHEME + '://' + join(CONFIG.WEBSERVER.HOST, 'videos', 'watch') + '/' const videoWatchRegex = new RegExp('([^/]+)$') @@ -29,33 +24,35 @@ const oembedValidator = [ query('maxheight').optional().isInt().withMessage('Should have a valid max height'), query('format').optional().isIn([ 'xml', 'json' ]).withMessage('Should have a valid format'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking oembed parameters', { parameters: req.query }) - checkErrors(req, res, () => { - if (req.query.format !== undefined && req.query.format !== 'json') { - return res.status(501) - .json({ error: 'Requested format is not implemented on server.' }) - .end() - } + if (areValidationErrors(req, res)) return - const startIsOk = req.query.url.startsWith(urlShouldStartWith) - const matches = videoWatchRegex.exec(req.query.url) - if (startIsOk === false || matches === null) { - return res.status(400) - .json({ error: 'Invalid url.' }) - .end() - } + if (req.query.format !== undefined && req.query.format !== 'json') { + return res.status(501) + .json({ error: 'Requested format is not implemented on server.' }) + .end() + } - const videoId = matches[1] - if (isIdOrUUIDValid(videoId) === false) { - return res.status(400) - .json({ error: 'Invalid video id.' }) - .end() - } + const startIsOk = req.query.url.startsWith(urlShouldStartWith) + const matches = videoWatchRegex.exec(req.query.url) + if (startIsOk === false || matches === null) { + return res.status(400) + .json({ error: 'Invalid url.' }) + .end() + } - checkVideoExists(videoId, res, next) - }) + const videoId = matches[1] + if (isIdOrUUIDValid(videoId) === false) { + return res.status(400) + .json({ error: 'Invalid video id.' }) + .end() + } + + if (!await isVideoExist(videoId, res)) return + + return next() } ] diff --git a/server/middlewares/validators/pagination.ts b/server/middlewares/validators/pagination.ts index a5a542cdf..0895b4eb8 100644 --- a/server/middlewares/validators/pagination.ts +++ b/server/middlewares/validators/pagination.ts @@ -1,8 +1,7 @@ -import { query } from 'express-validator/check' import * as express from 'express' - -import { checkErrors } from './utils' +import { query } from 'express-validator/check' import { logger } from '../../helpers' +import { areValidationErrors } from './utils' const paginationValidator = [ query('start').optional().isInt().withMessage('Should have a number start'), @@ -11,7 +10,9 @@ const paginationValidator = [ (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking pagination parameters', { parameters: req.query }) - checkErrors(req, res, next) + if (areValidationErrors(req, res)) return + + return next() } ] diff --git a/server/middlewares/validators/sort.ts b/server/middlewares/validators/sort.ts index 6fea41bb8..636f68885 100644 --- a/server/middlewares/validators/sort.ts +++ b/server/middlewares/validators/sort.ts @@ -1,9 +1,9 @@ import { query } from 'express-validator/check' import * as express from 'express' -import { checkErrors } from './utils' import { logger } from '../../helpers' import { SORTABLE_COLUMNS } from '../../initializers' +import { areValidationErrors } from './utils' // Initialize constants here for better performances const SORTABLE_USERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USERS) @@ -43,7 +43,9 @@ function checkSort (sortableColumns: string[]) { (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking sort parameters', { parameters: req.query }) - checkErrors(req, res, next) + if (areValidationErrors(req, res)) return + + return next() } ] } diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts index 6b845f62b..ac7435b7d 100644 --- a/server/middlewares/validators/users.ts +++ b/server/middlewares/validators/users.ts @@ -1,22 +1,19 @@ -import { body, param } from 'express-validator/check' -import 'express-validator' import * as express from 'express' -import * as Promise from 'bluebird' -import * as validator from 'validator' - -import { database as db } from '../../initializers/database' -import { checkErrors } from './utils' +import 'express-validator' +import { body, param } from 'express-validator/check' import { - isSignupAllowed, - logger, - isUserUsernameValid, - isUserPasswordValid, - isUserVideoQuotaValid, - isUserDisplayNSFWValid, isIdOrUUIDValid, - isUserRoleValid + isSignupAllowed, + isUserDisplayNSFWValid, + isUserPasswordValid, + isUserRoleValid, + isUserUsernameValid, + isUserVideoQuotaValid, + logger } from '../../helpers' -import { UserInstance, VideoInstance } from '../../models' +import { isVideoExist } from '../../helpers/custom-validators/videos' +import { database as db } from '../../initializers/database' +import { areValidationErrors } from './utils' const usersAddValidator = [ body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'), @@ -25,12 +22,13 @@ const usersAddValidator = [ body('videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'), body('role').custom(isUserRoleValid).withMessage('Should have a valid role'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking usersAdd parameters', { parameters: req.body }) - checkErrors(req, res, () => { - checkUserDoesNotAlreadyExist(req.body.username, req.body.email, res, next) - }) + if (areValidationErrors(req, res)) return + if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return + + return next() } ] @@ -39,37 +37,33 @@ const usersRegisterValidator = [ body('password').custom(isUserPasswordValid).withMessage('Should have a valid password'), body('email').isEmail().withMessage('Should have a valid email'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking usersRegister parameters', { parameters: req.body }) - checkErrors(req, res, () => { - checkUserDoesNotAlreadyExist(req.body.username, req.body.email, res, next) - }) + if (areValidationErrors(req, res)) return + if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return + + return next() } ] const usersRemoveValidator = [ param('id').isInt().not().isEmpty().withMessage('Should have a valid id'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking usersRemove parameters', { parameters: req.params }) - checkErrors(req, res, () => { - checkUserExists(req.params.id, res, (err, user) => { - if (err) { - logger.error('Error in usersRemoveValidator.', err) - return res.sendStatus(500) - } + if (areValidationErrors(req, res)) return + if (!await checkUserIdExist(req.params.id, res)) return - if (user.username === 'root') { - return res.status(400) - .send({ error: 'Cannot remove the root user' }) - .end() - } + const user = res.locals.user + if (user.username === 'root') { + return res.status(400) + .send({ error: 'Cannot remove the root user' }) + .end() + } - return next() - }) - }) + return next() } ] @@ -79,12 +73,13 @@ const usersUpdateValidator = [ body('videoQuota').optional().custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'), body('role').optional().custom(isUserRoleValid).withMessage('Should have a valid role'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking usersUpdate parameters', { parameters: req.body }) - checkErrors(req, res, () => { - checkUserExists(req.params.id, res, next) - }) + if (areValidationErrors(req, res)) return + if (!await checkUserIdExist(req.params.id, res)) return + + return next() } ] @@ -97,64 +92,48 @@ const usersUpdateMeValidator = [ // TODO: Add old password verification logger.debug('Checking usersUpdateMe parameters', { parameters: req.body }) - checkErrors(req, res, next) + if (areValidationErrors(req, res)) return + + return next() } ] const usersGetValidator = [ param('id').isInt().not().isEmpty().withMessage('Should have a valid id'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { - checkErrors(req, res, () => { - checkUserExists(req.params.id, res, next) - }) + async (req: express.Request, res: express.Response, next: express.NextFunction) => { + logger.debug('Checking usersGet parameters', { parameters: req.body }) + + if (areValidationErrors(req, res)) return + if (!await checkUserIdExist(req.params.id, res)) return + + return next() } ] const usersVideoRatingValidator = [ param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking usersVideoRating parameters', { parameters: req.params }) - checkErrors(req, res, () => { - let videoPromise: Promise + if (areValidationErrors(req, res)) return + if (!await isVideoExist(req.params.videoId, res)) return - if (validator.isUUID(req.params.videoId)) { - videoPromise = db.Video.loadByUUID(req.params.videoId) - } else { - videoPromise = db.Video.load(req.params.videoId) - } - - videoPromise - .then(video => { - if (!video) { - return res.status(404) - .json({ error: 'Video not found' }) - .end() - } - - return next() - }) - .catch(err => { - logger.error('Error in user request validator.', err) - return res.sendStatus(500) - }) - }) + return next() } ] const ensureUserRegistrationAllowed = [ - (req: express.Request, res: express.Response, next: express.NextFunction) => { - isSignupAllowed().then(allowed => { - if (allowed === false) { - return res.status(403) - .send({ error: 'User registration is not enabled or user limit is reached.' }) - .end() - } + async (req: express.Request, res: express.Response, next: express.NextFunction) => { + const allowed = await isSignupAllowed() + if (allowed === false) { + return res.status(403) + .send({ error: 'User registration is not enabled or user limit is reached.' }) + .end() + } - return next() - }) + return next() } ] @@ -173,37 +152,30 @@ export { // --------------------------------------------------------------------------- -function checkUserExists (id: number, res: express.Response, callback: (err: Error, user: UserInstance) => void) { - db.User.loadById(id) - .then(user => { - if (!user) { - return res.status(404) - .send({ error: 'User not found' }) - .end() - } +async function checkUserIdExist (id: number, res: express.Response) { + const user = await db.User.loadById(id) - res.locals.user = user - return callback(null, user) - }) - .catch(err => { - logger.error('Error in user request validator.', err) - return res.sendStatus(500) - }) + if (!user) { + res.status(404) + .send({ error: 'User not found' }) + .end() + + return false + } + + res.locals.user = user + return true } -function checkUserDoesNotAlreadyExist (username: string, email: string, res: express.Response, callback: () => void) { - db.User.loadByUsernameOrEmail(username, email) - .then(user => { - if (user) { - return res.status(409) - .send({ error: 'User with this username of email already exists.' }) - .end() - } +async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email: string, res: express.Response) { + const user = await db.User.loadByUsernameOrEmail(username, email) - return callback() - }) - .catch(err => { - logger.error('Error in usersAdd request validator.', err) - return res.sendStatus(500) - }) + if (user) { + res.status(409) + .send({ error: 'User with this username of email already exists.' }) + .end() + return false + } + + return true } diff --git a/server/middlewares/validators/utils.ts b/server/middlewares/validators/utils.ts index 77a1a0d4b..ca80acf29 100644 --- a/server/middlewares/validators/utils.ts +++ b/server/middlewares/validators/utils.ts @@ -1,19 +1,8 @@ -import { validationResult } from 'express-validator/check' import * as express from 'express' +import { validationResult } from 'express-validator/check' import { logger } from '../../helpers' -function checkErrors (req: express.Request, res: express.Response, next: express.NextFunction) { - const errors = validationResult(req) - - if (!errors.isEmpty()) { - logger.warn('Incorrect request parameters', { path: req.originalUrl, err: errors.mapped() }) - return res.status(400).json({ errors: errors.mapped() }) - } - - return next() -} - function areValidationErrors (req: express.Request, res: express.Response) { const errors = validationResult(req) @@ -30,6 +19,5 @@ function areValidationErrors (req: express.Request, res: express.Response) { // --------------------------------------------------------------------------- export { - checkErrors, areValidationErrors } diff --git a/server/middlewares/validators/video-blacklist.ts b/server/middlewares/validators/video-blacklist.ts index 3c8c31519..f1cc04950 100644 --- a/server/middlewares/validators/video-blacklist.ts +++ b/server/middlewares/validators/video-blacklist.ts @@ -1,35 +1,36 @@ -import { param } from 'express-validator/check' import * as express from 'express' - +import { param } from 'express-validator/check' +import { isIdOrUUIDValid, logger } from '../../helpers' +import { isVideoExist } from '../../helpers/custom-validators/videos' import { database as db } from '../../initializers/database' -import { checkErrors } from './utils' -import { logger, isIdOrUUIDValid, checkVideoExists } from '../../helpers' +import { VideoInstance } from '../../models/video/video-interface' +import { areValidationErrors } from './utils' const videosBlacklistRemoveValidator = [ param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking blacklistRemove parameters.', { parameters: req.params }) - checkErrors(req, res, () => { - checkVideoExists(req.params.videoId, res, () => { - checkVideoIsBlacklisted(req, res, next) - }) - }) + if (areValidationErrors(req, res)) return + if (!await isVideoExist(req.params.videoId, res)) return + if (!await checkVideoIsBlacklisted(res.locals.video, res)) return + + return next() } ] const videosBlacklistAddValidator = [ param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosBlacklist parameters', { parameters: req.params }) - checkErrors(req, res, () => { - checkVideoExists(req.params.videoId, res, () => { - checkVideoIsBlacklistable(req, res, next) - }) - }) + if (areValidationErrors(req, res)) return + if (!await isVideoExist(req.params.videoId, res)) return + if (!checkVideoIsBlacklistable(res.locals.video, res)) return + + return next() } ] @@ -41,27 +42,27 @@ export { } // --------------------------------------------------------------------------- -function checkVideoIsBlacklistable (req: express.Request, res: express.Response, callback: () => void) { - if (res.locals.video.isOwned() === true) { - return res.status(403) +function checkVideoIsBlacklistable (video: VideoInstance, res: express.Response) { + if (video.isOwned() === true) { + res.status(403) .json({ error: 'Cannot blacklist a local video' }) .end() + + return false } - callback() + return true } -function checkVideoIsBlacklisted (req: express.Request, res: express.Response, callback: () => void) { - db.BlacklistedVideo.loadByVideoId(res.locals.video.id) - .then(blacklistedVideo => { - if (!blacklistedVideo) return res.status(404).send('Blacklisted video not found') +async function checkVideoIsBlacklisted (video: VideoInstance, res: express.Response) { + const blacklistedVideo = await db.BlacklistedVideo.loadByVideoId(video.id) + if (!blacklistedVideo) { + res.status(404) + .send('Blacklisted video not found') - res.locals.blacklistedVideo = blacklistedVideo + return false + } - callback() - }) - .catch(err => { - logger.error('Error in blacklistRemove request validator', { error: err }) - return res.sendStatus(500) - }) + res.locals.blacklistedVideo = blacklistedVideo + return true } diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts index f30fbf0dc..4683c91e1 100644 --- a/server/middlewares/validators/video-channels.ts +++ b/server/middlewares/validators/video-channels.ts @@ -1,29 +1,30 @@ import * as express from 'express' import { body, param } from 'express-validator/check' import { UserRight } from '../../../shared' -import { checkAccountIdExists } from '../../helpers/custom-validators/accounts' import { isIdValid } from '../../helpers/custom-validators/misc' import { - checkVideoChannelExists, isVideoChannelDescriptionValid, - isVideoChannelExistsPromise, + isVideoChannelExist, isVideoChannelNameValid } from '../../helpers/custom-validators/video-channels' import { isIdOrUUIDValid } from '../../helpers/index' import { logger } from '../../helpers/logger' import { database as db } from '../../initializers' import { UserInstance } from '../../models' -import { areValidationErrors, checkErrors } from './utils' +import { areValidationErrors } from './utils' +import { isAccountIdExist } from '../../helpers/custom-validators/accounts' +import { VideoChannelInstance } from '../../models/video/video-channel-interface' const listVideoAccountChannelsValidator = [ param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking listVideoAccountChannelsValidator parameters', { parameters: req.body }) - checkErrors(req, res, () => { - checkAccountIdExists(req.params.accountId, res, next) - }) + if (areValidationErrors(req, res)) return + if (!await isAccountIdExist(req.params.accountId, res)) return + + return next() } ] @@ -34,7 +35,9 @@ const videoChannelsAddValidator = [ (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body }) - checkErrors(req, res, next) + if (areValidationErrors(req, res)) return + + return next() } ] @@ -43,56 +46,56 @@ const videoChannelsUpdateValidator = [ 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) => { + async (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 server' }) - .end() - } + if (areValidationErrors(req, res)) return + if (!await isVideoChannelExist(req.params.id, res)) return - if (res.locals.videoChannel.Account.userId !== res.locals.oauth.token.User.id) { - return res.status(403) - .json({ error: 'Cannot update video channel of another user' }) - .end() - } + // We need to make additional checks + if (res.locals.videoChannel.isOwned() === false) { + return res.status(403) + .json({ error: 'Cannot update video channel of another server' }) + .end() + } - next() - }) - }) + if (res.locals.videoChannel.Account.userId !== res.locals.oauth.token.User.id) { + return res.status(403) + .json({ error: 'Cannot update video channel of another user' }) + .end() + } + + return next() } ] const videoChannelsRemoveValidator = [ param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (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) - }) - }) - }) + if (areValidationErrors(req, res)) return + if (!await isVideoChannelExist(req.params.id, res)) return + + // Check if the user who did the request is able to delete the video + if (!checkUserCanDeleteVideoChannel(res.locals.user, res.locals.videoChannel, res)) return + if (!await checkVideoChannelIsNotTheLastOne(res)) return + + return next() } ] const videoChannelsGetValidator = [ param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (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) - }) + if (areValidationErrors(req, res)) return + if (!await isVideoChannelExist(req.params.id, res)) return + + return next() } ] @@ -104,7 +107,7 @@ const videoChannelsShareValidator = [ logger.debug('Checking videoChannelShare parameters', { parameters: req.params }) if (areValidationErrors(req, res)) return - if (!await isVideoChannelExistsPromise(req.params.id, res)) return + if (!await isVideoChannelExist(req.params.id, res)) return const share = await db.VideoChannelShare.load(res.locals.video.id, req.params.accountId) if (!share) { @@ -131,38 +134,40 @@ export { // --------------------------------------------------------------------------- -function checkUserCanDeleteVideoChannel (res: express.Response, callback: () => void) { - const user: UserInstance = res.locals.oauth.token.User - +function checkUserCanDeleteVideoChannel (user: UserInstance, videoChannel: VideoChannelInstance, res: express.Response) { // Retrieve the user who did the request - if (res.locals.videoChannel.isOwned() === false) { - return res.status(403) + if (videoChannel.isOwned() === false) { + res.status(403) .json({ error: 'Cannot remove video channel of another server.' }) .end() + + return false } // 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 account - if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && res.locals.videoChannel.Account.userId !== user.id) { - return res.status(403) + if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && videoChannel.Account.userId !== user.id) { + res.status(403) .json({ error: 'Cannot remove video channel of another user' }) .end() + + return false } - // If we reach this comment, we can delete the video - callback() + return true } -function checkVideoChannelIsNotTheLastOne (res: express.Response, callback: () => void) { - db.VideoChannel.countByAccount(res.locals.oauth.token.User.Account.id) - .then(count => { - if (count <= 1) { - return res.status(409) - .json({ error: 'Cannot remove the last channel of this user' }) - .end() - } +async function checkVideoChannelIsNotTheLastOne (res: express.Response) { + const count = await db.VideoChannel.countByAccount(res.locals.oauth.token.User.Account.id) - callback() - }) + if (count <= 1) { + res.status(409) + .json({ error: 'Cannot remove the last channel of this user' }) + .end() + + return false + } + + return true } diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts index 5ffc85210..3cbf98312 100644 --- a/server/middlewares/validators/videos.ts +++ b/server/middlewares/validators/videos.ts @@ -3,11 +3,11 @@ import { body, param, query } from 'express-validator/check' import { UserRight, VideoPrivacy } from '../../../shared' import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc' import { - checkVideoExists, isVideoAbuseReasonValid, isVideoCategoryValid, isVideoDescriptionValid, isVideoDurationValid, + isVideoExist, isVideoFile, isVideoLanguageValid, isVideoLicenceValid, @@ -20,12 +20,11 @@ import { 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 { authenticate } from '../oauth' -import { areValidationErrors, checkErrors } from './utils' -import { isVideoExistsPromise } from '../../helpers/index' +import { areValidationErrors } from './utils' const videosAddValidator = [ body('videofile').custom((value, { req }) => isVideoFile(req.files)).withMessage( @@ -42,68 +41,58 @@ const videosAddValidator = [ body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) - checkErrors(req, res, () => { - const videoFile: Express.Multer.File = req.files['videofile'][0] - const user = res.locals.oauth.token.User + if (areValidationErrors(req, res)) return - return db.VideoChannel.loadByIdAndAccount(req.body.channelId, user.Account.id) - .then(videoChannel => { - if (!videoChannel) { - res.status(400) - .json({ error: 'Unknown video video channel for this account.' }) - .end() + const videoFile: Express.Multer.File = req.files['videofile'][0] + const user = res.locals.oauth.token.User - return undefined - } + const videoChannel = await db.VideoChannel.loadByIdAndAccount(req.body.channelId, user.Account.id) + if (!videoChannel) { + res.status(400) + .json({ error: 'Unknown video video channel for this account.' }) + .end() - res.locals.videoChannel = videoChannel + return + } - return user.isAbleToUploadVideo(videoFile) - }) - .then(isAble => { - if (isAble === false) { - res.status(403) - .json({ error: 'The user video quota is exceeded with this video.' }) - .end() + res.locals.videoChannel = videoChannel - return undefined - } + const isAble = await user.isAbleToUploadVideo(videoFile) + if (isAble === false) { + res.status(403) + .json({ error: 'The user video quota is exceeded with this video.' }) + .end() - return getDurationFromVideoFile(videoFile.path) - .catch(err => { - logger.error('Invalid input file in videosAddValidator.', err) - res.status(400) - .json({ error: 'Invalid input file.' }) - .end() + return + } - return undefined - }) - }) - .then(duration => { - // Previous test failed, abort - if (duration === undefined) return undefined + let duration: number - if (!isVideoDurationValid('' + duration)) { - return res.status(400) - .json({ - error: 'Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).' - }) - .end() - } + try { + duration = await getDurationFromVideoFile(videoFile.path) + } catch (err) { + logger.error('Invalid input file in videosAddValidator.', err) + res.status(400) + .json({ error: 'Invalid input file.' }) + .end() - videoFile['duration'] = duration - next() - }) - .catch(err => { - logger.error('Error in video add validator', err) - res.sendStatus(500) + return + } - return undefined - }) - }) + if (!isVideoDurationValid('' + duration)) { + return res.status(400) + .json({ + error: 'Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).' + }) + .end() + } + + videoFile['duration'] = duration + + return next() } ] @@ -118,61 +107,59 @@ const videosUpdateValidator = [ body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosUpdate parameters', { parameters: req.body }) - checkErrors(req, res, () => { - checkVideoExists(req.params.id, res, () => { - const video = res.locals.video + if (areValidationErrors(req, res)) return + if (!await isVideoExist(req.params.id, res)) return - // We need to make additional checks - if (video.isOwned() === false) { - return res.status(403) - .json({ error: 'Cannot update video of another server' }) - .end() - } + const video = res.locals.video - if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) { - return res.status(403) - .json({ error: 'Cannot update video of another user' }) - .end() - } + // We need to make additional checks + if (video.isOwned() === false) { + return res.status(403) + .json({ error: 'Cannot update video of another server' }) + .end() + } - if (video.privacy !== VideoPrivacy.PRIVATE && req.body.privacy === VideoPrivacy.PRIVATE) { - return res.status(409) - .json({ error: 'Cannot set "private" a video that was not private anymore.' }) - .end() - } + if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) { + return res.status(403) + .json({ error: 'Cannot update video of another user' }) + .end() + } - next() - }) - }) + if (video.privacy !== VideoPrivacy.PRIVATE && req.body.privacy === VideoPrivacy.PRIVATE) { + return res.status(409) + .json({ error: 'Cannot set "private" a video that was not private anymore.' }) + .end() + } + + return next() } ] const videosGetValidator = [ param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosGet parameters', { parameters: req.params }) - checkErrors(req, res, () => { - checkVideoExists(req.params.id, res, () => { - const video = res.locals.video + if (areValidationErrors(req, res)) return + if (!await isVideoExist(req.params.id, res)) return - // Video is not private, anyone can access it - if (video.privacy !== VideoPrivacy.PRIVATE) return next() + const video = res.locals.video - authenticate(req, res, () => { - if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) { - return res.status(403) - .json({ error: 'Cannot get this private video of another user' }) - .end() - } + // Video is not private, anyone can access it + if (video.privacy !== VideoPrivacy.PRIVATE) return next() - next() - }) - }) + authenticate(req, res, () => { + if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) { + return res.status(403) + .json({ error: 'Cannot get this private video of another user' }) + .end() + } + + return next() }) } ] @@ -180,17 +167,16 @@ const videosGetValidator = [ const videosRemoveValidator = [ param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosRemove parameters', { parameters: req.params }) - checkErrors(req, res, () => { - checkVideoExists(req.params.id, res, () => { - // Check if the user who did the request is able to delete the video - checkUserCanDeleteVideo(res.locals.oauth.token.User, res, () => { - next() - }) - }) - }) + if (areValidationErrors(req, res)) return + if (!await isVideoExist(req.params.id, res)) return + + // Check if the user who did the request is able to delete the video + if (!checkUserCanDeleteVideo(res.locals.oauth.token.User, res.locals.video, res)) return + + return next() } ] @@ -201,7 +187,9 @@ const videosSearchValidator = [ (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videosSearch parameters', { parameters: req.params }) - checkErrors(req, res, next) + if (areValidationErrors(req, res)) return + + return next() } ] @@ -209,12 +197,13 @@ const videoAbuseReportValidator = [ 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) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videoAbuseReport parameters', { parameters: req.body }) - checkErrors(req, res, () => { - checkVideoExists(req.params.id, res, next) - }) + if (areValidationErrors(req, res)) return + if (!await isVideoExist(req.params.id, res)) return + + return next() } ] @@ -222,12 +211,13 @@ const videoRateValidator = [ 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) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking videoRate parameters', { parameters: req.body }) - checkErrors(req, res, () => { - checkVideoExists(req.params.id, res, next) - }) + if (areValidationErrors(req, res)) return + if (!await isVideoExist(req.params.id, res)) return + + return next() } ] @@ -239,7 +229,7 @@ const videosShareValidator = [ logger.debug('Checking videoShare parameters', { parameters: req.params }) if (areValidationErrors(req, res)) return - if (!await isVideoExistsPromise(req.params.id, res)) return + if (!await isVideoExist(req.params.id, res)) return const share = await db.VideoShare.load(req.params.accountId, res.locals.video.id) if (!share) { @@ -248,7 +238,6 @@ const videosShareValidator = [ } res.locals.videoShare = share - return next() } ] @@ -270,24 +259,25 @@ export { // --------------------------------------------------------------------------- -function checkUserCanDeleteVideo (user: UserInstance, res: express.Response, callback: () => void) { +function checkUserCanDeleteVideo (user: UserInstance, video: VideoInstance, res: express.Response) { // Retrieve the user who did the request - if (res.locals.video.isOwned() === false) { - return res.status(403) + if (video.isOwned() === false) { + res.status(403) .json({ error: 'Cannot remove video of another server, blacklist it' }) .end() + return false } // Check if the user can delete the video // The user can delete it if s/he is an admin // Or if s/he is the video's account - const account = res.locals.video.VideoChannel.Account + const account = video.VideoChannel.Account if (user.hasRight(UserRight.REMOVE_ANY_VIDEO) === false && account.userId !== user.id) { - return res.status(403) + res.status(403) .json({ error: 'Cannot remove video of another user' }) .end() + return false } - // If we reach this comment, we can delete the video - callback() + return true } diff --git a/server/middlewares/validators/webfinger.ts b/server/middlewares/validators/webfinger.ts index 7852c1c2b..34e62c66d 100644 --- a/server/middlewares/validators/webfinger.ts +++ b/server/middlewares/validators/webfinger.ts @@ -1,37 +1,31 @@ import * as express from 'express' import { query } from 'express-validator/check' import { isWebfingerResourceValid } from '../../helpers/custom-validators/webfinger' -import { database as db } from '../../initializers' -import { checkErrors } from './utils' import { logger } from '../../helpers/logger' +import { database as db } from '../../initializers' +import { areValidationErrors } from './utils' const webfingerValidator = [ query('resource').custom(isWebfingerResourceValid).withMessage('Should have a valid webfinger resource'), - (req: express.Request, res: express.Response, next: express.NextFunction) => { + async (req: express.Request, res: express.Response, next: express.NextFunction) => { logger.debug('Checking webfinger parameters', { parameters: req.query }) - checkErrors(req, res, () => { - // Remove 'acct:' from the beginning of the string - const nameWithHost = req.query.resource.substr(5) - const [ name ] = nameWithHost.split('@') + if (areValidationErrors(req, res)) return - db.Account.loadLocalByName(name) - .then(account => { - if (!account) { - return res.status(404) - .send({ error: 'Account not found' }) - .end() - } + // Remove 'acct:' from the beginning of the string + const nameWithHost = req.query.resource.substr(5) + const [ name ] = nameWithHost.split('@') - res.locals.account = account - return next() - }) - .catch(err => { - logger.error('Error in webfinger validator.', err) - return res.sendStatus(500) - }) - }) + const account = await db.Account.loadLocalByName(name) + if (!account) { + return res.status(404) + .send({ error: 'Account not found' }) + .end() + } + + res.locals.account = account + return next() } ] diff --git a/server/models/account/account.ts b/server/models/account/account.ts index fff3ce087..c721656cb 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts @@ -2,17 +2,12 @@ import * as Sequelize from 'sequelize' import { activityPubContextify, isAccountFollowersCountValid, - isAccountFollowersValid, isAccountFollowingCountValid, - isAccountFollowingValid, - isAccountInboxValid, - isAccountOutboxValid, isAccountPrivateKeyValid, isAccountPublicKeyValid, - isAccountSharedInboxValid, - isAccountUrlValid, isUserUsernameValid } from '../../helpers' +import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' import { CONFIG, CONSTRAINTS_FIELDS } from '../../initializers/constants' import { sendDeleteAccount } from '../../lib/activitypub/send/send-delete' @@ -61,7 +56,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes allowNull: false, validate: { urlValid: value => { - const res = isAccountUrlValid(value) + const res = isActivityPubUrlValid(value) if (res === false) throw new Error('URL is not valid.') } } @@ -111,7 +106,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes allowNull: false, validate: { inboxUrlValid: value => { - const res = isAccountInboxValid(value) + const res = isActivityPubUrlValid(value) if (res === false) throw new Error('Inbox URL is not valid.') } } @@ -121,7 +116,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes allowNull: false, validate: { outboxUrlValid: value => { - const res = isAccountOutboxValid(value) + const res = isActivityPubUrlValid(value) if (res === false) throw new Error('Outbox URL is not valid.') } } @@ -131,7 +126,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes allowNull: false, validate: { sharedInboxUrlValid: value => { - const res = isAccountSharedInboxValid(value) + const res = isActivityPubUrlValid(value) if (res === false) throw new Error('Shared inbox URL is not valid.') } } @@ -141,7 +136,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes allowNull: false, validate: { followersUrlValid: value => { - const res = isAccountFollowersValid(value) + const res = isActivityPubUrlValid(value) if (res === false) throw new Error('Followers URL is not valid.') } } @@ -151,7 +146,7 @@ export default function defineAccount (sequelize: Sequelize.Sequelize, DataTypes allowNull: false, validate: { followingUrlValid: value => { - const res = isAccountFollowingValid(value) + const res = isActivityPubUrlValid(value) if (res === false) throw new Error('Following URL is not valid.') } } diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index e11268b2c..54f12dce3 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts @@ -1,6 +1,5 @@ import * as Sequelize from 'sequelize' import { isVideoChannelDescriptionValid, isVideoChannelNameValid } from '../../helpers' -import { isVideoChannelUrlValid } from '../../helpers/custom-validators/video-channels' import { CONSTRAINTS_FIELDS } from '../../initializers/constants' import { sendDeleteVideoChannel } from '../../lib/activitypub/send/send-delete' @@ -8,6 +7,7 @@ import { addMethodsToModel, getSort } from '../utils' import { VideoChannelAttributes, VideoChannelInstance, VideoChannelMethods } from './video-channel-interface' import { getAnnounceActivityPubUrl } from '../../lib/activitypub/url' import { activityPubCollection } from '../../helpers/activitypub' +import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' let VideoChannel: Sequelize.Model let toFormattedJSON: VideoChannelMethods.ToFormattedJSON @@ -66,7 +66,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da allowNull: false, validate: { urlValid: value => { - const res = isVideoChannelUrlValid(value) + const res = isActivityPubUrlValid(value) if (res === false) throw new Error('Video channel URL is not valid.') } } diff --git a/server/models/video/video.ts b/server/models/video/video.ts index 4956b57ee..3f416d04c 100644 --- a/server/models/video/video.ts +++ b/server/models/video/video.ts @@ -7,7 +7,18 @@ import * as Sequelize from 'sequelize' import { VideoPrivacy, VideoResolution } from '../../../shared' import { VideoTorrentObject } from '../../../shared/models/activitypub/objects/video-torrent-object' import { activityPubCollection } from '../../helpers/activitypub' -import { isVideoCategoryValid, isVideoLanguageValid, isVideoPrivacyValid, isVideoUrlValid } from '../../helpers/custom-validators/videos' +import { createTorrentPromise, renamePromise, statPromise, unlinkPromise, writeFilePromise } from '../../helpers/core-utils' +import { isVideoCategoryValid, isVideoLanguageValid, isVideoPrivacyValid } from '../../helpers/custom-validators/videos' +import { generateImageFromVideoFile, getVideoFileHeight, transcode } from '../../helpers/ffmpeg-utils' +import { + isActivityPubUrlValid, + isVideoDescriptionValid, + isVideoDurationValid, + isVideoLicenceValid, + isVideoNameValid, + isVideoNSFWValid +} from '../../helpers/index' +import { logger } from '../../helpers/logger' import { API_VERSION, CONFIG, @@ -21,18 +32,12 @@ import { VIDEO_LICENCES, VIDEO_PRIVACIES } from '../../initializers/constants' +import { getAnnounceActivityPubUrl } from '../../lib/activitypub/url' import { sendDeleteVideo } from '../../lib/index' - import { addMethodsToModel, getSort } from '../utils' - import { TagInstance } from './tag-interface' import { VideoFileInstance, VideoFileModel } from './video-file-interface' import { VideoAttributes, VideoInstance, VideoMethods } from './video-interface' -import { isVideoNameValid, isVideoLicenceValid, isVideoNSFWValid, isVideoDescriptionValid, isVideoDurationValid } from '../../helpers/index' -import { logger } from '../../helpers/logger' -import { generateImageFromVideoFile, transcode, getVideoFileHeight } from '../../helpers/ffmpeg-utils' -import { createTorrentPromise, writeFilePromise, unlinkPromise, renamePromise, statPromise } from '../../helpers/core-utils' -import { getAnnounceActivityPubUrl } from '../../lib/activitypub/url' let Video: Sequelize.Model let getOriginalFile: VideoMethods.GetOriginalFile @@ -205,7 +210,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da allowNull: false, validate: { urlValid: value => { - const res = isVideoUrlValid(value) + const res = isActivityPubUrlValid(value) if (res === false) throw new Error('Video URL is not valid.') } } diff --git a/support/doc/server/code.md b/support/doc/server/code.md index f0ed62acc..7233eaf5b 100644 --- a/support/doc/server/code.md +++ b/support/doc/server/code.md @@ -55,10 +55,10 @@ If you want to test the decentralization feature, you can easily run 3 instances The server is composed by: - * a REST API (throught Express framework) + * a REST API (Express framework) * a WebTorrent Tracker -A video is seeded by the server throught the [WebSeed](http://www.bittorrent.org/beps/bep_0019.html) protocol (HTTP). +A video is seeded by the server with the [WebSeed](http://www.bittorrent.org/beps/bep_0019.html) protocol (HTTP). ![Architecture scheme](https://github.com/Chocobozzz/PeerTube/blob/master/support/doc/server/upload-video.png)