aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorRigel Kent <sendmemail@rigelk.eu>2020-12-08 21:16:10 +0100
committerGitHub <noreply@github.com>2020-12-08 21:16:10 +0100
commitf2eb23cd87cf32b8fe545178143b5f49e06a58da (patch)
treeaf7d59945af70e28fd85047e2c688c59a908f548 /server
parentc977fd3ec931c059111ddb2b8d6ddbb20b6b99a1 (diff)
downloadPeerTube-f2eb23cd87cf32b8fe545178143b5f49e06a58da.tar.gz
PeerTube-f2eb23cd87cf32b8fe545178143b5f49e06a58da.tar.zst
PeerTube-f2eb23cd87cf32b8fe545178143b5f49e06a58da.zip
emit more specific status codes on video upload (#3423)
- reduce http status codes list to potentially useful codes - convert more codes to typed ones - factorize html generator for error responses
Diffstat (limited to 'server')
-rw-r--r--server/controllers/client.ts32
-rw-r--r--server/controllers/static.ts14
-rw-r--r--server/helpers/custom-validators/misc.ts46
-rw-r--r--server/helpers/custom-validators/videos.ts8
-rw-r--r--server/helpers/youtube-dl.ts5
-rw-r--r--server/lib/activitypub/actor.ts3
-rw-r--r--server/lib/activitypub/playlist.ts3
-rw-r--r--server/lib/activitypub/videos.ts3
-rw-r--r--server/lib/client-html.ts42
-rw-r--r--server/middlewares/cache.ts6
-rw-r--r--server/middlewares/validators/videos/videos.ts41
-rw-r--r--server/tests/api/activitypub/client.ts3
-rw-r--r--server/tests/api/activitypub/refresher.ts15
-rw-r--r--server/tests/api/check-params/accounts.ts3
-rw-r--r--server/tests/api/check-params/contact-form.ts59
-rw-r--r--server/tests/api/check-params/users.ts12
-rw-r--r--server/tests/api/check-params/videos.ts18
-rw-r--r--server/tests/api/live/live-save-replay.ts33
-rw-r--r--server/tests/api/live/live.ts19
-rw-r--r--server/tests/api/server/config.ts9
-rw-r--r--server/tests/api/server/contact-form.ts3
-rw-r--r--server/tests/api/server/email.ts13
-rw-r--r--server/tests/api/server/follow-constraints.ts17
-rw-r--r--server/tests/api/server/handle-down.ts3
-rw-r--r--server/tests/api/server/no-client.ts3
-rw-r--r--server/tests/api/server/reverse-proxy.ts25
-rw-r--r--server/tests/api/videos/multiple-servers.ts5
-rw-r--r--server/tests/api/videos/video-change-ownership.ts14
-rw-r--r--server/tests/api/videos/video-hls.ts9
-rw-r--r--server/tests/api/videos/video-playlists.ts13
-rw-r--r--server/tests/api/videos/video-privacy.ts13
-rw-r--r--server/tests/api/videos/videos-history.ts3
-rw-r--r--server/tests/cli/reset-password.ts3
-rw-r--r--server/tests/feeds/feeds.ts17
-rw-r--r--server/tests/plugins/filter-hooks.ts24
-rw-r--r--server/tests/plugins/video-constants.ts10
-rw-r--r--server/tools/peertube-redundancy.ts5
37 files changed, 378 insertions, 176 deletions
diff --git a/server/controllers/client.ts b/server/controllers/client.ts
index 49e6fd661..bd1f19f8c 100644
--- a/server/controllers/client.ts
+++ b/server/controllers/client.ts
@@ -3,12 +3,11 @@ import { constants, promises as fs } from 'fs'
3import { join } from 'path' 3import { join } from 'path'
4import { CONFIG } from '@server/initializers/config' 4import { CONFIG } from '@server/initializers/config'
5import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@shared/core-utils/i18n' 5import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@shared/core-utils/i18n'
6import { HttpStatusCode } from '@shared/core-utils'
6import { root } from '../helpers/core-utils' 7import { root } from '../helpers/core-utils'
7import { logger } from '../helpers/logger' 8import { STATIC_MAX_AGE } from '../initializers/constants'
8import { ACCEPT_HEADERS, STATIC_MAX_AGE } from '../initializers/constants' 9import { ClientHtml, sendHTML, serveIndexHTML } from '../lib/client-html'
9import { ClientHtml } from '../lib/client-html'
10import { asyncMiddleware, embedCSP } from '../middlewares' 10import { asyncMiddleware, embedCSP } from '../middlewares'
11import { HttpStatusCode } from '@shared/core-utils'
12 11
13const clientsRouter = express.Router() 12const clientsRouter = express.Router()
14 13
@@ -118,31 +117,12 @@ function serveServerTranslations (req: express.Request, res: express.Response) {
118 return res.sendStatus(HttpStatusCode.NOT_FOUND_404) 117 return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
119} 118}
120 119
121async function serveIndexHTML (req: express.Request, res: express.Response) {
122 if (req.accepts(ACCEPT_HEADERS) === 'html') {
123 try {
124 await generateHTMLPage(req, res, req.params.language)
125 return
126 } catch (err) {
127 logger.error('Cannot generate HTML page.', err)
128 }
129 }
130
131 return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR_500).end()
132}
133
134async function generateEmbedHtmlPage (req: express.Request, res: express.Response) { 120async function generateEmbedHtmlPage (req: express.Request, res: express.Response) {
135 const html = await ClientHtml.getEmbedHTML() 121 const html = await ClientHtml.getEmbedHTML()
136 122
137 return sendHTML(html, res) 123 return sendHTML(html, res)
138} 124}
139 125
140async function generateHTMLPage (req: express.Request, res: express.Response, paramLang?: string) {
141 const html = await ClientHtml.getDefaultHTMLPage(req, res, paramLang)
142
143 return sendHTML(html, res)
144}
145
146async function generateWatchHtmlPage (req: express.Request, res: express.Response) { 126async function generateWatchHtmlPage (req: express.Request, res: express.Response) {
147 const html = await ClientHtml.getWatchHTMLPage(req.params.id + '', req, res) 127 const html = await ClientHtml.getWatchHTMLPage(req.params.id + '', req, res)
148 128
@@ -167,12 +147,6 @@ async function generateVideoChannelHtmlPage (req: express.Request, res: express.
167 return sendHTML(html, res) 147 return sendHTML(html, res)
168} 148}
169 149
170function sendHTML (html: string, res: express.Response) {
171 res.set('Content-Type', 'text/html; charset=UTF-8')
172
173 return res.send(html)
174}
175
176async function generateManifest (req: express.Request, res: express.Response) { 150async function generateManifest (req: express.Request, res: express.Response) {
177 const manifestPhysicalPath = join(root(), 'client', 'dist', 'manifest.webmanifest') 151 const manifestPhysicalPath = join(root(), 'client', 'dist', 'manifest.webmanifest')
178 const manifestJson = await fs.readFile(manifestPhysicalPath, 'utf8') 152 const manifestJson = await fs.readFile(manifestPhysicalPath, 'utf8')
diff --git a/server/controllers/static.ts b/server/controllers/static.ts
index ff77452dd..f12f00e1b 100644
--- a/server/controllers/static.ts
+++ b/server/controllers/static.ts
@@ -27,6 +27,7 @@ import { getTorrentFilePath, getVideoFilePath } from '@server/lib/video-paths'
27import { getThemeOrDefault } from '../lib/plugins/theme-utils' 27import { getThemeOrDefault } from '../lib/plugins/theme-utils'
28import { getEnabledResolutions, getRegisteredPlugins, getRegisteredThemes } from '@server/controllers/api/config' 28import { getEnabledResolutions, getRegisteredPlugins, getRegisteredThemes } from '@server/controllers/api/config'
29import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' 29import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
30import { serveIndexHTML } from '@server/lib/client-html'
30 31
31const staticRouter = express.Router() 32const staticRouter = express.Router()
32 33
@@ -119,6 +120,11 @@ staticRouter.get('/robots.txt',
119 } 120 }
120) 121)
121 122
123staticRouter.all('/teapot',
124 getCup,
125 asyncMiddleware(serveIndexHTML)
126)
127
122// security.txt service 128// security.txt service
123staticRouter.get('/security.txt', 129staticRouter.get('/security.txt',
124 (_, res: express.Response) => { 130 (_, res: express.Response) => {
@@ -391,3 +397,11 @@ function getHLSPlaylist (video: MVideoFullLight) {
391 397
392 return Object.assign(playlist, { Video: video }) 398 return Object.assign(playlist, { Video: video })
393} 399}
400
401function getCup (req: express.Request, res: express.Response, next: express.NextFunction) {
402 res.status(HttpStatusCode.I_AM_A_TEAPOT_418)
403 res.setHeader('Accept-Additions', 'Non-Dairy;1,Sugar;1')
404 res.setHeader('Safe', 'if-sepia-awake')
405
406 return next()
407}
diff --git a/server/helpers/custom-validators/misc.ts b/server/helpers/custom-validators/misc.ts
index 61c03f0c9..effdd98cb 100644
--- a/server/helpers/custom-validators/misc.ts
+++ b/server/helpers/custom-validators/misc.ts
@@ -86,6 +86,50 @@ function toIntArray (value: any) {
86 return value.map(v => validator.toInt(v)) 86 return value.map(v => validator.toInt(v))
87} 87}
88 88
89function isFileFieldValid (
90 files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
91 field: string,
92 optional = false
93) {
94 // Should have files
95 if (!files) return optional
96 if (isArray(files)) return optional
97
98 // Should have a file
99 const fileArray = files[field]
100 if (!fileArray || fileArray.length === 0) {
101 return optional
102 }
103
104 // The file should exist
105 const file = fileArray[0]
106 if (!file || !file.originalname) return false
107 return file
108}
109
110function isFileMimeTypeValid (
111 files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
112 mimeTypeRegex: string,
113 field: string,
114 optional = false
115) {
116 // Should have files
117 if (!files) return optional
118 if (isArray(files)) return optional
119
120 // Should have a file
121 const fileArray = files[field]
122 if (!fileArray || fileArray.length === 0) {
123 return optional
124 }
125
126 // The file should exist
127 const file = fileArray[0]
128 if (!file || !file.originalname) return false
129
130 return new RegExp(`^${mimeTypeRegex}$`, 'i').test(file.mimetype)
131}
132
89function isFileValid ( 133function isFileValid (
90 files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], 134 files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
91 mimeTypeRegex: string, 135 mimeTypeRegex: string,
@@ -132,5 +176,7 @@ export {
132 toIntOrNull, 176 toIntOrNull,
133 toArray, 177 toArray,
134 toIntArray, 178 toIntArray,
179 isFileFieldValid,
180 isFileMimeTypeValid,
135 isFileValid 181 isFileValid
136} 182}
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts
index 8b309ae42..87966798f 100644
--- a/server/helpers/custom-validators/videos.ts
+++ b/server/helpers/custom-validators/videos.ts
@@ -11,7 +11,7 @@ import {
11 VIDEO_STATES, 11 VIDEO_STATES,
12 VIDEO_LIVE 12 VIDEO_LIVE
13} from '../../initializers/constants' 13} from '../../initializers/constants'
14import { exists, isArray, isDateValid, isFileValid } from './misc' 14import { exists, isArray, isDateValid, isFileMimeTypeValid, isFileValid } from './misc'
15import * as magnetUtil from 'magnet-uri' 15import * as magnetUtil from 'magnet-uri'
16 16
17const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS 17const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
@@ -81,8 +81,8 @@ function isVideoFileExtnameValid (value: string) {
81 return exists(value) && (value === VIDEO_LIVE.EXTENSION || MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined) 81 return exists(value) && (value === VIDEO_LIVE.EXTENSION || MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined)
82} 82}
83 83
84function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) { 84function isVideoFileMimeTypeValid (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
85 return isFileValid(files, MIMETYPES.VIDEO.MIMETYPES_REGEX, 'videofile', null) 85 return isFileMimeTypeValid(files, MIMETYPES.VIDEO.MIMETYPES_REGEX, 'videofile')
86} 86}
87 87
88const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME 88const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
@@ -143,12 +143,12 @@ export {
143 isVideoFPSResolutionValid, 143 isVideoFPSResolutionValid,
144 isScheduleVideoUpdatePrivacyValid, 144 isScheduleVideoUpdatePrivacyValid,
145 isVideoOriginallyPublishedAtValid, 145 isVideoOriginallyPublishedAtValid,
146 isVideoFile,
147 isVideoMagnetUriValid, 146 isVideoMagnetUriValid,
148 isVideoStateValid, 147 isVideoStateValid,
149 isVideoViewsValid, 148 isVideoViewsValid,
150 isVideoRatingTypeValid, 149 isVideoRatingTypeValid,
151 isVideoFileExtnameValid, 150 isVideoFileExtnameValid,
151 isVideoFileMimeTypeValid,
152 isVideoDurationValid, 152 isVideoDurationValid,
153 isVideoTagValid, 153 isVideoTagValid,
154 isVideoPrivacyValid, 154 isVideoPrivacyValid,
diff --git a/server/helpers/youtube-dl.ts b/server/helpers/youtube-dl.ts
index 302b2e206..9e8ef90d8 100644
--- a/server/helpers/youtube-dl.ts
+++ b/server/helpers/youtube-dl.ts
@@ -7,6 +7,7 @@ import { ensureDir, remove, writeFile } from 'fs-extra'
7import * as request from 'request' 7import * as request from 'request'
8import { createWriteStream } from 'fs' 8import { createWriteStream } from 'fs'
9import { CONFIG } from '@server/initializers/config' 9import { CONFIG } from '@server/initializers/config'
10import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
10 11
11export type YoutubeDLInfo = { 12export type YoutubeDLInfo = {
12 name?: string 13 name?: string
@@ -154,7 +155,7 @@ async function updateYoutubeDLBinary () {
154 return res() 155 return res()
155 } 156 }
156 157
157 if (result.statusCode !== 302) { 158 if (result.statusCode !== HttpStatusCode.FOUND_302) {
158 logger.error('youtube-dl update error: did not get redirect for the latest version link. Status %d', result.statusCode) 159 logger.error('youtube-dl update error: did not get redirect for the latest version link. Status %d', result.statusCode)
159 return res() 160 return res()
160 } 161 }
@@ -164,7 +165,7 @@ async function updateYoutubeDLBinary () {
164 const newVersion = /yt-dl\.org\/downloads\/(\d{4}\.\d\d\.\d\d(\.\d)?)\/youtube-dl/.exec(url)[1] 165 const newVersion = /yt-dl\.org\/downloads\/(\d{4}\.\d\d\.\d\d(\.\d)?)\/youtube-dl/.exec(url)[1]
165 166
166 downloadFile.on('response', result => { 167 downloadFile.on('response', result => {
167 if (result.statusCode !== 200) { 168 if (result.statusCode !== HttpStatusCode.OK_200) {
168 logger.error('Cannot update youtube-dl: new version response is not 200, it\'s %d.', result.statusCode) 169 logger.error('Cannot update youtube-dl: new version response is not 200, it\'s %d.', result.statusCode)
169 return res() 170 return res()
170 } 171 }
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts
index fb5558ff6..52547536c 100644
--- a/server/lib/activitypub/actor.ts
+++ b/server/lib/activitypub/actor.ts
@@ -36,6 +36,7 @@ import {
36} from '../../types/models' 36} from '../../types/models'
37import { extname } from 'path' 37import { extname } from 'path'
38import { getServerActor } from '@server/models/application/application' 38import { getServerActor } from '@server/models/application/application'
39import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
39 40
40// Set account keys, this could be long so process after the account creation and do not block the client 41// Set account keys, this could be long so process after the account creation and do not block the client
41function setAsyncActorKeys <T extends MActor> (actor: T) { 42function setAsyncActorKeys <T extends MActor> (actor: T) {
@@ -277,7 +278,7 @@ async function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannel
277 278
278 const { result, statusCode } = await fetchRemoteActor(actorUrl) 279 const { result, statusCode } = await fetchRemoteActor(actorUrl)
279 280
280 if (statusCode === 404) { 281 if (statusCode === HttpStatusCode.NOT_FOUND_404) {
281 logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url) 282 logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url)
282 actor.Account 283 actor.Account
283 ? await actor.Account.destroy() 284 ? await actor.Account.destroy()
diff --git a/server/lib/activitypub/playlist.ts b/server/lib/activitypub/playlist.ts
index bd442b223..53298e968 100644
--- a/server/lib/activitypub/playlist.ts
+++ b/server/lib/activitypub/playlist.ts
@@ -18,6 +18,7 @@ import { createPlaylistMiniatureFromUrl } from '../thumbnail'
18import { FilteredModelAttributes } from '../../types/sequelize' 18import { FilteredModelAttributes } from '../../types/sequelize'
19import { MAccountDefault, MAccountId, MVideoId } from '../../types/models' 19import { MAccountDefault, MAccountId, MVideoId } from '../../types/models'
20import { MVideoPlaylist, MVideoPlaylistId, MVideoPlaylistOwner } from '../../types/models/video/video-playlist' 20import { MVideoPlaylist, MVideoPlaylistId, MVideoPlaylistOwner } from '../../types/models/video/video-playlist'
21import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
21 22
22function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: MAccountId, to: string[]) { 23function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: MAccountId, to: string[]) {
23 const privacy = to.includes(ACTIVITY_PUB.PUBLIC) 24 const privacy = to.includes(ACTIVITY_PUB.PUBLIC)
@@ -120,7 +121,7 @@ async function refreshVideoPlaylistIfNeeded (videoPlaylist: MVideoPlaylistOwner)
120 121
121 try { 122 try {
122 const { statusCode, playlistObject } = await fetchRemoteVideoPlaylist(videoPlaylist.url) 123 const { statusCode, playlistObject } = await fetchRemoteVideoPlaylist(videoPlaylist.url)
123 if (statusCode === 404) { 124 if (statusCode === HttpStatusCode.NOT_FOUND_404) {
124 logger.info('Cannot refresh remote video playlist %s: it does not exist anymore. Deleting it.', videoPlaylist.url) 125 logger.info('Cannot refresh remote video playlist %s: it does not exist anymore. Deleting it.', videoPlaylist.url)
125 126
126 await videoPlaylist.destroy() 127 await videoPlaylist.destroy()
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
index 04f0bfc23..b15d5da1c 100644
--- a/server/lib/activitypub/videos.ts
+++ b/server/lib/activitypub/videos.ts
@@ -76,6 +76,7 @@ import { sendCreateVideo, sendUpdateVideo } from './send'
76import { addVideoShares, shareVideoByServerAndChannel } from './share' 76import { addVideoShares, shareVideoByServerAndChannel } from './share'
77import { addVideoComments } from './video-comments' 77import { addVideoComments } from './video-comments'
78import { createRates } from './video-rates' 78import { createRates } from './video-rates'
79import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
79 80
80async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVideo: boolean, transaction?: sequelize.Transaction) { 81async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVideo: boolean, transaction?: sequelize.Transaction) {
81 const video = videoArg as MVideoAP 82 const video = videoArg as MVideoAP
@@ -488,7 +489,7 @@ async function refreshVideoIfNeeded (options: {
488 489
489 try { 490 try {
490 const { response, videoObject } = await fetchRemoteVideo(video.url) 491 const { response, videoObject } = await fetchRemoteVideo(video.url)
491 if (response.statusCode === 404) { 492 if (response.statusCode === HttpStatusCode.NOT_FOUND_404) {
492 logger.info('Cannot refresh remote video %s: video does not exist anymore. Deleting it.', video.url) 493 logger.info('Cannot refresh remote video %s: video does not exist anymore. Deleting it.', video.url)
493 494
494 // Video does not exist anymore 495 // Video does not exist anymore
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts
index d97d23180..32f5d29ab 100644
--- a/server/lib/client-html.ts
+++ b/server/lib/client-html.ts
@@ -1,4 +1,5 @@
1import * as express from 'express' 1import * as express from 'express'
2import * as Bluebird from 'bluebird'
2import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n' 3import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
3import { 4import {
4 AVATARS_SIZE, 5 AVATARS_SIZE,
@@ -6,7 +7,8 @@ import {
6 EMBED_SIZE, 7 EMBED_SIZE,
7 PLUGIN_GLOBAL_CSS_PATH, 8 PLUGIN_GLOBAL_CSS_PATH,
8 WEBSERVER, 9 WEBSERVER,
9 FILES_CONTENT_HASH 10 FILES_CONTENT_HASH,
11 ACCEPT_HEADERS
10} from '../initializers/constants' 12} from '../initializers/constants'
11import { join } from 'path' 13import { join } from 'path'
12import { escapeHTML, isTestInstance, sha256 } from '../helpers/core-utils' 14import { escapeHTML, isTestInstance, sha256 } from '../helpers/core-utils'
@@ -18,7 +20,6 @@ import { readFile } from 'fs-extra'
18import { getActivityStreamDuration } from '../models/video/video-format-utils' 20import { getActivityStreamDuration } from '../models/video/video-format-utils'
19import { AccountModel } from '../models/account/account' 21import { AccountModel } from '../models/account/account'
20import { VideoChannelModel } from '../models/video/video-channel' 22import { VideoChannelModel } from '../models/video/video-channel'
21import * as Bluebird from 'bluebird'
22import { CONFIG } from '../initializers/config' 23import { CONFIG } from '../initializers/config'
23import { logger } from '../helpers/logger' 24import { logger } from '../helpers/logger'
24import { MAccountActor, MChannelActor } from '../types/models' 25import { MAccountActor, MChannelActor } from '../types/models'
@@ -53,7 +54,7 @@ type Tags = {
53 } 54 }
54} 55}
55 56
56export class ClientHtml { 57class ClientHtml {
57 58
58 private static htmlCache: { [path: string]: string } = {} 59 private static htmlCache: { [path: string]: string } = {}
59 60
@@ -505,3 +506,38 @@ export class ClientHtml {
505 return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.META_TAGS, tagsString) 506 return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.META_TAGS, tagsString)
506 } 507 }
507} 508}
509
510function sendHTML (html: string, res: express.Response) {
511 res.set('Content-Type', 'text/html; charset=UTF-8')
512
513 return res.send(html)
514}
515
516async function serveIndexHTML (req: express.Request, res: express.Response) {
517 if (req.accepts(ACCEPT_HEADERS) === 'html' ||
518 !req.headers.accept) {
519 try {
520 await generateHTMLPage(req, res, req.params.language)
521 return
522 } catch (err) {
523 logger.error('Cannot generate HTML page.', err)
524 return res.sendStatus(HttpStatusCode.INTERNAL_SERVER_ERROR_500)
525 }
526 }
527
528 return res.sendStatus(HttpStatusCode.NOT_ACCEPTABLE_406)
529}
530
531// ---------------------------------------------------------------------------
532
533export {
534 ClientHtml,
535 sendHTML,
536 serveIndexHTML
537}
538
539async function generateHTMLPage (req: express.Request, res: express.Response, paramLang?: string) {
540 const html = await ClientHtml.getDefaultHTMLPage(req, res, paramLang)
541
542 return sendHTML(html, res)
543}
diff --git a/server/middlewares/cache.ts b/server/middlewares/cache.ts
index cb24d9e0e..0708ee8e8 100644
--- a/server/middlewares/cache.ts
+++ b/server/middlewares/cache.ts
@@ -1,5 +1,6 @@
1import { Redis } from '../lib/redis' 1import { Redis } from '../lib/redis'
2import * as apicache from 'apicache' 2import * as apicache from 'apicache'
3import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
3 4
4// Ensure Redis is initialized 5// Ensure Redis is initialized
5Redis.Instance.init() 6Redis.Instance.init()
@@ -8,7 +9,10 @@ const defaultOptions = {
8 redisClient: Redis.Instance.getClient(), 9 redisClient: Redis.Instance.getClient(),
9 appendKey: () => Redis.Instance.getPrefix(), 10 appendKey: () => Redis.Instance.getPrefix(),
10 statusCodes: { 11 statusCodes: {
11 exclude: [ 404, 403 ] 12 exclude: [
13 HttpStatusCode.FORBIDDEN_403,
14 HttpStatusCode.NOT_FOUND_404
15 ]
12 } 16 }
13} 17}
14 18
diff --git a/server/middlewares/validators/videos/videos.ts b/server/middlewares/validators/videos/videos.ts
index 9834f714b..8bc37b0ab 100644
--- a/server/middlewares/validators/videos/videos.ts
+++ b/server/middlewares/validators/videos/videos.ts
@@ -8,6 +8,7 @@ import { VideoChangeOwnershipAccept } from '../../../../shared/models/videos/vid
8import { 8import {
9 isBooleanValid, 9 isBooleanValid,
10 isDateValid, 10 isDateValid,
11 isFileFieldValid,
11 isIdOrUUIDValid, 12 isIdOrUUIDValid,
12 isIdValid, 13 isIdValid,
13 isUUIDValid, 14 isUUIDValid,
@@ -22,7 +23,8 @@ import {
22 isScheduleVideoUpdatePrivacyValid, 23 isScheduleVideoUpdatePrivacyValid,
23 isVideoCategoryValid, 24 isVideoCategoryValid,
24 isVideoDescriptionValid, 25 isVideoDescriptionValid,
25 isVideoFile, 26 isVideoFileMimeTypeValid,
27 isVideoFileSizeValid,
26 isVideoFilterValid, 28 isVideoFilterValid,
27 isVideoImage, 29 isVideoImage,
28 isVideoLanguageValid, 30 isVideoLanguageValid,
@@ -55,11 +57,11 @@ import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-c
55 57
56const videosAddValidator = getCommonVideoEditAttributes().concat([ 58const videosAddValidator = getCommonVideoEditAttributes().concat([
57 body('videofile') 59 body('videofile')
58 .custom((value, { req }) => isVideoFile(req.files)).withMessage( 60 .custom((value, { req }) => isFileFieldValid(req.files, 'videofile'))
59 'This file is not supported or too large. Please, make sure it is of the following type: ' + 61 .withMessage('Should have a file'),
60 CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ') 62 body('name')
61 ), 63 .custom(isVideoNameValid)
62 body('name').custom(isVideoNameValid).withMessage('Should have a valid name'), 64 .withMessage('Should have a valid name'),
63 body('channelId') 65 body('channelId')
64 .customSanitizer(toIntOrNull) 66 .customSanitizer(toIntOrNull)
65 .custom(isIdValid).withMessage('Should have correct video channel id'), 67 .custom(isIdValid).withMessage('Should have correct video channel id'),
@@ -75,8 +77,27 @@ const videosAddValidator = getCommonVideoEditAttributes().concat([
75 77
76 if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req) 78 if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req)
77 79
80 if (!isVideoFileMimeTypeValid(req.files)) {
81 res.status(HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
82 .json({
83 error: 'This file is not supported. Please, make sure it is of the following type: ' +
84 CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ')
85 })
86
87 return cleanUpReqFiles(req)
88 }
89
90 if (!isVideoFileSizeValid(videoFile.size.toString())) {
91 res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413)
92 .json({
93 error: 'This file is too large.'
94 })
95
96 return cleanUpReqFiles(req)
97 }
98
78 if (await isAbleToUploadVideo(user.id, videoFile.size) === false) { 99 if (await isAbleToUploadVideo(user.id, videoFile.size) === false) {
79 res.status(HttpStatusCode.FORBIDDEN_403) 100 res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413)
80 .json({ error: 'The user video quota is exceeded with this video.' }) 101 .json({ error: 'The user video quota is exceeded with this video.' })
81 102
82 return cleanUpReqFiles(req) 103 return cleanUpReqFiles(req)
@@ -88,8 +109,8 @@ const videosAddValidator = getCommonVideoEditAttributes().concat([
88 duration = await getDurationFromVideoFile(videoFile.path) 109 duration = await getDurationFromVideoFile(videoFile.path)
89 } catch (err) { 110 } catch (err) {
90 logger.error('Invalid input file in videosAddValidator.', { err }) 111 logger.error('Invalid input file in videosAddValidator.', { err })
91 res.status(HttpStatusCode.BAD_REQUEST_400) 112 res.status(HttpStatusCode.UNPROCESSABLE_ENTITY_422)
92 .json({ error: 'Invalid input file.' }) 113 .json({ error: 'Video file unreadable.' })
93 114
94 return cleanUpReqFiles(req) 115 return cleanUpReqFiles(req)
95 } 116 }
@@ -295,7 +316,7 @@ const videosAcceptChangeOwnershipValidator = [
295 const videoChangeOwnership = res.locals.videoChangeOwnership 316 const videoChangeOwnership = res.locals.videoChangeOwnership
296 const isAble = await isAbleToUploadVideo(user.id, videoChangeOwnership.Video.getMaxQualityFile().size) 317 const isAble = await isAbleToUploadVideo(user.id, videoChangeOwnership.Video.getMaxQualityFile().size)
297 if (isAble === false) { 318 if (isAble === false) {
298 res.status(HttpStatusCode.FORBIDDEN_403) 319 res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413)
299 .json({ error: 'The user video quota is exceeded with this video.' }) 320 .json({ error: 'The user video quota is exceeded with this video.' })
300 321
301 return 322 return
diff --git a/server/tests/api/activitypub/client.ts b/server/tests/api/activitypub/client.ts
index d16f05108..b6c538e19 100644
--- a/server/tests/api/activitypub/client.ts
+++ b/server/tests/api/activitypub/client.ts
@@ -11,6 +11,7 @@ import {
11 setAccessTokensToServers, 11 setAccessTokensToServers,
12 uploadVideo 12 uploadVideo
13} from '../../../../shared/extra-utils' 13} from '../../../../shared/extra-utils'
14import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
14 15
15const expect = chai.expect 16const expect = chai.expect
16 17
@@ -53,7 +54,7 @@ describe('Test activitypub', function () {
53 }) 54 })
54 55
55 it('Should redirect to the origin video object', async function () { 56 it('Should redirect to the origin video object', async function () {
56 const res = await makeActivityPubGetRequest(servers[1].url, '/videos/watch/' + videoUUID, 302) 57 const res = await makeActivityPubGetRequest(servers[1].url, '/videos/watch/' + videoUUID, HttpStatusCode.FOUND_302)
57 58
58 expect(res.header.location).to.equal('http://localhost:' + servers[0].port + '/videos/watch/' + videoUUID) 59 expect(res.header.location).to.equal('http://localhost:' + servers[0].port + '/videos/watch/' + videoUUID)
59 }) 60 })
diff --git a/server/tests/api/activitypub/refresher.ts b/server/tests/api/activitypub/refresher.ts
index 232c5d823..c717f1a30 100644
--- a/server/tests/api/activitypub/refresher.ts
+++ b/server/tests/api/activitypub/refresher.ts
@@ -24,6 +24,7 @@ import {
24} from '../../../../shared/extra-utils' 24} from '../../../../shared/extra-utils'
25import { getAccount } from '../../../../shared/extra-utils/users/accounts' 25import { getAccount } from '../../../../shared/extra-utils/users/accounts'
26import { VideoPlaylistPrivacy } from '../../../../shared/models/videos' 26import { VideoPlaylistPrivacy } from '../../../../shared/models/videos'
27import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
27 28
28describe('Test AP refresher', function () { 29describe('Test AP refresher', function () {
29 let servers: ServerInfo[] = [] 30 let servers: ServerInfo[] = []
@@ -86,8 +87,8 @@ describe('Test AP refresher', function () {
86 87
87 await waitJobs(servers) 88 await waitJobs(servers)
88 89
89 await getVideo(servers[0].url, videoUUID1, 404) 90 await getVideo(servers[0].url, videoUUID1, HttpStatusCode.NOT_FOUND_404)
90 await getVideo(servers[0].url, videoUUID2, 200) 91 await getVideo(servers[0].url, videoUUID2, HttpStatusCode.OK_200)
91 }) 92 })
92 93
93 it('Should not update a remote video if the remote instance is down', async function () { 94 it('Should not update a remote video if the remote instance is down', async function () {
@@ -106,7 +107,7 @@ describe('Test AP refresher', function () {
106 107
107 await reRunServer(servers[1]) 108 await reRunServer(servers[1])
108 109
109 await getVideo(servers[0].url, videoUUID3, 200) 110 await getVideo(servers[0].url, videoUUID3, HttpStatusCode.OK_200)
110 }) 111 })
111 }) 112 })
112 113
@@ -126,8 +127,8 @@ describe('Test AP refresher', function () {
126 127
127 await waitJobs(servers) 128 await waitJobs(servers)
128 129
129 await getAccount(servers[0].url, 'user1@localhost:' + servers[1].port, 200) 130 await getAccount(servers[0].url, 'user1@localhost:' + servers[1].port, HttpStatusCode.OK_200)
130 await getAccount(servers[0].url, 'user2@localhost:' + servers[1].port, 404) 131 await getAccount(servers[0].url, 'user2@localhost:' + servers[1].port, HttpStatusCode.NOT_FOUND_404)
131 }) 132 })
132 }) 133 })
133 134
@@ -146,8 +147,8 @@ describe('Test AP refresher', function () {
146 147
147 await waitJobs(servers) 148 await waitJobs(servers)
148 149
149 await getVideoPlaylist(servers[0].url, playlistUUID1, 200) 150 await getVideoPlaylist(servers[0].url, playlistUUID1, HttpStatusCode.OK_200)
150 await getVideoPlaylist(servers[0].url, playlistUUID2, 404) 151 await getVideoPlaylist(servers[0].url, playlistUUID2, HttpStatusCode.NOT_FOUND_404)
151 }) 152 })
152 }) 153 })
153 154
diff --git a/server/tests/api/check-params/accounts.ts b/server/tests/api/check-params/accounts.ts
index c29af7cd7..d1712cff6 100644
--- a/server/tests/api/check-params/accounts.ts
+++ b/server/tests/api/check-params/accounts.ts
@@ -9,6 +9,7 @@ import {
9 checkBadStartPagination 9 checkBadStartPagination
10} from '../../../../shared/extra-utils/requests/check-api-params' 10} from '../../../../shared/extra-utils/requests/check-api-params'
11import { getAccount } from '../../../../shared/extra-utils/users/accounts' 11import { getAccount } from '../../../../shared/extra-utils/users/accounts'
12import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
12 13
13describe('Test accounts API validators', function () { 14describe('Test accounts API validators', function () {
14 const path = '/api/v1/accounts/' 15 const path = '/api/v1/accounts/'
@@ -38,7 +39,7 @@ describe('Test accounts API validators', function () {
38 39
39 describe('When getting an account', function () { 40 describe('When getting an account', function () {
40 it('Should return 404 with a non existing name', async function () { 41 it('Should return 404 with a non existing name', async function () {
41 await getAccount(server.url, 'arfaze', 404) 42 await getAccount(server.url, 'arfaze', HttpStatusCode.NOT_FOUND_404)
42 }) 43 })
43 }) 44 })
44 45
diff --git a/server/tests/api/check-params/contact-form.ts b/server/tests/api/check-params/contact-form.ts
index b2126b9b0..c7f9c1b47 100644
--- a/server/tests/api/check-params/contact-form.ts
+++ b/server/tests/api/check-params/contact-form.ts
@@ -5,6 +5,7 @@ import 'mocha'
5import { cleanupTests, flushAndRunServer, immutableAssign, killallServers, reRunServer, ServerInfo } from '../../../../shared/extra-utils' 5import { cleanupTests, flushAndRunServer, immutableAssign, killallServers, reRunServer, ServerInfo } from '../../../../shared/extra-utils'
6import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form' 6import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form'
7import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email' 7import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
8import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
8 9
9describe('Test contact form API validators', function () { 10describe('Test contact form API validators', function () {
10 let server: ServerInfo 11 let server: ServerInfo
@@ -29,7 +30,7 @@ describe('Test contact form API validators', function () {
29 }) 30 })
30 31
31 it('Should not accept a contact form if emails are disabled', async function () { 32 it('Should not accept a contact form if emails are disabled', async function () {
32 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 409 })) 33 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: HttpStatusCode.CONFLICT_409 }))
33 }) 34 })
34 35
35 it('Should not accept a contact form if it is disabled in the configuration', async function () { 36 it('Should not accept a contact form if it is disabled in the configuration', async function () {
@@ -39,7 +40,7 @@ describe('Test contact form API validators', function () {
39 40
40 // Contact form is disabled 41 // Contact form is disabled
41 await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort }, contact_form: { enabled: false } }) 42 await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort }, contact_form: { enabled: false } })
42 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 409 })) 43 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: HttpStatusCode.CONFLICT_409 }))
43 }) 44 })
44 45
45 it('Should not accept a contact form if from email is invalid', async function () { 46 it('Should not accept a contact form if from email is invalid', async function () {
@@ -50,21 +51,57 @@ describe('Test contact form API validators', function () {
50 // Email & contact form enabled 51 // Email & contact form enabled
51 await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort } }) 52 await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort } })
52 53
53 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: 'badEmail' })) 54 await sendContactForm(immutableAssign(defaultBody, {
54 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: 'badEmail@' })) 55 url: server.url,
55 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: undefined })) 56 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
57 fromEmail: 'badEmail'
58 }))
59 await sendContactForm(immutableAssign(defaultBody, {
60 url: server.url,
61 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
62 fromEmail: 'badEmail@'
63 }))
64 await sendContactForm(immutableAssign(defaultBody, {
65 url: server.url,
66 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
67 fromEmail: undefined
68 }))
56 }) 69 })
57 70
58 it('Should not accept a contact form if from name is invalid', async function () { 71 it('Should not accept a contact form if from name is invalid', async function () {
59 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: 'name'.repeat(100) })) 72 await sendContactForm(immutableAssign(defaultBody, {
60 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: '' })) 73 url: server.url,
61 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: undefined })) 74 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
75 fromName: 'name'.repeat(100)
76 }))
77 await sendContactForm(immutableAssign(defaultBody, {
78 url: server.url,
79 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
80 fromName: ''
81 }))
82 await sendContactForm(immutableAssign(defaultBody, {
83 url: server.url,
84 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
85 fromName: undefined
86 }))
62 }) 87 })
63 88
64 it('Should not accept a contact form if body is invalid', async function () { 89 it('Should not accept a contact form if body is invalid', async function () {
65 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: 'body'.repeat(5000) })) 90 await sendContactForm(immutableAssign(defaultBody, {
66 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: 'a' })) 91 url: server.url,
67 await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: undefined })) 92 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
93 body: 'body'.repeat(5000)
94 }))
95 await sendContactForm(immutableAssign(defaultBody, {
96 url: server.url,
97 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
98 body: 'a'
99 }))
100 await sendContactForm(immutableAssign(defaultBody, {
101 url: server.url,
102 expectedStatus: HttpStatusCode.BAD_REQUEST_400,
103 body: undefined
104 }))
68 }) 105 })
69 106
70 it('Should accept a contact form with the correct parameters', async function () { 107 it('Should accept a contact form with the correct parameters', async function () {
diff --git a/server/tests/api/check-params/users.ts b/server/tests/api/check-params/users.ts
index 21ace36aa..0a13f5b67 100644
--- a/server/tests/api/check-params/users.ts
+++ b/server/tests/api/check-params/users.ts
@@ -1102,7 +1102,7 @@ describe('Test users API validators', function () {
1102 videoQuota: 42 1102 videoQuota: 42
1103 }) 1103 })
1104 1104
1105 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403) 1105 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
1106 }) 1106 })
1107 1107
1108 it('Should fail with a registered user having too many videos', async function () { 1108 it('Should fail with a registered user having too many videos', async function () {
@@ -1120,7 +1120,7 @@ describe('Test users API validators', function () {
1120 await uploadVideo(server.url, userAccessToken, videoAttributes) 1120 await uploadVideo(server.url, userAccessToken, videoAttributes)
1121 await uploadVideo(server.url, userAccessToken, videoAttributes) 1121 await uploadVideo(server.url, userAccessToken, videoAttributes)
1122 await uploadVideo(server.url, userAccessToken, videoAttributes) 1122 await uploadVideo(server.url, userAccessToken, videoAttributes)
1123 await uploadVideo(server.url, userAccessToken, videoAttributes, HttpStatusCode.FORBIDDEN_403) 1123 await uploadVideo(server.url, userAccessToken, videoAttributes, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
1124 }) 1124 })
1125 1125
1126 it('Should fail to import with HTTP/Torrent/magnet', async function () { 1126 it('Should fail to import with HTTP/Torrent/magnet', async function () {
@@ -1151,7 +1151,7 @@ describe('Test users API validators', function () {
1151 }) 1151 })
1152 1152
1153 describe('When having a daily video quota', function () { 1153 describe('When having a daily video quota', function () {
1154 it('Should fail with a user having too many videos', async function () { 1154 it('Should fail with a user having too many videos daily', async function () {
1155 await updateUser({ 1155 await updateUser({
1156 url: server.url, 1156 url: server.url,
1157 userId: rootId, 1157 userId: rootId,
@@ -1159,7 +1159,7 @@ describe('Test users API validators', function () {
1159 videoQuotaDaily: 42 1159 videoQuotaDaily: 42
1160 }) 1160 })
1161 1161
1162 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403) 1162 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
1163 }) 1163 })
1164 }) 1164 })
1165 1165
@@ -1173,7 +1173,7 @@ describe('Test users API validators', function () {
1173 videoQuotaDaily: 1024 * 1024 * 1024 1173 videoQuotaDaily: 1024 * 1024 * 1024
1174 }) 1174 })
1175 1175
1176 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403) 1176 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
1177 }) 1177 })
1178 1178
1179 it('Should fail if exceeding daily quota', async function () { 1179 it('Should fail if exceeding daily quota', async function () {
@@ -1185,7 +1185,7 @@ describe('Test users API validators', function () {
1185 videoQuotaDaily: 42 1185 videoQuotaDaily: 42
1186 }) 1186 })
1187 1187
1188 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403) 1188 await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
1189 }) 1189 })
1190 }) 1190 })
1191 1191
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts
index d60546917..5faba82c4 100644
--- a/server/tests/api/check-params/videos.ts
+++ b/server/tests/api/check-params/videos.ts
@@ -348,12 +348,26 @@ describe('Test videos API validator', function () {
348 let attaches = { 348 let attaches = {
349 videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short_fake.webm') 349 videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short_fake.webm')
350 } 350 }
351 await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 351 await makeUploadRequest({
352 url: server.url,
353 path: path + '/upload',
354 token: server.accessToken,
355 fields,
356 attaches,
357 statusCodeExpected: HttpStatusCode.UNPROCESSABLE_ENTITY_422
358 })
352 359
353 attaches = { 360 attaches = {
354 videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mkv') 361 videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mkv')
355 } 362 }
356 await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches }) 363 await makeUploadRequest({
364 url: server.url,
365 path: path + '/upload',
366 token: server.accessToken,
367 fields,
368 attaches,
369 statusCodeExpected: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415
370 })
357 }) 371 })
358 372
359 it('Should fail with an incorrect thumbnail file', async function () { 373 it('Should fail with an incorrect thumbnail file', async function () {
diff --git a/server/tests/api/live/live-save-replay.ts b/server/tests/api/live/live-save-replay.ts
index 3ffa0c093..e300ec345 100644
--- a/server/tests/api/live/live-save-replay.ts
+++ b/server/tests/api/live/live-save-replay.ts
@@ -25,6 +25,7 @@ import {
25 waitJobs, 25 waitJobs,
26 waitUntilLiveStarts 26 waitUntilLiveStarts
27} from '../../../../shared/extra-utils' 27} from '../../../../shared/extra-utils'
28import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
28 29
29const expect = chai.expect 30const expect = chai.expect
30 31
@@ -118,7 +119,7 @@ describe('Save replay setting', function () {
118 119
119 await waitJobs(servers) 120 await waitJobs(servers)
120 121
121 await checkVideosExist(liveVideoUUID, false, 200) 122 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
122 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE) 123 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
123 }) 124 })
124 125
@@ -130,7 +131,7 @@ describe('Save replay setting', function () {
130 131
131 await waitJobs(servers) 132 await waitJobs(servers)
132 133
133 await checkVideosExist(liveVideoUUID, true, 200) 134 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
134 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED) 135 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
135 }) 136 })
136 137
@@ -142,7 +143,7 @@ describe('Save replay setting', function () {
142 await waitJobs(servers) 143 await waitJobs(servers)
143 144
144 // Live still exist, but cannot be played anymore 145 // Live still exist, but cannot be played anymore
145 await checkVideosExist(liveVideoUUID, false, 200) 146 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
146 await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED) 147 await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
147 148
148 // No resolutions saved since we did not save replay 149 // No resolutions saved since we did not save replay
@@ -158,7 +159,7 @@ describe('Save replay setting', function () {
158 await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) 159 await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
159 160
160 await waitJobs(servers) 161 await waitJobs(servers)
161 await checkVideosExist(liveVideoUUID, true, 200) 162 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
162 163
163 await Promise.all([ 164 await Promise.all([
164 addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true), 165 addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
@@ -169,8 +170,8 @@ describe('Save replay setting', function () {
169 170
170 await checkVideosExist(liveVideoUUID, false) 171 await checkVideosExist(liveVideoUUID, false)
171 172
172 await getVideo(servers[0].url, liveVideoUUID, 401) 173 await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
173 await getVideo(servers[1].url, liveVideoUUID, 404) 174 await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
174 175
175 await checkLiveCleanup(servers[0], liveVideoUUID, []) 176 await checkLiveCleanup(servers[0], liveVideoUUID, [])
176 }) 177 })
@@ -184,7 +185,7 @@ describe('Save replay setting', function () {
184 await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) 185 await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
185 186
186 await waitJobs(servers) 187 await waitJobs(servers)
187 await checkVideosExist(liveVideoUUID, true, 200) 188 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
188 189
189 await Promise.all([ 190 await Promise.all([
190 testFfmpegStreamError(ffmpegCommand, true), 191 testFfmpegStreamError(ffmpegCommand, true),
@@ -193,7 +194,7 @@ describe('Save replay setting', function () {
193 194
194 await waitJobs(servers) 195 await waitJobs(servers)
195 196
196 await checkVideosExist(liveVideoUUID, false, 404) 197 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
197 await checkLiveCleanup(servers[0], liveVideoUUID, []) 198 await checkLiveCleanup(servers[0], liveVideoUUID, [])
198 }) 199 })
199 }) 200 })
@@ -207,7 +208,7 @@ describe('Save replay setting', function () {
207 208
208 await waitJobs(servers) 209 await waitJobs(servers)
209 210
210 await checkVideosExist(liveVideoUUID, false, 200) 211 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
211 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE) 212 await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
212 }) 213 })
213 214
@@ -219,7 +220,7 @@ describe('Save replay setting', function () {
219 220
220 await waitJobs(servers) 221 await waitJobs(servers)
221 222
222 await checkVideosExist(liveVideoUUID, true, 200) 223 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
223 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED) 224 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
224 }) 225 })
225 226
@@ -231,7 +232,7 @@ describe('Save replay setting', function () {
231 await waitJobs(servers) 232 await waitJobs(servers)
232 233
233 // Live has been transcoded 234 // Live has been transcoded
234 await checkVideosExist(liveVideoUUID, true, 200) 235 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
235 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED) 236 await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
236 }) 237 })
237 238
@@ -261,7 +262,7 @@ describe('Save replay setting', function () {
261 await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) 262 await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
262 263
263 await waitJobs(servers) 264 await waitJobs(servers)
264 await checkVideosExist(liveVideoUUID, true, 200) 265 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
265 266
266 await Promise.all([ 267 await Promise.all([
267 addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true), 268 addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
@@ -272,8 +273,8 @@ describe('Save replay setting', function () {
272 273
273 await checkVideosExist(liveVideoUUID, false) 274 await checkVideosExist(liveVideoUUID, false)
274 275
275 await getVideo(servers[0].url, liveVideoUUID, 401) 276 await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
276 await getVideo(servers[1].url, liveVideoUUID, 404) 277 await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
277 278
278 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ]) 279 await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
279 }) 280 })
@@ -287,7 +288,7 @@ describe('Save replay setting', function () {
287 await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID) 288 await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
288 289
289 await waitJobs(servers) 290 await waitJobs(servers)
290 await checkVideosExist(liveVideoUUID, true, 200) 291 await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
291 292
292 await Promise.all([ 293 await Promise.all([
293 removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID), 294 removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID),
@@ -296,7 +297,7 @@ describe('Save replay setting', function () {
296 297
297 await waitJobs(servers) 298 await waitJobs(servers)
298 299
299 await checkVideosExist(liveVideoUUID, false, 404) 300 await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
300 await checkLiveCleanup(servers[0], liveVideoUUID, []) 301 await checkLiveCleanup(servers[0], liveVideoUUID, [])
301 }) 302 })
302 }) 303 })
diff --git a/server/tests/api/live/live.ts b/server/tests/api/live/live.ts
index d784650b5..fdfc6105f 100644
--- a/server/tests/api/live/live.ts
+++ b/server/tests/api/live/live.ts
@@ -44,6 +44,7 @@ import {
44 waitUntilLiveStarts, 44 waitUntilLiveStarts,
45 waitUntilLog 45 waitUntilLog
46} from '../../../../shared/extra-utils' 46} from '../../../../shared/extra-utils'
47import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
47 48
48const expect = chai.expect 49const expect = chai.expect
49 50
@@ -164,8 +165,8 @@ describe('Test live', function () {
164 expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED) 165 expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED)
165 expect(video.nsfw).to.be.true 166 expect(video.nsfw).to.be.true
166 167
167 await makeRawRequest(server.url + video.thumbnailPath, 200) 168 await makeRawRequest(server.url + video.thumbnailPath, HttpStatusCode.OK_200)
168 await makeRawRequest(server.url + video.previewPath, 200) 169 await makeRawRequest(server.url + video.previewPath, HttpStatusCode.OK_200)
169 } 170 }
170 }) 171 })
171 172
@@ -179,7 +180,7 @@ describe('Test live', function () {
179 }) 180 })
180 181
181 it('Should not be able to update a live of another server', async function () { 182 it('Should not be able to update a live of another server', async function () {
182 await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, 403) 183 await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, HttpStatusCode.FORBIDDEN_403)
183 }) 184 })
184 185
185 it('Should update the live', async function () { 186 it('Should update the live', async function () {
@@ -215,8 +216,8 @@ describe('Test live', function () {
215 216
216 it('Should have the live deleted', async function () { 217 it('Should have the live deleted', async function () {
217 for (const server of servers) { 218 for (const server of servers) {
218 await getVideo(server.url, liveVideoUUID, 404) 219 await getVideo(server.url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
219 await getLive(server.url, server.accessToken, liveVideoUUID, 404) 220 await getLive(server.url, server.accessToken, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
220 } 221 }
221 }) 222 })
222 }) 223 })
@@ -430,8 +431,8 @@ describe('Test live', function () {
430 expect(video.files).to.have.lengthOf(0) 431 expect(video.files).to.have.lengthOf(0)
431 432
432 const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS) 433 const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS)
433 await makeRawRequest(hlsPlaylist.playlistUrl, 200) 434 await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200)
434 await makeRawRequest(hlsPlaylist.segmentsSha256Url, 200) 435 await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200)
435 436
436 expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length) 437 expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length)
437 438
@@ -455,8 +456,8 @@ describe('Test live', function () {
455 456
456 expect(probe.format.bit_rate).to.be.below(bitrateLimits[videoStream.height]) 457 expect(probe.format.bit_rate).to.be.below(bitrateLimits[videoStream.height])
457 458
458 await makeRawRequest(file.torrentUrl, 200) 459 await makeRawRequest(file.torrentUrl, HttpStatusCode.OK_200)
459 await makeRawRequest(file.fileUrl, 200) 460 await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200)
460 } 461 }
461 } 462 }
462 }) 463 })
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
index eb51d8909..a505b8ede 100644
--- a/server/tests/api/server/config.ts
+++ b/server/tests/api/server/config.ts
@@ -21,6 +21,7 @@ import {
21 uploadVideo 21 uploadVideo
22} from '../../../../shared/extra-utils' 22} from '../../../../shared/extra-utils'
23import { ServerConfig } from '../../../../shared/models' 23import { ServerConfig } from '../../../../shared/models'
24import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
24 25
25const expect = chai.expect 26const expect = chai.expect
26 27
@@ -237,8 +238,8 @@ describe('Test config', function () {
237 expect(data.video.file.extensions).to.contain('.webm') 238 expect(data.video.file.extensions).to.contain('.webm')
238 expect(data.video.file.extensions).to.contain('.ogv') 239 expect(data.video.file.extensions).to.contain('.ogv')
239 240
240 await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, 400) 241 await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
241 await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, 400) 242 await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
242 243
243 expect(data.contactForm.enabled).to.be.true 244 expect(data.contactForm.enabled).to.be.true
244 }) 245 })
@@ -427,8 +428,8 @@ describe('Test config', function () {
427 expect(data.video.file.extensions).to.contain('.ogg') 428 expect(data.video.file.extensions).to.contain('.ogg')
428 expect(data.video.file.extensions).to.contain('.flac') 429 expect(data.video.file.extensions).to.contain('.flac')
429 430
430 await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, 200) 431 await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, HttpStatusCode.OK_200)
431 await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, 200) 432 await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, HttpStatusCode.OK_200)
432 }) 433 })
433 434
434 it('Should have the configuration updated after a restart', async function () { 435 it('Should have the configuration updated after a restart', async function () {
diff --git a/server/tests/api/server/contact-form.ts b/server/tests/api/server/contact-form.ts
index c0965d9d1..9b4af1915 100644
--- a/server/tests/api/server/contact-form.ts
+++ b/server/tests/api/server/contact-form.ts
@@ -6,6 +6,7 @@ import { cleanupTests, flushAndRunServer, ServerInfo, setAccessTokensToServers,
6import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email' 6import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
7import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 7import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
8import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form' 8import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form'
9import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
9 10
10const expect = chai.expect 11const expect = chai.expect
11 12
@@ -67,7 +68,7 @@ describe('Test contact form', function () {
67 body: 'my super message', 68 body: 'my super message',
68 fromName: 'Super toto', 69 fromName: 'Super toto',
69 subject: 'my subject', 70 subject: 'my subject',
70 expectedStatus: 403 71 expectedStatus: HttpStatusCode.FORBIDDEN_403
71 }) 72 })
72 }) 73 })
73 74
diff --git a/server/tests/api/server/email.ts b/server/tests/api/server/email.ts
index 53f96a94f..17d9e902c 100644
--- a/server/tests/api/server/email.ts
+++ b/server/tests/api/server/email.ts
@@ -22,6 +22,7 @@ import {
22} from '../../../../shared/extra-utils' 22} from '../../../../shared/extra-utils'
23import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email' 23import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
24import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 24import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
25import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
25 26
26const expect = chai.expect 27const expect = chai.expect
27 28
@@ -116,7 +117,7 @@ describe('Test emails', function () {
116 }) 117 })
117 118
118 it('Should not reset the password with an invalid verification string', async function () { 119 it('Should not reset the password with an invalid verification string', async function () {
119 await resetPassword(server.url, userId, verificationString + 'b', 'super_password2', 403) 120 await resetPassword(server.url, userId, verificationString + 'b', 'super_password2', HttpStatusCode.FORBIDDEN_403)
120 }) 121 })
121 122
122 it('Should reset the password', async function () { 123 it('Should reset the password', async function () {
@@ -124,7 +125,7 @@ describe('Test emails', function () {
124 }) 125 })
125 126
126 it('Should not reset the password with the same verification string', async function () { 127 it('Should not reset the password with the same verification string', async function () {
127 await resetPassword(server.url, userId, verificationString, 'super_password3', 403) 128 await resetPassword(server.url, userId, verificationString, 'super_password3', HttpStatusCode.FORBIDDEN_403)
128 }) 129 })
129 130
130 it('Should login with this new password', async function () { 131 it('Should login with this new password', async function () {
@@ -169,7 +170,7 @@ describe('Test emails', function () {
169 }) 170 })
170 171
171 it('Should not reset the password with an invalid verification string', async function () { 172 it('Should not reset the password with an invalid verification string', async function () {
172 await resetPassword(server.url, userId2, verificationString2 + 'c', 'newly_created_password', 403) 173 await resetPassword(server.url, userId2, verificationString2 + 'c', 'newly_created_password', HttpStatusCode.FORBIDDEN_403)
173 }) 174 })
174 175
175 it('Should reset the password', async function () { 176 it('Should reset the password', async function () {
@@ -210,7 +211,7 @@ describe('Test emails', function () {
210 this.timeout(10000) 211 this.timeout(10000)
211 212
212 const reason = 'my super bad reason' 213 const reason = 'my super bad reason'
213 await blockUser(server.url, userId, server.accessToken, 204, reason) 214 await blockUser(server.url, userId, server.accessToken, HttpStatusCode.NO_CONTENT_204, reason)
214 215
215 await waitJobs(server) 216 await waitJobs(server)
216 expect(emails).to.have.lengthOf(4) 217 expect(emails).to.have.lengthOf(4)
@@ -228,7 +229,7 @@ describe('Test emails', function () {
228 it('Should send the notification email when unblocking a user', async function () { 229 it('Should send the notification email when unblocking a user', async function () {
229 this.timeout(10000) 230 this.timeout(10000)
230 231
231 await unblockUser(server.url, userId, server.accessToken, 204) 232 await unblockUser(server.url, userId, server.accessToken, HttpStatusCode.NO_CONTENT_204)
232 233
233 await waitJobs(server) 234 await waitJobs(server)
234 expect(emails).to.have.lengthOf(5) 235 expect(emails).to.have.lengthOf(5)
@@ -317,7 +318,7 @@ describe('Test emails', function () {
317 }) 318 })
318 319
319 it('Should not verify the email with an invalid verification string', async function () { 320 it('Should not verify the email with an invalid verification string', async function () {
320 await verifyEmail(server.url, userId, verificationString + 'b', false, 403) 321 await verifyEmail(server.url, userId, verificationString + 'b', false, HttpStatusCode.FORBIDDEN_403)
321 }) 322 })
322 323
323 it('Should verify the email', async function () { 324 it('Should verify the email', async function () {
diff --git a/server/tests/api/server/follow-constraints.ts b/server/tests/api/server/follow-constraints.ts
index a73440286..0846b04f4 100644
--- a/server/tests/api/server/follow-constraints.ts
+++ b/server/tests/api/server/follow-constraints.ts
@@ -17,6 +17,7 @@ import {
17import { unfollow } from '../../../../shared/extra-utils/server/follows' 17import { unfollow } from '../../../../shared/extra-utils/server/follows'
18import { userLogin } from '../../../../shared/extra-utils/users/login' 18import { userLogin } from '../../../../shared/extra-utils/users/login'
19import { createUser } from '../../../../shared/extra-utils/users/users' 19import { createUser } from '../../../../shared/extra-utils/users/users'
20import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
20 21
21const expect = chai.expect 22const expect = chai.expect
22 23
@@ -58,11 +59,11 @@ describe('Test follow constraints', function () {
58 describe('With an unlogged user', function () { 59 describe('With an unlogged user', function () {
59 60
60 it('Should get the local video', async function () { 61 it('Should get the local video', async function () {
61 await getVideo(servers[0].url, video1UUID, 200) 62 await getVideo(servers[0].url, video1UUID, HttpStatusCode.OK_200)
62 }) 63 })
63 64
64 it('Should get the remote video', async function () { 65 it('Should get the remote video', async function () {
65 await getVideo(servers[0].url, video2UUID, 200) 66 await getVideo(servers[0].url, video2UUID, HttpStatusCode.OK_200)
66 }) 67 })
67 68
68 it('Should list local account videos', async function () { 69 it('Should list local account videos', async function () {
@@ -98,11 +99,11 @@ describe('Test follow constraints', function () {
98 99
99 describe('With a logged user', function () { 100 describe('With a logged user', function () {
100 it('Should get the local video', async function () { 101 it('Should get the local video', async function () {
101 await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, 200) 102 await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, HttpStatusCode.OK_200)
102 }) 103 })
103 104
104 it('Should get the remote video', async function () { 105 it('Should get the remote video', async function () {
105 await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, 200) 106 await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, HttpStatusCode.OK_200)
106 }) 107 })
107 108
108 it('Should list local account videos', async function () { 109 it('Should list local account videos', async function () {
@@ -148,11 +149,11 @@ describe('Test follow constraints', function () {
148 describe('With an unlogged user', function () { 149 describe('With an unlogged user', function () {
149 150
150 it('Should get the local video', async function () { 151 it('Should get the local video', async function () {
151 await getVideo(servers[0].url, video1UUID, 200) 152 await getVideo(servers[0].url, video1UUID, HttpStatusCode.OK_200)
152 }) 153 })
153 154
154 it('Should not get the remote video', async function () { 155 it('Should not get the remote video', async function () {
155 await getVideo(servers[0].url, video2UUID, 403) 156 await getVideo(servers[0].url, video2UUID, HttpStatusCode.FORBIDDEN_403)
156 }) 157 })
157 158
158 it('Should list local account videos', async function () { 159 it('Should list local account videos', async function () {
@@ -188,11 +189,11 @@ describe('Test follow constraints', function () {
188 189
189 describe('With a logged user', function () { 190 describe('With a logged user', function () {
190 it('Should get the local video', async function () { 191 it('Should get the local video', async function () {
191 await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, 200) 192 await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, HttpStatusCode.OK_200)
192 }) 193 })
193 194
194 it('Should get the remote video', async function () { 195 it('Should get the remote video', async function () {
195 await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, 200) 196 await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, HttpStatusCode.OK_200)
196 }) 197 })
197 198
198 it('Should list local account videos', async function () { 199 it('Should list local account videos', async function () {
diff --git a/server/tests/api/server/handle-down.ts b/server/tests/api/server/handle-down.ts
index 2cf6e15ad..043754e70 100644
--- a/server/tests/api/server/handle-down.ts
+++ b/server/tests/api/server/handle-down.ts
@@ -33,6 +33,7 @@ import {
33 getVideoCommentThreads, 33 getVideoCommentThreads,
34 getVideoThreadComments 34 getVideoThreadComments
35} from '../../../../shared/extra-utils/videos/video-comments' 35} from '../../../../shared/extra-utils/videos/video-comments'
36import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
36 37
37const expect = chai.expect 38const expect = chai.expect
38 39
@@ -352,7 +353,7 @@ describe('Test handle downs', function () {
352 } 353 }
353 354
354 for (const id of videoIdsServer1) { 355 for (const id of videoIdsServer1) {
355 await getVideo(servers[1].url, id, 403) 356 await getVideo(servers[1].url, id, HttpStatusCode.FORBIDDEN_403)
356 } 357 }
357 }) 358 })
358 359
diff --git a/server/tests/api/server/no-client.ts b/server/tests/api/server/no-client.ts
index d0450aba0..d589f51f3 100644
--- a/server/tests/api/server/no-client.ts
+++ b/server/tests/api/server/no-client.ts
@@ -2,6 +2,7 @@ import 'mocha'
2import * as request from 'supertest' 2import * as request from 'supertest'
3import { ServerInfo } from '../../../../shared/extra-utils' 3import { ServerInfo } from '../../../../shared/extra-utils'
4import { cleanupTests, flushAndRunServer } from '../../../../shared/extra-utils/server/servers' 4import { cleanupTests, flushAndRunServer } from '../../../../shared/extra-utils/server/servers'
5import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
5 6
6describe('Start and stop server without web client routes', function () { 7describe('Start and stop server without web client routes', function () {
7 let server: ServerInfo 8 let server: ServerInfo
@@ -16,7 +17,7 @@ describe('Start and stop server without web client routes', function () {
16 const req = request(server.url) 17 const req = request(server.url)
17 .get('/') 18 .get('/')
18 19
19 return req.expect(404) 20 return req.expect(HttpStatusCode.NOT_FOUND_404)
20 }) 21 })
21 22
22 after(async function () { 23 after(async function () {
diff --git a/server/tests/api/server/reverse-proxy.ts b/server/tests/api/server/reverse-proxy.ts
index d0d79c4f6..17d1ee4a5 100644
--- a/server/tests/api/server/reverse-proxy.ts
+++ b/server/tests/api/server/reverse-proxy.ts
@@ -4,6 +4,7 @@ import 'mocha'
4import * as chai from 'chai' 4import * as chai from 'chai'
5import { cleanupTests, getVideo, registerUser, uploadVideo, userLogin, viewVideo, wait } from '../../../../shared/extra-utils' 5import { cleanupTests, getVideo, registerUser, uploadVideo, userLogin, viewVideo, wait } from '../../../../shared/extra-utils'
6import { flushAndRunServer, setAccessTokensToServers } from '../../../../shared/extra-utils/index' 6import { flushAndRunServer, setAccessTokensToServers } from '../../../../shared/extra-utils/index'
7import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
7 8
8const expect = chai.expect 9const expect = chai.expect
9 10
@@ -56,8 +57,8 @@ describe('Test application behind a reverse proxy', function () {
56 it('Should view a video 2 times with the X-Forwarded-For header set', async function () { 57 it('Should view a video 2 times with the X-Forwarded-For header set', async function () {
57 this.timeout(20000) 58 this.timeout(20000)
58 59
59 await viewVideo(server.url, videoId, 204, '0.0.0.1,127.0.0.1') 60 await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.1,127.0.0.1')
60 await viewVideo(server.url, videoId, 204, '0.0.0.2,127.0.0.1') 61 await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.2,127.0.0.1')
61 62
62 // Wait the repeatable job 63 // Wait the repeatable job
63 await wait(8000) 64 await wait(8000)
@@ -69,8 +70,8 @@ describe('Test application behind a reverse proxy', function () {
69 it('Should view a video only once with the same client IP in the X-Forwarded-For header', async function () { 70 it('Should view a video only once with the same client IP in the X-Forwarded-For header', async function () {
70 this.timeout(20000) 71 this.timeout(20000)
71 72
72 await viewVideo(server.url, videoId, 204, '0.0.0.4,0.0.0.3,::ffff:127.0.0.1') 73 await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.4,0.0.0.3,::ffff:127.0.0.1')
73 await viewVideo(server.url, videoId, 204, '0.0.0.5,0.0.0.3,127.0.0.1') 74 await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.5,0.0.0.3,127.0.0.1')
74 75
75 // Wait the repeatable job 76 // Wait the repeatable job
76 await wait(8000) 77 await wait(8000)
@@ -82,8 +83,8 @@ describe('Test application behind a reverse proxy', function () {
82 it('Should view a video two times with a different client IP in the X-Forwarded-For header', async function () { 83 it('Should view a video two times with a different client IP in the X-Forwarded-For header', async function () {
83 this.timeout(20000) 84 this.timeout(20000)
84 85
85 await viewVideo(server.url, videoId, 204, '0.0.0.8,0.0.0.6,127.0.0.1') 86 await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.8,0.0.0.6,127.0.0.1')
86 await viewVideo(server.url, videoId, 204, '0.0.0.8,0.0.0.7,127.0.0.1') 87 await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.8,0.0.0.7,127.0.0.1')
87 88
88 // Wait the repeatable job 89 // Wait the repeatable job
89 await wait(8000) 90 await wait(8000)
@@ -96,10 +97,10 @@ describe('Test application behind a reverse proxy', function () {
96 const user = { username: 'root', password: 'fail' } 97 const user = { username: 'root', password: 'fail' }
97 98
98 for (let i = 0; i < 19; i++) { 99 for (let i = 0; i < 19; i++) {
99 await userLogin(server, user, 400) 100 await userLogin(server, user, HttpStatusCode.BAD_REQUEST_400)
100 } 101 }
101 102
102 await userLogin(server, user, 429) 103 await userLogin(server, user, HttpStatusCode.TOO_MANY_REQUESTS_429)
103 }) 104 })
104 105
105 it('Should rate limit signup', async function () { 106 it('Should rate limit signup', async function () {
@@ -111,7 +112,7 @@ describe('Test application behind a reverse proxy', function () {
111 } 112 }
112 } 113 }
113 114
114 await registerUser(server.url, 'test42', 'password', 429) 115 await registerUser(server.url, 'test42', 'password', HttpStatusCode.TOO_MANY_REQUESTS_429)
115 }) 116 })
116 117
117 it('Should not rate limit failed signup', async function () { 118 it('Should not rate limit failed signup', async function () {
@@ -120,10 +121,10 @@ describe('Test application behind a reverse proxy', function () {
120 await wait(7000) 121 await wait(7000)
121 122
122 for (let i = 0; i < 3; i++) { 123 for (let i = 0; i < 3; i++) {
123 await registerUser(server.url, 'test' + i, 'password', 409) 124 await registerUser(server.url, 'test' + i, 'password', HttpStatusCode.CONFLICT_409)
124 } 125 }
125 126
126 await registerUser(server.url, 'test43', 'password', 204) 127 await registerUser(server.url, 'test43', 'password', HttpStatusCode.NO_CONTENT_204)
127 128
128 }) 129 })
129 130
@@ -140,7 +141,7 @@ describe('Test application behind a reverse proxy', function () {
140 } 141 }
141 } 142 }
142 143
143 await getVideo(server.url, videoId, 429) 144 await getVideo(server.url, videoId, HttpStatusCode.TOO_MANY_REQUESTS_429)
144 }) 145 })
145 146
146 after(async function () { 147 after(async function () {
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts
index fdd5e33f3..f754df04e 100644
--- a/server/tests/api/videos/multiple-servers.ts
+++ b/server/tests/api/videos/multiple-servers.ts
@@ -41,6 +41,7 @@ import {
41 findCommentId 41 findCommentId
42} from '../../../../shared/extra-utils/videos/video-comments' 42} from '../../../../shared/extra-utils/videos/video-comments'
43import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 43import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
44import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
44 45
45const expect = chai.expect 46const expect = chai.expect
46 47
@@ -999,7 +1000,7 @@ describe('Test multiple servers', function () {
999 expect(res.body.downloadEnabled).to.be.false 1000 expect(res.body.downloadEnabled).to.be.false
1000 1001
1001 const text = 'my super forbidden comment' 1002 const text = 'my super forbidden comment'
1002 await addVideoCommentThread(server.url, server.accessToken, videoUUID, text, 409) 1003 await addVideoCommentThread(server.url, server.accessToken, videoUUID, text, HttpStatusCode.CONFLICT_409)
1003 } 1004 }
1004 }) 1005 })
1005 }) 1006 })
@@ -1021,7 +1022,7 @@ describe('Test multiple servers', function () {
1021 const filePath = join(__dirname, '..', '..', 'fixtures', 'video_short.webm') 1022 const filePath = join(__dirname, '..', '..', 'fixtures', 'video_short.webm')
1022 1023
1023 await req.attach('videofile', filePath) 1024 await req.attach('videofile', filePath)
1024 .expect(200) 1025 .expect(HttpStatusCode.OK_200)
1025 1026
1026 await waitJobs(servers) 1027 await waitJobs(servers)
1027 1028
diff --git a/server/tests/api/videos/video-change-ownership.ts b/server/tests/api/videos/video-change-ownership.ts
index dee6575b9..fad4c8b1f 100644
--- a/server/tests/api/videos/video-change-ownership.ts
+++ b/server/tests/api/videos/video-change-ownership.ts
@@ -23,6 +23,7 @@ import {
23import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 23import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
24import { User } from '../../../../shared/models/users' 24import { User } from '../../../../shared/models/users'
25import { VideoDetails } from '../../../../shared/models/videos' 25import { VideoDetails } from '../../../../shared/models/videos'
26import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
26 27
27const expect = chai.expect 28const expect = chai.expect
28 29
@@ -140,7 +141,7 @@ describe('Test video change ownership - nominal', function () {
140 it('Should not be possible to refuse the change of ownership from first user', async function () { 141 it('Should not be possible to refuse the change of ownership from first user', async function () {
141 this.timeout(10000) 142 this.timeout(10000)
142 143
143 await refuseChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, 403) 144 await refuseChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, HttpStatusCode.FORBIDDEN_403)
144 }) 145 })
145 146
146 it('Should be possible to refuse the change of ownership from second user', async function () { 147 it('Should be possible to refuse the change of ownership from second user', async function () {
@@ -177,7 +178,7 @@ describe('Test video change ownership - nominal', function () {
177 const secondUserInformationResponse = await getMyUserInformation(servers[0].url, secondUserAccessToken) 178 const secondUserInformationResponse = await getMyUserInformation(servers[0].url, secondUserAccessToken)
178 const secondUserInformation: User = secondUserInformationResponse.body 179 const secondUserInformation: User = secondUserInformationResponse.body
179 const channelId = secondUserInformation.videoChannels[0].id 180 const channelId = secondUserInformation.videoChannels[0].id
180 await acceptChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, channelId, 403) 181 await acceptChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, channelId, HttpStatusCode.FORBIDDEN_403)
181 }) 182 })
182 183
183 it('Should be possible to accept the change of ownership from second user', async function () { 184 it('Should be possible to accept the change of ownership from second user', async function () {
@@ -294,7 +295,14 @@ describe('Test video change ownership - quota too small', function () {
294 const secondUserInformationResponse = await getMyUserInformation(server.url, secondUserAccessToken) 295 const secondUserInformationResponse = await getMyUserInformation(server.url, secondUserAccessToken)
295 const secondUserInformation: User = secondUserInformationResponse.body 296 const secondUserInformation: User = secondUserInformationResponse.body
296 const channelId = secondUserInformation.videoChannels[0].id 297 const channelId = secondUserInformation.videoChannels[0].id
297 await acceptChangeOwnership(server.url, secondUserAccessToken, lastRequestChangeOwnershipId, channelId, 403) 298
299 await acceptChangeOwnership(
300 server.url,
301 secondUserAccessToken,
302 lastRequestChangeOwnershipId,
303 channelId,
304 HttpStatusCode.PAYLOAD_TOO_LARGE_413
305 )
298 }) 306 })
299 307
300 after(async function () { 308 after(async function () {
diff --git a/server/tests/api/videos/video-hls.ts b/server/tests/api/videos/video-hls.ts
index 3a65cc1d2..f3dbbb114 100644
--- a/server/tests/api/videos/video-hls.ts
+++ b/server/tests/api/videos/video-hls.ts
@@ -26,6 +26,7 @@ import {
26import { VideoDetails } from '../../../../shared/models/videos' 26import { VideoDetails } from '../../../../shared/models/videos'
27import { VideoStreamingPlaylistType } from '../../../../shared/models/videos/video-streaming-playlist.type' 27import { VideoStreamingPlaylistType } from '../../../../shared/models/videos/video-streaming-playlist.type'
28import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants' 28import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants'
29import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
29 30
30const expect = chai.expect 31const expect = chai.expect
31 32
@@ -57,8 +58,8 @@ async function checkHlsPlaylist (servers: ServerInfo[], videoUUID: string, hlsOn
57 ) 58 )
58 expect(file.resolution.label).to.equal(resolution + 'p') 59 expect(file.resolution.label).to.equal(resolution + 'p')
59 60
60 await makeRawRequest(file.torrentUrl, 200) 61 await makeRawRequest(file.torrentUrl, HttpStatusCode.OK_200)
61 await makeRawRequest(file.fileUrl, 200) 62 await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200)
62 63
63 const torrent = await webtorrentAdd(file.magnetUri, true) 64 const torrent = await webtorrentAdd(file.magnetUri, true)
64 expect(torrent.files).to.be.an('array') 65 expect(torrent.files).to.be.an('array')
@@ -144,8 +145,8 @@ describe('Test HLS videos', function () {
144 await waitJobs(servers) 145 await waitJobs(servers)
145 146
146 for (const server of servers) { 147 for (const server of servers) {
147 await getVideo(server.url, videoUUID, 404) 148 await getVideo(server.url, videoUUID, HttpStatusCode.NOT_FOUND_404)
148 await getVideo(server.url, videoAudioUUID, 404) 149 await getVideo(server.url, videoAudioUUID, HttpStatusCode.NOT_FOUND_404)
149 } 150 }
150 }) 151 })
151 152
diff --git a/server/tests/api/videos/video-playlists.ts b/server/tests/api/videos/video-playlists.ts
index 7d1215990..0a96ea9a0 100644
--- a/server/tests/api/videos/video-playlists.ts
+++ b/server/tests/api/videos/video-playlists.ts
@@ -61,6 +61,7 @@ import {
61 removeServerFromAccountBlocklist, 61 removeServerFromAccountBlocklist,
62 removeServerFromServerBlocklist 62 removeServerFromServerBlocklist
63} from '../../../../shared/extra-utils/users/blocklist' 63} from '../../../../shared/extra-utils/users/blocklist'
64import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
64 65
65const expect = chai.expect 66const expect = chai.expect
66 67
@@ -1091,7 +1092,7 @@ describe('Test video playlists', function () {
1091 await waitJobs(servers) 1092 await waitJobs(servers)
1092 1093
1093 for (const server of servers) { 1094 for (const server of servers) {
1094 await getVideoPlaylist(server.url, videoPlaylistIds.uuid, 200) 1095 await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.OK_200)
1095 } 1096 }
1096 1097
1097 const playlistAttrs = { privacy: VideoPlaylistPrivacy.PRIVATE } 1098 const playlistAttrs = { privacy: VideoPlaylistPrivacy.PRIVATE }
@@ -1100,11 +1101,11 @@ describe('Test video playlists', function () {
1100 await waitJobs(servers) 1101 await waitJobs(servers)
1101 1102
1102 for (const server of [ servers[1], servers[2] ]) { 1103 for (const server of [ servers[1], servers[2] ]) {
1103 await getVideoPlaylist(server.url, videoPlaylistIds.uuid, 404) 1104 await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.NOT_FOUND_404)
1104 } 1105 }
1105 await getVideoPlaylist(servers[0].url, videoPlaylistIds.uuid, 401) 1106 await getVideoPlaylist(servers[0].url, videoPlaylistIds.uuid, HttpStatusCode.UNAUTHORIZED_401)
1106 1107
1107 await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistIds.uuid, 200) 1108 await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistIds.uuid, HttpStatusCode.OK_200)
1108 }) 1109 })
1109 }) 1110 })
1110 1111
@@ -1118,7 +1119,7 @@ describe('Test video playlists', function () {
1118 await waitJobs(servers) 1119 await waitJobs(servers)
1119 1120
1120 for (const server of servers) { 1121 for (const server of servers) {
1121 await getVideoPlaylist(server.url, playlistServer1UUID, 404) 1122 await getVideoPlaylist(server.url, playlistServer1UUID, HttpStatusCode.NOT_FOUND_404)
1122 } 1123 }
1123 }) 1124 })
1124 1125
@@ -1178,7 +1179,7 @@ describe('Test video playlists', function () {
1178 expect(res3.body.displayName).to.equal('channel playlist') 1179 expect(res3.body.displayName).to.equal('channel playlist')
1179 expect(res3.body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE) 1180 expect(res3.body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
1180 1181
1181 await getVideoPlaylist(servers[1].url, videoPlaylistUUID, 404) 1182 await getVideoPlaylist(servers[1].url, videoPlaylistUUID, HttpStatusCode.NOT_FOUND_404)
1182 }) 1183 })
1183 1184
1184 it('Should delete an account and delete its playlists', async function () { 1185 it('Should delete an account and delete its playlists', async function () {
diff --git a/server/tests/api/videos/video-privacy.ts b/server/tests/api/videos/video-privacy.ts
index 38e93bbe6..f25d75af4 100644
--- a/server/tests/api/videos/video-privacy.ts
+++ b/server/tests/api/videos/video-privacy.ts
@@ -18,6 +18,7 @@ import { createUser } from '../../../../shared/extra-utils/users/users'
18import { getMyVideos, getVideo, getVideoWithToken, updateVideo } from '../../../../shared/extra-utils/videos/videos' 18import { getMyVideos, getVideo, getVideoWithToken, updateVideo } from '../../../../shared/extra-utils/videos/videos'
19import { waitJobs } from '../../../../shared/extra-utils/server/jobs' 19import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
20import { Video } from '@shared/models' 20import { Video } from '@shared/models'
21import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
21 22
22const expect = chai.expect 23const expect = chai.expect
23 24
@@ -110,8 +111,8 @@ describe('Test video privacy', function () {
110 }) 111 })
111 112
112 it('Should not be able to watch the private/internal video with non authenticated user', async function () { 113 it('Should not be able to watch the private/internal video with non authenticated user', async function () {
113 await getVideo(servers[0].url, privateVideoUUID, 401) 114 await getVideo(servers[0].url, privateVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
114 await getVideo(servers[0].url, internalVideoUUID, 401) 115 await getVideo(servers[0].url, internalVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
115 }) 116 })
116 117
117 it('Should not be able to watch the private video with another user', async function () { 118 it('Should not be able to watch the private video with another user', async function () {
@@ -124,15 +125,15 @@ describe('Test video privacy', function () {
124 await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password }) 125 await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
125 126
126 anotherUserToken = await userLogin(servers[0], user) 127 anotherUserToken = await userLogin(servers[0], user)
127 await getVideoWithToken(servers[0].url, anotherUserToken, privateVideoUUID, 403) 128 await getVideoWithToken(servers[0].url, anotherUserToken, privateVideoUUID, HttpStatusCode.FORBIDDEN_403)
128 }) 129 })
129 130
130 it('Should be able to watch the internal video with another user', async function () { 131 it('Should be able to watch the internal video with another user', async function () {
131 await getVideoWithToken(servers[0].url, anotherUserToken, internalVideoUUID, 200) 132 await getVideoWithToken(servers[0].url, anotherUserToken, internalVideoUUID, HttpStatusCode.OK_200)
132 }) 133 })
133 134
134 it('Should be able to watch the private video with the correct user', async function () { 135 it('Should be able to watch the private video with the correct user', async function () {
135 await getVideoWithToken(servers[0].url, servers[0].accessToken, privateVideoUUID, 200) 136 await getVideoWithToken(servers[0].url, servers[0].accessToken, privateVideoUUID, HttpStatusCode.OK_200)
136 }) 137 })
137 138
138 it('Should upload an unlisted video on server 2', async function () { 139 it('Should upload an unlisted video on server 2', async function () {
@@ -202,7 +203,7 @@ describe('Test video privacy', function () {
202 }) 203 })
203 204
204 it('Should not be able to get non-federated unlisted video from federated server', async function () { 205 it('Should not be able to get non-federated unlisted video from federated server', async function () {
205 await getVideo(servers[1].url, nonFederatedUnlistedVideoUUID, 404) 206 await getVideo(servers[1].url, nonFederatedUnlistedVideoUUID, HttpStatusCode.NOT_FOUND_404)
206 }) 207 })
207 208
208 it('Should update the private and internal videos to public on server 1', async function () { 209 it('Should update the private and internal videos to public on server 1', async function () {
diff --git a/server/tests/api/videos/videos-history.ts b/server/tests/api/videos/videos-history.ts
index 6f90e9a57..661d603cb 100644
--- a/server/tests/api/videos/videos-history.ts
+++ b/server/tests/api/videos/videos-history.ts
@@ -20,6 +20,7 @@ import {
20} from '../../../../shared/extra-utils' 20} from '../../../../shared/extra-utils'
21import { Video, VideoDetails } from '../../../../shared/models/videos' 21import { Video, VideoDetails } from '../../../../shared/models/videos'
22import { listMyVideosHistory, removeMyVideosHistory, userWatchVideo } from '../../../../shared/extra-utils/videos/video-history' 22import { listMyVideosHistory, removeMyVideosHistory, userWatchVideo } from '../../../../shared/extra-utils/videos/video-history'
23import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
23 24
24const expect = chai.expect 25const expect = chai.expect
25 26
@@ -171,7 +172,7 @@ describe('Test videos history', function () {
171 videosHistoryEnabled: false 172 videosHistoryEnabled: false
172 }) 173 })
173 174
174 await userWatchVideo(server.url, server.accessToken, video2UUID, 8, 409) 175 await userWatchVideo(server.url, server.accessToken, video2UUID, 8, HttpStatusCode.CONFLICT_409)
175 }) 176 })
176 177
177 it('Should re-enable videos history', async function () { 178 it('Should re-enable videos history', async function () {
diff --git a/server/tests/cli/reset-password.ts b/server/tests/cli/reset-password.ts
index 6abb6738f..a84463b33 100644
--- a/server/tests/cli/reset-password.ts
+++ b/server/tests/cli/reset-password.ts
@@ -10,6 +10,7 @@ import {
10 ServerInfo, 10 ServerInfo,
11 setAccessTokensToServers 11 setAccessTokensToServers
12} from '../../../shared/extra-utils' 12} from '../../../shared/extra-utils'
13import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
13 14
14describe('Test reset password scripts', function () { 15describe('Test reset password scripts', function () {
15 let server: ServerInfo 16 let server: ServerInfo
@@ -28,7 +29,7 @@ describe('Test reset password scripts', function () {
28 const env = getEnvCli(server) 29 const env = getEnvCli(server)
29 await execCLI(`echo coucou | ${env} npm run reset-password -- -u user_1`) 30 await execCLI(`echo coucou | ${env} npm run reset-password -- -u user_1`)
30 31
31 await login(server.url, server.client, { username: 'user_1', password: 'coucou' }, 200) 32 await login(server.url, server.client, { username: 'user_1', password: 'coucou' }, HttpStatusCode.OK_200)
32 }) 33 })
33 34
34 after(async function () { 35 after(async function () {
diff --git a/server/tests/feeds/feeds.ts b/server/tests/feeds/feeds.ts
index 92a468192..f1055ea44 100644
--- a/server/tests/feeds/feeds.ts
+++ b/server/tests/feeds/feeds.ts
@@ -31,6 +31,7 @@ import {
31import { waitJobs } from '../../../shared/extra-utils/server/jobs' 31import { waitJobs } from '../../../shared/extra-utils/server/jobs'
32import { addVideoCommentThread } from '../../../shared/extra-utils/videos/video-comments' 32import { addVideoCommentThread } from '../../../shared/extra-utils/videos/video-comments'
33import { User } from '../../../shared/models/users' 33import { User } from '../../../shared/models/users'
34import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
34 35
35chai.use(require('chai-xml')) 36chai.use(require('chai-xml'))
36chai.use(require('chai-json-schema')) 37chai.use(require('chai-json-schema'))
@@ -330,11 +331,16 @@ describe('Test syndication feeds', () => {
330 }) 331 })
331 332
332 it('Should fail with an invalid token', async function () { 333 it('Should fail with an invalid token', async function () {
333 await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: 'toto' }, 403) 334 await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: 'toto' }, HttpStatusCode.FORBIDDEN_403)
334 }) 335 })
335 336
336 it('Should fail with a token of another user', async function () { 337 it('Should fail with a token of another user', async function () {
337 await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: userFeedToken }, 403) 338 await getJSONfeed(
339 servers[0].url,
340 'subscriptions',
341 { accountId: feeduserAccountId, token: userFeedToken },
342 HttpStatusCode.FORBIDDEN_403
343 )
338 }) 344 })
339 345
340 it('Should list no videos for a user with videos but no subscriptions', async function () { 346 it('Should list no videos for a user with videos but no subscriptions', async function () {
@@ -382,7 +388,12 @@ describe('Test syndication feeds', () => {
382 it('Should renew the token, and so have an invalid old token', async function () { 388 it('Should renew the token, and so have an invalid old token', async function () {
383 await renewUserScopedTokens(servers[0].url, userAccessToken) 389 await renewUserScopedTokens(servers[0].url, userAccessToken)
384 390
385 await getJSONfeed(servers[0].url, 'subscriptions', { accountId: userAccountId, token: userFeedToken, version: 3 }, 403) 391 await getJSONfeed(
392 servers[0].url,
393 'subscriptions',
394 { accountId: userAccountId, token: userFeedToken, version: 3 },
395 HttpStatusCode.FORBIDDEN_403
396 )
386 }) 397 })
387 398
388 it('Should succeed with the new token', async function () { 399 it('Should succeed with the new token', async function () {
diff --git a/server/tests/plugins/filter-hooks.ts b/server/tests/plugins/filter-hooks.ts
index 2441940c3..cdde6cd30 100644
--- a/server/tests/plugins/filter-hooks.ts
+++ b/server/tests/plugins/filter-hooks.ts
@@ -31,6 +31,7 @@ import { cleanupTests, flushAndRunMultipleServers, ServerInfo } from '../../../s
31import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports' 31import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports'
32import { VideoDetails, VideoImport, VideoImportState, VideoPrivacy } from '../../../shared/models/videos' 32import { VideoDetails, VideoImport, VideoImportState, VideoPrivacy } from '../../../shared/models/videos'
33import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model' 33import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
34import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
34 35
35const expect = chai.expect 36const expect = chai.expect
36 37
@@ -127,7 +128,7 @@ describe('Test plugin filter hooks', function () {
127 }) 128 })
128 129
129 it('Should run filter:api.video.upload.accept.result', async function () { 130 it('Should run filter:api.video.upload.accept.result', async function () {
130 await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video with bad word' }, 403) 131 await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video with bad word' }, HttpStatusCode.FORBIDDEN_403)
131 }) 132 })
132 133
133 it('Should run filter:api.live-video.create.accept.result', async function () { 134 it('Should run filter:api.live-video.create.accept.result', async function () {
@@ -137,7 +138,7 @@ describe('Test plugin filter hooks', function () {
137 channelId: servers[0].videoChannel.id 138 channelId: servers[0].videoChannel.id
138 } 139 }
139 140
140 await createLive(servers[0].url, servers[0].accessToken, attributes, 403) 141 await createLive(servers[0].url, servers[0].accessToken, attributes, HttpStatusCode.FORBIDDEN_403)
141 }) 142 })
142 143
143 it('Should run filter:api.video.pre-import-url.accept.result', async function () { 144 it('Should run filter:api.video.pre-import-url.accept.result', async function () {
@@ -147,7 +148,7 @@ describe('Test plugin filter hooks', function () {
147 channelId: servers[0].videoChannel.id, 148 channelId: servers[0].videoChannel.id,
148 targetUrl: getGoodVideoUrl() + 'bad' 149 targetUrl: getGoodVideoUrl() + 'bad'
149 } 150 }
150 await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, 403) 151 await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, HttpStatusCode.FORBIDDEN_403)
151 }) 152 })
152 153
153 it('Should run filter:api.video.pre-import-torrent.accept.result', async function () { 154 it('Should run filter:api.video.pre-import-torrent.accept.result', async function () {
@@ -157,7 +158,7 @@ describe('Test plugin filter hooks', function () {
157 channelId: servers[0].videoChannel.id, 158 channelId: servers[0].videoChannel.id,
158 torrentfile: 'video-720p.torrent' as any 159 torrentfile: 'video-720p.torrent' as any
159 } 160 }
160 await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, 403) 161 await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, HttpStatusCode.FORBIDDEN_403)
161 }) 162 })
162 163
163 it('Should run filter:api.video.post-import-url.accept.result', async function () { 164 it('Should run filter:api.video.post-import-url.accept.result', async function () {
@@ -219,15 +220,22 @@ describe('Test plugin filter hooks', function () {
219 }) 220 })
220 221
221 it('Should run filter:api.video-thread.create.accept.result', async function () { 222 it('Should run filter:api.video-thread.create.accept.result', async function () {
222 await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment with bad word', 403) 223 await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment with bad word', HttpStatusCode.FORBIDDEN_403)
223 }) 224 })
224 225
225 it('Should run filter:api.video-comment-reply.create.accept.result', async function () { 226 it('Should run filter:api.video-comment-reply.create.accept.result', async function () {
226 const res = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'thread') 227 const res = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'thread')
227 threadId = res.body.comment.id 228 threadId = res.body.comment.id
228 229
229 await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'comment with bad word', 403) 230 await addVideoCommentReply(
230 await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'comment with good word', 200) 231 servers[0].url,
232 servers[0].accessToken,
233 videoUUID,
234 threadId,
235 'comment with bad word',
236 HttpStatusCode.FORBIDDEN_403
237 )
238 await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'comment with good word', HttpStatusCode.OK_200)
231 }) 239 })
232 240
233 it('Should run filter:api.video-threads.list.params', async function () { 241 it('Should run filter:api.video-threads.list.params', async function () {
@@ -326,7 +334,7 @@ describe('Test plugin filter hooks', function () {
326 }) 334 })
327 335
328 it('Should not allow a signup', async function () { 336 it('Should not allow a signup', async function () {
329 const res = await registerUser(servers[0].url, 'jma', 'password', 403) 337 const res = await registerUser(servers[0].url, 'jma', 'password', HttpStatusCode.FORBIDDEN_403)
330 338
331 expect(res.body.error).to.equal('No jma') 339 expect(res.body.error).to.equal('No jma')
332 }) 340 })
diff --git a/server/tests/plugins/video-constants.ts b/server/tests/plugins/video-constants.ts
index fec9196e2..5ee41fee1 100644
--- a/server/tests/plugins/video-constants.ts
+++ b/server/tests/plugins/video-constants.ts
@@ -16,6 +16,7 @@ import {
16 uploadVideo 16 uploadVideo
17} from '../../../shared/extra-utils' 17} from '../../../shared/extra-utils'
18import { VideoDetails, VideoPlaylistPrivacy } from '../../../shared/models/videos' 18import { VideoDetails, VideoPlaylistPrivacy } from '../../../shared/models/videos'
19import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
19 20
20const expect = chai.expect 21const expect = chai.expect
21 22
@@ -89,12 +90,17 @@ describe('Test plugin altering video constants', function () {
89 90
90 it('Should not be able to create a video with this privacy', async function () { 91 it('Should not be able to create a video with this privacy', async function () {
91 const attrs = { name: 'video', privacy: 2 } 92 const attrs = { name: 'video', privacy: 2 }
92 await uploadVideo(server.url, server.accessToken, attrs, 400) 93 await uploadVideo(server.url, server.accessToken, attrs, HttpStatusCode.BAD_REQUEST_400)
93 }) 94 })
94 95
95 it('Should not be able to create a video with this privacy', async function () { 96 it('Should not be able to create a video with this privacy', async function () {
96 const attrs = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE } 97 const attrs = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE }
97 await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs: attrs, expectedStatus: 400 }) 98 await createVideoPlaylist({
99 url: server.url,
100 token: server.accessToken,
101 playlistAttrs: attrs,
102 expectedStatus: HttpStatusCode.BAD_REQUEST_400
103 })
98 }) 104 })
99 105
100 it('Should be able to upload a video with these values', async function () { 106 it('Should be able to upload a video with these values', async function () {
diff --git a/server/tools/peertube-redundancy.ts b/server/tools/peertube-redundancy.ts
index 1ab58a438..fe482daf4 100644
--- a/server/tools/peertube-redundancy.ts
+++ b/server/tools/peertube-redundancy.ts
@@ -7,6 +7,7 @@ import * as program from 'commander'
7import { getAdminTokenOrDie, getServerCredentials } from './cli' 7import { getAdminTokenOrDie, getServerCredentials } from './cli'
8import { VideoRedundanciesTarget, VideoRedundancy } from '@shared/models' 8import { VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
9import { addVideoRedundancy, listVideoRedundancies, removeVideoRedundancy } from '@shared/extra-utils/server/redundancy' 9import { addVideoRedundancy, listVideoRedundancies, removeVideoRedundancy } from '@shared/extra-utils/server/redundancy'
10import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
10import validator from 'validator' 11import validator from 'validator'
11import * as CliTable3 from 'cli-table3' 12import * as CliTable3 from 'cli-table3'
12import { URL } from 'url' 13import { URL } from 'url'
@@ -124,9 +125,9 @@ async function addRedundancyCLI (options: { videoId: number }) {
124 125
125 process.exit(0) 126 process.exit(0)
126 } catch (err) { 127 } catch (err) {
127 if (err.message.includes(409)) { 128 if (err.message.includes(HttpStatusCode.CONFLICT_409)) {
128 console.error('This video is already duplicated by your instance.') 129 console.error('This video is already duplicated by your instance.')
129 } else if (err.message.includes(404)) { 130 } else if (err.message.includes(HttpStatusCode.NOT_FOUND_404)) {
130 console.error('This video id does not exist.') 131 console.error('This video id does not exist.')
131 } else { 132 } else {
132 console.error(err) 133 console.error(err)