aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/middlewares
diff options
context:
space:
mode:
Diffstat (limited to 'server/middlewares')
-rw-r--r--server/middlewares/activitypub.ts15
-rw-r--r--server/middlewares/oauth.ts3
-rw-r--r--server/middlewares/servers.ts3
-rw-r--r--server/middlewares/user-right.ts4
-rw-r--r--server/middlewares/validators/abuse.ts21
-rw-r--r--server/middlewares/validators/activitypub/activity.ts7
-rw-r--r--server/middlewares/validators/blocklist.ts9
-rw-r--r--server/middlewares/validators/bulk.ts3
-rw-r--r--server/middlewares/validators/config.ts11
-rw-r--r--server/middlewares/validators/feeds.ts5
-rw-r--r--server/middlewares/validators/follows.ts15
-rw-r--r--server/middlewares/validators/oembed.ts15
-rw-r--r--server/middlewares/validators/plugins.ts23
-rw-r--r--server/middlewares/validators/redundancy.ts23
-rw-r--r--server/middlewares/validators/server.ts13
-rw-r--r--server/middlewares/validators/themes.ts5
-rw-r--r--server/middlewares/validators/user-subscriptions.ts3
-rw-r--r--server/middlewares/validators/users.ts55
-rw-r--r--server/middlewares/validators/utils.ts4
-rw-r--r--server/middlewares/validators/videos/video-blacklist.ts3
-rw-r--r--server/middlewares/validators/videos/video-channels.ts19
-rw-r--r--server/middlewares/validators/videos/video-comments.ts13
-rw-r--r--server/middlewares/validators/videos/video-imports.ts9
-rw-r--r--server/middlewares/validators/videos/video-live.ts21
-rw-r--r--server/middlewares/validators/videos/video-playlists.ts27
-rw-r--r--server/middlewares/validators/videos/video-rates.ts3
-rw-r--r--server/middlewares/validators/videos/video-shares.ts3
-rw-r--r--server/middlewares/validators/videos/video-watch.ts3
-rw-r--r--server/middlewares/validators/videos/videos.ts23
-rw-r--r--server/middlewares/validators/webfinger.ts7
30 files changed, 208 insertions, 160 deletions
diff --git a/server/middlewares/activitypub.ts b/server/middlewares/activitypub.ts
index d00594059..ce94a2129 100644
--- a/server/middlewares/activitypub.ts
+++ b/server/middlewares/activitypub.ts
@@ -7,6 +7,7 @@ import { getOrCreateActorAndServerAndModel } from '../lib/activitypub/actor'
7import { loadActorUrlOrGetFromWebfinger } from '../helpers/webfinger' 7import { loadActorUrlOrGetFromWebfinger } from '../helpers/webfinger'
8import { isActorDeleteActivityValid } from '@server/helpers/custom-validators/activitypub/actor' 8import { isActorDeleteActivityValid } from '@server/helpers/custom-validators/activitypub/actor'
9import { getAPId } from '@server/helpers/activitypub' 9import { getAPId } from '@server/helpers/activitypub'
10import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
10 11
11async function checkSignature (req: Request, res: Response, next: NextFunction) { 12async function checkSignature (req: Request, res: Response, next: NextFunction) {
12 try { 13 try {
@@ -28,11 +29,11 @@ async function checkSignature (req: Request, res: Response, next: NextFunction)
28 const activity: ActivityDelete = req.body 29 const activity: ActivityDelete = req.body
29 if (isActorDeleteActivityValid(activity) && activity.object === activity.actor) { 30 if (isActorDeleteActivityValid(activity) && activity.object === activity.actor) {
30 logger.debug('Handling signature error on actor delete activity', { err }) 31 logger.debug('Handling signature error on actor delete activity', { err })
31 return res.sendStatus(204) 32 return res.sendStatus(HttpStatusCode.NO_CONTENT_204)
32 } 33 }
33 34
34 logger.warn('Error in ActivityPub signature checker.', { err }) 35 logger.warn('Error in ActivityPub signature checker.', { err })
35 return res.sendStatus(403) 36 return res.sendStatus(HttpStatusCode.FORBIDDEN_403)
36 } 37 }
37} 38}
38 39
@@ -70,13 +71,13 @@ async function checkHttpSignature (req: Request, res: Response) {
70 } catch (err) { 71 } catch (err) {
71 logger.warn('Invalid signature because of exception in signature parser', { reqBody: req.body, err }) 72 logger.warn('Invalid signature because of exception in signature parser', { reqBody: req.body, err })
72 73
73 res.status(403).json({ error: err.message }) 74 res.status(HttpStatusCode.FORBIDDEN_403).json({ error: err.message })
74 return false 75 return false
75 } 76 }
76 77
77 const keyId = parsed.keyId 78 const keyId = parsed.keyId
78 if (!keyId) { 79 if (!keyId) {
79 res.sendStatus(403) 80 res.sendStatus(HttpStatusCode.FORBIDDEN_403)
80 return false 81 return false
81 } 82 }
82 83
@@ -93,7 +94,7 @@ async function checkHttpSignature (req: Request, res: Response) {
93 if (verified !== true) { 94 if (verified !== true) {
94 logger.warn('Signature from %s is invalid', actorUrl, { parsed }) 95 logger.warn('Signature from %s is invalid', actorUrl, { parsed })
95 96
96 res.sendStatus(403) 97 res.sendStatus(HttpStatusCode.FORBIDDEN_403)
97 return false 98 return false
98 } 99 }
99 100
@@ -106,7 +107,7 @@ async function checkJsonLDSignature (req: Request, res: Response) {
106 const signatureObject: ActivityPubSignature = req.body.signature 107 const signatureObject: ActivityPubSignature = req.body.signature
107 108
108 if (!signatureObject || !signatureObject.creator) { 109 if (!signatureObject || !signatureObject.creator) {
109 res.sendStatus(403) 110 res.sendStatus(HttpStatusCode.FORBIDDEN_403)
110 return false 111 return false
111 } 112 }
112 113
@@ -120,7 +121,7 @@ async function checkJsonLDSignature (req: Request, res: Response) {
120 if (verified !== true) { 121 if (verified !== true) {
121 logger.warn('Signature not verified.', req.body) 122 logger.warn('Signature not verified.', req.body)
122 123
123 res.sendStatus(403) 124 res.sendStatus(HttpStatusCode.FORBIDDEN_403)
124 return false 125 return false
125 } 126 }
126 127
diff --git a/server/middlewares/oauth.ts b/server/middlewares/oauth.ts
index bd60a3639..ab5301415 100644
--- a/server/middlewares/oauth.ts
+++ b/server/middlewares/oauth.ts
@@ -3,6 +3,7 @@ import { Socket } from 'socket.io'
3import { oAuthServer } from '@server/lib/auth' 3import { oAuthServer } from '@server/lib/auth'
4import { logger } from '../helpers/logger' 4import { logger } from '../helpers/logger'
5import { getAccessToken } from '../lib/oauth-model' 5import { getAccessToken } from '../lib/oauth-model'
6import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
6 7
7function authenticate (req: express.Request, res: express.Response, next: express.NextFunction, authenticateInQuery = false) { 8function authenticate (req: express.Request, res: express.Response, next: express.NextFunction, authenticateInQuery = false) {
8 const options = authenticateInQuery ? { allowBearerTokensInQueryString: true } : {} 9 const options = authenticateInQuery ? { allowBearerTokensInQueryString: true } : {}
@@ -50,7 +51,7 @@ function authenticatePromiseIfNeeded (req: express.Request, res: express.Respons
50 // Already authenticated? (or tried to) 51 // Already authenticated? (or tried to)
51 if (res.locals.oauth?.token.User) return resolve() 52 if (res.locals.oauth?.token.User) return resolve()
52 53
53 if (res.locals.authenticated === false) return res.sendStatus(401) 54 if (res.locals.authenticated === false) return res.sendStatus(HttpStatusCode.UNAUTHORIZED_401)
54 55
55 authenticate(req, res, () => resolve(), authenticateInQuery) 56 authenticate(req, res, () => resolve(), authenticateInQuery)
56 }) 57 })
diff --git a/server/middlewares/servers.ts b/server/middlewares/servers.ts
index 9c0af443a..5e1c165f0 100644
--- a/server/middlewares/servers.ts
+++ b/server/middlewares/servers.ts
@@ -1,5 +1,6 @@
1import * as express from 'express' 1import * as express from 'express'
2import { getHostWithPort } from '../helpers/express-utils' 2import { getHostWithPort } from '../helpers/express-utils'
3import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
3 4
4function setBodyHostsPort (req: express.Request, res: express.Response, next: express.NextFunction) { 5function setBodyHostsPort (req: express.Request, res: express.Response, next: express.NextFunction) {
5 if (!req.body.hosts) return next() 6 if (!req.body.hosts) return next()
@@ -9,7 +10,7 @@ function setBodyHostsPort (req: express.Request, res: express.Response, next: ex
9 10
10 // Problem with the url parsing? 11 // Problem with the url parsing?
11 if (hostWithPort === null) { 12 if (hostWithPort === null) {
12 return res.sendStatus(500) 13 return res.sendStatus(HttpStatusCode.INTERNAL_SERVER_ERROR_500)
13 } 14 }
14 15
15 req.body.hosts[i] = hostWithPort 16 req.body.hosts[i] = hostWithPort
diff --git a/server/middlewares/user-right.ts b/server/middlewares/user-right.ts
index aaf0b323a..45dda4781 100644
--- a/server/middlewares/user-right.ts
+++ b/server/middlewares/user-right.ts
@@ -1,6 +1,7 @@
1import * as express from 'express' 1import * as express from 'express'
2import { UserRight } from '../../shared' 2import { UserRight } from '../../shared'
3import { logger } from '../helpers/logger' 3import { logger } from '../helpers/logger'
4import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
4 5
5function ensureUserHasRight (userRight: UserRight) { 6function ensureUserHasRight (userRight: UserRight) {
6 return function (req: express.Request, res: express.Response, next: express.NextFunction) { 7 return function (req: express.Request, res: express.Response, next: express.NextFunction) {
@@ -9,7 +10,8 @@ function ensureUserHasRight (userRight: UserRight) {
9 const message = `User ${user.username} does not have right ${userRight} to access to ${req.path}.` 10 const message = `User ${user.username} does not have right ${userRight} to access to ${req.path}.`
10 logger.info(message) 11 logger.info(message)
11 12
12 return res.status(403).json({ error: message }) 13 return res.status(HttpStatusCode.FORBIDDEN_403)
14 .json({ error: message })
13 } 15 }
14 16
15 return next() 17 return next()
diff --git a/server/middlewares/validators/abuse.ts b/server/middlewares/validators/abuse.ts
index 99403ca40..3b897fdef 100644
--- a/server/middlewares/validators/abuse.ts
+++ b/server/middlewares/validators/abuse.ts
@@ -19,6 +19,7 @@ import { doesAbuseExist, doesAccountIdExist, doesVideoExist } from '@server/help
19import { AbuseMessageModel } from '@server/models/abuse/abuse-message' 19import { AbuseMessageModel } from '@server/models/abuse/abuse-message'
20import { AbuseCreate, UserRight } from '@shared/models' 20import { AbuseCreate, UserRight } from '@shared/models'
21import { areValidationErrors } from './utils' 21import { areValidationErrors } from './utils'
22import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
22 23
23const abuseReportValidator = [ 24const abuseReportValidator = [
24 body('account.id') 25 body('account.id')
@@ -70,8 +71,8 @@ const abuseReportValidator = [
70 if (body.comment?.id && !await doesCommentIdExist(body.comment.id, res)) return 71 if (body.comment?.id && !await doesCommentIdExist(body.comment.id, res)) return
71 72
72 if (!body.video?.id && !body.account?.id && !body.comment?.id) { 73 if (!body.video?.id && !body.account?.id && !body.comment?.id) {
73 res.status(400) 74 res.status(HttpStatusCode.BAD_REQUEST_400)
74 .json({ error: 'video id or account id or comment id is required.' }) 75 .json({ error: 'video id or account id or comment id is required.' })
75 76
76 return 77 return
77 } 78 }
@@ -194,7 +195,8 @@ const getAbuseValidator = [
194 const message = `User ${user.username} does not have right to get abuse ${abuse.id}` 195 const message = `User ${user.username} does not have right to get abuse ${abuse.id}`
195 logger.warn(message) 196 logger.warn(message)
196 197
197 return res.status(403).json({ error: message }) 198 return res.status(HttpStatusCode.FORBIDDEN_403)
199 .json({ error: message })
198 } 200 }
199 201
200 return next() 202 return next()
@@ -207,9 +209,10 @@ const checkAbuseValidForMessagesValidator = [
207 209
208 const abuse = res.locals.abuse 210 const abuse = res.locals.abuse
209 if (abuse.ReporterAccount.isOwned() === false) { 211 if (abuse.ReporterAccount.isOwned() === false) {
210 return res.status(400).json({ 212 return res.status(HttpStatusCode.BAD_REQUEST_400)
211 error: 'This abuse was created by a user of your instance.' 213 .json({
212 }) 214 error: 'This abuse was created by a user of your instance.'
215 })
213 } 216 }
214 217
215 return next() 218 return next()
@@ -243,11 +246,13 @@ const deleteAbuseMessageValidator = [
243 const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id) 246 const abuseMessage = await AbuseMessageModel.loadByIdAndAbuseId(messageId, abuse.id)
244 247
245 if (!abuseMessage) { 248 if (!abuseMessage) {
246 return res.status(404).json({ error: 'Abuse message not found' }) 249 return res.status(HttpStatusCode.NOT_FOUND_404)
250 .json({ error: 'Abuse message not found' })
247 } 251 }
248 252
249 if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuseMessage.accountId !== user.Account.id) { 253 if (user.hasRight(UserRight.MANAGE_ABUSES) !== true && abuseMessage.accountId !== user.Account.id) {
250 return res.status(403).json({ error: 'Cannot delete this abuse message' }) 254 return res.status(HttpStatusCode.FORBIDDEN_403)
255 .json({ error: 'Cannot delete this abuse message' })
251 } 256 }
252 257
253 res.locals.abuseMessage = abuseMessage 258 res.locals.abuseMessage = abuseMessage
diff --git a/server/middlewares/validators/activitypub/activity.ts b/server/middlewares/validators/activitypub/activity.ts
index 7350be5d5..255d8eb17 100644
--- a/server/middlewares/validators/activitypub/activity.ts
+++ b/server/middlewares/validators/activitypub/activity.ts
@@ -2,20 +2,23 @@ import * as express from 'express'
2import { isRootActivityValid } from '../../../helpers/custom-validators/activitypub/activity' 2import { isRootActivityValid } from '../../../helpers/custom-validators/activitypub/activity'
3import { logger } from '../../../helpers/logger' 3import { logger } from '../../../helpers/logger'
4import { getServerActor } from '@server/models/application/application' 4import { getServerActor } from '@server/models/application/application'
5import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
5 6
6async function activityPubValidator (req: express.Request, res: express.Response, next: express.NextFunction) { 7async function activityPubValidator (req: express.Request, res: express.Response, next: express.NextFunction) {
7 logger.debug('Checking activity pub parameters') 8 logger.debug('Checking activity pub parameters')
8 9
9 if (!isRootActivityValid(req.body)) { 10 if (!isRootActivityValid(req.body)) {
10 logger.warn('Incorrect activity parameters.', { activity: req.body }) 11 logger.warn('Incorrect activity parameters.', { activity: req.body })
11 return res.status(400).json({ error: 'Incorrect activity.' }) 12 return res.status(HttpStatusCode.BAD_REQUEST_400)
13 .json({ error: 'Incorrect activity.' })
12 } 14 }
13 15
14 const serverActor = await getServerActor() 16 const serverActor = await getServerActor()
15 const remoteActor = res.locals.signature.actor 17 const remoteActor = res.locals.signature.actor
16 if (serverActor.id === remoteActor.id) { 18 if (serverActor.id === remoteActor.id) {
17 logger.error('Receiving request in INBOX by ourselves!', req.body) 19 logger.error('Receiving request in INBOX by ourselves!', req.body)
18 return res.status(409).end() 20 return res.status(HttpStatusCode.CONFLICT_409)
21 .end()
19 } 22 }
20 23
21 return next() 24 return next()
diff --git a/server/middlewares/validators/blocklist.ts b/server/middlewares/validators/blocklist.ts
index c24fa9609..f61811a1a 100644
--- a/server/middlewares/validators/blocklist.ts
+++ b/server/middlewares/validators/blocklist.ts
@@ -9,6 +9,7 @@ import { ServerModel } from '../../models/server/server'
9import { WEBSERVER } from '../../initializers/constants' 9import { WEBSERVER } from '../../initializers/constants'
10import { doesAccountNameWithHostExist } from '../../helpers/middlewares' 10import { doesAccountNameWithHostExist } from '../../helpers/middlewares'
11import { getServerActor } from '@server/models/application/application' 11import { getServerActor } from '@server/models/application/application'
12import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
12 13
13const blockAccountValidator = [ 14const blockAccountValidator = [
14 body('accountName').exists().withMessage('Should have an account name with host'), 15 body('accountName').exists().withMessage('Should have an account name with host'),
@@ -23,7 +24,7 @@ const blockAccountValidator = [
23 const accountToBlock = res.locals.account 24 const accountToBlock = res.locals.account
24 25
25 if (user.Account.id === accountToBlock.id) { 26 if (user.Account.id === accountToBlock.id) {
26 res.status(409) 27 res.status(HttpStatusCode.CONFLICT_409)
27 .json({ error: 'You cannot block yourself.' }) 28 .json({ error: 'You cannot block yourself.' })
28 29
29 return 30 return
@@ -78,7 +79,7 @@ const blockServerValidator = [
78 const host: string = req.body.host 79 const host: string = req.body.host
79 80
80 if (host === WEBSERVER.HOST) { 81 if (host === WEBSERVER.HOST) {
81 return res.status(409) 82 return res.status(HttpStatusCode.CONFLICT_409)
82 .json({ error: 'You cannot block your own server.' }) 83 .json({ error: 'You cannot block your own server.' })
83 } 84 }
84 85
@@ -136,7 +137,7 @@ export {
136async function doesUnblockAccountExist (accountId: number, targetAccountId: number, res: express.Response) { 137async function doesUnblockAccountExist (accountId: number, targetAccountId: number, res: express.Response) {
137 const accountBlock = await AccountBlocklistModel.loadByAccountAndTarget(accountId, targetAccountId) 138 const accountBlock = await AccountBlocklistModel.loadByAccountAndTarget(accountId, targetAccountId)
138 if (!accountBlock) { 139 if (!accountBlock) {
139 res.status(404) 140 res.status(HttpStatusCode.NOT_FOUND_404)
140 .json({ error: 'Account block entry not found.' }) 141 .json({ error: 'Account block entry not found.' })
141 142
142 return false 143 return false
@@ -150,7 +151,7 @@ async function doesUnblockAccountExist (accountId: number, targetAccountId: numb
150async function doesUnblockServerExist (accountId: number, host: string, res: express.Response) { 151async function doesUnblockServerExist (accountId: number, host: string, res: express.Response) {
151 const serverBlock = await ServerBlocklistModel.loadByAccountAndHost(accountId, host) 152 const serverBlock = await ServerBlocklistModel.loadByAccountAndHost(accountId, host)
152 if (!serverBlock) { 153 if (!serverBlock) {
153 res.status(404) 154 res.status(HttpStatusCode.NOT_FOUND_404)
154 .json({ error: 'Server block entry not found.' }) 155 .json({ error: 'Server block entry not found.' })
155 156
156 return false 157 return false
diff --git a/server/middlewares/validators/bulk.ts b/server/middlewares/validators/bulk.ts
index f9b0f565a..cfb16d352 100644
--- a/server/middlewares/validators/bulk.ts
+++ b/server/middlewares/validators/bulk.ts
@@ -6,6 +6,7 @@ import { UserRight } from '@shared/models'
6import { BulkRemoveCommentsOfBody } from '@shared/models/bulk/bulk-remove-comments-of-body.model' 6import { BulkRemoveCommentsOfBody } from '@shared/models/bulk/bulk-remove-comments-of-body.model'
7import { logger } from '../../helpers/logger' 7import { logger } from '../../helpers/logger'
8import { areValidationErrors } from './utils' 8import { areValidationErrors } from './utils'
9import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
9 10
10const bulkRemoveCommentsOfValidator = [ 11const bulkRemoveCommentsOfValidator = [
11 body('accountName').exists().withMessage('Should have an account name with host'), 12 body('accountName').exists().withMessage('Should have an account name with host'),
@@ -22,7 +23,7 @@ const bulkRemoveCommentsOfValidator = [
22 const body = req.body as BulkRemoveCommentsOfBody 23 const body = req.body as BulkRemoveCommentsOfBody
23 24
24 if (body.scope === 'instance' && user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) !== true) { 25 if (body.scope === 'instance' && user.hasRight(UserRight.REMOVE_ANY_VIDEO_COMMENT) !== true) {
25 return res.status(403) 26 return res.status(HttpStatusCode.FORBIDDEN_403)
26 .json({ 27 .json({
27 error: 'User cannot remove any comments of this instance.' 28 error: 'User cannot remove any comments of this instance.'
28 }) 29 })
diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts
index d0071ccc1..93de453a7 100644
--- a/server/middlewares/validators/config.ts
+++ b/server/middlewares/validators/config.ts
@@ -8,6 +8,7 @@ import { isUserNSFWPolicyValid, isUserVideoQuotaDailyValid, isUserVideoQuotaVali
8import { logger } from '../../helpers/logger' 8import { logger } from '../../helpers/logger'
9import { isThemeRegistered } from '../../lib/plugins/theme-utils' 9import { isThemeRegistered } from '../../lib/plugins/theme-utils'
10import { areValidationErrors } from './utils' 10import { areValidationErrors } from './utils'
11import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
11 12
12const customConfigUpdateValidator = [ 13const customConfigUpdateValidator = [
13 body('instance.name').exists().withMessage('Should have a valid instance name'), 14 body('instance.name').exists().withMessage('Should have a valid instance name'),
@@ -105,9 +106,9 @@ function checkInvalidConfigIfEmailDisabled (customConfig: CustomConfig, res: exp
105 if (isEmailEnabled()) return true 106 if (isEmailEnabled()) return true
106 107
107 if (customConfig.signup.requiresEmailVerification === true) { 108 if (customConfig.signup.requiresEmailVerification === true) {
108 res.status(400) 109 res.status(HttpStatusCode.BAD_REQUEST_400)
109 .send({ error: 'Emailer is disabled but you require signup email verification.' }) 110 .send({ error: 'Emailer is disabled but you require signup email verification.' })
110 .end() 111 .end()
111 return false 112 return false
112 } 113 }
113 114
@@ -118,7 +119,7 @@ function checkInvalidTranscodingConfig (customConfig: CustomConfig, res: express
118 if (customConfig.transcoding.enabled === false) return true 119 if (customConfig.transcoding.enabled === false) return true
119 120
120 if (customConfig.transcoding.webtorrent.enabled === false && customConfig.transcoding.hls.enabled === false) { 121 if (customConfig.transcoding.webtorrent.enabled === false && customConfig.transcoding.hls.enabled === false) {
121 res.status(400) 122 res.status(HttpStatusCode.BAD_REQUEST_400)
122 .send({ error: 'You need to enable at least webtorrent transcoding or hls transcoding' }) 123 .send({ error: 'You need to enable at least webtorrent transcoding or hls transcoding' })
123 .end() 124 .end()
124 return false 125 return false
@@ -131,7 +132,7 @@ function checkInvalidLiveConfig (customConfig: CustomConfig, res: express.Respon
131 if (customConfig.live.enabled === false) return true 132 if (customConfig.live.enabled === false) return true
132 133
133 if (customConfig.live.allowReplay === true && customConfig.transcoding.enabled === false) { 134 if (customConfig.live.allowReplay === true && customConfig.transcoding.enabled === false) {
134 res.status(400) 135 res.status(HttpStatusCode.BAD_REQUEST_400)
135 .send({ error: 'You cannot allow live replay if transcoding is not enabled' }) 136 .send({ error: 'You cannot allow live replay if transcoding is not enabled' })
136 .end() 137 .end()
137 return false 138 return false
diff --git a/server/middlewares/validators/feeds.ts b/server/middlewares/validators/feeds.ts
index 18469bad3..617661813 100644
--- a/server/middlewares/validators/feeds.ts
+++ b/server/middlewares/validators/feeds.ts
@@ -12,6 +12,7 @@ import {
12} from '../../helpers/middlewares' 12} from '../../helpers/middlewares'
13import { doesVideoExist } from '../../helpers/middlewares/videos' 13import { doesVideoExist } from '../../helpers/middlewares/videos'
14import { areValidationErrors } from './utils' 14import { areValidationErrors } from './utils'
15import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
15 16
16const feedsFormatValidator = [ 17const feedsFormatValidator = [
17 param('format').optional().custom(isValidRSSFeed).withMessage('Should have a valid format (rss, atom, json)'), 18 param('format').optional().custom(isValidRSSFeed).withMessage('Should have a valid format (rss, atom, json)'),
@@ -35,7 +36,7 @@ function setFeedFormatContentType (req: express.Request, res: express.Response,
35 if (req.accepts(acceptableContentTypes)) { 36 if (req.accepts(acceptableContentTypes)) {
36 res.set('Content-Type', req.accepts(acceptableContentTypes) as string) 37 res.set('Content-Type', req.accepts(acceptableContentTypes) as string)
37 } else { 38 } else {
38 return res.status(406) 39 return res.status(HttpStatusCode.NOT_ACCEPTABLE_406)
39 .json({ 40 .json({
40 message: `You should accept at least one of the following content-types: ${acceptableContentTypes.join(', ')}` 41 message: `You should accept at least one of the following content-types: ${acceptableContentTypes.join(', ')}`
41 }) 42 })
@@ -105,7 +106,7 @@ const videoCommentsFeedsValidator = [
105 if (areValidationErrors(req, res)) return 106 if (areValidationErrors(req, res)) return
106 107
107 if (req.query.videoId && (req.query.videoChannelId || req.query.videoChannelName)) { 108 if (req.query.videoId && (req.query.videoChannelId || req.query.videoChannelName)) {
108 return res.status(400) 109 return res.status(HttpStatusCode.BAD_REQUEST_400)
109 .json({ 110 .json({
110 message: 'videoId cannot be mixed with a channel filter' 111 message: 'videoId cannot be mixed with a channel filter'
111 }) 112 })
diff --git a/server/middlewares/validators/follows.ts b/server/middlewares/validators/follows.ts
index 2c1ddf2df..a590aca99 100644
--- a/server/middlewares/validators/follows.ts
+++ b/server/middlewares/validators/follows.ts
@@ -12,6 +12,7 @@ import { isActorTypeValid, isValidActorHandle } from '../../helpers/custom-valid
12import { MActorFollowActorsDefault } from '@server/types/models' 12import { MActorFollowActorsDefault } from '@server/types/models'
13import { isFollowStateValid } from '@server/helpers/custom-validators/follows' 13import { isFollowStateValid } from '@server/helpers/custom-validators/follows'
14import { getServerActor } from '@server/models/application/application' 14import { getServerActor } from '@server/models/application/application'
15import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
15 16
16const listFollowsValidator = [ 17const listFollowsValidator = [
17 query('state') 18 query('state')
@@ -34,7 +35,8 @@ const followValidator = [
34 (req: express.Request, res: express.Response, next: express.NextFunction) => { 35 (req: express.Request, res: express.Response, next: express.NextFunction) => {
35 // Force https if the administrator wants to make friends 36 // Force https if the administrator wants to make friends
36 if (isTestInstance() === false && WEBSERVER.SCHEME === 'http') { 37 if (isTestInstance() === false && WEBSERVER.SCHEME === 'http') {
37 return res.status(500) 38 return res
39 .status(HttpStatusCode.INTERNAL_SERVER_ERROR_500)
38 .json({ 40 .json({
39 error: 'Cannot follow on a non HTTPS web server.' 41 error: 'Cannot follow on a non HTTPS web server.'
40 }) 42 })
@@ -62,7 +64,7 @@ const removeFollowingValidator = [
62 64
63 if (!follow) { 65 if (!follow) {
64 return res 66 return res
65 .status(404) 67 .status(HttpStatusCode.NOT_FOUND_404)
66 .json({ 68 .json({
67 error: `Following ${req.params.host} not found.` 69 error: `Following ${req.params.host} not found.`
68 }) 70 })
@@ -95,7 +97,7 @@ const getFollowerValidator = [
95 97
96 if (!follow) { 98 if (!follow) {
97 return res 99 return res
98 .status(404) 100 .status(HttpStatusCode.NOT_FOUND_404)
99 .json({ 101 .json({
100 error: `Follower ${req.params.nameWithHost} not found.` 102 error: `Follower ${req.params.nameWithHost} not found.`
101 }) 103 })
@@ -113,7 +115,12 @@ const acceptOrRejectFollowerValidator = [
113 115
114 const follow = res.locals.follow 116 const follow = res.locals.follow
115 if (follow.state !== 'pending') { 117 if (follow.state !== 'pending') {
116 return res.status(400).json({ error: 'Follow is not in pending state.' }).end() 118 return res
119 .status(HttpStatusCode.BAD_REQUEST_400)
120 .json({
121 error: 'Follow is not in pending state.'
122 })
123 .end()
117 } 124 }
118 125
119 return next() 126 return next()
diff --git a/server/middlewares/validators/oembed.ts b/server/middlewares/validators/oembed.ts
index c9f9ea0c0..86623efcd 100644
--- a/server/middlewares/validators/oembed.ts
+++ b/server/middlewares/validators/oembed.ts
@@ -9,6 +9,7 @@ import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc'
9import { logger } from '../../helpers/logger' 9import { logger } from '../../helpers/logger'
10import { WEBSERVER } from '../../initializers/constants' 10import { WEBSERVER } from '../../initializers/constants'
11import { areValidationErrors } from './utils' 11import { areValidationErrors } from './utils'
12import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
12 13
13const startVideoPlaylistsURL = WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, 'videos', 'watch', 'playlist') + '/' 14const startVideoPlaylistsURL = WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, 'videos', 'watch', 'playlist') + '/'
14const startVideosURL = WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, 'videos', 'watch') + '/' 15const startVideosURL = WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, 'videos', 'watch') + '/'
@@ -36,7 +37,7 @@ const oembedValidator = [
36 if (areValidationErrors(req, res)) return 37 if (areValidationErrors(req, res)) return
37 38
38 if (req.query.format !== undefined && req.query.format !== 'json') { 39 if (req.query.format !== undefined && req.query.format !== 'json') {
39 return res.status(501) 40 return res.status(HttpStatusCode.NOT_IMPLEMENTED_501)
40 .json({ error: 'Requested format is not implemented on server.' }) 41 .json({ error: 'Requested format is not implemented on server.' })
41 } 42 }
42 43
@@ -50,13 +51,13 @@ const oembedValidator = [
50 const matches = watchRegex.exec(url) 51 const matches = watchRegex.exec(url)
51 52
52 if (startIsOk === false || matches === null) { 53 if (startIsOk === false || matches === null) {
53 return res.status(400) 54 return res.status(HttpStatusCode.BAD_REQUEST_400)
54 .json({ error: 'Invalid url.' }) 55 .json({ error: 'Invalid url.' })
55 } 56 }
56 57
57 const elementId = matches[1] 58 const elementId = matches[1]
58 if (isIdOrUUIDValid(elementId) === false) { 59 if (isIdOrUUIDValid(elementId) === false) {
59 return res.status(400) 60 return res.status(HttpStatusCode.BAD_REQUEST_400)
60 .json({ error: 'Invalid video or playlist id.' }) 61 .json({ error: 'Invalid video or playlist id.' })
61 } 62 }
62 63
@@ -64,12 +65,12 @@ const oembedValidator = [
64 const video = await fetchVideo(elementId, 'all') 65 const video = await fetchVideo(elementId, 'all')
65 66
66 if (!video) { 67 if (!video) {
67 return res.status(404) 68 return res.status(HttpStatusCode.NOT_FOUND_404)
68 .json({ error: 'Video not found' }) 69 .json({ error: 'Video not found' })
69 } 70 }
70 71
71 if (video.privacy !== VideoPrivacy.PUBLIC) { 72 if (video.privacy !== VideoPrivacy.PUBLIC) {
72 return res.status(403) 73 return res.status(HttpStatusCode.FORBIDDEN_403)
73 .json({ error: 'Video is not public' }) 74 .json({ error: 'Video is not public' })
74 } 75 }
75 76
@@ -81,12 +82,12 @@ const oembedValidator = [
81 82
82 const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannelSummary(elementId, undefined) 83 const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannelSummary(elementId, undefined)
83 if (!videoPlaylist) { 84 if (!videoPlaylist) {
84 return res.status(404) 85 return res.status(HttpStatusCode.NOT_FOUND_404)
85 .json({ error: 'Video playlist not found' }) 86 .json({ error: 'Video playlist not found' })
86 } 87 }
87 88
88 if (videoPlaylist.privacy !== VideoPlaylistPrivacy.PUBLIC) { 89 if (videoPlaylist.privacy !== VideoPlaylistPrivacy.PUBLIC) {
89 return res.status(403) 90 return res.status(HttpStatusCode.FORBIDDEN_403)
90 .json({ error: 'Playlist is not public' }) 91 .json({ error: 'Playlist is not public' })
91 } 92 }
92 93
diff --git a/server/middlewares/validators/plugins.ts b/server/middlewares/validators/plugins.ts
index cba261dc0..bbac55a50 100644
--- a/server/middlewares/validators/plugins.ts
+++ b/server/middlewares/validators/plugins.ts
@@ -9,6 +9,7 @@ import { PluginModel } from '../../models/server/plugin'
9import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/install-plugin.model' 9import { InstallOrUpdatePlugin } from '../../../shared/models/plugins/install-plugin.model'
10import { PluginType } from '../../../shared/models/plugins/plugin.type' 10import { PluginType } from '../../../shared/models/plugins/plugin.type'
11import { CONFIG } from '../../initializers/config' 11import { CONFIG } from '../../initializers/config'
12import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
12 13
13const getPluginValidator = (pluginType: PluginType, withVersion = true) => { 14const getPluginValidator = (pluginType: PluginType, withVersion = true) => {
14 const validators: (ValidationChain | express.Handler)[] = [ 15 const validators: (ValidationChain | express.Handler)[] = [
@@ -30,8 +31,8 @@ const getPluginValidator = (pluginType: PluginType, withVersion = true) => {
30 const npmName = PluginModel.buildNpmName(req.params.pluginName, pluginType) 31 const npmName = PluginModel.buildNpmName(req.params.pluginName, pluginType)
31 const plugin = PluginManager.Instance.getRegisteredPluginOrTheme(npmName) 32 const plugin = PluginManager.Instance.getRegisteredPluginOrTheme(npmName)
32 33
33 if (!plugin) return res.sendStatus(404) 34 if (!plugin) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
34 if (withVersion && plugin.version !== req.params.pluginVersion) return res.sendStatus(404) 35 if (withVersion && plugin.version !== req.params.pluginVersion) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
35 36
36 res.locals.registeredPlugin = plugin 37 res.locals.registeredPlugin = plugin
37 38
@@ -49,10 +50,10 @@ const getExternalAuthValidator = [
49 if (areValidationErrors(req, res)) return 50 if (areValidationErrors(req, res)) return
50 51
51 const plugin = res.locals.registeredPlugin 52 const plugin = res.locals.registeredPlugin
52 if (!plugin.registerHelpersStore) return res.sendStatus(404) 53 if (!plugin.registerHelpersStore) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
53 54
54 const externalAuth = plugin.registerHelpersStore.getExternalAuths().find(a => a.authName === req.params.authName) 55 const externalAuth = plugin.registerHelpersStore.getExternalAuths().find(a => a.authName === req.params.authName)
55 if (!externalAuth) return res.sendStatus(404) 56 if (!externalAuth) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
56 57
57 res.locals.externalAuth = externalAuth 58 res.locals.externalAuth = externalAuth
58 59
@@ -106,7 +107,7 @@ const installOrUpdatePluginValidator = [
106 107
107 const body: InstallOrUpdatePlugin = req.body 108 const body: InstallOrUpdatePlugin = req.body
108 if (!body.path && !body.npmName) { 109 if (!body.path && !body.npmName) {
109 return res.status(400) 110 return res.status(HttpStatusCode.BAD_REQUEST_400)
110 .json({ error: 'Should have either a npmName or a path' }) 111 .json({ error: 'Should have either a npmName or a path' })
111 .end() 112 .end()
112 } 113 }
@@ -137,9 +138,9 @@ const existingPluginValidator = [
137 138
138 const plugin = await PluginModel.loadByNpmName(req.params.npmName) 139 const plugin = await PluginModel.loadByNpmName(req.params.npmName)
139 if (!plugin) { 140 if (!plugin) {
140 return res.status(404) 141 return res.status(HttpStatusCode.NOT_FOUND_404)
141 .json({ error: 'Plugin not found' }) 142 .json({ error: 'Plugin not found' })
142 .end() 143 .end()
143 } 144 }
144 145
145 res.locals.plugin = plugin 146 res.locals.plugin = plugin
@@ -178,9 +179,9 @@ const listAvailablePluginsValidator = [
178 if (areValidationErrors(req, res)) return 179 if (areValidationErrors(req, res)) return
179 180
180 if (CONFIG.PLUGINS.INDEX.ENABLED === false) { 181 if (CONFIG.PLUGINS.INDEX.ENABLED === false) {
181 return res.status(400) 182 return res.status(HttpStatusCode.BAD_REQUEST_400)
182 .json({ error: 'Plugin index is not enabled' }) 183 .json({ error: 'Plugin index is not enabled' })
183 .end() 184 .end()
184 } 185 }
185 186
186 return next() 187 return next()
diff --git a/server/middlewares/validators/redundancy.ts b/server/middlewares/validators/redundancy.ts
index 8cd3bc33d..6d2dd39c9 100644
--- a/server/middlewares/validators/redundancy.ts
+++ b/server/middlewares/validators/redundancy.ts
@@ -8,6 +8,7 @@ import { isHostValid } from '../../helpers/custom-validators/servers'
8import { ServerModel } from '../../models/server/server' 8import { ServerModel } from '../../models/server/server'
9import { doesVideoExist } from '../../helpers/middlewares' 9import { doesVideoExist } from '../../helpers/middlewares'
10import { isVideoRedundancyTarget } from '@server/helpers/custom-validators/video-redundancies' 10import { isVideoRedundancyTarget } from '@server/helpers/custom-validators/video-redundancies'
11import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
11 12
12const videoFileRedundancyGetValidator = [ 13const videoFileRedundancyGetValidator = [
13 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'), 14 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid video id'),
@@ -34,11 +35,11 @@ const videoFileRedundancyGetValidator = [
34 return f.resolution === paramResolution && (!req.params.fps || paramFPS) 35 return f.resolution === paramResolution && (!req.params.fps || paramFPS)
35 }) 36 })
36 37
37 if (!videoFile) return res.status(404).json({ error: 'Video file not found.' }) 38 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).json({ error: 'Video file not found.' })
38 res.locals.videoFile = videoFile 39 res.locals.videoFile = videoFile
39 40
40 const videoRedundancy = await VideoRedundancyModel.loadLocalByFileId(videoFile.id) 41 const videoRedundancy = await VideoRedundancyModel.loadLocalByFileId(videoFile.id)
41 if (!videoRedundancy) return res.status(404).json({ error: 'Video redundancy not found.' }) 42 if (!videoRedundancy) return res.status(HttpStatusCode.NOT_FOUND_404).json({ error: 'Video redundancy not found.' })
42 res.locals.videoRedundancy = videoRedundancy 43 res.locals.videoRedundancy = videoRedundancy
43 44
44 return next() 45 return next()
@@ -64,11 +65,11 @@ const videoPlaylistRedundancyGetValidator = [
64 const paramPlaylistType = req.params.streamingPlaylistType as unknown as number // We casted to int above 65 const paramPlaylistType = req.params.streamingPlaylistType as unknown as number // We casted to int above
65 const videoStreamingPlaylist = video.VideoStreamingPlaylists.find(p => p.type === paramPlaylistType) 66 const videoStreamingPlaylist = video.VideoStreamingPlaylists.find(p => p.type === paramPlaylistType)
66 67
67 if (!videoStreamingPlaylist) return res.status(404).json({ error: 'Video playlist not found.' }) 68 if (!videoStreamingPlaylist) return res.status(HttpStatusCode.NOT_FOUND_404).json({ error: 'Video playlist not found.' })
68 res.locals.videoStreamingPlaylist = videoStreamingPlaylist 69 res.locals.videoStreamingPlaylist = videoStreamingPlaylist
69 70
70 const videoRedundancy = await VideoRedundancyModel.loadLocalByStreamingPlaylistId(videoStreamingPlaylist.id) 71 const videoRedundancy = await VideoRedundancyModel.loadLocalByStreamingPlaylistId(videoStreamingPlaylist.id)
71 if (!videoRedundancy) return res.status(404).json({ error: 'Video redundancy not found.' }) 72 if (!videoRedundancy) return res.status(HttpStatusCode.NOT_FOUND_404).json({ error: 'Video redundancy not found.' })
72 res.locals.videoRedundancy = videoRedundancy 73 res.locals.videoRedundancy = videoRedundancy
73 74
74 return next() 75 return next()
@@ -90,7 +91,7 @@ const updateServerRedundancyValidator = [
90 91
91 if (!server) { 92 if (!server) {
92 return res 93 return res
93 .status(404) 94 .status(HttpStatusCode.NOT_FOUND_404)
94 .json({ 95 .json({
95 error: `Server ${req.params.host} not found.` 96 error: `Server ${req.params.host} not found.`
96 }) 97 })
@@ -128,15 +129,15 @@ const addVideoRedundancyValidator = [
128 if (!await doesVideoExist(req.body.videoId, res, 'only-video')) return 129 if (!await doesVideoExist(req.body.videoId, res, 'only-video')) return
129 130
130 if (res.locals.onlyVideo.remote === false) { 131 if (res.locals.onlyVideo.remote === false) {
131 return res.status(400) 132 return res.status(HttpStatusCode.BAD_REQUEST_400)
132 .json({ error: 'Cannot create a redundancy on a local video' }) 133 .json({ error: 'Cannot create a redundancy on a local video' })
133 .end() 134 .end()
134 } 135 }
135 136
136 const alreadyExists = await VideoRedundancyModel.isLocalByVideoUUIDExists(res.locals.onlyVideo.uuid) 137 const alreadyExists = await VideoRedundancyModel.isLocalByVideoUUIDExists(res.locals.onlyVideo.uuid)
137 if (alreadyExists) { 138 if (alreadyExists) {
138 return res.status(409) 139 return res.status(HttpStatusCode.CONFLICT_409)
139 .json({ error: 'This video is already duplicated by your instance.' }) 140 .json({ error: 'This video is already duplicated by your instance.' })
140 } 141 }
141 142
142 return next() 143 return next()
@@ -155,7 +156,7 @@ const removeVideoRedundancyValidator = [
155 156
156 const redundancy = await VideoRedundancyModel.loadByIdWithVideo(parseInt(req.params.redundancyId, 10)) 157 const redundancy = await VideoRedundancyModel.loadByIdWithVideo(parseInt(req.params.redundancyId, 10))
157 if (!redundancy) { 158 if (!redundancy) {
158 return res.status(404) 159 return res.status(HttpStatusCode.NOT_FOUND_404)
159 .json({ error: 'Video redundancy not found' }) 160 .json({ error: 'Video redundancy not found' })
160 .end() 161 .end()
161 } 162 }
diff --git a/server/middlewares/validators/server.ts b/server/middlewares/validators/server.ts
index 6158c3363..fe6704716 100644
--- a/server/middlewares/validators/server.ts
+++ b/server/middlewares/validators/server.ts
@@ -7,6 +7,7 @@ import { body } from 'express-validator'
7import { isUserDisplayNameValid } from '../../helpers/custom-validators/users' 7import { isUserDisplayNameValid } from '../../helpers/custom-validators/users'
8import { Redis } from '../../lib/redis' 8import { Redis } from '../../lib/redis'
9import { CONFIG, isEmailEnabled } from '../../initializers/config' 9import { CONFIG, isEmailEnabled } from '../../initializers/config'
10import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
10 11
11const serverGetValidator = [ 12const serverGetValidator = [
12 body('host').custom(isHostValid).withMessage('Should have a valid host'), 13 body('host').custom(isHostValid).withMessage('Should have a valid host'),
@@ -18,9 +19,9 @@ const serverGetValidator = [
18 19
19 const server = await ServerModel.loadByHost(req.body.host) 20 const server = await ServerModel.loadByHost(req.body.host)
20 if (!server) { 21 if (!server) {
21 return res.status(404) 22 return res.status(HttpStatusCode.NOT_FOUND_404)
22 .send({ error: 'Server host not found.' }) 23 .send({ error: 'Server host not found.' })
23 .end() 24 .end()
24 } 25 }
25 26
26 res.locals.server = server 27 res.locals.server = server
@@ -44,14 +45,14 @@ const contactAdministratorValidator = [
44 45
45 if (CONFIG.CONTACT_FORM.ENABLED === false) { 46 if (CONFIG.CONTACT_FORM.ENABLED === false) {
46 return res 47 return res
47 .status(409) 48 .status(HttpStatusCode.CONFLICT_409)
48 .send({ error: 'Contact form is not enabled on this instance.' }) 49 .send({ error: 'Contact form is not enabled on this instance.' })
49 .end() 50 .end()
50 } 51 }
51 52
52 if (isEmailEnabled() === false) { 53 if (isEmailEnabled() === false) {
53 return res 54 return res
54 .status(409) 55 .status(HttpStatusCode.CONFLICT_409)
55 .send({ error: 'Emailer is not enabled on this instance.' }) 56 .send({ error: 'Emailer is not enabled on this instance.' })
56 .end() 57 .end()
57 } 58 }
@@ -60,7 +61,7 @@ const contactAdministratorValidator = [
60 logger.info('Refusing a contact form by %s: already sent one recently.', req.ip) 61 logger.info('Refusing a contact form by %s: already sent one recently.', req.ip)
61 62
62 return res 63 return res
63 .status(403) 64 .status(HttpStatusCode.FORBIDDEN_403)
64 .send({ error: 'You already sent a contact form recently.' }) 65 .send({ error: 'You already sent a contact form recently.' })
65 .end() 66 .end()
66 } 67 }
diff --git a/server/middlewares/validators/themes.ts b/server/middlewares/validators/themes.ts
index 82794656d..a726a567b 100644
--- a/server/middlewares/validators/themes.ts
+++ b/server/middlewares/validators/themes.ts
@@ -5,6 +5,7 @@ import { areValidationErrors } from './utils'
5import { isPluginNameValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins' 5import { isPluginNameValid, isPluginVersionValid } from '../../helpers/custom-validators/plugins'
6import { PluginManager } from '../../lib/plugins/plugin-manager' 6import { PluginManager } from '../../lib/plugins/plugin-manager'
7import { isSafePath } from '../../helpers/custom-validators/misc' 7import { isSafePath } from '../../helpers/custom-validators/misc'
8import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
8 9
9const serveThemeCSSValidator = [ 10const serveThemeCSSValidator = [
10 param('themeName').custom(isPluginNameValid).withMessage('Should have a valid theme name'), 11 param('themeName').custom(isPluginNameValid).withMessage('Should have a valid theme name'),
@@ -19,11 +20,11 @@ const serveThemeCSSValidator = [
19 const theme = PluginManager.Instance.getRegisteredThemeByShortName(req.params.themeName) 20 const theme = PluginManager.Instance.getRegisteredThemeByShortName(req.params.themeName)
20 21
21 if (!theme || theme.version !== req.params.themeVersion) { 22 if (!theme || theme.version !== req.params.themeVersion) {
22 return res.sendStatus(404) 23 return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
23 } 24 }
24 25
25 if (theme.css.includes(req.params.staticEndpoint) === false) { 26 if (theme.css.includes(req.params.staticEndpoint) === false) {
26 return res.sendStatus(404) 27 return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
27 } 28 }
28 29
29 res.locals.registeredPlugin = theme 30 res.locals.registeredPlugin = theme
diff --git a/server/middlewares/validators/user-subscriptions.ts b/server/middlewares/validators/user-subscriptions.ts
index a54ecb704..0d0c8ccbf 100644
--- a/server/middlewares/validators/user-subscriptions.ts
+++ b/server/middlewares/validators/user-subscriptions.ts
@@ -6,6 +6,7 @@ import { ActorFollowModel } from '../../models/activitypub/actor-follow'
6import { areValidActorHandles, isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor' 6import { areValidActorHandles, isValidActorHandle } from '../../helpers/custom-validators/activitypub/actor'
7import { toArray } from '../../helpers/custom-validators/misc' 7import { toArray } from '../../helpers/custom-validators/misc'
8import { WEBSERVER } from '../../initializers/constants' 8import { WEBSERVER } from '../../initializers/constants'
9import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
9 10
10const userSubscriptionListValidator = [ 11const userSubscriptionListValidator = [
11 query('search').optional().not().isEmpty().withMessage('Should have a valid search'), 12 query('search').optional().not().isEmpty().withMessage('Should have a valid search'),
@@ -61,7 +62,7 @@ const userSubscriptionGetValidator = [
61 62
62 if (!subscription || !subscription.ActorFollowing.VideoChannel) { 63 if (!subscription || !subscription.ActorFollowing.VideoChannel) {
63 return res 64 return res
64 .status(404) 65 .status(HttpStatusCode.NOT_FOUND_404)
65 .json({ 66 .json({
66 error: `Subscription ${req.params.uri} not found.` 67 error: `Subscription ${req.params.uri} not found.`
67 }) 68 })
diff --git a/server/middlewares/validators/users.ts b/server/middlewares/validators/users.ts
index c91c378b3..c93895f2f 100644
--- a/server/middlewares/validators/users.ts
+++ b/server/middlewares/validators/users.ts
@@ -37,6 +37,7 @@ import { doesVideoExist } from '../../helpers/middlewares'
37import { UserRole } from '../../../shared/models/users' 37import { UserRole } from '../../../shared/models/users'
38import { MUserDefault } from '@server/types/models' 38import { MUserDefault } from '@server/types/models'
39import { Hooks } from '@server/lib/plugins/hooks' 39import { Hooks } from '@server/lib/plugins/hooks'
40import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
40 41
41const usersListValidator = [ 42const usersListValidator = [
42 query('blocked') 43 query('blocked')
@@ -73,19 +74,22 @@ const usersAddValidator = [
73 74
74 const authUser = res.locals.oauth.token.User 75 const authUser = res.locals.oauth.token.User
75 if (authUser.role !== UserRole.ADMINISTRATOR && req.body.role !== UserRole.USER) { 76 if (authUser.role !== UserRole.ADMINISTRATOR && req.body.role !== UserRole.USER) {
76 return res.status(403) 77 return res
78 .status(HttpStatusCode.FORBIDDEN_403)
77 .json({ error: 'You can only create users (and not administrators or moderators)' }) 79 .json({ error: 'You can only create users (and not administrators or moderators)' })
78 } 80 }
79 81
80 if (req.body.channelName) { 82 if (req.body.channelName) {
81 if (req.body.channelName === req.body.username) { 83 if (req.body.channelName === req.body.username) {
82 return res.status(400) 84 return res
85 .status(HttpStatusCode.BAD_REQUEST_400)
83 .json({ error: 'Channel name cannot be the same as user username.' }) 86 .json({ error: 'Channel name cannot be the same as user username.' })
84 } 87 }
85 88
86 const existing = await ActorModel.loadLocalByName(req.body.channelName) 89 const existing = await ActorModel.loadLocalByName(req.body.channelName)
87 if (existing) { 90 if (existing) {
88 return res.status(409) 91 return res
92 .status(HttpStatusCode.CONFLICT_409)
89 .json({ error: `Channel with name ${req.body.channelName} already exists.` }) 93 .json({ error: `Channel with name ${req.body.channelName} already exists.` })
90 } 94 }
91 } 95 }
@@ -118,18 +122,19 @@ const usersRegisterValidator = [
118 const body: UserRegister = req.body 122 const body: UserRegister = req.body
119 if (body.channel) { 123 if (body.channel) {
120 if (!body.channel.name || !body.channel.displayName) { 124 if (!body.channel.name || !body.channel.displayName) {
121 return res.status(400) 125 return res
126 .status(HttpStatusCode.BAD_REQUEST_400)
122 .json({ error: 'Channel is optional but if you specify it, channel.name and channel.displayName are required.' }) 127 .json({ error: 'Channel is optional but if you specify it, channel.name and channel.displayName are required.' })
123 } 128 }
124 129
125 if (body.channel.name === body.username) { 130 if (body.channel.name === body.username) {
126 return res.status(400) 131 return res.status(HttpStatusCode.BAD_REQUEST_400)
127 .json({ error: 'Channel name cannot be the same as user username.' }) 132 .json({ error: 'Channel name cannot be the same as user username.' })
128 } 133 }
129 134
130 const existing = await ActorModel.loadLocalByName(body.channel.name) 135 const existing = await ActorModel.loadLocalByName(body.channel.name)
131 if (existing) { 136 if (existing) {
132 return res.status(409) 137 return res.status(HttpStatusCode.CONFLICT_409)
133 .json({ error: `Channel with name ${body.channel.name} already exists.` }) 138 .json({ error: `Channel with name ${body.channel.name} already exists.` })
134 } 139 }
135 } 140 }
@@ -149,7 +154,7 @@ const usersRemoveValidator = [
149 154
150 const user = res.locals.user 155 const user = res.locals.user
151 if (user.username === 'root') { 156 if (user.username === 'root') {
152 return res.status(400) 157 return res.status(HttpStatusCode.BAD_REQUEST_400)
153 .json({ error: 'Cannot remove the root user' }) 158 .json({ error: 'Cannot remove the root user' })
154 } 159 }
155 160
@@ -169,7 +174,7 @@ const usersBlockingValidator = [
169 174
170 const user = res.locals.user 175 const user = res.locals.user
171 if (user.username === 'root') { 176 if (user.username === 'root') {
172 return res.status(400) 177 return res.status(HttpStatusCode.BAD_REQUEST_400)
173 .json({ error: 'Cannot block the root user' }) 178 .json({ error: 'Cannot block the root user' })
174 } 179 }
175 180
@@ -181,7 +186,7 @@ const deleteMeValidator = [
181 (req: express.Request, res: express.Response, next: express.NextFunction) => { 186 (req: express.Request, res: express.Response, next: express.NextFunction) => {
182 const user = res.locals.oauth.token.User 187 const user = res.locals.oauth.token.User
183 if (user.username === 'root') { 188 if (user.username === 'root') {
184 return res.status(400) 189 return res.status(HttpStatusCode.BAD_REQUEST_400)
185 .json({ error: 'You cannot delete your root account.' }) 190 .json({ error: 'You cannot delete your root account.' })
186 .end() 191 .end()
187 } 192 }
@@ -211,8 +216,8 @@ const usersUpdateValidator = [
211 216
212 const user = res.locals.user 217 const user = res.locals.user
213 if (user.username === 'root' && req.body.role !== undefined && user.role !== req.body.role) { 218 if (user.username === 'root' && req.body.role !== undefined && user.role !== req.body.role) {
214 return res.status(400) 219 return res.status(HttpStatusCode.BAD_REQUEST_400)
215 .json({ error: 'Cannot change root role.' }) 220 .json({ error: 'Cannot change root role.' })
216 } 221 }
217 222
218 return next() 223 return next()
@@ -267,17 +272,17 @@ const usersUpdateMeValidator = [
267 272
268 if (req.body.password || req.body.email) { 273 if (req.body.password || req.body.email) {
269 if (user.pluginAuth !== null) { 274 if (user.pluginAuth !== null) {
270 return res.status(400) 275 return res.status(HttpStatusCode.BAD_REQUEST_400)
271 .json({ error: 'You cannot update your email or password that is associated with an external auth system.' }) 276 .json({ error: 'You cannot update your email or password that is associated with an external auth system.' })
272 } 277 }
273 278
274 if (!req.body.currentPassword) { 279 if (!req.body.currentPassword) {
275 return res.status(400) 280 return res.status(HttpStatusCode.BAD_REQUEST_400)
276 .json({ error: 'currentPassword parameter is missing.' }) 281 .json({ error: 'currentPassword parameter is missing.' })
277 } 282 }
278 283
279 if (await user.isPasswordMatch(req.body.currentPassword) !== true) { 284 if (await user.isPasswordMatch(req.body.currentPassword) !== true) {
280 return res.status(401) 285 return res.status(HttpStatusCode.UNAUTHORIZED_401)
281 .json({ error: 'currentPassword is invalid.' }) 286 .json({ error: 'currentPassword is invalid.' })
282 } 287 }
283 } 288 }
@@ -329,7 +334,7 @@ const ensureUserRegistrationAllowed = [
329 ) 334 )
330 335
331 if (allowedResult.allowed === false) { 336 if (allowedResult.allowed === false) {
332 return res.status(403) 337 return res.status(HttpStatusCode.FORBIDDEN_403)
333 .json({ error: allowedResult.errorMessage || 'User registration is not enabled or user limit is reached.' }) 338 .json({ error: allowedResult.errorMessage || 'User registration is not enabled or user limit is reached.' })
334 } 339 }
335 340
@@ -342,7 +347,7 @@ const ensureUserRegistrationAllowedForIP = [
342 const allowed = isSignupAllowedForCurrentIP(req.ip) 347 const allowed = isSignupAllowedForCurrentIP(req.ip)
343 348
344 if (allowed === false) { 349 if (allowed === false) {
345 return res.status(403) 350 return res.status(HttpStatusCode.FORBIDDEN_403)
346 .json({ error: 'You are not on a network authorized for registration.' }) 351 .json({ error: 'You are not on a network authorized for registration.' })
347 } 352 }
348 353
@@ -362,7 +367,7 @@ const usersAskResetPasswordValidator = [
362 if (!exists) { 367 if (!exists) {
363 logger.debug('User with email %s does not exist (asking reset password).', req.body.email) 368 logger.debug('User with email %s does not exist (asking reset password).', req.body.email)
364 // Do not leak our emails 369 // Do not leak our emails
365 return res.status(204).end() 370 return res.status(HttpStatusCode.NO_CONTENT_204).end()
366 } 371 }
367 372
368 return next() 373 return next()
@@ -385,7 +390,7 @@ const usersResetPasswordValidator = [
385 390
386 if (redisVerificationString !== req.body.verificationString) { 391 if (redisVerificationString !== req.body.verificationString) {
387 return res 392 return res
388 .status(403) 393 .status(HttpStatusCode.FORBIDDEN_403)
389 .json({ error: 'Invalid verification string.' }) 394 .json({ error: 'Invalid verification string.' })
390 } 395 }
391 396
@@ -404,7 +409,7 @@ const usersAskSendVerifyEmailValidator = [
404 if (!exists) { 409 if (!exists) {
405 logger.debug('User with email %s does not exist (asking verify email).', req.body.email) 410 logger.debug('User with email %s does not exist (asking verify email).', req.body.email)
406 // Do not leak our emails 411 // Do not leak our emails
407 return res.status(204).end() 412 return res.status(HttpStatusCode.NO_CONTENT_204).end()
408 } 413 }
409 414
410 return next() 415 return next()
@@ -432,7 +437,7 @@ const usersVerifyEmailValidator = [
432 437
433 if (redisVerificationString !== req.body.verificationString) { 438 if (redisVerificationString !== req.body.verificationString) {
434 return res 439 return res
435 .status(403) 440 .status(HttpStatusCode.FORBIDDEN_403)
436 .json({ error: 'Invalid verification string.' }) 441 .json({ error: 'Invalid verification string.' })
437 } 442 }
438 443
@@ -449,7 +454,7 @@ const ensureAuthUserOwnsAccountValidator = [
449 const user = res.locals.oauth.token.User 454 const user = res.locals.oauth.token.User
450 455
451 if (res.locals.account.id !== user.Account.id) { 456 if (res.locals.account.id !== user.Account.id) {
452 return res.status(403) 457 return res.status(HttpStatusCode.FORBIDDEN_403)
453 .json({ error: 'Only owner can access ratings list.' }) 458 .json({ error: 'Only owner can access ratings list.' })
454 } 459 }
455 460
@@ -465,7 +470,7 @@ const ensureCanManageUser = [
465 if (authUser.role === UserRole.ADMINISTRATOR) return next() 470 if (authUser.role === UserRole.ADMINISTRATOR) return next()
466 if (authUser.role === UserRole.MODERATOR && onUser.role === UserRole.USER) return next() 471 if (authUser.role === UserRole.MODERATOR && onUser.role === UserRole.USER) return next()
467 472
468 return res.status(403) 473 return res.status(HttpStatusCode.FORBIDDEN_403)
469 .json({ error: 'A moderator can only manager users.' }) 474 .json({ error: 'A moderator can only manager users.' })
470 } 475 }
471] 476]
@@ -509,14 +514,14 @@ async function checkUserNameOrEmailDoesNotAlreadyExist (username: string, email:
509 const user = await UserModel.loadByUsernameOrEmail(username, email) 514 const user = await UserModel.loadByUsernameOrEmail(username, email)
510 515
511 if (user) { 516 if (user) {
512 res.status(409) 517 res.status(HttpStatusCode.CONFLICT_409)
513 .json({ error: 'User with this username or email already exists.' }) 518 .json({ error: 'User with this username or email already exists.' })
514 return false 519 return false
515 } 520 }
516 521
517 const actor = await ActorModel.loadLocalByName(username) 522 const actor = await ActorModel.loadLocalByName(username)
518 if (actor) { 523 if (actor) {
519 res.status(409) 524 res.status(HttpStatusCode.CONFLICT_409)
520 .json({ error: 'Another actor (account/channel) with this name on this instance already exists or has already existed.' }) 525 .json({ error: 'Another actor (account/channel) with this name on this instance already exists or has already existed.' })
521 return false 526 return false
522 } 527 }
@@ -529,7 +534,7 @@ async function checkUserExist (finder: () => Bluebird<MUserDefault>, res: expres
529 534
530 if (!user) { 535 if (!user) {
531 if (abortResponse === true) { 536 if (abortResponse === true) {
532 res.status(404) 537 res.status(HttpStatusCode.NOT_FOUND_404)
533 .json({ error: 'User not found' }) 538 .json({ error: 'User not found' })
534 } 539 }
535 540
diff --git a/server/middlewares/validators/utils.ts b/server/middlewares/validators/utils.ts
index 43e5652fa..2899bed6f 100644
--- a/server/middlewares/validators/utils.ts
+++ b/server/middlewares/validators/utils.ts
@@ -1,13 +1,15 @@
1import * as express from 'express' 1import * as express from 'express'
2import { query, validationResult } from 'express-validator' 2import { query, validationResult } from 'express-validator'
3import { logger } from '../../helpers/logger' 3import { logger } from '../../helpers/logger'
4import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
4 5
5function areValidationErrors (req: express.Request, res: express.Response) { 6function areValidationErrors (req: express.Request, res: express.Response) {
6 const errors = validationResult(req) 7 const errors = validationResult(req)
7 8
8 if (!errors.isEmpty()) { 9 if (!errors.isEmpty()) {
9 logger.warn('Incorrect request parameters', { path: req.originalUrl, err: errors.mapped() }) 10 logger.warn('Incorrect request parameters', { path: req.originalUrl, err: errors.mapped() })
10 res.status(400).json({ errors: errors.mapped() }) 11 res.status(HttpStatusCode.BAD_REQUEST_400)
12 .json({ errors: errors.mapped() })
11 13
12 return true 14 return true
13 } 15 }
diff --git a/server/middlewares/validators/videos/video-blacklist.ts b/server/middlewares/validators/videos/video-blacklist.ts
index 808fefc25..88c788a43 100644
--- a/server/middlewares/validators/videos/video-blacklist.ts
+++ b/server/middlewares/validators/videos/video-blacklist.ts
@@ -5,6 +5,7 @@ import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../..
5import { logger } from '../../../helpers/logger' 5import { logger } from '../../../helpers/logger'
6import { doesVideoBlacklistExist, doesVideoExist } from '../../../helpers/middlewares' 6import { doesVideoBlacklistExist, doesVideoExist } from '../../../helpers/middlewares'
7import { areValidationErrors } from '../utils' 7import { areValidationErrors } from '../utils'
8import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
8 9
9const videosBlacklistRemoveValidator = [ 10const videosBlacklistRemoveValidator = [
10 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), 11 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
@@ -39,7 +40,7 @@ const videosBlacklistAddValidator = [
39 const video = res.locals.videoAll 40 const video = res.locals.videoAll
40 if (req.body.unfederate === true && video.remote === true) { 41 if (req.body.unfederate === true && video.remote === true) {
41 return res 42 return res
42 .status(409) 43 .status(HttpStatusCode.CONFLICT_409)
43 .send({ error: 'You cannot unfederate a remote video.' }) 44 .send({ error: 'You cannot unfederate a remote video.' })
44 .end() 45 .end()
45 } 46 }
diff --git a/server/middlewares/validators/videos/video-channels.ts b/server/middlewares/validators/videos/video-channels.ts
index 2e4e755e7..57ac548b9 100644
--- a/server/middlewares/validators/videos/video-channels.ts
+++ b/server/middlewares/validators/videos/video-channels.ts
@@ -15,6 +15,7 @@ import { doesLocalVideoChannelNameExist, doesVideoChannelNameWithHostExist } fro
15import { ActorModel } from '../../../models/activitypub/actor' 15import { ActorModel } from '../../../models/activitypub/actor'
16import { VideoChannelModel } from '../../../models/video/video-channel' 16import { VideoChannelModel } from '../../../models/video/video-channel'
17import { areValidationErrors } from '../utils' 17import { areValidationErrors } from '../utils'
18import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
18 19
19const videoChannelsAddValidator = [ 20const videoChannelsAddValidator = [
20 body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'), 21 body('name').custom(isActorPreferredUsernameValid).withMessage('Should have a valid channel name'),
@@ -29,7 +30,7 @@ const videoChannelsAddValidator = [
29 30
30 const actor = await ActorModel.loadLocalByName(req.body.name) 31 const actor = await ActorModel.loadLocalByName(req.body.name)
31 if (actor) { 32 if (actor) {
32 res.status(409) 33 res.status(HttpStatusCode.CONFLICT_409)
33 .send({ error: 'Another actor (account/channel) with this name on this instance already exists or has already existed.' }) 34 .send({ error: 'Another actor (account/channel) with this name on this instance already exists or has already existed.' })
34 .end() 35 .end()
35 return false 36 return false
@@ -37,7 +38,7 @@ const videoChannelsAddValidator = [
37 38
38 const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id) 39 const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id)
39 if (count >= VIDEO_CHANNELS.MAX_PER_USER) { 40 if (count >= VIDEO_CHANNELS.MAX_PER_USER) {
40 res.status(400) 41 res.status(HttpStatusCode.BAD_REQUEST_400)
41 .send({ error: `You cannot create more than ${VIDEO_CHANNELS.MAX_PER_USER} channels` }) 42 .send({ error: `You cannot create more than ${VIDEO_CHANNELS.MAX_PER_USER} channels` })
42 .end() 43 .end()
43 return false 44 return false
@@ -70,13 +71,13 @@ const videoChannelsUpdateValidator = [
70 71
71 // We need to make additional checks 72 // We need to make additional checks
72 if (res.locals.videoChannel.Actor.isOwned() === false) { 73 if (res.locals.videoChannel.Actor.isOwned() === false) {
73 return res.status(403) 74 return res.status(HttpStatusCode.FORBIDDEN_403)
74 .json({ error: 'Cannot update video channel of another server' }) 75 .json({ error: 'Cannot update video channel of another server' })
75 .end() 76 .end()
76 } 77 }
77 78
78 if (res.locals.videoChannel.Account.userId !== res.locals.oauth.token.User.id) { 79 if (res.locals.videoChannel.Account.userId !== res.locals.oauth.token.User.id) {
79 return res.status(403) 80 return res.status(HttpStatusCode.FORBIDDEN_403)
80 .json({ error: 'Cannot update video channel of another user' }) 81 .json({ error: 'Cannot update video channel of another user' })
81 .end() 82 .end()
82 } 83 }
@@ -155,7 +156,7 @@ export {
155 156
156function checkUserCanDeleteVideoChannel (user: MUser, videoChannel: MChannelAccountDefault, res: express.Response) { 157function checkUserCanDeleteVideoChannel (user: MUser, videoChannel: MChannelAccountDefault, res: express.Response) {
157 if (videoChannel.Actor.isOwned() === false) { 158 if (videoChannel.Actor.isOwned() === false) {
158 res.status(403) 159 res.status(HttpStatusCode.FORBIDDEN_403)
159 .json({ error: 'Cannot remove video channel of another server.' }) 160 .json({ error: 'Cannot remove video channel of another server.' })
160 .end() 161 .end()
161 162
@@ -166,7 +167,7 @@ function checkUserCanDeleteVideoChannel (user: MUser, videoChannel: MChannelAcco
166 // The user can delete it if s/he is an admin 167 // The user can delete it if s/he is an admin
167 // Or if s/he is the video channel's account 168 // Or if s/he is the video channel's account
168 if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && videoChannel.Account.userId !== user.id) { 169 if (user.hasRight(UserRight.REMOVE_ANY_VIDEO_CHANNEL) === false && videoChannel.Account.userId !== user.id) {
169 res.status(403) 170 res.status(HttpStatusCode.FORBIDDEN_403)
170 .json({ error: 'Cannot remove video channel of another user' }) 171 .json({ error: 'Cannot remove video channel of another user' })
171 .end() 172 .end()
172 173
@@ -180,9 +181,9 @@ async function checkVideoChannelIsNotTheLastOne (res: express.Response) {
180 const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id) 181 const count = await VideoChannelModel.countByAccount(res.locals.oauth.token.User.Account.id)
181 182
182 if (count <= 1) { 183 if (count <= 1) {
183 res.status(409) 184 res.status(HttpStatusCode.CONFLICT_409)
184 .json({ error: 'Cannot remove the last channel of this user' }) 185 .json({ error: 'Cannot remove the last channel of this user' })
185 .end() 186 .end()
186 187
187 return false 188 return false
188 } 189 }
diff --git a/server/middlewares/validators/videos/video-comments.ts b/server/middlewares/validators/videos/video-comments.ts
index a3c9febc4..226c9d436 100644
--- a/server/middlewares/validators/videos/video-comments.ts
+++ b/server/middlewares/validators/videos/video-comments.ts
@@ -14,6 +14,7 @@ import { AcceptResult, isLocalVideoCommentReplyAccepted, isLocalVideoThreadAccep
14import { Hooks } from '../../../lib/plugins/hooks' 14import { Hooks } from '../../../lib/plugins/hooks'
15import { MCommentOwnerVideoReply, MVideo, MVideoFullLight } from '../../../types/models/video' 15import { MCommentOwnerVideoReply, MVideo, MVideoFullLight } from '../../../types/models/video'
16import { areValidationErrors } from '../utils' 16import { areValidationErrors } from '../utils'
17import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
17 18
18const listVideoCommentsValidator = [ 19const listVideoCommentsValidator = [
19 query('isLocal') 20 query('isLocal')
@@ -154,8 +155,8 @@ export {
154 155
155function isVideoCommentsEnabled (video: MVideo, res: express.Response) { 156function isVideoCommentsEnabled (video: MVideo, res: express.Response) {
156 if (video.commentsEnabled !== true) { 157 if (video.commentsEnabled !== true) {
157 res.status(409) 158 res.status(HttpStatusCode.CONFLICT_409)
158 .json({ error: 'Video comments are disabled for this video.' }) 159 .json({ error: 'Video comments are disabled for this video.' })
159 160
160 return false 161 return false
161 } 162 }
@@ -165,8 +166,8 @@ function isVideoCommentsEnabled (video: MVideo, res: express.Response) {
165 166
166function checkUserCanDeleteVideoComment (user: MUserAccountUrl, videoComment: MCommentOwnerVideoReply, res: express.Response) { 167function checkUserCanDeleteVideoComment (user: MUserAccountUrl, videoComment: MCommentOwnerVideoReply, res: express.Response) {
167 if (videoComment.isDeleted()) { 168 if (videoComment.isDeleted()) {
168 res.status(409) 169 res.status(HttpStatusCode.CONFLICT_409)
169 .json({ error: 'This comment is already deleted' }) 170 .json({ error: 'This comment is already deleted' })
170 171
171 return false 172 return false
172 } 173 }
@@ -178,7 +179,7 @@ function checkUserCanDeleteVideoComment (user: MUserAccountUrl, videoComment: MC
178 videoComment.accountId !== userAccount.id && // Not the comment owner 179 videoComment.accountId !== userAccount.id && // Not the comment owner
179 videoComment.Video.VideoChannel.accountId !== userAccount.id // Not the video owner 180 videoComment.Video.VideoChannel.accountId !== userAccount.id // Not the video owner
180 ) { 181 ) {
181 res.status(403) 182 res.status(HttpStatusCode.FORBIDDEN_403)
182 .json({ error: 'Cannot remove video comment of another user' }) 183 .json({ error: 'Cannot remove video comment of another user' })
183 184
184 return false 185 return false
@@ -214,7 +215,7 @@ async function isVideoCommentAccepted (req: express.Request, res: express.Respon
214 215
215 if (!acceptedResult || acceptedResult.accepted !== true) { 216 if (!acceptedResult || acceptedResult.accepted !== true) {
216 logger.info('Refused local comment.', { acceptedResult, acceptParameters }) 217 logger.info('Refused local comment.', { acceptedResult, acceptParameters })
217 res.status(403) 218 res.status(HttpStatusCode.FORBIDDEN_403)
218 .json({ error: acceptedResult.errorMessage || 'Refused local comment' }) 219 .json({ error: acceptedResult.errorMessage || 'Refused local comment' })
219 220
220 return false 221 return false
diff --git a/server/middlewares/validators/videos/video-imports.ts b/server/middlewares/validators/videos/video-imports.ts
index d69aff118..0d41933a6 100644
--- a/server/middlewares/validators/videos/video-imports.ts
+++ b/server/middlewares/validators/videos/video-imports.ts
@@ -13,6 +13,7 @@ import { CONFIG } from '../../../initializers/config'
13import { CONSTRAINTS_FIELDS } from '../../../initializers/constants' 13import { CONSTRAINTS_FIELDS } from '../../../initializers/constants'
14import { areValidationErrors } from '../utils' 14import { areValidationErrors } from '../utils'
15import { getCommonVideoEditAttributes } from './videos' 15import { getCommonVideoEditAttributes } from './videos'
16import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
16 17
17const videoImportAddValidator = getCommonVideoEditAttributes().concat([ 18const videoImportAddValidator = getCommonVideoEditAttributes().concat([
18 body('channelId') 19 body('channelId')
@@ -44,14 +45,14 @@ const videoImportAddValidator = getCommonVideoEditAttributes().concat([
44 45
45 if (req.body.targetUrl && CONFIG.IMPORT.VIDEOS.HTTP.ENABLED !== true) { 46 if (req.body.targetUrl && CONFIG.IMPORT.VIDEOS.HTTP.ENABLED !== true) {
46 cleanUpReqFiles(req) 47 cleanUpReqFiles(req)
47 return res.status(409) 48 return res.status(HttpStatusCode.CONFLICT_409)
48 .json({ error: 'HTTP import is not enabled on this instance.' }) 49 .json({ error: 'HTTP import is not enabled on this instance.' })
49 .end() 50 .end()
50 } 51 }
51 52
52 if (CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED !== true && (req.body.magnetUri || torrentFile)) { 53 if (CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED !== true && (req.body.magnetUri || torrentFile)) {
53 cleanUpReqFiles(req) 54 cleanUpReqFiles(req)
54 return res.status(409) 55 return res.status(HttpStatusCode.CONFLICT_409)
55 .json({ error: 'Torrent/magnet URI import is not enabled on this instance.' }) 56 .json({ error: 'Torrent/magnet URI import is not enabled on this instance.' })
56 .end() 57 .end()
57 } 58 }
@@ -62,7 +63,7 @@ const videoImportAddValidator = getCommonVideoEditAttributes().concat([
62 if (!req.body.targetUrl && !req.body.magnetUri && !torrentFile) { 63 if (!req.body.targetUrl && !req.body.magnetUri && !torrentFile) {
63 cleanUpReqFiles(req) 64 cleanUpReqFiles(req)
64 65
65 return res.status(400) 66 return res.status(HttpStatusCode.BAD_REQUEST_400)
66 .json({ error: 'Should have a magnetUri or a targetUrl or a torrent file.' }) 67 .json({ error: 'Should have a magnetUri or a targetUrl or a torrent file.' })
67 .end() 68 .end()
68 } 69 }
@@ -100,7 +101,7 @@ async function isImportAccepted (req: express.Request, res: express.Response) {
100 101
101 if (!acceptedResult || acceptedResult.accepted !== true) { 102 if (!acceptedResult || acceptedResult.accepted !== true) {
102 logger.info('Refused to import video.', { acceptedResult, acceptParameters }) 103 logger.info('Refused to import video.', { acceptedResult, acceptParameters })
103 res.status(403) 104 res.status(HttpStatusCode.FORBIDDEN_403)
104 .json({ error: acceptedResult.errorMessage || 'Refused to import video' }) 105 .json({ error: acceptedResult.errorMessage || 'Refused to import video' })
105 106
106 return false 107 return false
diff --git a/server/middlewares/validators/videos/video-live.ts b/server/middlewares/validators/videos/video-live.ts
index 69a14ccb1..3a73e1272 100644
--- a/server/middlewares/validators/videos/video-live.ts
+++ b/server/middlewares/validators/videos/video-live.ts
@@ -13,6 +13,7 @@ import { getCommonVideoEditAttributes } from './videos'
13import { VideoModel } from '@server/models/video/video' 13import { VideoModel } from '@server/models/video/video'
14import { Hooks } from '@server/lib/plugins/hooks' 14import { Hooks } from '@server/lib/plugins/hooks'
15import { isLocalLiveVideoAccepted } from '@server/lib/moderation' 15import { isLocalLiveVideoAccepted } from '@server/lib/moderation'
16import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
16 17
17const videoLiveGetValidator = [ 18const videoLiveGetValidator = [
18 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'), 19 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid videoId'),
@@ -28,7 +29,7 @@ const videoLiveGetValidator = [
28 if (!checkUserCanManageVideo(user, res.locals.videoAll, UserRight.GET_ANY_LIVE, res, false)) return 29 if (!checkUserCanManageVideo(user, res.locals.videoAll, UserRight.GET_ANY_LIVE, res, false)) return
29 30
30 const videoLive = await VideoLiveModel.loadByVideoId(res.locals.videoAll.id) 31 const videoLive = await VideoLiveModel.loadByVideoId(res.locals.videoAll.id)
31 if (!videoLive) return res.sendStatus(404) 32 if (!videoLive) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
32 33
33 res.locals.videoLive = videoLive 34 res.locals.videoLive = videoLive
34 35
@@ -62,21 +63,21 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([
62 if (CONFIG.LIVE.ENABLED !== true) { 63 if (CONFIG.LIVE.ENABLED !== true) {
63 cleanUpReqFiles(req) 64 cleanUpReqFiles(req)
64 65
65 return res.status(403) 66 return res.status(HttpStatusCode.FORBIDDEN_403)
66 .json({ error: 'Live is not enabled on this instance' }) 67 .json({ error: 'Live is not enabled on this instance' })
67 } 68 }
68 69
69 if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) { 70 if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) {
70 cleanUpReqFiles(req) 71 cleanUpReqFiles(req)
71 72
72 return res.status(403) 73 return res.status(HttpStatusCode.FORBIDDEN_403)
73 .json({ error: 'Saving live replay is not allowed instance' }) 74 .json({ error: 'Saving live replay is not allowed instance' })
74 } 75 }
75 76
76 if (req.body.permanentLive && req.body.saveReplay) { 77 if (req.body.permanentLive && req.body.saveReplay) {
77 cleanUpReqFiles(req) 78 cleanUpReqFiles(req)
78 79
79 return res.status(400) 80 return res.status(HttpStatusCode.BAD_REQUEST_400)
80 .json({ error: 'Cannot set this live as permanent while saving its replay' }) 81 .json({ error: 'Cannot set this live as permanent while saving its replay' })
81 } 82 }
82 83
@@ -89,7 +90,7 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([
89 if (totalInstanceLives >= CONFIG.LIVE.MAX_INSTANCE_LIVES) { 90 if (totalInstanceLives >= CONFIG.LIVE.MAX_INSTANCE_LIVES) {
90 cleanUpReqFiles(req) 91 cleanUpReqFiles(req)
91 92
92 return res.status(403) 93 return res.status(HttpStatusCode.FORBIDDEN_403)
93 .json({ 94 .json({
94 code: ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED, 95 code: ServerErrorCode.MAX_INSTANCE_LIVES_LIMIT_REACHED,
95 error: 'Cannot create this live because the max instance lives limit is reached.' 96 error: 'Cannot create this live because the max instance lives limit is reached.'
@@ -103,7 +104,7 @@ const videoLiveAddValidator = getCommonVideoEditAttributes().concat([
103 if (totalUserLives >= CONFIG.LIVE.MAX_USER_LIVES) { 104 if (totalUserLives >= CONFIG.LIVE.MAX_USER_LIVES) {
104 cleanUpReqFiles(req) 105 cleanUpReqFiles(req)
105 106
106 return res.status(403) 107 return res.status(HttpStatusCode.FORBIDDEN_403)
107 .json({ 108 .json({
108 code: ServerErrorCode.MAX_USER_LIVES_LIMIT_REACHED, 109 code: ServerErrorCode.MAX_USER_LIVES_LIMIT_REACHED,
109 error: 'Cannot create this live because the max user lives limit is reached.' 110 error: 'Cannot create this live because the max user lives limit is reached.'
@@ -129,17 +130,17 @@ const videoLiveUpdateValidator = [
129 if (areValidationErrors(req, res)) return 130 if (areValidationErrors(req, res)) return
130 131
131 if (req.body.permanentLive && req.body.saveReplay) { 132 if (req.body.permanentLive && req.body.saveReplay) {
132 return res.status(400) 133 return res.status(HttpStatusCode.BAD_REQUEST_400)
133 .json({ error: 'Cannot set this live as permanent while saving its replay' }) 134 .json({ error: 'Cannot set this live as permanent while saving its replay' })
134 } 135 }
135 136
136 if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) { 137 if (CONFIG.LIVE.ALLOW_REPLAY !== true && req.body.saveReplay === true) {
137 return res.status(403) 138 return res.status(HttpStatusCode.FORBIDDEN_403)
138 .json({ error: 'Saving live replay is not allowed instance' }) 139 .json({ error: 'Saving live replay is not allowed instance' })
139 } 140 }
140 141
141 if (res.locals.videoAll.state !== VideoState.WAITING_FOR_LIVE) { 142 if (res.locals.videoAll.state !== VideoState.WAITING_FOR_LIVE) {
142 return res.status(400) 143 return res.status(HttpStatusCode.BAD_REQUEST_400)
143 .json({ error: 'Cannot update a live that has already started' }) 144 .json({ error: 'Cannot update a live that has already started' })
144 } 145 }
145 146
@@ -176,7 +177,7 @@ async function isLiveVideoAccepted (req: express.Request, res: express.Response)
176 if (!acceptedResult || acceptedResult.accepted !== true) { 177 if (!acceptedResult || acceptedResult.accepted !== true) {
177 logger.info('Refused local live video.', { acceptedResult, acceptParameters }) 178 logger.info('Refused local live video.', { acceptedResult, acceptParameters })
178 179
179 res.status(403) 180 res.status(HttpStatusCode.FORBIDDEN_403)
180 .json({ error: acceptedResult.errorMessage || 'Refused local live video' }) 181 .json({ error: acceptedResult.errorMessage || 'Refused local live video' })
181 182
182 return false 183 return false
diff --git a/server/middlewares/validators/videos/video-playlists.ts b/server/middlewares/validators/videos/video-playlists.ts
index 4647eae44..c7a6f68e3 100644
--- a/server/middlewares/validators/videos/video-playlists.ts
+++ b/server/middlewares/validators/videos/video-playlists.ts
@@ -29,6 +29,7 @@ import { VideoPlaylistType } from '../../../../shared/models/videos/playlist/vid
29import { doesVideoChannelIdExist, doesVideoExist, doesVideoPlaylistExist, VideoPlaylistFetchType } from '../../../helpers/middlewares' 29import { doesVideoChannelIdExist, doesVideoExist, doesVideoPlaylistExist, VideoPlaylistFetchType } from '../../../helpers/middlewares'
30import { MVideoPlaylist } from '../../../types/models/video/video-playlist' 30import { MVideoPlaylist } from '../../../types/models/video/video-playlist'
31import { MUserAccountId } from '@server/types/models' 31import { MUserAccountId } from '@server/types/models'
32import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
32 33
33const videoPlaylistsAddValidator = getCommonPlaylistEditAttributes().concat([ 34const videoPlaylistsAddValidator = getCommonPlaylistEditAttributes().concat([
34 body('displayName') 35 body('displayName')
@@ -44,7 +45,7 @@ const videoPlaylistsAddValidator = getCommonPlaylistEditAttributes().concat([
44 45
45 if (body.privacy === VideoPlaylistPrivacy.PUBLIC && !body.videoChannelId) { 46 if (body.privacy === VideoPlaylistPrivacy.PUBLIC && !body.videoChannelId) {
46 cleanUpReqFiles(req) 47 cleanUpReqFiles(req)
47 return res.status(400) 48 return res.status(HttpStatusCode.BAD_REQUEST_400)
48 .json({ error: 'Cannot set "public" a playlist that is not assigned to a channel.' }) 49 .json({ error: 'Cannot set "public" a playlist that is not assigned to a channel.' })
49 } 50 }
50 51
@@ -83,13 +84,13 @@ const videoPlaylistsUpdateValidator = getCommonPlaylistEditAttributes().concat([
83 ) 84 )
84 ) { 85 ) {
85 cleanUpReqFiles(req) 86 cleanUpReqFiles(req)
86 return res.status(400) 87 return res.status(HttpStatusCode.BAD_REQUEST_400)
87 .json({ error: 'Cannot set "public" a playlist that is not assigned to a channel.' }) 88 .json({ error: 'Cannot set "public" a playlist that is not assigned to a channel.' })
88 } 89 }
89 90
90 if (videoPlaylist.type === VideoPlaylistType.WATCH_LATER) { 91 if (videoPlaylist.type === VideoPlaylistType.WATCH_LATER) {
91 cleanUpReqFiles(req) 92 cleanUpReqFiles(req)
92 return res.status(400) 93 return res.status(HttpStatusCode.BAD_REQUEST_400)
93 .json({ error: 'Cannot update a watch later playlist.' }) 94 .json({ error: 'Cannot update a watch later playlist.' })
94 } 95 }
95 96
@@ -112,7 +113,7 @@ const videoPlaylistsDeleteValidator = [
112 113
113 const videoPlaylist = getPlaylist(res) 114 const videoPlaylist = getPlaylist(res)
114 if (videoPlaylist.type === VideoPlaylistType.WATCH_LATER) { 115 if (videoPlaylist.type === VideoPlaylistType.WATCH_LATER) {
115 return res.status(400) 116 return res.status(HttpStatusCode.BAD_REQUEST_400)
116 .json({ error: 'Cannot delete a watch later playlist.' }) 117 .json({ error: 'Cannot delete a watch later playlist.' })
117 } 118 }
118 119
@@ -142,7 +143,7 @@ const videoPlaylistsGetValidator = (fetchType: VideoPlaylistFetchType) => {
142 if (videoPlaylist.privacy === VideoPlaylistPrivacy.UNLISTED) { 143 if (videoPlaylist.privacy === VideoPlaylistPrivacy.UNLISTED) {
143 if (isUUIDValid(req.params.playlistId)) return next() 144 if (isUUIDValid(req.params.playlistId)) return next()
144 145
145 return res.status(404).end() 146 return res.status(HttpStatusCode.NOT_FOUND_404).end()
146 } 147 }
147 148
148 if (videoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) { 149 if (videoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) {
@@ -154,7 +155,7 @@ const videoPlaylistsGetValidator = (fetchType: VideoPlaylistFetchType) => {
154 !user || 155 !user ||
155 (videoPlaylist.OwnerAccount.id !== user.Account.id && !user.hasRight(UserRight.UPDATE_ANY_VIDEO_PLAYLIST)) 156 (videoPlaylist.OwnerAccount.id !== user.Account.id && !user.hasRight(UserRight.UPDATE_ANY_VIDEO_PLAYLIST))
156 ) { 157 ) {
157 return res.status(403) 158 return res.status(HttpStatusCode.FORBIDDEN_403)
158 .json({ error: 'Cannot get this private video playlist.' }) 159 .json({ error: 'Cannot get this private video playlist.' })
159 } 160 }
160 161
@@ -231,7 +232,7 @@ const videoPlaylistsUpdateOrRemoveVideoValidator = [
231 232
232 const videoPlaylistElement = await VideoPlaylistElementModel.loadById(req.params.playlistElementId) 233 const videoPlaylistElement = await VideoPlaylistElementModel.loadById(req.params.playlistElementId)
233 if (!videoPlaylistElement) { 234 if (!videoPlaylistElement) {
234 res.status(404) 235 res.status(HttpStatusCode.NOT_FOUND_404)
235 .json({ error: 'Video playlist element not found' }) 236 .json({ error: 'Video playlist element not found' })
236 .end() 237 .end()
237 238
@@ -261,7 +262,7 @@ const videoPlaylistElementAPGetValidator = [
261 262
262 const videoPlaylistElement = await VideoPlaylistElementModel.loadByPlaylistAndElementIdForAP(playlistId, playlistElementId) 263 const videoPlaylistElement = await VideoPlaylistElementModel.loadByPlaylistAndElementIdForAP(playlistId, playlistElementId)
263 if (!videoPlaylistElement) { 264 if (!videoPlaylistElement) {
264 res.status(404) 265 res.status(HttpStatusCode.NOT_FOUND_404)
265 .json({ error: 'Video playlist element not found' }) 266 .json({ error: 'Video playlist element not found' })
266 .end() 267 .end()
267 268
@@ -269,7 +270,7 @@ const videoPlaylistElementAPGetValidator = [
269 } 270 }
270 271
271 if (videoPlaylistElement.VideoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) { 272 if (videoPlaylistElement.VideoPlaylist.privacy === VideoPlaylistPrivacy.PRIVATE) {
272 return res.status(403).end() 273 return res.status(HttpStatusCode.FORBIDDEN_403).end()
273 } 274 }
274 275
275 res.locals.videoPlaylistElementAP = videoPlaylistElement 276 res.locals.videoPlaylistElementAP = videoPlaylistElement
@@ -305,7 +306,7 @@ const videoPlaylistsReorderVideosValidator = [
305 const reorderLength: number = req.body.reorderLength 306 const reorderLength: number = req.body.reorderLength
306 307
307 if (startPosition >= nextPosition || insertAfterPosition >= nextPosition) { 308 if (startPosition >= nextPosition || insertAfterPosition >= nextPosition) {
308 res.status(400) 309 res.status(HttpStatusCode.BAD_REQUEST_400)
309 .json({ error: `Start position or insert after position exceed the playlist limits (max: ${nextPosition - 1})` }) 310 .json({ error: `Start position or insert after position exceed the playlist limits (max: ${nextPosition - 1})` })
310 .end() 311 .end()
311 312
@@ -313,7 +314,7 @@ const videoPlaylistsReorderVideosValidator = [
313 } 314 }
314 315
315 if (reorderLength && reorderLength + startPosition > nextPosition) { 316 if (reorderLength && reorderLength + startPosition > nextPosition) {
316 res.status(400) 317 res.status(HttpStatusCode.BAD_REQUEST_400)
317 .json({ error: `Reorder length with this start position exceeds the playlist limits (max: ${nextPosition - startPosition})` }) 318 .json({ error: `Reorder length with this start position exceeds the playlist limits (max: ${nextPosition - startPosition})` })
318 .end() 319 .end()
319 320
@@ -399,7 +400,7 @@ function getCommonPlaylistEditAttributes () {
399 400
400function checkUserCanManageVideoPlaylist (user: MUserAccountId, videoPlaylist: MVideoPlaylist, right: UserRight, res: express.Response) { 401function checkUserCanManageVideoPlaylist (user: MUserAccountId, videoPlaylist: MVideoPlaylist, right: UserRight, res: express.Response) {
401 if (videoPlaylist.isOwned() === false) { 402 if (videoPlaylist.isOwned() === false) {
402 res.status(403) 403 res.status(HttpStatusCode.FORBIDDEN_403)
403 .json({ error: 'Cannot manage video playlist of another server.' }) 404 .json({ error: 'Cannot manage video playlist of another server.' })
404 .end() 405 .end()
405 406
@@ -410,7 +411,7 @@ function checkUserCanManageVideoPlaylist (user: MUserAccountId, videoPlaylist: M
410 // The user can delete it if s/he is an admin 411 // The user can delete it if s/he is an admin
411 // Or if s/he is the video playlist's owner 412 // Or if s/he is the video playlist's owner
412 if (user.hasRight(right) === false && videoPlaylist.ownerAccountId !== user.Account.id) { 413 if (user.hasRight(right) === false && videoPlaylist.ownerAccountId !== user.Account.id) {
413 res.status(403) 414 res.status(HttpStatusCode.FORBIDDEN_403)
414 .json({ error: 'Cannot manage video playlist of another user' }) 415 .json({ error: 'Cannot manage video playlist of another user' })
415 .end() 416 .end()
416 417
diff --git a/server/middlewares/validators/videos/video-rates.ts b/server/middlewares/validators/videos/video-rates.ts
index 15a8c7983..7dcba15f1 100644
--- a/server/middlewares/validators/videos/video-rates.ts
+++ b/server/middlewares/validators/videos/video-rates.ts
@@ -9,6 +9,7 @@ import { AccountVideoRateModel } from '../../../models/account/account-video-rat
9import { VideoRateType } from '../../../../shared/models/videos' 9import { VideoRateType } from '../../../../shared/models/videos'
10import { isAccountNameValid } from '../../../helpers/custom-validators/accounts' 10import { isAccountNameValid } from '../../../helpers/custom-validators/accounts'
11import { doesVideoExist } from '../../../helpers/middlewares' 11import { doesVideoExist } from '../../../helpers/middlewares'
12import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
12 13
13const videoUpdateRateValidator = [ 14const videoUpdateRateValidator = [
14 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 15 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
@@ -36,7 +37,7 @@ const getAccountVideoRateValidatorFactory = function (rateType: VideoRateType) {
36 37
37 const rate = await AccountVideoRateModel.loadLocalAndPopulateVideo(rateType, req.params.name, req.params.videoId) 38 const rate = await AccountVideoRateModel.loadLocalAndPopulateVideo(rateType, req.params.name, req.params.videoId)
38 if (!rate) { 39 if (!rate) {
39 return res.status(404) 40 return res.status(HttpStatusCode.NOT_FOUND_404)
40 .json({ error: 'Video rate not found' }) 41 .json({ error: 'Video rate not found' })
41 } 42 }
42 43
diff --git a/server/middlewares/validators/videos/video-shares.ts b/server/middlewares/validators/videos/video-shares.ts
index 20fc96243..f0d8e0c36 100644
--- a/server/middlewares/validators/videos/video-shares.ts
+++ b/server/middlewares/validators/videos/video-shares.ts
@@ -5,6 +5,7 @@ import { logger } from '../../../helpers/logger'
5import { VideoShareModel } from '../../../models/video/video-share' 5import { VideoShareModel } from '../../../models/video/video-share'
6import { areValidationErrors } from '../utils' 6import { areValidationErrors } from '../utils'
7import { doesVideoExist } from '../../../helpers/middlewares' 7import { doesVideoExist } from '../../../helpers/middlewares'
8import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
8 9
9const videosShareValidator = [ 10const videosShareValidator = [
10 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 11 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
@@ -20,7 +21,7 @@ const videosShareValidator = [
20 21
21 const share = await VideoShareModel.load(req.params.actorId, video.id) 22 const share = await VideoShareModel.load(req.params.actorId, video.id)
22 if (!share) { 23 if (!share) {
23 return res.status(404) 24 return res.status(HttpStatusCode.NOT_FOUND_404)
24 .end() 25 .end()
25 } 26 }
26 27
diff --git a/server/middlewares/validators/videos/video-watch.ts b/server/middlewares/validators/videos/video-watch.ts
index d6ca1d341..29ce0dab6 100644
--- a/server/middlewares/validators/videos/video-watch.ts
+++ b/server/middlewares/validators/videos/video-watch.ts
@@ -4,6 +4,7 @@ import { isIdOrUUIDValid, toIntOrNull } from '../../../helpers/custom-validators
4import { areValidationErrors } from '../utils' 4import { areValidationErrors } from '../utils'
5import { logger } from '../../../helpers/logger' 5import { logger } from '../../../helpers/logger'
6import { doesVideoExist } from '../../../helpers/middlewares' 6import { doesVideoExist } from '../../../helpers/middlewares'
7import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
7 8
8const videoWatchingValidator = [ 9const videoWatchingValidator = [
9 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 10 param('videoId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
@@ -20,7 +21,7 @@ const videoWatchingValidator = [
20 const user = res.locals.oauth.token.User 21 const user = res.locals.oauth.token.User
21 if (user.videosHistoryEnabled === false) { 22 if (user.videosHistoryEnabled === false) {
22 logger.warn('Cannot set videos to watch by user %d: videos history is disabled.', user.id) 23 logger.warn('Cannot set videos to watch by user %d: videos history is disabled.', user.id)
23 return res.status(409).end() 24 return res.status(HttpStatusCode.CONFLICT_409).end()
24 } 25 }
25 26
26 return next() 27 return next()
diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts
index af0072d73..9834f714b 100644
--- a/server/middlewares/validators/videos/videos.ts
+++ b/server/middlewares/validators/videos/videos.ts
@@ -51,6 +51,7 @@ import { AccountModel } from '../../../models/account/account'
51import { VideoModel } from '../../../models/video/video' 51import { VideoModel } from '../../../models/video/video'
52import { authenticatePromiseIfNeeded } from '../../oauth' 52import { authenticatePromiseIfNeeded } from '../../oauth'
53import { areValidationErrors } from '../utils' 53import { areValidationErrors } from '../utils'
54import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
54 55
55const videosAddValidator = getCommonVideoEditAttributes().concat([ 56const videosAddValidator = getCommonVideoEditAttributes().concat([
56 body('videofile') 57 body('videofile')
@@ -75,7 +76,7 @@ const videosAddValidator = getCommonVideoEditAttributes().concat([
75 if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req) 76 if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req)
76 77
77 if (await isAbleToUploadVideo(user.id, videoFile.size) === false) { 78 if (await isAbleToUploadVideo(user.id, videoFile.size) === false) {
78 res.status(403) 79 res.status(HttpStatusCode.FORBIDDEN_403)
79 .json({ error: 'The user video quota is exceeded with this video.' }) 80 .json({ error: 'The user video quota is exceeded with this video.' })
80 81
81 return cleanUpReqFiles(req) 82 return cleanUpReqFiles(req)
@@ -87,7 +88,7 @@ const videosAddValidator = getCommonVideoEditAttributes().concat([
87 duration = await getDurationFromVideoFile(videoFile.path) 88 duration = await getDurationFromVideoFile(videoFile.path)
88 } catch (err) { 89 } catch (err) {
89 logger.error('Invalid input file in videosAddValidator.', { err }) 90 logger.error('Invalid input file in videosAddValidator.', { err })
90 res.status(400) 91 res.status(HttpStatusCode.BAD_REQUEST_400)
91 .json({ error: 'Invalid input file.' }) 92 .json({ error: 'Invalid input file.' })
92 93
93 return cleanUpReqFiles(req) 94 return cleanUpReqFiles(req)
@@ -147,7 +148,7 @@ async function checkVideoFollowConstraints (req: express.Request, res: express.R
147 const serverActor = await getServerActor() 148 const serverActor = await getServerActor()
148 if (await VideoModel.checkVideoHasInstanceFollow(video.id, serverActor.id) === true) return next() 149 if (await VideoModel.checkVideoHasInstanceFollow(video.id, serverActor.id) === true) return next()
149 150
150 return res.status(403) 151 return res.status(HttpStatusCode.FORBIDDEN_403)
151 .json({ 152 .json({
152 errorCode: ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS, 153 errorCode: ServerErrorCode.DOES_NOT_RESPECT_FOLLOW_CONSTRAINTS,
153 error: 'Cannot get this video regarding follow constraints.', 154 error: 'Cannot get this video regarding follow constraints.',
@@ -182,7 +183,7 @@ const videosCustomGetValidator = (
182 183
183 // Only the owner or a user that have blacklist rights can see the video 184 // Only the owner or a user that have blacklist rights can see the video
184 if (!user || !user.canGetVideo(videoAll)) { 185 if (!user || !user.canGetVideo(videoAll)) {
185 return res.status(403) 186 return res.status(HttpStatusCode.FORBIDDEN_403)
186 .json({ error: 'Cannot get this private/internal or blacklisted video.' }) 187 .json({ error: 'Cannot get this private/internal or blacklisted video.' })
187 } 188 }
188 189
@@ -197,7 +198,7 @@ const videosCustomGetValidator = (
197 if (isUUIDValid(req.params.id)) return next() 198 if (isUUIDValid(req.params.id)) return next()
198 199
199 // Don't leak this unlisted video 200 // Don't leak this unlisted video
200 return res.status(404).end() 201 return res.status(HttpStatusCode.NOT_FOUND_404).end()
201 } 202 }
202 } 203 }
203 ] 204 ]
@@ -250,7 +251,7 @@ const videosChangeOwnershipValidator = [
250 251
251 const nextOwner = await AccountModel.loadLocalByName(req.body.username) 252 const nextOwner = await AccountModel.loadLocalByName(req.body.username)
252 if (!nextOwner) { 253 if (!nextOwner) {
253 res.status(400) 254 res.status(HttpStatusCode.BAD_REQUEST_400)
254 .json({ error: 'Changing video ownership to a remote account is not supported yet' }) 255 .json({ error: 'Changing video ownership to a remote account is not supported yet' })
255 256
256 return 257 return
@@ -276,7 +277,7 @@ const videosTerminateChangeOwnershipValidator = [
276 const videoChangeOwnership = res.locals.videoChangeOwnership 277 const videoChangeOwnership = res.locals.videoChangeOwnership
277 278
278 if (videoChangeOwnership.status !== VideoChangeOwnershipStatus.WAITING) { 279 if (videoChangeOwnership.status !== VideoChangeOwnershipStatus.WAITING) {
279 res.status(403) 280 res.status(HttpStatusCode.FORBIDDEN_403)
280 .json({ error: 'Ownership already accepted or refused' }) 281 .json({ error: 'Ownership already accepted or refused' })
281 return 282 return
282 } 283 }
@@ -294,7 +295,7 @@ const videosAcceptChangeOwnershipValidator = [
294 const videoChangeOwnership = res.locals.videoChangeOwnership 295 const videoChangeOwnership = res.locals.videoChangeOwnership
295 const isAble = await isAbleToUploadVideo(user.id, videoChangeOwnership.Video.getMaxQualityFile().size) 296 const isAble = await isAbleToUploadVideo(user.id, videoChangeOwnership.Video.getMaxQualityFile().size)
296 if (isAble === false) { 297 if (isAble === false) {
297 res.status(403) 298 res.status(HttpStatusCode.FORBIDDEN_403)
298 .json({ error: 'The user video quota is exceeded with this video.' }) 299 .json({ error: 'The user video quota is exceeded with this video.' })
299 300
300 return 301 return
@@ -433,7 +434,7 @@ const commonVideosFiltersValidator = [
433 (req.query.filter === 'all-local' || req.query.filter === 'all') && 434 (req.query.filter === 'all-local' || req.query.filter === 'all') &&
434 (!user || user.hasRight(UserRight.SEE_ALL_VIDEOS) === false) 435 (!user || user.hasRight(UserRight.SEE_ALL_VIDEOS) === false)
435 ) { 436 ) {
436 res.status(401) 437 res.status(HttpStatusCode.UNAUTHORIZED_401)
437 .json({ error: 'You are not allowed to see all local videos.' }) 438 .json({ error: 'You are not allowed to see all local videos.' })
438 439
439 return 440 return
@@ -473,7 +474,7 @@ function areErrorsInScheduleUpdate (req: express.Request, res: express.Response)
473 if (!req.body.scheduleUpdate.updateAt) { 474 if (!req.body.scheduleUpdate.updateAt) {
474 logger.warn('Invalid parameters: scheduleUpdate.updateAt is mandatory.') 475 logger.warn('Invalid parameters: scheduleUpdate.updateAt is mandatory.')
475 476
476 res.status(400) 477 res.status(HttpStatusCode.BAD_REQUEST_400)
477 .json({ error: 'Schedule update at is mandatory.' }) 478 .json({ error: 'Schedule update at is mandatory.' })
478 479
479 return true 480 return true
@@ -498,7 +499,7 @@ async function isVideoAccepted (req: express.Request, res: express.Response, vid
498 499
499 if (!acceptedResult || acceptedResult.accepted !== true) { 500 if (!acceptedResult || acceptedResult.accepted !== true) {
500 logger.info('Refused local video.', { acceptedResult, acceptParameters }) 501 logger.info('Refused local video.', { acceptedResult, acceptParameters })
501 res.status(403) 502 res.status(HttpStatusCode.FORBIDDEN_403)
502 .json({ error: acceptedResult.errorMessage || 'Refused local video' }) 503 .json({ error: acceptedResult.errorMessage || 'Refused local video' })
503 504
504 return false 505 return false
diff --git a/server/middlewares/validators/webfinger.ts b/server/middlewares/validators/webfinger.ts
index 5fe864f8b..a71422ed8 100644
--- a/server/middlewares/validators/webfinger.ts
+++ b/server/middlewares/validators/webfinger.ts
@@ -5,6 +5,7 @@ import { logger } from '../../helpers/logger'
5import { ActorModel } from '../../models/activitypub/actor' 5import { ActorModel } from '../../models/activitypub/actor'
6import { areValidationErrors } from './utils' 6import { areValidationErrors } from './utils'
7import { getHostWithPort } from '../../helpers/express-utils' 7import { getHostWithPort } from '../../helpers/express-utils'
8import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
8 9
9const webfingerValidator = [ 10const webfingerValidator = [
10 query('resource').custom(isWebfingerLocalResourceValid).withMessage('Should have a valid webfinger resource'), 11 query('resource').custom(isWebfingerLocalResourceValid).withMessage('Should have a valid webfinger resource'),
@@ -20,9 +21,9 @@ const webfingerValidator = [
20 21
21 const actor = await ActorModel.loadLocalUrlByName(name) 22 const actor = await ActorModel.loadLocalUrlByName(name)
22 if (!actor) { 23 if (!actor) {
23 return res.status(404) 24 return res.status(HttpStatusCode.NOT_FOUND_404)
24 .send({ error: 'Actor not found' }) 25 .send({ error: 'Actor not found' })
25 .end() 26 .end()
26 } 27 }
27 28
28 res.locals.actorUrl = actor 29 res.locals.actorUrl = actor