aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/middlewares
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2017-11-27 17:30:46 +0100
committerChocobozzz <florian.bigard@gmail.com>2017-11-27 19:43:01 +0100
commita2431b7dcbc72c05101dcdbe631ff84a823aeb51 (patch)
tree09278a822905622a70ff976a75e09d99bc45639a /server/middlewares
parentfcaf1e0aa84213a1b1f1b1a44a3276eae35ebe70 (diff)
downloadPeerTube-a2431b7dcbc72c05101dcdbe631ff84a823aeb51.tar.gz
PeerTube-a2431b7dcbc72c05101dcdbe631ff84a823aeb51.tar.zst
PeerTube-a2431b7dcbc72c05101dcdbe631ff84a823aeb51.zip
Refractor validators
Diffstat (limited to 'server/middlewares')
-rw-r--r--server/middlewares/async.ts7
-rw-r--r--server/middlewares/validators/account.ts15
-rw-r--r--server/middlewares/validators/activitypub/activity.ts6
-rw-r--r--server/middlewares/validators/activitypub/signature.ts17
-rw-r--r--server/middlewares/validators/follows.ts32
-rw-r--r--server/middlewares/validators/oembed.ts59
-rw-r--r--server/middlewares/validators/pagination.ts9
-rw-r--r--server/middlewares/validators/sort.ts6
-rw-r--r--server/middlewares/validators/users.ts198
-rw-r--r--server/middlewares/validators/utils.ts14
-rw-r--r--server/middlewares/validators/video-blacklist.ts63
-rw-r--r--server/middlewares/validators/video-channels.ts129
-rw-r--r--server/middlewares/validators/videos.ts252
-rw-r--r--server/middlewares/validators/webfinger.ts42
14 files changed, 398 insertions, 451 deletions
diff --git a/server/middlewares/async.ts b/server/middlewares/async.ts
index 9692f9be7..534891899 100644
--- a/server/middlewares/async.ts
+++ b/server/middlewares/async.ts
@@ -1,9 +1,12 @@
1import { Request, Response, NextFunction, RequestHandler } from 'express'
2import { eachSeries } from 'async' 1import { eachSeries } from 'async'
2import { NextFunction, Request, RequestHandler, Response } from 'express'
3 3
4// Syntactic sugar to avoid try/catch in express controllers 4// Syntactic sugar to avoid try/catch in express controllers
5// Thanks: https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016 5// Thanks: https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016
6function asyncMiddleware (fun: RequestHandler | RequestHandler[]) { 6
7export type RequestPromiseHandler = (req: Request, res: Response, next: NextFunction) => Promise<any>
8
9function asyncMiddleware (fun: RequestPromiseHandler | RequestPromiseHandler[]) {
7 return (req: Request, res: Response, next: NextFunction) => { 10 return (req: Request, res: Response, next: NextFunction) => {
8 if (Array.isArray(fun) === true) { 11 if (Array.isArray(fun) === true) {
9 return eachSeries(fun as RequestHandler[], (f, cb) => { 12 return eachSeries(fun as RequestHandler[], (f, cb) => {
diff --git a/server/middlewares/validators/account.ts b/server/middlewares/validators/account.ts
index 47ed6a7bb..70f4e4d3b 100644
--- a/server/middlewares/validators/account.ts
+++ b/server/middlewares/validators/account.ts
@@ -1,18 +1,19 @@
1import * as express from 'express' 1import * as express from 'express'
2import { param } from 'express-validator/check' 2import { param } from 'express-validator/check'
3import { logger } from '../../helpers' 3import { logger, isLocalAccountNameExist } from '../../helpers'
4import { checkLocalAccountNameExists, isAccountNameValid } from '../../helpers/custom-validators/accounts' 4import { isAccountNameValid } from '../../helpers/custom-validators/accounts'
5import { checkErrors } from './utils' 5import { areValidationErrors } from './utils'
6 6
7const localAccountValidator = [ 7const localAccountValidator = [
8 param('name').custom(isAccountNameValid).withMessage('Should have a valid account name'), 8 param('name').custom(isAccountNameValid).withMessage('Should have a valid account name'),
9 9
10 (req: express.Request, res: express.Response, next: express.NextFunction) => { 10 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
11 logger.debug('Checking localAccountValidator parameters', { parameters: req.params }) 11 logger.debug('Checking localAccountValidator parameters', { parameters: req.params })
12 12
13 checkErrors(req, res, () => { 13 if (areValidationErrors(req, res)) return
14 checkLocalAccountNameExists(req.params.name, res, next) 14 if (!await isLocalAccountNameExist(req.params.name, res)) return
15 }) 15
16 return next()
16 } 17 }
17] 18]
18 19
diff --git a/server/middlewares/validators/activitypub/activity.ts b/server/middlewares/validators/activitypub/activity.ts
index 0de8b2d85..8aa82298c 100644
--- a/server/middlewares/validators/activitypub/activity.ts
+++ b/server/middlewares/validators/activitypub/activity.ts
@@ -1,7 +1,7 @@
1import * as express from 'express' 1import * as express from 'express'
2import { body } from 'express-validator/check' 2import { body } from 'express-validator/check'
3import { isRootActivityValid, logger } from '../../../helpers' 3import { isRootActivityValid, logger } from '../../../helpers'
4import { checkErrors } from '../utils' 4import { areValidationErrors } from '../utils'
5 5
6const activityPubValidator = [ 6const activityPubValidator = [
7 body('').custom((value, { req }) => isRootActivityValid(req.body)), 7 body('').custom((value, { req }) => isRootActivityValid(req.body)),
@@ -9,7 +9,9 @@ const activityPubValidator = [
9 (req: express.Request, res: express.Response, next: express.NextFunction) => { 9 (req: express.Request, res: express.Response, next: express.NextFunction) => {
10 logger.debug('Checking activity pub parameters', { parameters: req.body }) 10 logger.debug('Checking activity pub parameters', { parameters: req.body })
11 11
12 checkErrors(req, res, next) 12 if (areValidationErrors(req, res)) return
13
14 return next()
13 } 15 }
14] 16]
15 17
diff --git a/server/middlewares/validators/activitypub/signature.ts b/server/middlewares/validators/activitypub/signature.ts
index 0ce15c1f6..360685512 100644
--- a/server/middlewares/validators/activitypub/signature.ts
+++ b/server/middlewares/validators/activitypub/signature.ts
@@ -1,14 +1,7 @@
1import { body } from 'express-validator/check'
2import * as express from 'express' 1import * as express from 'express'
3 2import { body } from 'express-validator/check'
4import { 3import { isDateValid, isSignatureCreatorValid, isSignatureTypeValid, isSignatureValueValid, logger } from '../../../helpers'
5 logger, 4import { areValidationErrors } from '../utils'
6 isDateValid,
7 isSignatureTypeValid,
8 isSignatureCreatorValid,
9 isSignatureValueValid
10} from '../../../helpers'
11import { checkErrors } from '../utils'
12 5
13const signatureValidator = [ 6const signatureValidator = [
14 body('signature.type').custom(isSignatureTypeValid).withMessage('Should have a valid signature type'), 7 body('signature.type').custom(isSignatureTypeValid).withMessage('Should have a valid signature type'),
@@ -19,7 +12,9 @@ const signatureValidator = [
19 (req: express.Request, res: express.Response, next: express.NextFunction) => { 12 (req: express.Request, res: express.Response, next: express.NextFunction) => {
20 logger.debug('Checking activitypub signature parameter', { parameters: { signature: req.body.signature } }) 13 logger.debug('Checking activitypub signature parameter', { parameters: { signature: req.body.signature } })
21 14
22 checkErrors(req, res, next) 15 if (areValidationErrors(req, res)) return
16
17 return next()
23 } 18 }
24] 19]
25 20
diff --git a/server/middlewares/validators/follows.ts b/server/middlewares/validators/follows.ts
index ddc4c1de1..605872ecf 100644
--- a/server/middlewares/validators/follows.ts
+++ b/server/middlewares/validators/follows.ts
@@ -4,7 +4,7 @@ import { isTestInstance } from '../../helpers/core-utils'
4import { isEachUniqueHostValid } from '../../helpers/custom-validators/servers' 4import { isEachUniqueHostValid } from '../../helpers/custom-validators/servers'
5import { logger } from '../../helpers/logger' 5import { logger } from '../../helpers/logger'
6import { CONFIG, database as db } from '../../initializers' 6import { CONFIG, database as db } from '../../initializers'
7import { checkErrors } from './utils' 7import { areValidationErrors } from './utils'
8import { getServerAccount } from '../../helpers/utils' 8import { getServerAccount } from '../../helpers/utils'
9import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' 9import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc'
10 10
@@ -23,34 +23,30 @@ const followValidator = [
23 23
24 logger.debug('Checking follow parameters', { parameters: req.body }) 24 logger.debug('Checking follow parameters', { parameters: req.body })
25 25
26 checkErrors(req, res, next) 26 if (areValidationErrors(req, res)) return
27
28 return next()
27 } 29 }
28] 30]
29 31
30const removeFollowingValidator = [ 32const removeFollowingValidator = [
31 param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'), 33 param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'),
32 34
33 (req: express.Request, res: express.Response, next: express.NextFunction) => { 35 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
34 logger.debug('Checking unfollow parameters', { parameters: req.params }) 36 logger.debug('Checking unfollow parameters', { parameters: req.params })
35 37
36 checkErrors(req, res, async () => { 38 if (areValidationErrors(req, res)) return
37 try {
38 const serverAccount = await getServerAccount()
39 const follow = await db.AccountFollow.loadByAccountAndTarget(serverAccount.id, req.params.accountId)
40 39
41 if (!follow) { 40 const serverAccount = await getServerAccount()
42 return res.status(404) 41 const follow = await db.AccountFollow.loadByAccountAndTarget(serverAccount.id, req.params.accountId)
43 .end()
44 }
45 42
46 res.locals.follow = follow 43 if (!follow) {
44 return res.status(404)
45 .end()
46 }
47 47
48 return next() 48 res.locals.follow = follow
49 } catch (err) { 49 return next()
50 logger.error('Error in remove following validator.', err)
51 return res.sendStatus(500)
52 }
53 })
54 } 50 }
55] 51]
56 52
diff --git a/server/middlewares/validators/oembed.ts b/server/middlewares/validators/oembed.ts
index f8e34d2d4..31f06dc65 100644
--- a/server/middlewares/validators/oembed.ts
+++ b/server/middlewares/validators/oembed.ts
@@ -1,15 +1,10 @@
1import { query } from 'express-validator/check'
2import * as express from 'express' 1import * as express from 'express'
2import { query } from 'express-validator/check'
3import { join } from 'path' 3import { join } from 'path'
4 4import { isIdOrUUIDValid, isTestInstance, logger } from '../../helpers'
5import { checkErrors } from './utils'
6import { CONFIG } from '../../initializers' 5import { CONFIG } from '../../initializers'
7import { 6import { areValidationErrors } from './utils'
8 logger, 7import { isVideoExist } from '../../helpers/custom-validators/videos'
9 isTestInstance,
10 checkVideoExists,
11 isIdOrUUIDValid
12} from '../../helpers'
13 8
14const urlShouldStartWith = CONFIG.WEBSERVER.SCHEME + '://' + join(CONFIG.WEBSERVER.HOST, 'videos', 'watch') + '/' 9const urlShouldStartWith = CONFIG.WEBSERVER.SCHEME + '://' + join(CONFIG.WEBSERVER.HOST, 'videos', 'watch') + '/'
15const videoWatchRegex = new RegExp('([^/]+)$') 10const videoWatchRegex = new RegExp('([^/]+)$')
@@ -29,33 +24,35 @@ const oembedValidator = [
29 query('maxheight').optional().isInt().withMessage('Should have a valid max height'), 24 query('maxheight').optional().isInt().withMessage('Should have a valid max height'),
30 query('format').optional().isIn([ 'xml', 'json' ]).withMessage('Should have a valid format'), 25 query('format').optional().isIn([ 'xml', 'json' ]).withMessage('Should have a valid format'),
31 26
32 (req: express.Request, res: express.Response, next: express.NextFunction) => { 27 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
33 logger.debug('Checking oembed parameters', { parameters: req.query }) 28 logger.debug('Checking oembed parameters', { parameters: req.query })
34 29
35 checkErrors(req, res, () => { 30 if (areValidationErrors(req, res)) return
36 if (req.query.format !== undefined && req.query.format !== 'json') { 31
37 return res.status(501) 32 if (req.query.format !== undefined && req.query.format !== 'json') {
38 .json({ error: 'Requested format is not implemented on server.' }) 33 return res.status(501)
39 .end() 34 .json({ error: 'Requested format is not implemented on server.' })
40 } 35 .end()
36 }
37
38 const startIsOk = req.query.url.startsWith(urlShouldStartWith)
39 const matches = videoWatchRegex.exec(req.query.url)
40 if (startIsOk === false || matches === null) {
41 return res.status(400)
42 .json({ error: 'Invalid url.' })
43 .end()
44 }
41 45
42 const startIsOk = req.query.url.startsWith(urlShouldStartWith) 46 const videoId = matches[1]
43 const matches = videoWatchRegex.exec(req.query.url) 47 if (isIdOrUUIDValid(videoId) === false) {
44 if (startIsOk === false || matches === null) { 48 return res.status(400)
45 return res.status(400) 49 .json({ error: 'Invalid video id.' })
46 .json({ error: 'Invalid url.' }) 50 .end()
47 .end() 51 }
48 }
49 52
50 const videoId = matches[1] 53 if (!await isVideoExist(videoId, res)) return
51 if (isIdOrUUIDValid(videoId) === false) {
52 return res.status(400)
53 .json({ error: 'Invalid video id.' })
54 .end()
55 }
56 54
57 checkVideoExists(videoId, res, next) 55 return next()
58 })
59 } 56 }
60] 57]
61 58
diff --git a/server/middlewares/validators/pagination.ts b/server/middlewares/validators/pagination.ts
index a5a542cdf..0895b4eb8 100644
--- a/server/middlewares/validators/pagination.ts
+++ b/server/middlewares/validators/pagination.ts
@@ -1,8 +1,7 @@
1import { query } from 'express-validator/check'
2import * as express from 'express' 1import * as express from 'express'
3 2import { query } from 'express-validator/check'
4import { checkErrors } from './utils'
5import { logger } from '../../helpers' 3import { logger } from '../../helpers'
4import { areValidationErrors } from './utils'
6 5
7const paginationValidator = [ 6const paginationValidator = [
8 query('start').optional().isInt().withMessage('Should have a number start'), 7 query('start').optional().isInt().withMessage('Should have a number start'),
@@ -11,7 +10,9 @@ const paginationValidator = [
11 (req: express.Request, res: express.Response, next: express.NextFunction) => { 10 (req: express.Request, res: express.Response, next: express.NextFunction) => {
12 logger.debug('Checking pagination parameters', { parameters: req.query }) 11 logger.debug('Checking pagination parameters', { parameters: req.query })
13 12
14 checkErrors(req, res, next) 13 if (areValidationErrors(req, res)) return
14
15 return next()
15 } 16 }
16] 17]
17 18
diff --git a/server/middlewares/validators/sort.ts b/server/middlewares/validators/sort.ts
index 6fea41bb8..636f68885 100644
--- a/server/middlewares/validators/sort.ts
+++ b/server/middlewares/validators/sort.ts
@@ -1,9 +1,9 @@
1import { query } from 'express-validator/check' 1import { query } from 'express-validator/check'
2import * as express from 'express' 2import * as express from 'express'
3 3
4import { checkErrors } from './utils'
5import { logger } from '../../helpers' 4import { logger } from '../../helpers'
6import { SORTABLE_COLUMNS } from '../../initializers' 5import { SORTABLE_COLUMNS } from '../../initializers'
6import { areValidationErrors } from './utils'
7 7
8// Initialize constants here for better performances 8// Initialize constants here for better performances
9const SORTABLE_USERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USERS) 9const SORTABLE_USERS_COLUMNS = createSortableColumns(SORTABLE_COLUMNS.USERS)
@@ -43,7 +43,9 @@ function checkSort (sortableColumns: string[]) {
43 (req: express.Request, res: express.Response, next: express.NextFunction) => { 43 (req: express.Request, res: express.Response, next: express.NextFunction) => {
44 logger.debug('Checking sort parameters', { parameters: req.query }) 44 logger.debug('Checking sort parameters', { parameters: req.query })
45 45
46 checkErrors(req, res, next) 46 if (areValidationErrors(req, res)) return
47
48 return next()
47 } 49 }
48 ] 50 ]
49} 51}
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index 6b845f62b..ac7435b7d 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -1,22 +1,19 @@
1import { body, param } from 'express-validator/check'
2import 'express-validator'
3import * as express from 'express' 1import * as express from 'express'
4import * as Promise from 'bluebird' 2import 'express-validator'
5import * as validator from 'validator' 3import { body, param } from 'express-validator/check'
6
7import { database as db } from '../../initializers/database'
8import { checkErrors } from './utils'
9import { 4import {
5 isIdOrUUIDValid,
10 isSignupAllowed, 6 isSignupAllowed,
11 logger, 7 isUserDisplayNSFWValid,
12 isUserUsernameValid,
13 isUserPasswordValid, 8 isUserPasswordValid,
9 isUserRoleValid,
10 isUserUsernameValid,
14 isUserVideoQuotaValid, 11 isUserVideoQuotaValid,
15 isUserDisplayNSFWValid, 12 logger
16 isIdOrUUIDValid,
17 isUserRoleValid
18} from '../../helpers' 13} from '../../helpers'
19import { UserInstance, VideoInstance } from '../../models' 14import { isVideoExist } from '../../helpers/custom-validators/videos'
15import { database as db } from '../../initializers/database'
16import { areValidationErrors } from './utils'
20 17
21const usersAddValidator = [ 18const usersAddValidator = [
22 body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'), 19 body('username').custom(isUserUsernameValid).withMessage('Should have a valid username (lowercase alphanumeric characters)'),
@@ -25,12 +22,13 @@ const usersAddValidator = [
25 body('videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'), 22 body('videoQuota').custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'),
26 body('role').custom(isUserRoleValid).withMessage('Should have a valid role'), 23 body('role').custom(isUserRoleValid).withMessage('Should have a valid role'),
27 24
28 (req: express.Request, res: express.Response, next: express.NextFunction) => { 25 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
29 logger.debug('Checking usersAdd parameters', { parameters: req.body }) 26 logger.debug('Checking usersAdd parameters', { parameters: req.body })
30 27
31 checkErrors(req, res, () => { 28 if (areValidationErrors(req, res)) return
32 checkUserDoesNotAlreadyExist(req.body.username, req.body.email, res, next) 29 if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return
33 }) 30
31 return next()
34 } 32 }
35] 33]
36 34
@@ -39,37 +37,33 @@ const usersRegisterValidator = [
39 body('password').custom(isUserPasswordValid).withMessage('Should have a valid password'), 37 body('password').custom(isUserPasswordValid).withMessage('Should have a valid password'),
40 body('email').isEmail().withMessage('Should have a valid email'), 38 body('email').isEmail().withMessage('Should have a valid email'),
41 39
42 (req: express.Request, res: express.Response, next: express.NextFunction) => { 40 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
43 logger.debug('Checking usersRegister parameters', { parameters: req.body }) 41 logger.debug('Checking usersRegister parameters', { parameters: req.body })
44 42
45 checkErrors(req, res, () => { 43 if (areValidationErrors(req, res)) return
46 checkUserDoesNotAlreadyExist(req.body.username, req.body.email, res, next) 44 if (!await checkUserNameOrEmailDoesNotAlreadyExist(req.body.username, req.body.email, res)) return
47 }) 45
46 return next()
48 } 47 }
49] 48]
50 49
51const usersRemoveValidator = [ 50const usersRemoveValidator = [
52 param('id').isInt().not().isEmpty().withMessage('Should have a valid id'), 51 param('id').isInt().not().isEmpty().withMessage('Should have a valid id'),
53 52
54 (req: express.Request, res: express.Response, next: express.NextFunction) => { 53 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
55 logger.debug('Checking usersRemove parameters', { parameters: req.params }) 54 logger.debug('Checking usersRemove parameters', { parameters: req.params })
56 55
57 checkErrors(req, res, () => { 56 if (areValidationErrors(req, res)) return
58 checkUserExists(req.params.id, res, (err, user) => { 57 if (!await checkUserIdExist(req.params.id, res)) return
59 if (err) { 58
60 logger.error('Error in usersRemoveValidator.', err) 59 const user = res.locals.user
61 return res.sendStatus(500) 60 if (user.username === 'root') {
62 } 61 return res.status(400)
63 62 .send({ error: 'Cannot remove the root user' })
64 if (user.username === 'root') { 63 .end()
65 return res.status(400) 64 }
66 .send({ error: 'Cannot remove the root user' }) 65
67 .end() 66 return next()
68 }
69
70 return next()
71 })
72 })
73 } 67 }
74] 68]
75 69
@@ -79,12 +73,13 @@ const usersUpdateValidator = [
79 body('videoQuota').optional().custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'), 73 body('videoQuota').optional().custom(isUserVideoQuotaValid).withMessage('Should have a valid user quota'),
80 body('role').optional().custom(isUserRoleValid).withMessage('Should have a valid role'), 74 body('role').optional().custom(isUserRoleValid).withMessage('Should have a valid role'),
81 75
82 (req: express.Request, res: express.Response, next: express.NextFunction) => { 76 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
83 logger.debug('Checking usersUpdate parameters', { parameters: req.body }) 77 logger.debug('Checking usersUpdate parameters', { parameters: req.body })
84 78
85 checkErrors(req, res, () => { 79 if (areValidationErrors(req, res)) return
86 checkUserExists(req.params.id, res, next) 80 if (!await checkUserIdExist(req.params.id, res)) return
87 }) 81
82 return next()
88 } 83 }
89] 84]
90 85
@@ -97,64 +92,48 @@ const usersUpdateMeValidator = [
97 // TODO: Add old password verification 92 // TODO: Add old password verification
98 logger.debug('Checking usersUpdateMe parameters', { parameters: req.body }) 93 logger.debug('Checking usersUpdateMe parameters', { parameters: req.body })
99 94
100 checkErrors(req, res, next) 95 if (areValidationErrors(req, res)) return
96
97 return next()
101 } 98 }
102] 99]
103 100
104const usersGetValidator = [ 101const usersGetValidator = [
105 param('id').isInt().not().isEmpty().withMessage('Should have a valid id'), 102 param('id').isInt().not().isEmpty().withMessage('Should have a valid id'),
106 103
107 (req: express.Request, res: express.Response, next: express.NextFunction) => { 104 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
108 checkErrors(req, res, () => { 105 logger.debug('Checking usersGet parameters', { parameters: req.body })
109 checkUserExists(req.params.id, res, next) 106
110 }) 107 if (areValidationErrors(req, res)) return
108 if (!await checkUserIdExist(req.params.id, res)) return
109
110 return next()
111 } 111 }
112] 112]
113 113
114const usersVideoRatingValidator = [ 114const usersVideoRatingValidator = [
115 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), 115 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'),
116 116
117 (req: express.Request, res: express.Response, next: express.NextFunction) => { 117 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
118 logger.debug('Checking usersVideoRating parameters', { parameters: req.params }) 118 logger.debug('Checking usersVideoRating parameters', { parameters: req.params })
119 119
120 checkErrors(req, res, () => { 120 if (areValidationErrors(req, res)) return
121 let videoPromise: Promise<VideoInstance> 121 if (!await isVideoExist(req.params.videoId, res)) return
122 122
123 if (validator.isUUID(req.params.videoId)) { 123 return next()
124 videoPromise = db.Video.loadByUUID(req.params.videoId)
125 } else {
126 videoPromise = db.Video.load(req.params.videoId)
127 }
128
129 videoPromise
130 .then(video => {
131 if (!video) {
132 return res.status(404)
133 .json({ error: 'Video not found' })
134 .end()
135 }
136
137 return next()
138 })
139 .catch(err => {
140 logger.error('Error in user request validator.', err)
141 return res.sendStatus(500)
142 })
143 })
144 } 124 }
145] 125]
146 126
147const ensureUserRegistrationAllowed = [ 127const ensureUserRegistrationAllowed = [
148 (req: express.Request, res: express.Response, next: express.NextFunction) => { 128 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
149 isSignupAllowed().then(allowed => { 129 const allowed = await isSignupAllowed()
150 if (allowed === false) { 130 if (allowed === false) {
151 return res.status(403) 131 return res.status(403)
152 .send({ error: 'User registration is not enabled or user limit is reached.' }) 132 .send({ error: 'User registration is not enabled or user limit is reached.' })
153 .end() 133 .end()
154 } 134 }
155 135
156 return next() 136 return next()
157 })
158 } 137 }
159] 138]
160 139
@@ -173,37 +152,30 @@ export {
173 152
174// --------------------------------------------------------------------------- 153// ---------------------------------------------------------------------------
175 154
176function checkUserExists (id: number, res: express.Response, callback: (err: Error, user: UserInstance) => void) { 155async function checkUserIdExist (id: number, res: express.Response) {
177 db.User.loadById(id) 156 const user = await db.User.loadById(id)
178 .then(user => { 157
179 if (!user) { 158 if (!user) {
180 return res.status(404) 159 res.status(404)
181 .send({ error: 'User not found' }) 160 .send({ error: 'User not found' })
182 .end() 161 .end()
183 } 162
184 163 return false
185 res.locals.user = user 164 }
186 return callback(null, user) 165
187 }) 166 res.locals.user = user
188 .catch(err => { 167 return true
189 logger.error('Error in user request validator.', err)
190 return res.sendStatus(500)
191 })
192} 168}
193 169
194function checkUserDoesNotAlreadyExist (username: string, email: string, res: express.Response, callback: () => void) { 170async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email: string, res: express.Response) {
195 db.User.loadByUsernameOrEmail(username, email) 171 const user = await db.User.loadByUsernameOrEmail(username, email)
196 .then(user => { 172
197 if (user) { 173 if (user) {
198 return res.status(409) 174 res.status(409)
199 .send({ error: 'User with this username of email already exists.' }) 175 .send({ error: 'User with this username of email already exists.' })
200 .end() 176 .end()
201 } 177 return false
202 178 }
203 return callback() 179
204 }) 180 return true
205 .catch(err => {
206 logger.error('Error in usersAdd request validator.', err)
207 return res.sendStatus(500)
208 })
209} 181}
diff --git a/server/middlewares/validators/utils.ts b/server/middlewares/validators/utils.ts
index 77a1a0d4b..ca80acf29 100644
--- a/server/middlewares/validators/utils.ts
+++ b/server/middlewares/validators/utils.ts
@@ -1,19 +1,8 @@
1import { validationResult } from 'express-validator/check'
2import * as express from 'express' 1import * as express from 'express'
2import { validationResult } from 'express-validator/check'
3 3
4import { logger } from '../../helpers' 4import { logger } from '../../helpers'
5 5
6function checkErrors (req: express.Request, res: express.Response, next: express.NextFunction) {
7 const errors = validationResult(req)
8
9 if (!errors.isEmpty()) {
10 logger.warn('Incorrect request parameters', { path: req.originalUrl, err: errors.mapped() })
11 return res.status(400).json({ errors: errors.mapped() })
12 }
13
14 return next()
15}
16
17function areValidationErrors (req: express.Request, res: express.Response) { 6function areValidationErrors (req: express.Request, res: express.Response) {
18 const errors = validationResult(req) 7 const errors = validationResult(req)
19 8
@@ -30,6 +19,5 @@ function areValidationErrors (req: express.Request, res: express.Response) {
30// --------------------------------------------------------------------------- 19// ---------------------------------------------------------------------------
31 20
32export { 21export {
33 checkErrors,
34 areValidationErrors 22 areValidationErrors
35} 23}
diff --git a/server/middlewares/validators/video-blacklist.ts b/server/middlewares/validators/video-blacklist.ts
index 3c8c31519..f1cc04950 100644
--- a/server/middlewares/validators/video-blacklist.ts
+++ b/server/middlewares/validators/video-blacklist.ts
@@ -1,35 +1,36 @@
1import { param } from 'express-validator/check'
2import * as express from 'express' 1import * as express from 'express'
3 2import { param } from 'express-validator/check'
3import { isIdOrUUIDValid, logger } from '../../helpers'
4import { isVideoExist } from '../../helpers/custom-validators/videos'
4import { database as db } from '../../initializers/database' 5import { database as db } from '../../initializers/database'
5import { checkErrors } from './utils' 6import { VideoInstance } from '../../models/video/video-interface'
6import { logger, isIdOrUUIDValid, checkVideoExists } from '../../helpers' 7import { areValidationErrors } from './utils'
7 8
8const videosBlacklistRemoveValidator = [ 9const videosBlacklistRemoveValidator = [
9 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), 10 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
10 11
11 (req: express.Request, res: express.Response, next: express.NextFunction) => { 12 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
12 logger.debug('Checking blacklistRemove parameters.', { parameters: req.params }) 13 logger.debug('Checking blacklistRemove parameters.', { parameters: req.params })
13 14
14 checkErrors(req, res, () => { 15 if (areValidationErrors(req, res)) return
15 checkVideoExists(req.params.videoId, res, () => { 16 if (!await isVideoExist(req.params.videoId, res)) return
16 checkVideoIsBlacklisted(req, res, next) 17 if (!await checkVideoIsBlacklisted(res.locals.video, res)) return
17 }) 18
18 }) 19 return next()
19 } 20 }
20] 21]
21 22
22const videosBlacklistAddValidator = [ 23const videosBlacklistAddValidator = [
23 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), 24 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
24 25
25 (req: express.Request, res: express.Response, next: express.NextFunction) => { 26 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
26 logger.debug('Checking videosBlacklist parameters', { parameters: req.params }) 27 logger.debug('Checking videosBlacklist parameters', { parameters: req.params })
27 28
28 checkErrors(req, res, () => { 29 if (areValidationErrors(req, res)) return
29 checkVideoExists(req.params.videoId, res, () => { 30 if (!await isVideoExist(req.params.videoId, res)) return
30 checkVideoIsBlacklistable(req, res, next) 31 if (!checkVideoIsBlacklistable(res.locals.video, res)) return
31 }) 32
32 }) 33 return next()
33 } 34 }
34] 35]
35 36
@@ -41,27 +42,27 @@ export {
41} 42}
42// --------------------------------------------------------------------------- 43// ---------------------------------------------------------------------------
43 44
44function checkVideoIsBlacklistable (req: express.Request, res: express.Response, callback: () => void) { 45function checkVideoIsBlacklistable (video: VideoInstance, res: express.Response) {
45 if (res.locals.video.isOwned() === true) { 46 if (video.isOwned() === true) {
46 return res.status(403) 47 res.status(403)
47 .json({ error: 'Cannot blacklist a local video' }) 48 .json({ error: 'Cannot blacklist a local video' })
48 .end() 49 .end()
50
51 return false
49 } 52 }
50 53
51 callback() 54 return true
52} 55}
53 56
54function checkVideoIsBlacklisted (req: express.Request, res: express.Response, callback: () => void) { 57async function checkVideoIsBlacklisted (video: VideoInstance, res: express.Response) {
55 db.BlacklistedVideo.loadByVideoId(res.locals.video.id) 58 const blacklistedVideo = await db.BlacklistedVideo.loadByVideoId(video.id)
56 .then(blacklistedVideo => { 59 if (!blacklistedVideo) {
57 if (!blacklistedVideo) return res.status(404).send('Blacklisted video not found') 60 res.status(404)
61 .send('Blacklisted video not found')
58 62
59 res.locals.blacklistedVideo = blacklistedVideo 63 return false
64 }
60 65
61 callback() 66 res.locals.blacklistedVideo = blacklistedVideo
62 }) 67 return true
63 .catch(err => {
64 logger.error('Error in blacklistRemove request validator', { error: err })
65 return res.sendStatus(500)
66 })
67} 68}
diff --git a/server/middlewares/validators/video-channels.ts b/server/middlewares/validators/video-channels.ts
index f30fbf0dc..4683c91e1 100644
--- a/server/middlewares/validators/video-channels.ts
+++ b/server/middlewares/validators/video-channels.ts
@@ -1,29 +1,30 @@
1import * as express from 'express' 1import * as express from 'express'
2import { body, param } from 'express-validator/check' 2import { body, param } from 'express-validator/check'
3import { UserRight } from '../../../shared' 3import { UserRight } from '../../../shared'
4import { checkAccountIdExists } from '../../helpers/custom-validators/accounts'
5import { isIdValid } from '../../helpers/custom-validators/misc' 4import { isIdValid } from '../../helpers/custom-validators/misc'
6import { 5import {
7 checkVideoChannelExists,
8 isVideoChannelDescriptionValid, 6 isVideoChannelDescriptionValid,
9 isVideoChannelExistsPromise, 7 isVideoChannelExist,
10 isVideoChannelNameValid 8 isVideoChannelNameValid
11} from '../../helpers/custom-validators/video-channels' 9} from '../../helpers/custom-validators/video-channels'
12import { isIdOrUUIDValid } from '../../helpers/index' 10import { isIdOrUUIDValid } from '../../helpers/index'
13import { logger } from '../../helpers/logger' 11import { logger } from '../../helpers/logger'
14import { database as db } from '../../initializers' 12import { database as db } from '../../initializers'
15import { UserInstance } from '../../models' 13import { UserInstance } from '../../models'
16import { areValidationErrors, checkErrors } from './utils' 14import { areValidationErrors } from './utils'
15import { isAccountIdExist } from '../../helpers/custom-validators/accounts'
16import { VideoChannelInstance } from '../../models/video/video-channel-interface'
17 17
18const listVideoAccountChannelsValidator = [ 18const listVideoAccountChannelsValidator = [
19 param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'), 19 param('accountId').custom(isIdOrUUIDValid).withMessage('Should have a valid account id'),
20 20
21 (req: express.Request, res: express.Response, next: express.NextFunction) => { 21 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
22 logger.debug('Checking listVideoAccountChannelsValidator parameters', { parameters: req.body }) 22 logger.debug('Checking listVideoAccountChannelsValidator parameters', { parameters: req.body })
23 23
24 checkErrors(req, res, () => { 24 if (areValidationErrors(req, res)) return
25 checkAccountIdExists(req.params.accountId, res, next) 25 if (!await isAccountIdExist(req.params.accountId, res)) return
26 }) 26
27 return next()
27 } 28 }
28] 29]
29 30
@@ -34,7 +35,9 @@ const videoChannelsAddValidator = [
34 (req: express.Request, res: express.Response, next: express.NextFunction) => { 35 (req: express.Request, res: express.Response, next: express.NextFunction) => {
35 logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body }) 36 logger.debug('Checking videoChannelsAdd parameters', { parameters: req.body })
36 37
37 checkErrors(req, res, next) 38 if (areValidationErrors(req, res)) return
39
40 return next()
38 } 41 }
39] 42]
40 43
@@ -43,56 +46,56 @@ const videoChannelsUpdateValidator = [
43 body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'), 46 body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
44 body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'), 47 body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
45 48
46 (req: express.Request, res: express.Response, next: express.NextFunction) => { 49 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
47 logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body }) 50 logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body })
48 51
49 checkErrors(req, res, () => { 52 if (areValidationErrors(req, res)) return
50 checkVideoChannelExists(req.params.id, res, () => { 53 if (!await isVideoChannelExist(req.params.id, res)) return
51 // We need to make additional checks 54
52 if (res.locals.videoChannel.isOwned() === false) { 55 // We need to make additional checks
53 return res.status(403) 56 if (res.locals.videoChannel.isOwned() === false) {
54 .json({ error: 'Cannot update video channel of another server' }) 57 return res.status(403)
55 .end() 58 .json({ error: 'Cannot update video channel of another server' })
56 } 59 .end()
57 60 }
58 if (res.locals.videoChannel.Account.userId !== res.locals.oauth.token.User.id) { 61
59 return res.status(403) 62 if (res.locals.videoChannel.Account.userId !== res.locals.oauth.token.User.id) {
60 .json({ error: 'Cannot update video channel of another user' }) 63 return res.status(403)
61 .end() 64 .json({ error: 'Cannot update video channel of another user' })
62 } 65 .end()
63 66 }
64 next() 67
65 }) 68 return next()
66 })
67 } 69 }
68] 70]
69 71
70const videoChannelsRemoveValidator = [ 72const videoChannelsRemoveValidator = [
71 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 73 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
72 74
73 (req: express.Request, res: express.Response, next: express.NextFunction) => { 75 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
74 logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params }) 76 logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params })
75 77
76 checkErrors(req, res, () => { 78 if (areValidationErrors(req, res)) return
77 checkVideoChannelExists(req.params.id, res, () => { 79 if (!await isVideoChannelExist(req.params.id, res)) return
78 // Check if the user who did the request is able to delete the video 80
79 checkUserCanDeleteVideoChannel(res, () => { 81 // Check if the user who did the request is able to delete the video
80 checkVideoChannelIsNotTheLastOne(res, next) 82 if (!checkUserCanDeleteVideoChannel(res.locals.user, res.locals.videoChannel, res)) return
81 }) 83 if (!await checkVideoChannelIsNotTheLastOne(res)) return
82 }) 84
83 }) 85 return next()
84 } 86 }
85] 87]
86 88
87const videoChannelsGetValidator = [ 89const videoChannelsGetValidator = [
88 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 90 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
89 91
90 (req: express.Request, res: express.Response, next: express.NextFunction) => { 92 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
91 logger.debug('Checking videoChannelsGet parameters', { parameters: req.params }) 93 logger.debug('Checking videoChannelsGet parameters', { parameters: req.params })
92 94
93 checkErrors(req, res, () => { 95 if (areValidationErrors(req, res)) return
94 checkVideoChannelExists(req.params.id, res, next) 96 if (!await isVideoChannelExist(req.params.id, res)) return
95 }) 97
98 return next()
96 } 99 }
97] 100]
98 101
@@ -104,7 +107,7 @@ const videoChannelsShareValidator = [
104 logger.debug('Checking videoChannelShare parameters', { parameters: req.params }) 107 logger.debug('Checking videoChannelShare parameters', { parameters: req.params })
105 108
106 if (areValidationErrors(req, res)) return 109 if (areValidationErrors(req, res)) return
107 if (!await isVideoChannelExistsPromise(req.params.id, res)) return 110 if (!await isVideoChannelExist(req.params.id, res)) return
108 111
109 const share = await db.VideoChannelShare.load(res.locals.video.id, req.params.accountId) 112 const share = await db.VideoChannelShare.load(res.locals.video.id, req.params.accountId)
110 if (!share) { 113 if (!share) {
@@ -131,38 +134,40 @@ export {
131 134
132// --------------------------------------------------------------------------- 135// ---------------------------------------------------------------------------
133 136
134function checkUserCanDeleteVideoChannel (res: express.Response, callback: () => void) { 137function checkUserCanDeleteVideoChannel (user: UserInstance, videoChannel: VideoChannelInstance, res: express.Response) {
135 const user: UserInstance = res.locals.oauth.token.User
136
137 // Retrieve the user who did the request 138 // Retrieve the user who did the request
138 if (res.locals.videoChannel.isOwned() === false) { 139 if (videoChannel.isOwned() === false) {
139 return res.status(403) 140 res.status(403)
140 .json({ error: 'Cannot remove video channel of another server.' }) 141 .json({ error: 'Cannot remove video channel of another server.' })
141 .end() 142 .end()
143
144 return false
142 } 145 }
143 146
144 // Check if the user can delete the video channel 147 // Check if the user can delete the video channel
145 // The user can delete it if s/he is an admin 148 // The user can delete it if s/he is an admin
146 // Or if s/he is the video channel's account 149 // Or if s/he is the video channel's account
147 if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && res.locals.videoChannel.Account.userId !== user.id) { 150 if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && videoChannel.Account.userId !== user.id) {
148 return res.status(403) 151 res.status(403)
149 .json({ error: 'Cannot remove video channel of another user' }) 152 .json({ error: 'Cannot remove video channel of another user' })
150 .end() 153 .end()
154
155 return false
151 } 156 }
152 157
153 // If we reach this comment, we can delete the video 158 return true
154 callback()
155} 159}
156 160
157function checkVideoChannelIsNotTheLastOne (res: express.Response, callback: () => void) { 161async function checkVideoChannelIsNotTheLastOne (res: express.Response) {
158 db.VideoChannel.countByAccount(res.locals.oauth.token.User.Account.id) 162 const count = await db.VideoChannel.countByAccount(res.locals.oauth.token.User.Account.id)
159 .then(count => { 163
160 if (count <= 1) { 164 if (count <= 1) {
161 return res.status(409) 165 res.status(409)
162 .json({ error: 'Cannot remove the last channel of this user' }) 166 .json({ error: 'Cannot remove the last channel of this user' })
163 .end() 167 .end()
164 } 168
165 169 return false
166 callback() 170 }
167 }) 171
172 return true
168} 173}
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts
index 5ffc85210..3cbf98312 100644
--- a/server/middlewares/validators/videos.ts
+++ b/server/middlewares/validators/videos.ts
@@ -3,11 +3,11 @@ import { body, param, query } from 'express-validator/check'
3import { UserRight, VideoPrivacy } from '../../../shared' 3import { UserRight, VideoPrivacy } from '../../../shared'
4import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc' 4import { isIdOrUUIDValid, isIdValid } from '../../helpers/custom-validators/misc'
5import { 5import {
6 checkVideoExists,
7 isVideoAbuseReasonValid, 6 isVideoAbuseReasonValid,
8 isVideoCategoryValid, 7 isVideoCategoryValid,
9 isVideoDescriptionValid, 8 isVideoDescriptionValid,
10 isVideoDurationValid, 9 isVideoDurationValid,
10 isVideoExist,
11 isVideoFile, 11 isVideoFile,
12 isVideoLanguageValid, 12 isVideoLanguageValid,
13 isVideoLicenceValid, 13 isVideoLicenceValid,
@@ -20,12 +20,11 @@ import {
20import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' 20import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils'
21import { logger } from '../../helpers/logger' 21import { logger } from '../../helpers/logger'
22import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers' 22import { CONSTRAINTS_FIELDS, SEARCHABLE_COLUMNS } from '../../initializers'
23
24import { database as db } from '../../initializers/database' 23import { database as db } from '../../initializers/database'
25import { UserInstance } from '../../models/account/user-interface' 24import { UserInstance } from '../../models/account/user-interface'
25import { VideoInstance } from '../../models/video/video-interface'
26import { authenticate } from '../oauth' 26import { authenticate } from '../oauth'
27import { areValidationErrors, checkErrors } from './utils' 27import { areValidationErrors } from './utils'
28import { isVideoExistsPromise } from '../../helpers/index'
29 28
30const videosAddValidator = [ 29const videosAddValidator = [
31 body('videofile').custom((value, { req }) => isVideoFile(req.files)).withMessage( 30 body('videofile').custom((value, { req }) => isVideoFile(req.files)).withMessage(
@@ -42,68 +41,58 @@ const videosAddValidator = [
42 body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'), 41 body('privacy').custom(isVideoPrivacyValid).withMessage('Should have correct video privacy'),
43 body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), 42 body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'),
44 43
45 (req: express.Request, res: express.Response, next: express.NextFunction) => { 44 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
46 logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files }) 45 logger.debug('Checking videosAdd parameters', { parameters: req.body, files: req.files })
47 46
48 checkErrors(req, res, () => { 47 if (areValidationErrors(req, res)) return
49 const videoFile: Express.Multer.File = req.files['videofile'][0] 48
50 const user = res.locals.oauth.token.User 49 const videoFile: Express.Multer.File = req.files['videofile'][0]
50 const user = res.locals.oauth.token.User
51 51
52 return db.VideoChannel.loadByIdAndAccount(req.body.channelId, user.Account.id) 52 const videoChannel = await db.VideoChannel.loadByIdAndAccount(req.body.channelId, user.Account.id)
53 .then(videoChannel => { 53 if (!videoChannel) {
54 if (!videoChannel) { 54 res.status(400)
55 res.status(400) 55 .json({ error: 'Unknown video video channel for this account.' })
56 .json({ error: 'Unknown video video channel for this account.' }) 56 .end()
57 .end()
58 57
59 return undefined 58 return
60 } 59 }
61 60
62 res.locals.videoChannel = videoChannel 61 res.locals.videoChannel = videoChannel
63 62
64 return user.isAbleToUploadVideo(videoFile) 63 const isAble = await user.isAbleToUploadVideo(videoFile)
65 }) 64 if (isAble === false) {
66 .then(isAble => { 65 res.status(403)
67 if (isAble === false) { 66 .json({ error: 'The user video quota is exceeded with this video.' })
68 res.status(403) 67 .end()
69 .json({ error: 'The user video quota is exceeded with this video.' }) 68
70 .end() 69 return
71 70 }
72 return undefined 71
73 } 72 let duration: number
74 73
75 return getDurationFromVideoFile(videoFile.path) 74 try {
76 .catch(err => { 75 duration = await getDurationFromVideoFile(videoFile.path)
77 logger.error('Invalid input file in videosAddValidator.', err) 76 } catch (err) {
78 res.status(400) 77 logger.error('Invalid input file in videosAddValidator.', err)
79 .json({ error: 'Invalid input file.' }) 78 res.status(400)
80 .end() 79 .json({ error: 'Invalid input file.' })
81 80 .end()
82 return undefined 81
83 }) 82 return
84 }) 83 }
85 .then(duration => { 84
86 // Previous test failed, abort 85 if (!isVideoDurationValid('' + duration)) {
87 if (duration === undefined) return undefined 86 return res.status(400)
88 87 .json({
89 if (!isVideoDurationValid('' + duration)) { 88 error: 'Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).'
90 return res.status(400) 89 })
91 .json({ 90 .end()
92 error: 'Duration of the video file is too big (max: ' + CONSTRAINTS_FIELDS.VIDEOS.DURATION.max + 's).' 91 }
93 }) 92
94 .end() 93 videoFile['duration'] = duration
95 } 94
96 95 return next()
97 videoFile['duration'] = duration
98 next()
99 })
100 .catch(err => {
101 logger.error('Error in video add validator', err)
102 res.sendStatus(500)
103
104 return undefined
105 })
106 })
107 } 96 }
108] 97]
109 98
@@ -118,61 +107,59 @@ const videosUpdateValidator = [
118 body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'), 107 body('description').optional().custom(isVideoDescriptionValid).withMessage('Should have a valid description'),
119 body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'), 108 body('tags').optional().custom(isVideoTagsValid).withMessage('Should have correct tags'),
120 109
121 (req: express.Request, res: express.Response, next: express.NextFunction) => { 110 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
122 logger.debug('Checking videosUpdate parameters', { parameters: req.body }) 111 logger.debug('Checking videosUpdate parameters', { parameters: req.body })
123 112
124 checkErrors(req, res, () => { 113 if (areValidationErrors(req, res)) return
125 checkVideoExists(req.params.id, res, () => { 114 if (!await isVideoExist(req.params.id, res)) return
126 const video = res.locals.video 115
127 116 const video = res.locals.video
128 // We need to make additional checks 117
129 if (video.isOwned() === false) { 118 // We need to make additional checks
130 return res.status(403) 119 if (video.isOwned() === false) {
131 .json({ error: 'Cannot update video of another server' }) 120 return res.status(403)
132 .end() 121 .json({ error: 'Cannot update video of another server' })
133 } 122 .end()
134 123 }
135 if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) { 124
136 return res.status(403) 125 if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) {
137 .json({ error: 'Cannot update video of another user' }) 126 return res.status(403)
138 .end() 127 .json({ error: 'Cannot update video of another user' })
139 } 128 .end()
140 129 }
141 if (video.privacy !== VideoPrivacy.PRIVATE && req.body.privacy === VideoPrivacy.PRIVATE) { 130
142 return res.status(409) 131 if (video.privacy !== VideoPrivacy.PRIVATE && req.body.privacy === VideoPrivacy.PRIVATE) {
143 .json({ error: 'Cannot set "private" a video that was not private anymore.' }) 132 return res.status(409)
144 .end() 133 .json({ error: 'Cannot set "private" a video that was not private anymore.' })
145 } 134 .end()
146 135 }
147 next() 136
148 }) 137 return next()
149 })
150 } 138 }
151] 139]
152 140
153const videosGetValidator = [ 141const videosGetValidator = [
154 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 142 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
155 143
156 (req: express.Request, res: express.Response, next: express.NextFunction) => { 144 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
157 logger.debug('Checking videosGet parameters', { parameters: req.params }) 145 logger.debug('Checking videosGet parameters', { parameters: req.params })
158 146
159 checkErrors(req, res, () => { 147 if (areValidationErrors(req, res)) return
160 checkVideoExists(req.params.id, res, () => { 148 if (!await isVideoExist(req.params.id, res)) return
161 const video = res.locals.video
162 149
163 // Video is not private, anyone can access it 150 const video = res.locals.video
164 if (video.privacy !== VideoPrivacy.PRIVATE) return next()
165 151
166 authenticate(req, res, () => { 152 // Video is not private, anyone can access it
167 if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) { 153 if (video.privacy !== VideoPrivacy.PRIVATE) return next()
168 return res.status(403)
169 .json({ error: 'Cannot get this private video of another user' })
170 .end()
171 }
172 154
173 next() 155 authenticate(req, res, () => {
174 }) 156 if (video.VideoChannel.Account.userId !== res.locals.oauth.token.User.id) {
175 }) 157 return res.status(403)
158 .json({ error: 'Cannot get this private video of another user' })
159 .end()
160 }
161
162 return next()
176 }) 163 })
177 } 164 }
178] 165]
@@ -180,17 +167,16 @@ const videosGetValidator = [
180const videosRemoveValidator = [ 167const videosRemoveValidator = [
181 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 168 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
182 169
183 (req: express.Request, res: express.Response, next: express.NextFunction) => { 170 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
184 logger.debug('Checking videosRemove parameters', { parameters: req.params }) 171 logger.debug('Checking videosRemove parameters', { parameters: req.params })
185 172
186 checkErrors(req, res, () => { 173 if (areValidationErrors(req, res)) return
187 checkVideoExists(req.params.id, res, () => { 174 if (!await isVideoExist(req.params.id, res)) return
188 // Check if the user who did the request is able to delete the video 175
189 checkUserCanDeleteVideo(res.locals.oauth.token.User, res, () => { 176 // Check if the user who did the request is able to delete the video
190 next() 177 if (!checkUserCanDeleteVideo(res.locals.oauth.token.User, res.locals.video, res)) return
191 }) 178
192 }) 179 return next()
193 })
194 } 180 }
195] 181]
196 182
@@ -201,7 +187,9 @@ const videosSearchValidator = [
201 (req: express.Request, res: express.Response, next: express.NextFunction) => { 187 (req: express.Request, res: express.Response, next: express.NextFunction) => {
202 logger.debug('Checking videosSearch parameters', { parameters: req.params }) 188 logger.debug('Checking videosSearch parameters', { parameters: req.params })
203 189
204 checkErrors(req, res, next) 190 if (areValidationErrors(req, res)) return
191
192 return next()
205 } 193 }
206] 194]
207 195
@@ -209,12 +197,13 @@ const videoAbuseReportValidator = [
209 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 197 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
210 body('reason').custom(isVideoAbuseReasonValid).withMessage('Should have a valid reason'), 198 body('reason').custom(isVideoAbuseReasonValid).withMessage('Should have a valid reason'),
211 199
212 (req: express.Request, res: express.Response, next: express.NextFunction) => { 200 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
213 logger.debug('Checking videoAbuseReport parameters', { parameters: req.body }) 201 logger.debug('Checking videoAbuseReport parameters', { parameters: req.body })
214 202
215 checkErrors(req, res, () => { 203 if (areValidationErrors(req, res)) return
216 checkVideoExists(req.params.id, res, next) 204 if (!await isVideoExist(req.params.id, res)) return
217 }) 205
206 return next()
218 } 207 }
219] 208]
220 209
@@ -222,12 +211,13 @@ const videoRateValidator = [
222 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 211 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
223 body('rating').custom(isVideoRatingTypeValid).withMessage('Should have a valid rate type'), 212 body('rating').custom(isVideoRatingTypeValid).withMessage('Should have a valid rate type'),
224 213
225 (req: express.Request, res: express.Response, next: express.NextFunction) => { 214 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
226 logger.debug('Checking videoRate parameters', { parameters: req.body }) 215 logger.debug('Checking videoRate parameters', { parameters: req.body })
227 216
228 checkErrors(req, res, () => { 217 if (areValidationErrors(req, res)) return
229 checkVideoExists(req.params.id, res, next) 218 if (!await isVideoExist(req.params.id, res)) return
230 }) 219
220 return next()
231 } 221 }
232] 222]
233 223
@@ -239,7 +229,7 @@ const videosShareValidator = [
239 logger.debug('Checking videoShare parameters', { parameters: req.params }) 229 logger.debug('Checking videoShare parameters', { parameters: req.params })
240 230
241 if (areValidationErrors(req, res)) return 231 if (areValidationErrors(req, res)) return
242 if (!await isVideoExistsPromise(req.params.id, res)) return 232 if (!await isVideoExist(req.params.id, res)) return
243 233
244 const share = await db.VideoShare.load(req.params.accountId, res.locals.video.id) 234 const share = await db.VideoShare.load(req.params.accountId, res.locals.video.id)
245 if (!share) { 235 if (!share) {
@@ -248,7 +238,6 @@ const videosShareValidator = [
248 } 238 }
249 239
250 res.locals.videoShare = share 240 res.locals.videoShare = share
251
252 return next() 241 return next()
253 } 242 }
254] 243]
@@ -270,24 +259,25 @@ export {
270 259
271// --------------------------------------------------------------------------- 260// ---------------------------------------------------------------------------
272 261
273function checkUserCanDeleteVideo (user: UserInstance, res: express.Response, callback: () => void) { 262function checkUserCanDeleteVideo (user: UserInstance, video: VideoInstance, res: express.Response) {
274 // Retrieve the user who did the request 263 // Retrieve the user who did the request
275 if (res.locals.video.isOwned() === false) { 264 if (video.isOwned() === false) {
276 return res.status(403) 265 res.status(403)
277 .json({ error: 'Cannot remove video of another server, blacklist it' }) 266 .json({ error: 'Cannot remove video of another server, blacklist it' })
278 .end() 267 .end()
268 return false
279 } 269 }
280 270
281 // Check if the user can delete the video 271 // Check if the user can delete the video
282 // The user can delete it if s/he is an admin 272 // The user can delete it if s/he is an admin
283 // Or if s/he is the video's account 273 // Or if s/he is the video's account
284 const account = res.locals.video.VideoChannel.Account 274 const account = video.VideoChannel.Account
285 if (user.hasRight(UserRight.REMOVE_ANY_VIDEO) === false && account.userId !== user.id) { 275 if (user.hasRight(UserRight.REMOVE_ANY_VIDEO) === false && account.userId !== user.id) {
286 return res.status(403) 276 res.status(403)
287 .json({ error: 'Cannot remove video of another user' }) 277 .json({ error: 'Cannot remove video of another user' })
288 .end() 278 .end()
279 return false
289 } 280 }
290 281
291 // If we reach this comment, we can delete the video 282 return true
292 callback()
293} 283}
diff --git a/server/middlewares/validators/webfinger.ts b/server/middlewares/validators/webfinger.ts
index 7852c1c2b..34e62c66d 100644
--- a/server/middlewares/validators/webfinger.ts
+++ b/server/middlewares/validators/webfinger.ts
@@ -1,37 +1,31 @@
1import * as express from 'express' 1import * as express from 'express'
2import { query } from 'express-validator/check' 2import { query } from 'express-validator/check'
3import { isWebfingerResourceValid } from '../../helpers/custom-validators/webfinger' 3import { isWebfingerResourceValid } from '../../helpers/custom-validators/webfinger'
4import { database as db } from '../../initializers'
5import { checkErrors } from './utils'
6import { logger } from '../../helpers/logger' 4import { logger } from '../../helpers/logger'
5import { database as db } from '../../initializers'
6import { areValidationErrors } from './utils'
7 7
8const webfingerValidator = [ 8const webfingerValidator = [
9 query('resource').custom(isWebfingerResourceValid).withMessage('Should have a valid webfinger resource'), 9 query('resource').custom(isWebfingerResourceValid).withMessage('Should have a valid webfinger resource'),
10 10
11 (req: express.Request, res: express.Response, next: express.NextFunction) => { 11 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
12 logger.debug('Checking webfinger parameters', { parameters: req.query }) 12 logger.debug('Checking webfinger parameters', { parameters: req.query })
13 13
14 checkErrors(req, res, () => { 14 if (areValidationErrors(req, res)) return
15 // Remove 'acct:' from the beginning of the string 15
16 const nameWithHost = req.query.resource.substr(5) 16 // Remove 'acct:' from the beginning of the string
17 const [ name ] = nameWithHost.split('@') 17 const nameWithHost = req.query.resource.substr(5)
18 18 const [ name ] = nameWithHost.split('@')
19 db.Account.loadLocalByName(name) 19
20 .then(account => { 20 const account = await db.Account.loadLocalByName(name)
21 if (!account) { 21 if (!account) {
22 return res.status(404) 22 return res.status(404)
23 .send({ error: 'Account not found' }) 23 .send({ error: 'Account not found' })
24 .end() 24 .end()
25 } 25 }
26 26
27 res.locals.account = account 27 res.locals.account = account
28 return next() 28 return next()
29 })
30 .catch(err => {
31 logger.error('Error in webfinger validator.', err)
32 return res.sendStatus(500)
33 })
34 })
35 } 29 }
36] 30]
37 31