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)
)
)
activityPubClientRouter.get('/video-channels/:id',
- executeIfActivityPub(videoChannelsGetValidator),
+ executeIfActivityPub(asyncMiddleware(videoChannelsGetValidator)),
executeIfActivityPub(asyncMiddleware(videoChannelController))
)
serverFollowsRouter.delete('/following/:accountId',
authenticate,
ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
- removeFollowingValidator,
+ asyncMiddleware(removeFollowingValidator),
asyncMiddleware(removeFollow)
)
usersRouter.get('/me/videos/:videoId/rating',
authenticate,
- usersVideoRatingValidator,
+ asyncMiddleware(usersVideoRatingValidator),
asyncMiddleware(getUserVideoRating)
)
)
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)
)
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)
)
)
abuseVideoRouter.post('/:id/abuse',
authenticate,
- videoAbuseReportValidator,
+ asyncMiddleware(videoAbuseReportValidator),
asyncMiddleware(reportVideoAbuseRetryWrapper)
)
blacklistRouter.post('/:videoId/blacklist',
authenticate,
ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST),
- videosBlacklistAddValidator,
+ asyncMiddleware(videosBlacklistAddValidator),
asyncMiddleware(addVideoToBlacklist)
)
blacklistRouter.delete('/:videoId/blacklist',
authenticate,
ensureUserHasRight(UserRight.MANAGE_VIDEO_BLACKLIST),
- videosBlacklistRemoveValidator,
+ asyncMiddleware(videosBlacklistRemoveValidator),
asyncMiddleware(removeVideoFromBlacklistController)
)
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,
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()
)
videoChannelRouter.get('/accounts/:accountId/channels',
- listVideoAccountChannelsValidator,
+ asyncMiddleware(listVideoAccountChannelsValidator),
asyncMiddleware(listVideoAccountChannels)
)
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)
)
)
videosRouter.put('/:id',
authenticate,
- videosUpdateValidator,
+ asyncMiddleware(videosUpdateValidator),
asyncMiddleware(updateVideoRetryWrapper)
)
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)
)
rateVideoRouter.put('/:id/rate',
authenticate,
- videoRateValidator,
+ asyncMiddleware(videoRateValidator),
asyncMiddleware(rateVideoRetryWrapper)
)
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
+)
// ---------------------------------------------------------------------------
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
)
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<AccountInstance>
if (validator.isInt('' + id)) {
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<AccountInstance>, res: express.Response, callback: (err: Error, account: AccountInstance) => any) {
- p.then(account => {
- if (!account) {
- return res.status(404)
- .send({ error: 'Account not found' })
- .end()
- }
-
- res.locals.account = account
- return callback(null, account)
- })
- .catch(err => {
- logger.error('Error in account request validator.', err)
- return res.sendStatus(500)
- })
+async function isAccountExist (p: Bluebird<AccountInstance>, res: Response) {
+ const account = await p
+
+ 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
}
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' &&
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' &&
}
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)
}
export {
isAccountEndpointsObjectValid,
- isAccountSharedInboxValid,
isAccountPublicKeyObjectValid,
- isAccountPublicKeyIdValid,
isAccountTypeValid,
- isAccountPublicKeyOwnerValid,
isAccountPublicKeyValid,
- isAccountIdValid,
- isAccountFollowingValid,
- isAccountFollowersValid,
- isAccountInboxValid,
- isAccountOutboxValid,
isAccountPreferredUsernameValid,
- isAccountUrlValid,
isAccountPrivateKeyValid,
isRemoteAccountValid,
isAccountFollowingCountValid,
isVideoNSFWValid,
isVideoTagValid,
isVideoTruncatedDescriptionValid,
- isVideoUrlValid,
isVideoViewsValid
} from '../videos'
import { isActivityPubUrlValid, isBaseActivityValid } from './misc'
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
}
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 })
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
}
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 })
) ||
(
-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)
}
return exists(value) && validator.isLength(value, VIDEO_CHANNELS_CONSTRAINTS_FIELDS.NAME)
}
-function checkVideoChannelExists (id: string, res: express.Response, callback: () => void) {
- let promise: Bluebird<VideoChannelInstance>
- 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)
export {
isVideoChannelDescriptionValid,
- checkVideoChannelExists,
isVideoChannelNameValid,
- isVideoChannelExistsPromise,
- isVideoChannelUrlValid
+ isVideoChannelExist
}
-import * as Bluebird from 'bluebird'
import { Response } from 'express'
import 'express-validator'
import { values } from 'lodash'
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
return VIDEO_CATEGORIES[value] !== undefined
}
-function isVideoUrlValid (value: string) {
- return isActivityPubUrlValid(value)
-}
-
function isVideoLicenceValid (value: number) {
return VIDEO_LICENCES[value] !== undefined
}
return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
}
-function checkVideoExists (id: string, res: Response, callback: () => void) {
- let promise: Bluebird<VideoInstance>
- 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)) {
isVideoRatingTypeValid,
isVideoDurationValid,
isVideoTagValid,
- isVideoUrlValid,
isVideoPrivacyValid,
isVideoFileResolutionValid,
isVideoFileSizeValid,
- checkVideoExists,
- isVideoExistsPromise
+ isVideoExist
}
-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<any>
+
+function asyncMiddleware (fun: RequestPromiseHandler | RequestPromiseHandler[]) {
return (req: Request, res: Response, next: NextFunction) => {
if (Array.isArray(fun) === true) {
return eachSeries(fun as RequestHandler[], (f, cb) => {
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()
}
]
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)),
(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()
}
]
-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'),
(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()
}
]
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'
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()
}
]
-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('([^/]+)$')
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
+
+ if (req.query.format !== undefined && req.query.format !== 'json') {
+ return res.status(501)
+ .json({ error: 'Requested format is not implemented on server.' })
+ .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()
+ }
- 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()
- }
+ const videoId = matches[1]
+ if (isIdOrUUIDValid(videoId) === false) {
+ return res.status(400)
+ .json({ error: 'Invalid video id.' })
+ .end()
+ }
- const videoId = matches[1]
- if (isIdOrUUIDValid(videoId) === false) {
- return res.status(400)
- .json({ error: 'Invalid video id.' })
- .end()
- }
+ if (!await isVideoExist(videoId, res)) return
- checkVideoExists(videoId, res, next)
- })
+ return next()
}
]
-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'),
(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()
}
]
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)
(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()
}
]
}
-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 {
+ isIdOrUUIDValid,
isSignupAllowed,
- logger,
- isUserUsernameValid,
+ isUserDisplayNSFWValid,
isUserPasswordValid,
+ isUserRoleValid,
+ isUserUsernameValid,
isUserVideoQuotaValid,
- isUserDisplayNSFWValid,
- isIdOrUUIDValid,
- isUserRoleValid
+ 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)'),
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()
}
]
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 (user.username === 'root') {
- return res.status(400)
- .send({ error: 'Cannot remove the root user' })
- .end()
- }
-
- return next()
- })
- })
+ if (areValidationErrors(req, res)) return
+ if (!await checkUserIdExist(req.params.id, res)) return
+
+ const user = res.locals.user
+ if (user.username === 'root') {
+ return res.status(400)
+ .send({ error: 'Cannot remove the root user' })
+ .end()
+ }
+
+ return next()
}
]
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()
}
]
// 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<VideoInstance>
-
- 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)
- })
- })
+ if (areValidationErrors(req, res)) return
+ if (!await isVideoExist(req.params.videoId, res)) return
+
+ 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()
- }
-
- return next()
- })
+ 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()
}
]
// ---------------------------------------------------------------------------
-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()
- }
-
- res.locals.user = user
- return callback(null, user)
- })
- .catch(err => {
- logger.error('Error in user request validator.', err)
- return res.sendStatus(500)
- })
+async function checkUserIdExist (id: number, res: express.Response) {
+ const user = await db.User.loadById(id)
+
+ 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()
- }
-
- return callback()
- })
- .catch(err => {
- logger.error('Error in usersAdd request validator.', err)
- return res.sendStatus(500)
- })
+async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email: string, res: express.Response) {
+ const user = await db.User.loadByUsernameOrEmail(username, email)
+
+ if (user) {
+ res.status(409)
+ .send({ error: 'User with this username of email already exists.' })
+ .end()
+ return false
+ }
+
+ return true
}
-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)
// ---------------------------------------------------------------------------
export {
- checkErrors,
areValidationErrors
}
-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()
}
]
}
// ---------------------------------------------------------------------------
-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
}
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()
}
]
(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()
}
]
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 (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()
- }
-
- next()
- })
- })
+ if (areValidationErrors(req, res)) return
+ if (!await isVideoChannelExist(req.params.id, res)) return
+
+ // 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 (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()
}
]
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) {
// ---------------------------------------------------------------------------
-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()
- }
-
- callback()
- })
+async function checkVideoChannelIsNotTheLastOne (res: express.Response) {
+ const count = await db.VideoChannel.countByAccount(res.locals.oauth.token.User.Account.id)
+
+ if (count <= 1) {
+ res.status(409)
+ .json({ error: 'Cannot remove the last channel of this user' })
+ .end()
+
+ return false
+ }
+
+ return true
}
import { UserRight, VideoPrivacy } from '../../../shared'
import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc'
import {
- checkVideoExists,
isVideoAbuseReasonValid,
isVideoCategoryValid,
isVideoDescriptionValid,
isVideoDurationValid,
+ isVideoExist,
isVideoFile,
isVideoLanguageValid,
isVideoLicenceValid,
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(
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
+
+ const videoFile: Express.Multer.File = req.files['videofile'][0]
+ const user = res.locals.oauth.token.User
- 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 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()
- return undefined
- }
-
- res.locals.videoChannel = videoChannel
-
- return user.isAbleToUploadVideo(videoFile)
- })
- .then(isAble => {
- if (isAble === false) {
- res.status(403)
- .json({ error: 'The user video quota is exceeded with this video.' })
- .end()
-
- return undefined
- }
-
- return getDurationFromVideoFile(videoFile.path)
- .catch(err => {
- logger.error('Invalid input file in videosAddValidator.', err)
- res.status(400)
- .json({ error: 'Invalid input file.' })
- .end()
-
- return undefined
- })
- })
- .then(duration => {
- // Previous test failed, abort
- if (duration === undefined) 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
- next()
- })
- .catch(err => {
- logger.error('Error in video add validator', err)
- res.sendStatus(500)
-
- return undefined
- })
- })
+ return
+ }
+
+ res.locals.videoChannel = videoChannel
+
+ 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
+ }
+
+ let duration: number
+
+ 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()
+
+ return
+ }
+
+ 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()
}
]
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
-
- // 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.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) {
- return res.status(403)
- .json({ error: 'Cannot update video of another user' })
- .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()
- }
-
- next()
- })
- })
+ if (areValidationErrors(req, res)) return
+ if (!await isVideoExist(req.params.id, res)) return
+
+ const video = res.locals.video
+
+ // 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.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) {
+ return res.status(403)
+ .json({ error: 'Cannot update video of another user' })
+ .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()
+ }
+
+ 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()
})
}
]
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()
}
]
(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()
}
]
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()
}
]
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()
}
]
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) {
}
res.locals.videoShare = share
-
return next()
}
]
// ---------------------------------------------------------------------------
-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
}
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('@')
-
- db.Account.loadLocalByName(name)
- .then(account => {
- if (!account) {
- return res.status(404)
- .send({ error: 'Account not found' })
- .end()
- }
-
- res.locals.account = account
- return next()
- })
- .catch(err => {
- logger.error('Error in webfinger validator.', err)
- return res.sendStatus(500)
- })
- })
+ if (areValidationErrors(req, res)) return
+
+ // Remove 'acct:' from the beginning of the string
+ const nameWithHost = req.query.resource.substr(5)
+ const [ name ] = nameWithHost.split('@')
+
+ 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()
}
]
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'
allowNull: false,
validate: {
urlValid: value => {
- const res = isAccountUrlValid(value)
+ const res = isActivityPubUrlValid(value)
if (res === false) throw new Error('URL is not valid.')
}
}
allowNull: false,
validate: {
inboxUrlValid: value => {
- const res = isAccountInboxValid(value)
+ const res = isActivityPubUrlValid(value)
if (res === false) throw new Error('Inbox URL is not valid.')
}
}
allowNull: false,
validate: {
outboxUrlValid: value => {
- const res = isAccountOutboxValid(value)
+ const res = isActivityPubUrlValid(value)
if (res === false) throw new Error('Outbox URL is not valid.')
}
}
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.')
}
}
allowNull: false,
validate: {
followersUrlValid: value => {
- const res = isAccountFollowersValid(value)
+ const res = isActivityPubUrlValid(value)
if (res === false) throw new Error('Followers URL is not valid.')
}
}
allowNull: false,
validate: {
followingUrlValid: value => {
- const res = isAccountFollowingValid(value)
+ const res = isActivityPubUrlValid(value)
if (res === false) throw new Error('Following URL is not valid.')
}
}
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'
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<VideoChannelInstance, VideoChannelAttributes>
let toFormattedJSON: VideoChannelMethods.ToFormattedJSON
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.')
}
}
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,
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<VideoInstance, VideoAttributes>
let getOriginalFile: VideoMethods.GetOriginalFile
allowNull: false,
validate: {
urlValid: value => {
- const res = isVideoUrlValid(value)
+ const res = isActivityPubUrlValid(value)
if (res === false) throw new Error('Video URL is not valid.')
}
}
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)