mirror of https://github.com/Chocobozzz/PeerTube
Refractor validators
parent
fcaf1e0aa8
commit
a2431b7dcb
|
@ -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))
|
||||
)
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ serverFollowsRouter.post('/following',
|
|||
serverFollowsRouter.delete('/following/:accountId',
|
||||
authenticate,
|
||||
ensureUserHasRight(UserRight.MANAGE_SERVER_FOLLOW),
|
||||
removeFollowingValidator,
|
||||
asyncMiddleware(removeFollowingValidator),
|
||||
asyncMiddleware(removeFollow)
|
||||
)
|
||||
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ abuseVideoRouter.get('/abuse',
|
|||
)
|
||||
abuseVideoRouter.post('/:id/abuse',
|
||||
authenticate,
|
||||
videoAbuseReportValidator,
|
||||
asyncMiddleware(videoAbuseReportValidator),
|
||||
asyncMiddleware(reportVideoAbuseRetryWrapper)
|
||||
)
|
||||
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ const rateVideoRouter = express.Router()
|
|||
|
||||
rateVideoRouter.put('/:id/rate',
|
||||
authenticate,
|
||||
videoRateValidator,
|
||||
asyncMiddleware(videoRateValidator),
|
||||
asyncMiddleware(rateVideoRetryWrapper)
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -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<AccountInstance>
|
||||
|
||||
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<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()
|
||||
}
|
||||
async function isAccountExist (p: Bluebird<AccountInstance>, 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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 })
|
||||
) ||
|
||||
(
|
||||
|
|
|
@ -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<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)
|
||||
|
@ -72,8 +40,6 @@ async function isVideoChannelExistsPromise (id: string, res: express.Response) {
|
|||
|
||||
export {
|
||||
isVideoChannelDescriptionValid,
|
||||
checkVideoChannelExists,
|
||||
isVideoChannelNameValid,
|
||||
isVideoChannelExistsPromise,
|
||||
isVideoChannelUrlValid
|
||||
isVideoChannelExist
|
||||
}
|
||||
|
|
|
@ -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<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)) {
|
||||
|
@ -169,10 +138,8 @@ export {
|
|||
isVideoRatingTypeValid,
|
||||
isVideoDurationValid,
|
||||
isVideoTagValid,
|
||||
isVideoUrlValid,
|
||||
isVideoPrivacyValid,
|
||||
isVideoFileResolutionValid,
|
||||
isVideoFileSizeValid,
|
||||
checkVideoExists,
|
||||
isVideoExistsPromise
|
||||
isVideoExist
|
||||
}
|
||||
|
|
|
@ -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<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) => {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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<VideoInstance>
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
@ -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.')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<VideoChannelInstance, VideoChannelAttributes>
|
||||
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.')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<VideoInstance, VideoAttributes>
|
||||
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.')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue