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
This commit is contained in:
parent
c977fd3ec9
commit
f2eb23cd87
|
@ -10,6 +10,7 @@ import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
|
||||||
import { InstanceService } from '@app/shared/shared-instance'
|
import { InstanceService } from '@app/shared/shared-instance'
|
||||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
|
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
|
||||||
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
import { ServerConfig } from '@shared/models'
|
import { ServerConfig } from '@shared/models'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -78,7 +79,7 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit {
|
||||||
},
|
},
|
||||||
|
|
||||||
err => {
|
err => {
|
||||||
this.error = err.status === 403
|
this.error = err.status === HttpStatusCode.FORBIDDEN_403
|
||||||
? $localize`You already sent this form recently`
|
? $localize`You already sent this form recently`
|
||||||
: err.message
|
: err.message
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { AuthService, Notifier, RedirectService, RestExtractor, ScreenService, U
|
||||||
import { Account, AccountService, DropdownAction, ListOverflowItem, VideoChannel, VideoChannelService } from '@app/shared/shared-main'
|
import { Account, AccountService, DropdownAction, ListOverflowItem, VideoChannel, VideoChannelService } from '@app/shared/shared-main'
|
||||||
import { AccountReportComponent } from '@app/shared/shared-moderation'
|
import { AccountReportComponent } from '@app/shared/shared-moderation'
|
||||||
import { User, UserRight } from '@shared/models'
|
import { User, UserRight } from '@shared/models'
|
||||||
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './accounts.component.html',
|
templateUrl: './accounts.component.html',
|
||||||
|
@ -47,7 +48,10 @@ export class AccountsComponent implements OnInit, OnDestroy {
|
||||||
switchMap(accountId => this.accountService.getAccount(accountId)),
|
switchMap(accountId => this.accountService.getAccount(accountId)),
|
||||||
tap(account => this.onAccount(account)),
|
tap(account => this.onAccount(account)),
|
||||||
switchMap(account => this.videoChannelService.listAccountVideoChannels(account)),
|
switchMap(account => this.videoChannelService.listAccountVideoChannels(account)),
|
||||||
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 404 ]))
|
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [
|
||||||
|
HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
HttpStatusCode.NOT_FOUND_404
|
||||||
|
]))
|
||||||
)
|
)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
videoChannels => this.videoChannels = videoChannels.data,
|
videoChannels => this.videoChannels = videoChannels.data,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
import { FormValidatorService } from '@app/shared/shared-forms'
|
import { FormValidatorService } from '@app/shared/shared-forms'
|
||||||
import { VideoChannelService } from '@app/shared/shared-main'
|
import { VideoChannelService } from '@app/shared/shared-main'
|
||||||
import { VideoChannelCreate } from '@shared/models'
|
import { VideoChannelCreate } from '@shared/models'
|
||||||
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
import { MyVideoChannelEdit } from './my-video-channel-edit'
|
import { MyVideoChannelEdit } from './my-video-channel-edit'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -58,7 +59,7 @@ export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements
|
||||||
},
|
},
|
||||||
|
|
||||||
err => {
|
err => {
|
||||||
if (err.status === 409) {
|
if (err.status === HttpStatusCode.CONFLICT_409) {
|
||||||
this.error = $localize`This name already exists on this instance.`
|
this.error = $localize`This name already exists on this instance.`
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { ActivatedRoute } from '@angular/router'
|
||||||
import { AuthService, Notifier, RestExtractor, ScreenService } from '@app/core'
|
import { AuthService, Notifier, RestExtractor, ScreenService } from '@app/core'
|
||||||
import { ListOverflowItem, VideoChannel, VideoChannelService } from '@app/shared/shared-main'
|
import { ListOverflowItem, VideoChannel, VideoChannelService } from '@app/shared/shared-main'
|
||||||
import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription'
|
import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription'
|
||||||
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './video-channels.component.html',
|
templateUrl: './video-channels.component.html',
|
||||||
|
@ -37,7 +38,10 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
|
||||||
map(params => params[ 'videoChannelName' ]),
|
map(params => params[ 'videoChannelName' ]),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
switchMap(videoChannelName => this.videoChannelService.getVideoChannel(videoChannelName)),
|
switchMap(videoChannelName => this.videoChannelService.getVideoChannel(videoChannelName)),
|
||||||
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 404 ]))
|
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [
|
||||||
|
HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
HttpStatusCode.NOT_FOUND_404
|
||||||
|
]))
|
||||||
)
|
)
|
||||||
.subscribe(videoChannel => {
|
.subscribe(videoChannel => {
|
||||||
this.videoChannel = videoChannel
|
this.videoChannel = videoChannel
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { BytesPipe, VideoCaptionService, VideoEdit, VideoService } from '@app/sh
|
||||||
import { LoadingBarService } from '@ngx-loading-bar/core'
|
import { LoadingBarService } from '@ngx-loading-bar/core'
|
||||||
import { VideoPrivacy } from '@shared/models'
|
import { VideoPrivacy } from '@shared/models'
|
||||||
import { VideoSend } from './video-send'
|
import { VideoSend } from './video-send'
|
||||||
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-video-upload',
|
selector: 'my-video-upload',
|
||||||
|
@ -129,6 +130,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
|
||||||
cancelUpload () {
|
cancelUpload () {
|
||||||
if (this.videoUploadObservable !== null) {
|
if (this.videoUploadObservable !== null) {
|
||||||
this.videoUploadObservable.unsubscribe()
|
this.videoUploadObservable.unsubscribe()
|
||||||
|
}
|
||||||
|
|
||||||
this.isUploadingVideo = false
|
this.isUploadingVideo = false
|
||||||
this.videoUploadPercents = 0
|
this.videoUploadPercents = 0
|
||||||
|
@ -140,7 +142,6 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
|
||||||
|
|
||||||
this.notifier.info($localize`Upload cancelled`)
|
this.notifier.info($localize`Upload cancelled`)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
uploadFirstStep (clickedOnButton = false) {
|
uploadFirstStep (clickedOnButton = false) {
|
||||||
const videofile = this.getVideoFile()
|
const videofile = this.getVideoFile()
|
||||||
|
@ -229,6 +230,11 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
|
||||||
notifier: this.notifier,
|
notifier: this.notifier,
|
||||||
sticky: false
|
sticky: false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413 ||
|
||||||
|
err.status === HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415) {
|
||||||
|
this.cancelUpload()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ import { isWebRTCDisabled, timeToInt } from '../../../assets/player/utils'
|
||||||
import { environment } from '../../../environments/environment'
|
import { environment } from '../../../environments/environment'
|
||||||
import { VideoSupportComponent } from './modal/video-support.component'
|
import { VideoSupportComponent } from './modal/video-support.component'
|
||||||
import { VideoWatchPlaylistComponent } from './video-watch-playlist.component'
|
import { VideoWatchPlaylistComponent } from './video-watch-playlist.component'
|
||||||
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
type URLOptions = CustomizationOptions & { playerMode: PlayerMode }
|
type URLOptions = CustomizationOptions & { playerMode: PlayerMode }
|
||||||
|
|
||||||
|
@ -412,13 +413,25 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
$localize`This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="${originUrl}">${originUrl}</a>?`,
|
$localize`This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="${originUrl}">${originUrl}</a>?`,
|
||||||
$localize`Redirection`
|
$localize`Redirection`
|
||||||
).then(res => {
|
).then(res => {
|
||||||
if (res === false) return this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ])
|
if (res === false) {
|
||||||
|
return this.restExtractor.redirectTo404IfNotFound(err, [
|
||||||
|
HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
HttpStatusCode.UNAUTHORIZED_401,
|
||||||
|
HttpStatusCode.FORBIDDEN_403,
|
||||||
|
HttpStatusCode.NOT_FOUND_404
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
return window.location.href = originUrl
|
return window.location.href = originUrl
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ])
|
return this.restExtractor.redirectTo404IfNotFound(err, [
|
||||||
|
HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
HttpStatusCode.UNAUTHORIZED_401,
|
||||||
|
HttpStatusCode.FORBIDDEN_403,
|
||||||
|
HttpStatusCode.NOT_FOUND_404
|
||||||
|
])
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.subscribe(([ video, captionsResult ]) => {
|
.subscribe(([ video, captionsResult ]) => {
|
||||||
|
@ -450,7 +463,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
|
||||||
this.playlistService.getVideoPlaylist(playlistId)
|
this.playlistService.getVideoPlaylist(playlistId)
|
||||||
.pipe(
|
.pipe(
|
||||||
// If 401, the video is private or blocked so redirect to 404
|
// If 401, the video is private or blocked so redirect to 404
|
||||||
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ]))
|
catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [
|
||||||
|
HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
HttpStatusCode.UNAUTHORIZED_401,
|
||||||
|
HttpStatusCode.FORBIDDEN_403,
|
||||||
|
HttpStatusCode.NOT_FOUND_404
|
||||||
|
]))
|
||||||
)
|
)
|
||||||
.subscribe(playlist => {
|
.subscribe(playlist => {
|
||||||
this.playlist = playlist
|
this.playlist = playlist
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { environment } from '../../../environments/environment'
|
||||||
import { RestExtractor } from '../rest/rest-extractor.service'
|
import { RestExtractor } from '../rest/rest-extractor.service'
|
||||||
import { AuthStatus } from './auth-status.model'
|
import { AuthStatus } from './auth-status.model'
|
||||||
import { AuthUser } from './auth-user.model'
|
import { AuthUser } from './auth-user.model'
|
||||||
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
interface UserLoginWithUsername extends UserLogin {
|
interface UserLoginWithUsername extends UserLogin {
|
||||||
access_token: string
|
access_token: string
|
||||||
|
@ -94,7 +95,7 @@ export class AuthService {
|
||||||
error => {
|
error => {
|
||||||
let errorMessage = error.message
|
let errorMessage = error.message
|
||||||
|
|
||||||
if (error.status === 403) {
|
if (error.status === HttpStatusCode.FORBIDDEN_403) {
|
||||||
errorMessage = $localize`Cannot retrieve OAuth Client credentials: ${error.text}.
|
errorMessage = $localize`Cannot retrieve OAuth Client credentials: ${error.text}.
|
||||||
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.`
|
Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.`
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'
|
||||||
import { Router } from '@angular/router'
|
import { Router } from '@angular/router'
|
||||||
import { dateToHuman } from '@app/helpers'
|
import { dateToHuman } from '@app/helpers'
|
||||||
import { ResultList } from '@shared/models'
|
import { ResultList } from '@shared/models'
|
||||||
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RestExtractor {
|
export class RestExtractor {
|
||||||
|
@ -57,9 +58,9 @@ export class RestExtractor {
|
||||||
errorMessage = errorsArray.join('. ')
|
errorMessage = errorsArray.join('. ')
|
||||||
} else if (err.error && err.error.error) {
|
} else if (err.error && err.error.error) {
|
||||||
errorMessage = err.error.error
|
errorMessage = err.error.error
|
||||||
} else if (err.status === 413) {
|
} else if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413) {
|
||||||
errorMessage = $localize`Media is too large for the server. Please contact you administrator if you want to increase the limit size.`
|
errorMessage = $localize`Media is too large for the server. Please contact you administrator if you want to increase the limit size.`
|
||||||
} else if (err.status === 429) {
|
} else if (err.status === HttpStatusCode.TOO_MANY_REQUESTS_429) {
|
||||||
const secondsLeft = err.headers.get('retry-after')
|
const secondsLeft = err.headers.get('retry-after')
|
||||||
if (secondsLeft) {
|
if (secondsLeft) {
|
||||||
const minutesLeft = Math.floor(parseInt(secondsLeft, 10) / 60)
|
const minutesLeft = Math.floor(parseInt(secondsLeft, 10) / 60)
|
||||||
|
@ -67,7 +68,7 @@ export class RestExtractor {
|
||||||
} else {
|
} else {
|
||||||
errorMessage = $localize`Too many attempts, please try again later.`
|
errorMessage = $localize`Too many attempts, please try again later.`
|
||||||
}
|
}
|
||||||
} else if (err.status === 500) {
|
} else if (err.status === HttpStatusCode.INTERNAL_SERVER_ERROR_500) {
|
||||||
errorMessage = $localize`Server error. Please retry later.`
|
errorMessage = $localize`Server error. Please retry later.`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +93,7 @@ export class RestExtractor {
|
||||||
return observableThrowError(errorObj)
|
return observableThrowError(errorObj)
|
||||||
}
|
}
|
||||||
|
|
||||||
redirectTo404IfNotFound (obj: { status: number }, status = [ 404 ]) {
|
redirectTo404IfNotFound (obj: { status: number }, status = [ HttpStatusCode.NOT_FOUND_404 ]) {
|
||||||
if (obj && obj.status && status.indexOf(obj.status) !== -1) {
|
if (obj && obj.status && status.indexOf(obj.status) !== -1) {
|
||||||
// Do not use redirectService to avoid circular dependencies
|
// Do not use redirectService to avoid circular dependencies
|
||||||
this.router.navigate([ '/404' ], { skipLocationChange: true })
|
this.router.navigate([ '/404' ], { skipLocationChange: true })
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
PluginType,
|
PluginType,
|
||||||
ClientHookName
|
ClientHookName
|
||||||
} from '../../../../shared/models'
|
} from '../../../../shared/models'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
import { P2PMediaLoaderOptions, PeertubePlayerManagerOptions, PlayerMode } from '../../assets/player/peertube-player-manager'
|
import { P2PMediaLoaderOptions, PeertubePlayerManagerOptions, PlayerMode } from '../../assets/player/peertube-player-manager'
|
||||||
import { VideoJSCaption } from '../../assets/player/peertube-videojs-typings'
|
import { VideoJSCaption } from '../../assets/player/peertube-videojs-typings'
|
||||||
import { TranslationsManager } from '../../assets/player/translations-manager'
|
import { TranslationsManager } from '../../assets/player/translations-manager'
|
||||||
|
@ -85,7 +86,7 @@ export class PeerTubeEmbed {
|
||||||
refreshFetch (url: string, options?: RequestInit) {
|
refreshFetch (url: string, options?: RequestInit) {
|
||||||
return fetch(url, options)
|
return fetch(url, options)
|
||||||
.then((res: Response) => {
|
.then((res: Response) => {
|
||||||
if (res.status !== 401) return res
|
if (res.status !== HttpStatusCode.UNAUTHORIZED_401) return res
|
||||||
|
|
||||||
const refreshingTokenPromise = new Promise((resolve, reject) => {
|
const refreshingTokenPromise = new Promise((resolve, reject) => {
|
||||||
const clientId: string = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID)
|
const clientId: string = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID)
|
||||||
|
@ -107,7 +108,7 @@ export class PeerTubeEmbed {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: objectToUrlEncoded(data)
|
body: objectToUrlEncoded(data)
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res.status === 401) return undefined
|
if (res.status === HttpStatusCode.UNAUTHORIZED_401) return undefined
|
||||||
|
|
||||||
return res.json()
|
return res.json()
|
||||||
}).then((obj: UserRefreshToken & { code: 'invalid_grant'}) => {
|
}).then((obj: UserRefreshToken & { code: 'invalid_grant'}) => {
|
||||||
|
@ -338,7 +339,7 @@ export class PeerTubeEmbed {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
playlistResponse = await playlistPromise
|
playlistResponse = await playlistPromise
|
||||||
isResponseOk = playlistResponse.status === 200
|
isResponseOk = playlistResponse.status === HttpStatusCode.OK_200
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
isResponseOk = false
|
isResponseOk = false
|
||||||
|
@ -347,7 +348,7 @@ export class PeerTubeEmbed {
|
||||||
if (!isResponseOk) {
|
if (!isResponseOk) {
|
||||||
const serverTranslations = await this.translationsPromise
|
const serverTranslations = await this.translationsPromise
|
||||||
|
|
||||||
if (playlistResponse?.status === 404) {
|
if (playlistResponse?.status === HttpStatusCode.NOT_FOUND_404) {
|
||||||
this.playlistNotFound(serverTranslations)
|
this.playlistNotFound(serverTranslations)
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
@ -367,7 +368,7 @@ export class PeerTubeEmbed {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
videoResponse = await videoPromise
|
videoResponse = await videoPromise
|
||||||
isResponseOk = videoResponse.status === 200
|
isResponseOk = videoResponse.status === HttpStatusCode.OK_200
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
|
||||||
|
@ -377,7 +378,7 @@ export class PeerTubeEmbed {
|
||||||
if (!isResponseOk) {
|
if (!isResponseOk) {
|
||||||
const serverTranslations = await this.translationsPromise
|
const serverTranslations = await this.translationsPromise
|
||||||
|
|
||||||
if (videoResponse?.status === 404) {
|
if (videoResponse?.status === HttpStatusCode.NOT_FOUND_404) {
|
||||||
this.videoNotFound(serverTranslations)
|
this.videoNotFound(serverTranslations)
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,11 @@ import { constants, promises as fs } from 'fs'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { CONFIG } from '@server/initializers/config'
|
import { CONFIG } from '@server/initializers/config'
|
||||||
import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@shared/core-utils/i18n'
|
import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@shared/core-utils/i18n'
|
||||||
import { root } from '../helpers/core-utils'
|
|
||||||
import { logger } from '../helpers/logger'
|
|
||||||
import { ACCEPT_HEADERS, STATIC_MAX_AGE } from '../initializers/constants'
|
|
||||||
import { ClientHtml } from '../lib/client-html'
|
|
||||||
import { asyncMiddleware, embedCSP } from '../middlewares'
|
|
||||||
import { HttpStatusCode } from '@shared/core-utils'
|
import { HttpStatusCode } from '@shared/core-utils'
|
||||||
|
import { root } from '../helpers/core-utils'
|
||||||
|
import { STATIC_MAX_AGE } from '../initializers/constants'
|
||||||
|
import { ClientHtml, sendHTML, serveIndexHTML } from '../lib/client-html'
|
||||||
|
import { asyncMiddleware, embedCSP } from '../middlewares'
|
||||||
|
|
||||||
const clientsRouter = express.Router()
|
const clientsRouter = express.Router()
|
||||||
|
|
||||||
|
@ -118,31 +117,12 @@ function serveServerTranslations (req: express.Request, res: express.Response) {
|
||||||
return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
|
return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function serveIndexHTML (req: express.Request, res: express.Response) {
|
|
||||||
if (req.accepts(ACCEPT_HEADERS) === 'html') {
|
|
||||||
try {
|
|
||||||
await generateHTMLPage(req, res, req.params.language)
|
|
||||||
return
|
|
||||||
} catch (err) {
|
|
||||||
logger.error('Cannot generate HTML page.', err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR_500).end()
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateEmbedHtmlPage (req: express.Request, res: express.Response) {
|
async function generateEmbedHtmlPage (req: express.Request, res: express.Response) {
|
||||||
const html = await ClientHtml.getEmbedHTML()
|
const html = await ClientHtml.getEmbedHTML()
|
||||||
|
|
||||||
return sendHTML(html, res)
|
return sendHTML(html, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateHTMLPage (req: express.Request, res: express.Response, paramLang?: string) {
|
|
||||||
const html = await ClientHtml.getDefaultHTMLPage(req, res, paramLang)
|
|
||||||
|
|
||||||
return sendHTML(html, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateWatchHtmlPage (req: express.Request, res: express.Response) {
|
async function generateWatchHtmlPage (req: express.Request, res: express.Response) {
|
||||||
const html = await ClientHtml.getWatchHTMLPage(req.params.id + '', req, res)
|
const html = await ClientHtml.getWatchHTMLPage(req.params.id + '', req, res)
|
||||||
|
|
||||||
|
@ -167,12 +147,6 @@ async function generateVideoChannelHtmlPage (req: express.Request, res: express.
|
||||||
return sendHTML(html, res)
|
return sendHTML(html, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendHTML (html: string, res: express.Response) {
|
|
||||||
res.set('Content-Type', 'text/html; charset=UTF-8')
|
|
||||||
|
|
||||||
return res.send(html)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateManifest (req: express.Request, res: express.Response) {
|
async function generateManifest (req: express.Request, res: express.Response) {
|
||||||
const manifestPhysicalPath = join(root(), 'client', 'dist', 'manifest.webmanifest')
|
const manifestPhysicalPath = join(root(), 'client', 'dist', 'manifest.webmanifest')
|
||||||
const manifestJson = await fs.readFile(manifestPhysicalPath, 'utf8')
|
const manifestJson = await fs.readFile(manifestPhysicalPath, 'utf8')
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { getTorrentFilePath, getVideoFilePath } from '@server/lib/video-paths'
|
||||||
import { getThemeOrDefault } from '../lib/plugins/theme-utils'
|
import { getThemeOrDefault } from '../lib/plugins/theme-utils'
|
||||||
import { getEnabledResolutions, getRegisteredPlugins, getRegisteredThemes } from '@server/controllers/api/config'
|
import { getEnabledResolutions, getRegisteredPlugins, getRegisteredThemes } from '@server/controllers/api/config'
|
||||||
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
|
import { serveIndexHTML } from '@server/lib/client-html'
|
||||||
|
|
||||||
const staticRouter = express.Router()
|
const staticRouter = express.Router()
|
||||||
|
|
||||||
|
@ -119,6 +120,11 @@ staticRouter.get('/robots.txt',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
staticRouter.all('/teapot',
|
||||||
|
getCup,
|
||||||
|
asyncMiddleware(serveIndexHTML)
|
||||||
|
)
|
||||||
|
|
||||||
// security.txt service
|
// security.txt service
|
||||||
staticRouter.get('/security.txt',
|
staticRouter.get('/security.txt',
|
||||||
(_, res: express.Response) => {
|
(_, res: express.Response) => {
|
||||||
|
@ -391,3 +397,11 @@ function getHLSPlaylist (video: MVideoFullLight) {
|
||||||
|
|
||||||
return Object.assign(playlist, { Video: video })
|
return Object.assign(playlist, { Video: video })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getCup (req: express.Request, res: express.Response, next: express.NextFunction) {
|
||||||
|
res.status(HttpStatusCode.I_AM_A_TEAPOT_418)
|
||||||
|
res.setHeader('Accept-Additions', 'Non-Dairy;1,Sugar;1')
|
||||||
|
res.setHeader('Safe', 'if-sepia-awake')
|
||||||
|
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
|
|
@ -86,6 +86,50 @@ function toIntArray (value: any) {
|
||||||
return value.map(v => validator.toInt(v))
|
return value.map(v => validator.toInt(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isFileFieldValid (
|
||||||
|
files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
|
||||||
|
field: string,
|
||||||
|
optional = false
|
||||||
|
) {
|
||||||
|
// Should have files
|
||||||
|
if (!files) return optional
|
||||||
|
if (isArray(files)) return optional
|
||||||
|
|
||||||
|
// Should have a file
|
||||||
|
const fileArray = files[field]
|
||||||
|
if (!fileArray || fileArray.length === 0) {
|
||||||
|
return optional
|
||||||
|
}
|
||||||
|
|
||||||
|
// The file should exist
|
||||||
|
const file = fileArray[0]
|
||||||
|
if (!file || !file.originalname) return false
|
||||||
|
return file
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFileMimeTypeValid (
|
||||||
|
files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
|
||||||
|
mimeTypeRegex: string,
|
||||||
|
field: string,
|
||||||
|
optional = false
|
||||||
|
) {
|
||||||
|
// Should have files
|
||||||
|
if (!files) return optional
|
||||||
|
if (isArray(files)) return optional
|
||||||
|
|
||||||
|
// Should have a file
|
||||||
|
const fileArray = files[field]
|
||||||
|
if (!fileArray || fileArray.length === 0) {
|
||||||
|
return optional
|
||||||
|
}
|
||||||
|
|
||||||
|
// The file should exist
|
||||||
|
const file = fileArray[0]
|
||||||
|
if (!file || !file.originalname) return false
|
||||||
|
|
||||||
|
return new RegExp(`^${mimeTypeRegex}$`, 'i').test(file.mimetype)
|
||||||
|
}
|
||||||
|
|
||||||
function isFileValid (
|
function isFileValid (
|
||||||
files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
|
files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
|
||||||
mimeTypeRegex: string,
|
mimeTypeRegex: string,
|
||||||
|
@ -132,5 +176,7 @@ export {
|
||||||
toIntOrNull,
|
toIntOrNull,
|
||||||
toArray,
|
toArray,
|
||||||
toIntArray,
|
toIntArray,
|
||||||
|
isFileFieldValid,
|
||||||
|
isFileMimeTypeValid,
|
||||||
isFileValid
|
isFileValid
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import {
|
||||||
VIDEO_STATES,
|
VIDEO_STATES,
|
||||||
VIDEO_LIVE
|
VIDEO_LIVE
|
||||||
} from '../../initializers/constants'
|
} from '../../initializers/constants'
|
||||||
import { exists, isArray, isDateValid, isFileValid } from './misc'
|
import { exists, isArray, isDateValid, isFileMimeTypeValid, isFileValid } from './misc'
|
||||||
import * as magnetUtil from 'magnet-uri'
|
import * as magnetUtil from 'magnet-uri'
|
||||||
|
|
||||||
const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
|
const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
|
||||||
|
@ -81,8 +81,8 @@ function isVideoFileExtnameValid (value: string) {
|
||||||
return exists(value) && (value === VIDEO_LIVE.EXTENSION || MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined)
|
return exists(value) && (value === VIDEO_LIVE.EXTENSION || MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
|
function isVideoFileMimeTypeValid (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
|
||||||
return isFileValid(files, MIMETYPES.VIDEO.MIMETYPES_REGEX, 'videofile', null)
|
return isFileMimeTypeValid(files, MIMETYPES.VIDEO.MIMETYPES_REGEX, 'videofile')
|
||||||
}
|
}
|
||||||
|
|
||||||
const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
|
const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
|
||||||
|
@ -143,12 +143,12 @@ export {
|
||||||
isVideoFPSResolutionValid,
|
isVideoFPSResolutionValid,
|
||||||
isScheduleVideoUpdatePrivacyValid,
|
isScheduleVideoUpdatePrivacyValid,
|
||||||
isVideoOriginallyPublishedAtValid,
|
isVideoOriginallyPublishedAtValid,
|
||||||
isVideoFile,
|
|
||||||
isVideoMagnetUriValid,
|
isVideoMagnetUriValid,
|
||||||
isVideoStateValid,
|
isVideoStateValid,
|
||||||
isVideoViewsValid,
|
isVideoViewsValid,
|
||||||
isVideoRatingTypeValid,
|
isVideoRatingTypeValid,
|
||||||
isVideoFileExtnameValid,
|
isVideoFileExtnameValid,
|
||||||
|
isVideoFileMimeTypeValid,
|
||||||
isVideoDurationValid,
|
isVideoDurationValid,
|
||||||
isVideoTagValid,
|
isVideoTagValid,
|
||||||
isVideoPrivacyValid,
|
isVideoPrivacyValid,
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { ensureDir, remove, writeFile } from 'fs-extra'
|
||||||
import * as request from 'request'
|
import * as request from 'request'
|
||||||
import { createWriteStream } from 'fs'
|
import { createWriteStream } from 'fs'
|
||||||
import { CONFIG } from '@server/initializers/config'
|
import { CONFIG } from '@server/initializers/config'
|
||||||
|
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
export type YoutubeDLInfo = {
|
export type YoutubeDLInfo = {
|
||||||
name?: string
|
name?: string
|
||||||
|
@ -154,7 +155,7 @@ async function updateYoutubeDLBinary () {
|
||||||
return res()
|
return res()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.statusCode !== 302) {
|
if (result.statusCode !== HttpStatusCode.FOUND_302) {
|
||||||
logger.error('youtube-dl update error: did not get redirect for the latest version link. Status %d', result.statusCode)
|
logger.error('youtube-dl update error: did not get redirect for the latest version link. Status %d', result.statusCode)
|
||||||
return res()
|
return res()
|
||||||
}
|
}
|
||||||
|
@ -164,7 +165,7 @@ async function updateYoutubeDLBinary () {
|
||||||
const newVersion = /yt-dl\.org\/downloads\/(\d{4}\.\d\d\.\d\d(\.\d)?)\/youtube-dl/.exec(url)[1]
|
const newVersion = /yt-dl\.org\/downloads\/(\d{4}\.\d\d\.\d\d(\.\d)?)\/youtube-dl/.exec(url)[1]
|
||||||
|
|
||||||
downloadFile.on('response', result => {
|
downloadFile.on('response', result => {
|
||||||
if (result.statusCode !== 200) {
|
if (result.statusCode !== HttpStatusCode.OK_200) {
|
||||||
logger.error('Cannot update youtube-dl: new version response is not 200, it\'s %d.', result.statusCode)
|
logger.error('Cannot update youtube-dl: new version response is not 200, it\'s %d.', result.statusCode)
|
||||||
return res()
|
return res()
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ import {
|
||||||
} from '../../types/models'
|
} from '../../types/models'
|
||||||
import { extname } from 'path'
|
import { extname } from 'path'
|
||||||
import { getServerActor } from '@server/models/application/application'
|
import { getServerActor } from '@server/models/application/application'
|
||||||
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
// Set account keys, this could be long so process after the account creation and do not block the client
|
// Set account keys, this could be long so process after the account creation and do not block the client
|
||||||
function setAsyncActorKeys <T extends MActor> (actor: T) {
|
function setAsyncActorKeys <T extends MActor> (actor: T) {
|
||||||
|
@ -277,7 +278,7 @@ async function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannel
|
||||||
|
|
||||||
const { result, statusCode } = await fetchRemoteActor(actorUrl)
|
const { result, statusCode } = await fetchRemoteActor(actorUrl)
|
||||||
|
|
||||||
if (statusCode === 404) {
|
if (statusCode === HttpStatusCode.NOT_FOUND_404) {
|
||||||
logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url)
|
logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url)
|
||||||
actor.Account
|
actor.Account
|
||||||
? await actor.Account.destroy()
|
? await actor.Account.destroy()
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { createPlaylistMiniatureFromUrl } from '../thumbnail'
|
||||||
import { FilteredModelAttributes } from '../../types/sequelize'
|
import { FilteredModelAttributes } from '../../types/sequelize'
|
||||||
import { MAccountDefault, MAccountId, MVideoId } from '../../types/models'
|
import { MAccountDefault, MAccountId, MVideoId } from '../../types/models'
|
||||||
import { MVideoPlaylist, MVideoPlaylistId, MVideoPlaylistOwner } from '../../types/models/video/video-playlist'
|
import { MVideoPlaylist, MVideoPlaylistId, MVideoPlaylistOwner } from '../../types/models/video/video-playlist'
|
||||||
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: MAccountId, to: string[]) {
|
function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: MAccountId, to: string[]) {
|
||||||
const privacy = to.includes(ACTIVITY_PUB.PUBLIC)
|
const privacy = to.includes(ACTIVITY_PUB.PUBLIC)
|
||||||
|
@ -120,7 +121,7 @@ async function refreshVideoPlaylistIfNeeded (videoPlaylist: MVideoPlaylistOwner)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { statusCode, playlistObject } = await fetchRemoteVideoPlaylist(videoPlaylist.url)
|
const { statusCode, playlistObject } = await fetchRemoteVideoPlaylist(videoPlaylist.url)
|
||||||
if (statusCode === 404) {
|
if (statusCode === HttpStatusCode.NOT_FOUND_404) {
|
||||||
logger.info('Cannot refresh remote video playlist %s: it does not exist anymore. Deleting it.', videoPlaylist.url)
|
logger.info('Cannot refresh remote video playlist %s: it does not exist anymore. Deleting it.', videoPlaylist.url)
|
||||||
|
|
||||||
await videoPlaylist.destroy()
|
await videoPlaylist.destroy()
|
||||||
|
|
|
@ -76,6 +76,7 @@ import { sendCreateVideo, sendUpdateVideo } from './send'
|
||||||
import { addVideoShares, shareVideoByServerAndChannel } from './share'
|
import { addVideoShares, shareVideoByServerAndChannel } from './share'
|
||||||
import { addVideoComments } from './video-comments'
|
import { addVideoComments } from './video-comments'
|
||||||
import { createRates } from './video-rates'
|
import { createRates } from './video-rates'
|
||||||
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVideo: boolean, transaction?: sequelize.Transaction) {
|
async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVideo: boolean, transaction?: sequelize.Transaction) {
|
||||||
const video = videoArg as MVideoAP
|
const video = videoArg as MVideoAP
|
||||||
|
@ -488,7 +489,7 @@ async function refreshVideoIfNeeded (options: {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { response, videoObject } = await fetchRemoteVideo(video.url)
|
const { response, videoObject } = await fetchRemoteVideo(video.url)
|
||||||
if (response.statusCode === 404) {
|
if (response.statusCode === HttpStatusCode.NOT_FOUND_404) {
|
||||||
logger.info('Cannot refresh remote video %s: video does not exist anymore. Deleting it.', video.url)
|
logger.info('Cannot refresh remote video %s: video does not exist anymore. Deleting it.', video.url)
|
||||||
|
|
||||||
// Video does not exist anymore
|
// Video does not exist anymore
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import * as express from 'express'
|
import * as express from 'express'
|
||||||
|
import * as Bluebird from 'bluebird'
|
||||||
import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
|
import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
|
||||||
import {
|
import {
|
||||||
AVATARS_SIZE,
|
AVATARS_SIZE,
|
||||||
|
@ -6,7 +7,8 @@ import {
|
||||||
EMBED_SIZE,
|
EMBED_SIZE,
|
||||||
PLUGIN_GLOBAL_CSS_PATH,
|
PLUGIN_GLOBAL_CSS_PATH,
|
||||||
WEBSERVER,
|
WEBSERVER,
|
||||||
FILES_CONTENT_HASH
|
FILES_CONTENT_HASH,
|
||||||
|
ACCEPT_HEADERS
|
||||||
} from '../initializers/constants'
|
} from '../initializers/constants'
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import { escapeHTML, isTestInstance, sha256 } from '../helpers/core-utils'
|
import { escapeHTML, isTestInstance, sha256 } from '../helpers/core-utils'
|
||||||
|
@ -18,7 +20,6 @@ import { readFile } from 'fs-extra'
|
||||||
import { getActivityStreamDuration } from '../models/video/video-format-utils'
|
import { getActivityStreamDuration } from '../models/video/video-format-utils'
|
||||||
import { AccountModel } from '../models/account/account'
|
import { AccountModel } from '../models/account/account'
|
||||||
import { VideoChannelModel } from '../models/video/video-channel'
|
import { VideoChannelModel } from '../models/video/video-channel'
|
||||||
import * as Bluebird from 'bluebird'
|
|
||||||
import { CONFIG } from '../initializers/config'
|
import { CONFIG } from '../initializers/config'
|
||||||
import { logger } from '../helpers/logger'
|
import { logger } from '../helpers/logger'
|
||||||
import { MAccountActor, MChannelActor } from '../types/models'
|
import { MAccountActor, MChannelActor } from '../types/models'
|
||||||
|
@ -53,7 +54,7 @@ type Tags = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ClientHtml {
|
class ClientHtml {
|
||||||
|
|
||||||
private static htmlCache: { [path: string]: string } = {}
|
private static htmlCache: { [path: string]: string } = {}
|
||||||
|
|
||||||
|
@ -505,3 +506,38 @@ export class ClientHtml {
|
||||||
return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.META_TAGS, tagsString)
|
return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.META_TAGS, tagsString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function sendHTML (html: string, res: express.Response) {
|
||||||
|
res.set('Content-Type', 'text/html; charset=UTF-8')
|
||||||
|
|
||||||
|
return res.send(html)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function serveIndexHTML (req: express.Request, res: express.Response) {
|
||||||
|
if (req.accepts(ACCEPT_HEADERS) === 'html' ||
|
||||||
|
!req.headers.accept) {
|
||||||
|
try {
|
||||||
|
await generateHTMLPage(req, res, req.params.language)
|
||||||
|
return
|
||||||
|
} catch (err) {
|
||||||
|
logger.error('Cannot generate HTML page.', err)
|
||||||
|
return res.sendStatus(HttpStatusCode.INTERNAL_SERVER_ERROR_500)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.sendStatus(HttpStatusCode.NOT_ACCEPTABLE_406)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export {
|
||||||
|
ClientHtml,
|
||||||
|
sendHTML,
|
||||||
|
serveIndexHTML
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateHTMLPage (req: express.Request, res: express.Response, paramLang?: string) {
|
||||||
|
const html = await ClientHtml.getDefaultHTMLPage(req, res, paramLang)
|
||||||
|
|
||||||
|
return sendHTML(html, res)
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { Redis } from '../lib/redis'
|
import { Redis } from '../lib/redis'
|
||||||
import * as apicache from 'apicache'
|
import * as apicache from 'apicache'
|
||||||
|
import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
// Ensure Redis is initialized
|
// Ensure Redis is initialized
|
||||||
Redis.Instance.init()
|
Redis.Instance.init()
|
||||||
|
@ -8,7 +9,10 @@ const defaultOptions = {
|
||||||
redisClient: Redis.Instance.getClient(),
|
redisClient: Redis.Instance.getClient(),
|
||||||
appendKey: () => Redis.Instance.getPrefix(),
|
appendKey: () => Redis.Instance.getPrefix(),
|
||||||
statusCodes: {
|
statusCodes: {
|
||||||
exclude: [ 404, 403 ]
|
exclude: [
|
||||||
|
HttpStatusCode.FORBIDDEN_403,
|
||||||
|
HttpStatusCode.NOT_FOUND_404
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { VideoChangeOwnershipAccept } from '../../../../shared/models/videos/vid
|
||||||
import {
|
import {
|
||||||
isBooleanValid,
|
isBooleanValid,
|
||||||
isDateValid,
|
isDateValid,
|
||||||
|
isFileFieldValid,
|
||||||
isIdOrUUIDValid,
|
isIdOrUUIDValid,
|
||||||
isIdValid,
|
isIdValid,
|
||||||
isUUIDValid,
|
isUUIDValid,
|
||||||
|
@ -22,7 +23,8 @@ import {
|
||||||
isScheduleVideoUpdatePrivacyValid,
|
isScheduleVideoUpdatePrivacyValid,
|
||||||
isVideoCategoryValid,
|
isVideoCategoryValid,
|
||||||
isVideoDescriptionValid,
|
isVideoDescriptionValid,
|
||||||
isVideoFile,
|
isVideoFileMimeTypeValid,
|
||||||
|
isVideoFileSizeValid,
|
||||||
isVideoFilterValid,
|
isVideoFilterValid,
|
||||||
isVideoImage,
|
isVideoImage,
|
||||||
isVideoLanguageValid,
|
isVideoLanguageValid,
|
||||||
|
@ -55,11 +57,11 @@ import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-c
|
||||||
|
|
||||||
const videosAddValidator = getCommonVideoEditAttributes().concat([
|
const videosAddValidator = getCommonVideoEditAttributes().concat([
|
||||||
body('videofile')
|
body('videofile')
|
||||||
.custom((value, { req }) => isVideoFile(req.files)).withMessage(
|
.custom((value, { req }) => isFileFieldValid(req.files, 'videofile'))
|
||||||
'This file is not supported or too large. Please, make sure it is of the following type: ' +
|
.withMessage('Should have a file'),
|
||||||
CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ')
|
body('name')
|
||||||
),
|
.custom(isVideoNameValid)
|
||||||
body('name').custom(isVideoNameValid).withMessage('Should have a valid name'),
|
.withMessage('Should have a valid name'),
|
||||||
body('channelId')
|
body('channelId')
|
||||||
.customSanitizer(toIntOrNull)
|
.customSanitizer(toIntOrNull)
|
||||||
.custom(isIdValid).withMessage('Should have correct video channel id'),
|
.custom(isIdValid).withMessage('Should have correct video channel id'),
|
||||||
|
@ -75,8 +77,27 @@ const videosAddValidator = getCommonVideoEditAttributes().concat([
|
||||||
|
|
||||||
if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req)
|
if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req)
|
||||||
|
|
||||||
|
if (!isVideoFileMimeTypeValid(req.files)) {
|
||||||
|
res.status(HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
|
||||||
|
.json({
|
||||||
|
error: 'This file is not supported. Please, make sure it is of the following type: ' +
|
||||||
|
CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ')
|
||||||
|
})
|
||||||
|
|
||||||
|
return cleanUpReqFiles(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isVideoFileSizeValid(videoFile.size.toString())) {
|
||||||
|
res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413)
|
||||||
|
.json({
|
||||||
|
error: 'This file is too large.'
|
||||||
|
})
|
||||||
|
|
||||||
|
return cleanUpReqFiles(req)
|
||||||
|
}
|
||||||
|
|
||||||
if (await isAbleToUploadVideo(user.id, videoFile.size) === false) {
|
if (await isAbleToUploadVideo(user.id, videoFile.size) === false) {
|
||||||
res.status(HttpStatusCode.FORBIDDEN_403)
|
res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413)
|
||||||
.json({ error: 'The user video quota is exceeded with this video.' })
|
.json({ error: 'The user video quota is exceeded with this video.' })
|
||||||
|
|
||||||
return cleanUpReqFiles(req)
|
return cleanUpReqFiles(req)
|
||||||
|
@ -88,8 +109,8 @@ const videosAddValidator = getCommonVideoEditAttributes().concat([
|
||||||
duration = await getDurationFromVideoFile(videoFile.path)
|
duration = await getDurationFromVideoFile(videoFile.path)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Invalid input file in videosAddValidator.', { err })
|
logger.error('Invalid input file in videosAddValidator.', { err })
|
||||||
res.status(HttpStatusCode.BAD_REQUEST_400)
|
res.status(HttpStatusCode.UNPROCESSABLE_ENTITY_422)
|
||||||
.json({ error: 'Invalid input file.' })
|
.json({ error: 'Video file unreadable.' })
|
||||||
|
|
||||||
return cleanUpReqFiles(req)
|
return cleanUpReqFiles(req)
|
||||||
}
|
}
|
||||||
|
@ -295,7 +316,7 @@ const videosAcceptChangeOwnershipValidator = [
|
||||||
const videoChangeOwnership = res.locals.videoChangeOwnership
|
const videoChangeOwnership = res.locals.videoChangeOwnership
|
||||||
const isAble = await isAbleToUploadVideo(user.id, videoChangeOwnership.Video.getMaxQualityFile().size)
|
const isAble = await isAbleToUploadVideo(user.id, videoChangeOwnership.Video.getMaxQualityFile().size)
|
||||||
if (isAble === false) {
|
if (isAble === false) {
|
||||||
res.status(HttpStatusCode.FORBIDDEN_403)
|
res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413)
|
||||||
.json({ error: 'The user video quota is exceeded with this video.' })
|
.json({ error: 'The user video quota is exceeded with this video.' })
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -11,6 +11,7 @@ import {
|
||||||
setAccessTokensToServers,
|
setAccessTokensToServers,
|
||||||
uploadVideo
|
uploadVideo
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ describe('Test activitypub', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should redirect to the origin video object', async function () {
|
it('Should redirect to the origin video object', async function () {
|
||||||
const res = await makeActivityPubGetRequest(servers[1].url, '/videos/watch/' + videoUUID, 302)
|
const res = await makeActivityPubGetRequest(servers[1].url, '/videos/watch/' + videoUUID, HttpStatusCode.FOUND_302)
|
||||||
|
|
||||||
expect(res.header.location).to.equal('http://localhost:' + servers[0].port + '/videos/watch/' + videoUUID)
|
expect(res.header.location).to.equal('http://localhost:' + servers[0].port + '/videos/watch/' + videoUUID)
|
||||||
})
|
})
|
||||||
|
|
|
@ -24,6 +24,7 @@ import {
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
import { getAccount } from '../../../../shared/extra-utils/users/accounts'
|
import { getAccount } from '../../../../shared/extra-utils/users/accounts'
|
||||||
import { VideoPlaylistPrivacy } from '../../../../shared/models/videos'
|
import { VideoPlaylistPrivacy } from '../../../../shared/models/videos'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
describe('Test AP refresher', function () {
|
describe('Test AP refresher', function () {
|
||||||
let servers: ServerInfo[] = []
|
let servers: ServerInfo[] = []
|
||||||
|
@ -86,8 +87,8 @@ describe('Test AP refresher', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await getVideo(servers[0].url, videoUUID1, 404)
|
await getVideo(servers[0].url, videoUUID1, HttpStatusCode.NOT_FOUND_404)
|
||||||
await getVideo(servers[0].url, videoUUID2, 200)
|
await getVideo(servers[0].url, videoUUID2, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not update a remote video if the remote instance is down', async function () {
|
it('Should not update a remote video if the remote instance is down', async function () {
|
||||||
|
@ -106,7 +107,7 @@ describe('Test AP refresher', function () {
|
||||||
|
|
||||||
await reRunServer(servers[1])
|
await reRunServer(servers[1])
|
||||||
|
|
||||||
await getVideo(servers[0].url, videoUUID3, 200)
|
await getVideo(servers[0].url, videoUUID3, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -126,8 +127,8 @@ describe('Test AP refresher', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await getAccount(servers[0].url, 'user1@localhost:' + servers[1].port, 200)
|
await getAccount(servers[0].url, 'user1@localhost:' + servers[1].port, HttpStatusCode.OK_200)
|
||||||
await getAccount(servers[0].url, 'user2@localhost:' + servers[1].port, 404)
|
await getAccount(servers[0].url, 'user2@localhost:' + servers[1].port, HttpStatusCode.NOT_FOUND_404)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -146,8 +147,8 @@ describe('Test AP refresher', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await getVideoPlaylist(servers[0].url, playlistUUID1, 200)
|
await getVideoPlaylist(servers[0].url, playlistUUID1, HttpStatusCode.OK_200)
|
||||||
await getVideoPlaylist(servers[0].url, playlistUUID2, 404)
|
await getVideoPlaylist(servers[0].url, playlistUUID2, HttpStatusCode.NOT_FOUND_404)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
checkBadStartPagination
|
checkBadStartPagination
|
||||||
} from '../../../../shared/extra-utils/requests/check-api-params'
|
} from '../../../../shared/extra-utils/requests/check-api-params'
|
||||||
import { getAccount } from '../../../../shared/extra-utils/users/accounts'
|
import { getAccount } from '../../../../shared/extra-utils/users/accounts'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
describe('Test accounts API validators', function () {
|
describe('Test accounts API validators', function () {
|
||||||
const path = '/api/v1/accounts/'
|
const path = '/api/v1/accounts/'
|
||||||
|
@ -38,7 +39,7 @@ describe('Test accounts API validators', function () {
|
||||||
|
|
||||||
describe('When getting an account', function () {
|
describe('When getting an account', function () {
|
||||||
it('Should return 404 with a non existing name', async function () {
|
it('Should return 404 with a non existing name', async function () {
|
||||||
await getAccount(server.url, 'arfaze', 404)
|
await getAccount(server.url, 'arfaze', HttpStatusCode.NOT_FOUND_404)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'mocha'
|
||||||
import { cleanupTests, flushAndRunServer, immutableAssign, killallServers, reRunServer, ServerInfo } from '../../../../shared/extra-utils'
|
import { cleanupTests, flushAndRunServer, immutableAssign, killallServers, reRunServer, ServerInfo } from '../../../../shared/extra-utils'
|
||||||
import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form'
|
import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form'
|
||||||
import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
|
import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
describe('Test contact form API validators', function () {
|
describe('Test contact form API validators', function () {
|
||||||
let server: ServerInfo
|
let server: ServerInfo
|
||||||
|
@ -29,7 +30,7 @@ describe('Test contact form API validators', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not accept a contact form if emails are disabled', async function () {
|
it('Should not accept a contact form if emails are disabled', async function () {
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 409 }))
|
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: HttpStatusCode.CONFLICT_409 }))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not accept a contact form if it is disabled in the configuration', async function () {
|
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 () {
|
||||||
|
|
||||||
// Contact form is disabled
|
// Contact form is disabled
|
||||||
await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort }, contact_form: { enabled: false } })
|
await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort }, contact_form: { enabled: false } })
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 409 }))
|
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: HttpStatusCode.CONFLICT_409 }))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not accept a contact form if from email is invalid', async function () {
|
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 () {
|
||||||
// Email & contact form enabled
|
// Email & contact form enabled
|
||||||
await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort } })
|
await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort } })
|
||||||
|
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: 'badEmail' }))
|
await sendContactForm(immutableAssign(defaultBody, {
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: 'badEmail@' }))
|
url: server.url,
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: undefined }))
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
fromEmail: 'badEmail'
|
||||||
|
}))
|
||||||
|
await sendContactForm(immutableAssign(defaultBody, {
|
||||||
|
url: server.url,
|
||||||
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
fromEmail: 'badEmail@'
|
||||||
|
}))
|
||||||
|
await sendContactForm(immutableAssign(defaultBody, {
|
||||||
|
url: server.url,
|
||||||
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
fromEmail: undefined
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not accept a contact form if from name is invalid', async function () {
|
it('Should not accept a contact form if from name is invalid', async function () {
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: 'name'.repeat(100) }))
|
await sendContactForm(immutableAssign(defaultBody, {
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: '' }))
|
url: server.url,
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: undefined }))
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
fromName: 'name'.repeat(100)
|
||||||
|
}))
|
||||||
|
await sendContactForm(immutableAssign(defaultBody, {
|
||||||
|
url: server.url,
|
||||||
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
fromName: ''
|
||||||
|
}))
|
||||||
|
await sendContactForm(immutableAssign(defaultBody, {
|
||||||
|
url: server.url,
|
||||||
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
fromName: undefined
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not accept a contact form if body is invalid', async function () {
|
it('Should not accept a contact form if body is invalid', async function () {
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: 'body'.repeat(5000) }))
|
await sendContactForm(immutableAssign(defaultBody, {
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: 'a' }))
|
url: server.url,
|
||||||
await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: undefined }))
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
body: 'body'.repeat(5000)
|
||||||
|
}))
|
||||||
|
await sendContactForm(immutableAssign(defaultBody, {
|
||||||
|
url: server.url,
|
||||||
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
body: 'a'
|
||||||
|
}))
|
||||||
|
await sendContactForm(immutableAssign(defaultBody, {
|
||||||
|
url: server.url,
|
||||||
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400,
|
||||||
|
body: undefined
|
||||||
|
}))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should accept a contact form with the correct parameters', async function () {
|
it('Should accept a contact form with the correct parameters', async function () {
|
||||||
|
|
|
@ -1102,7 +1102,7 @@ describe('Test users API validators', function () {
|
||||||
videoQuota: 42
|
videoQuota: 42
|
||||||
})
|
})
|
||||||
|
|
||||||
await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403)
|
await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a registered user having too many videos', async function () {
|
it('Should fail with a registered user having too many videos', async function () {
|
||||||
|
@ -1120,7 +1120,7 @@ describe('Test users API validators', function () {
|
||||||
await uploadVideo(server.url, userAccessToken, videoAttributes)
|
await uploadVideo(server.url, userAccessToken, videoAttributes)
|
||||||
await uploadVideo(server.url, userAccessToken, videoAttributes)
|
await uploadVideo(server.url, userAccessToken, videoAttributes)
|
||||||
await uploadVideo(server.url, userAccessToken, videoAttributes)
|
await uploadVideo(server.url, userAccessToken, videoAttributes)
|
||||||
await uploadVideo(server.url, userAccessToken, videoAttributes, HttpStatusCode.FORBIDDEN_403)
|
await uploadVideo(server.url, userAccessToken, videoAttributes, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail to import with HTTP/Torrent/magnet', async function () {
|
it('Should fail to import with HTTP/Torrent/magnet', async function () {
|
||||||
|
@ -1151,7 +1151,7 @@ describe('Test users API validators', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('When having a daily video quota', function () {
|
describe('When having a daily video quota', function () {
|
||||||
it('Should fail with a user having too many videos', async function () {
|
it('Should fail with a user having too many videos daily', async function () {
|
||||||
await updateUser({
|
await updateUser({
|
||||||
url: server.url,
|
url: server.url,
|
||||||
userId: rootId,
|
userId: rootId,
|
||||||
|
@ -1159,7 +1159,7 @@ describe('Test users API validators', function () {
|
||||||
videoQuotaDaily: 42
|
videoQuotaDaily: 42
|
||||||
})
|
})
|
||||||
|
|
||||||
await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403)
|
await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1173,7 +1173,7 @@ describe('Test users API validators', function () {
|
||||||
videoQuotaDaily: 1024 * 1024 * 1024
|
videoQuotaDaily: 1024 * 1024 * 1024
|
||||||
})
|
})
|
||||||
|
|
||||||
await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403)
|
await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail if exceeding daily quota', async function () {
|
it('Should fail if exceeding daily quota', async function () {
|
||||||
|
@ -1185,7 +1185,7 @@ describe('Test users API validators', function () {
|
||||||
videoQuotaDaily: 42
|
videoQuotaDaily: 42
|
||||||
})
|
})
|
||||||
|
|
||||||
await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403)
|
await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -348,12 +348,26 @@ describe('Test videos API validator', function () {
|
||||||
let attaches = {
|
let attaches = {
|
||||||
videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short_fake.webm')
|
videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short_fake.webm')
|
||||||
}
|
}
|
||||||
await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
|
await makeUploadRequest({
|
||||||
|
url: server.url,
|
||||||
|
path: path + '/upload',
|
||||||
|
token: server.accessToken,
|
||||||
|
fields,
|
||||||
|
attaches,
|
||||||
|
statusCodeExpected: HttpStatusCode.UNPROCESSABLE_ENTITY_422
|
||||||
|
})
|
||||||
|
|
||||||
attaches = {
|
attaches = {
|
||||||
videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mkv')
|
videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mkv')
|
||||||
}
|
}
|
||||||
await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
|
await makeUploadRequest({
|
||||||
|
url: server.url,
|
||||||
|
path: path + '/upload',
|
||||||
|
token: server.accessToken,
|
||||||
|
fields,
|
||||||
|
attaches,
|
||||||
|
statusCodeExpected: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with an incorrect thumbnail file', async function () {
|
it('Should fail with an incorrect thumbnail file', async function () {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
waitJobs,
|
waitJobs,
|
||||||
waitUntilLiveStarts
|
waitUntilLiveStarts
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -118,7 +119,7 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await checkVideosExist(liveVideoUUID, false, 200)
|
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
|
||||||
await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
|
await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -130,7 +131,7 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await checkVideosExist(liveVideoUUID, true, 200)
|
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
|
||||||
await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
|
await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -142,7 +143,7 @@ describe('Save replay setting', function () {
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
// Live still exist, but cannot be played anymore
|
// Live still exist, but cannot be played anymore
|
||||||
await checkVideosExist(liveVideoUUID, false, 200)
|
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
|
||||||
await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
|
await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
|
||||||
|
|
||||||
// No resolutions saved since we did not save replay
|
// No resolutions saved since we did not save replay
|
||||||
|
@ -158,7 +159,7 @@ describe('Save replay setting', function () {
|
||||||
await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
await checkVideosExist(liveVideoUUID, true, 200)
|
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
|
addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
|
||||||
|
@ -169,8 +170,8 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
await checkVideosExist(liveVideoUUID, false)
|
await checkVideosExist(liveVideoUUID, false)
|
||||||
|
|
||||||
await getVideo(servers[0].url, liveVideoUUID, 401)
|
await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
|
||||||
await getVideo(servers[1].url, liveVideoUUID, 404)
|
await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
|
||||||
|
|
||||||
await checkLiveCleanup(servers[0], liveVideoUUID, [])
|
await checkLiveCleanup(servers[0], liveVideoUUID, [])
|
||||||
})
|
})
|
||||||
|
@ -184,7 +185,7 @@ describe('Save replay setting', function () {
|
||||||
await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
await checkVideosExist(liveVideoUUID, true, 200)
|
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
testFfmpegStreamError(ffmpegCommand, true),
|
testFfmpegStreamError(ffmpegCommand, true),
|
||||||
|
@ -193,7 +194,7 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await checkVideosExist(liveVideoUUID, false, 404)
|
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
|
||||||
await checkLiveCleanup(servers[0], liveVideoUUID, [])
|
await checkLiveCleanup(servers[0], liveVideoUUID, [])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -207,7 +208,7 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await checkVideosExist(liveVideoUUID, false, 200)
|
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
|
||||||
await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
|
await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -219,7 +220,7 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await checkVideosExist(liveVideoUUID, true, 200)
|
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
|
||||||
await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
|
await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -231,7 +232,7 @@ describe('Save replay setting', function () {
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
// Live has been transcoded
|
// Live has been transcoded
|
||||||
await checkVideosExist(liveVideoUUID, true, 200)
|
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
|
||||||
await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
|
await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -261,7 +262,7 @@ describe('Save replay setting', function () {
|
||||||
await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
await checkVideosExist(liveVideoUUID, true, 200)
|
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
|
addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
|
||||||
|
@ -272,8 +273,8 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
await checkVideosExist(liveVideoUUID, false)
|
await checkVideosExist(liveVideoUUID, false)
|
||||||
|
|
||||||
await getVideo(servers[0].url, liveVideoUUID, 401)
|
await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
|
||||||
await getVideo(servers[1].url, liveVideoUUID, 404)
|
await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
|
||||||
|
|
||||||
await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
|
await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
|
||||||
})
|
})
|
||||||
|
@ -287,7 +288,7 @@ describe('Save replay setting', function () {
|
||||||
await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
await checkVideosExist(liveVideoUUID, true, 200)
|
await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID),
|
removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID),
|
||||||
|
@ -296,7 +297,7 @@ describe('Save replay setting', function () {
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
await checkVideosExist(liveVideoUUID, false, 404)
|
await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
|
||||||
await checkLiveCleanup(servers[0], liveVideoUUID, [])
|
await checkLiveCleanup(servers[0], liveVideoUUID, [])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -44,6 +44,7 @@ import {
|
||||||
waitUntilLiveStarts,
|
waitUntilLiveStarts,
|
||||||
waitUntilLog
|
waitUntilLog
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -164,8 +165,8 @@ describe('Test live', function () {
|
||||||
expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED)
|
expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED)
|
||||||
expect(video.nsfw).to.be.true
|
expect(video.nsfw).to.be.true
|
||||||
|
|
||||||
await makeRawRequest(server.url + video.thumbnailPath, 200)
|
await makeRawRequest(server.url + video.thumbnailPath, HttpStatusCode.OK_200)
|
||||||
await makeRawRequest(server.url + video.previewPath, 200)
|
await makeRawRequest(server.url + video.previewPath, HttpStatusCode.OK_200)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -179,7 +180,7 @@ describe('Test live', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not be able to update a live of another server', async function () {
|
it('Should not be able to update a live of another server', async function () {
|
||||||
await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, 403)
|
await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should update the live', async function () {
|
it('Should update the live', async function () {
|
||||||
|
@ -215,8 +216,8 @@ describe('Test live', function () {
|
||||||
|
|
||||||
it('Should have the live deleted', async function () {
|
it('Should have the live deleted', async function () {
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await getVideo(server.url, liveVideoUUID, 404)
|
await getVideo(server.url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
|
||||||
await getLive(server.url, server.accessToken, liveVideoUUID, 404)
|
await getLive(server.url, server.accessToken, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -430,8 +431,8 @@ describe('Test live', function () {
|
||||||
expect(video.files).to.have.lengthOf(0)
|
expect(video.files).to.have.lengthOf(0)
|
||||||
|
|
||||||
const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS)
|
const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS)
|
||||||
await makeRawRequest(hlsPlaylist.playlistUrl, 200)
|
await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200)
|
||||||
await makeRawRequest(hlsPlaylist.segmentsSha256Url, 200)
|
await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200)
|
||||||
|
|
||||||
expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length)
|
expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length)
|
||||||
|
|
||||||
|
@ -455,8 +456,8 @@ describe('Test live', function () {
|
||||||
|
|
||||||
expect(probe.format.bit_rate).to.be.below(bitrateLimits[videoStream.height])
|
expect(probe.format.bit_rate).to.be.below(bitrateLimits[videoStream.height])
|
||||||
|
|
||||||
await makeRawRequest(file.torrentUrl, 200)
|
await makeRawRequest(file.torrentUrl, HttpStatusCode.OK_200)
|
||||||
await makeRawRequest(file.fileUrl, 200)
|
await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
uploadVideo
|
uploadVideo
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
import { ServerConfig } from '../../../../shared/models'
|
import { ServerConfig } from '../../../../shared/models'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -237,8 +238,8 @@ describe('Test config', function () {
|
||||||
expect(data.video.file.extensions).to.contain('.webm')
|
expect(data.video.file.extensions).to.contain('.webm')
|
||||||
expect(data.video.file.extensions).to.contain('.ogv')
|
expect(data.video.file.extensions).to.contain('.ogv')
|
||||||
|
|
||||||
await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, 400)
|
await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
|
||||||
await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, 400)
|
await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
|
||||||
|
|
||||||
expect(data.contactForm.enabled).to.be.true
|
expect(data.contactForm.enabled).to.be.true
|
||||||
})
|
})
|
||||||
|
@ -427,8 +428,8 @@ describe('Test config', function () {
|
||||||
expect(data.video.file.extensions).to.contain('.ogg')
|
expect(data.video.file.extensions).to.contain('.ogg')
|
||||||
expect(data.video.file.extensions).to.contain('.flac')
|
expect(data.video.file.extensions).to.contain('.flac')
|
||||||
|
|
||||||
await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, 200)
|
await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, HttpStatusCode.OK_200)
|
||||||
await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, 200)
|
await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should have the configuration updated after a restart', async function () {
|
it('Should have the configuration updated after a restart', async function () {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { cleanupTests, flushAndRunServer, ServerInfo, setAccessTokensToServers,
|
||||||
import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
|
import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
|
||||||
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
||||||
import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form'
|
import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -67,7 +68,7 @@ describe('Test contact form', function () {
|
||||||
body: 'my super message',
|
body: 'my super message',
|
||||||
fromName: 'Super toto',
|
fromName: 'Super toto',
|
||||||
subject: 'my subject',
|
subject: 'my subject',
|
||||||
expectedStatus: 403
|
expectedStatus: HttpStatusCode.FORBIDDEN_403
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import {
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
|
import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
|
||||||
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -116,7 +117,7 @@ describe('Test emails', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not reset the password with an invalid verification string', async function () {
|
it('Should not reset the password with an invalid verification string', async function () {
|
||||||
await resetPassword(server.url, userId, verificationString + 'b', 'super_password2', 403)
|
await resetPassword(server.url, userId, verificationString + 'b', 'super_password2', HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should reset the password', async function () {
|
it('Should reset the password', async function () {
|
||||||
|
@ -124,7 +125,7 @@ describe('Test emails', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not reset the password with the same verification string', async function () {
|
it('Should not reset the password with the same verification string', async function () {
|
||||||
await resetPassword(server.url, userId, verificationString, 'super_password3', 403)
|
await resetPassword(server.url, userId, verificationString, 'super_password3', HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should login with this new password', async function () {
|
it('Should login with this new password', async function () {
|
||||||
|
@ -169,7 +170,7 @@ describe('Test emails', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not reset the password with an invalid verification string', async function () {
|
it('Should not reset the password with an invalid verification string', async function () {
|
||||||
await resetPassword(server.url, userId2, verificationString2 + 'c', 'newly_created_password', 403)
|
await resetPassword(server.url, userId2, verificationString2 + 'c', 'newly_created_password', HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should reset the password', async function () {
|
it('Should reset the password', async function () {
|
||||||
|
@ -210,7 +211,7 @@ describe('Test emails', function () {
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
|
|
||||||
const reason = 'my super bad reason'
|
const reason = 'my super bad reason'
|
||||||
await blockUser(server.url, userId, server.accessToken, 204, reason)
|
await blockUser(server.url, userId, server.accessToken, HttpStatusCode.NO_CONTENT_204, reason)
|
||||||
|
|
||||||
await waitJobs(server)
|
await waitJobs(server)
|
||||||
expect(emails).to.have.lengthOf(4)
|
expect(emails).to.have.lengthOf(4)
|
||||||
|
@ -228,7 +229,7 @@ describe('Test emails', function () {
|
||||||
it('Should send the notification email when unblocking a user', async function () {
|
it('Should send the notification email when unblocking a user', async function () {
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
|
|
||||||
await unblockUser(server.url, userId, server.accessToken, 204)
|
await unblockUser(server.url, userId, server.accessToken, HttpStatusCode.NO_CONTENT_204)
|
||||||
|
|
||||||
await waitJobs(server)
|
await waitJobs(server)
|
||||||
expect(emails).to.have.lengthOf(5)
|
expect(emails).to.have.lengthOf(5)
|
||||||
|
@ -317,7 +318,7 @@ describe('Test emails', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not verify the email with an invalid verification string', async function () {
|
it('Should not verify the email with an invalid verification string', async function () {
|
||||||
await verifyEmail(server.url, userId, verificationString + 'b', false, 403)
|
await verifyEmail(server.url, userId, verificationString + 'b', false, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should verify the email', async function () {
|
it('Should verify the email', async function () {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import {
|
||||||
import { unfollow } from '../../../../shared/extra-utils/server/follows'
|
import { unfollow } from '../../../../shared/extra-utils/server/follows'
|
||||||
import { userLogin } from '../../../../shared/extra-utils/users/login'
|
import { userLogin } from '../../../../shared/extra-utils/users/login'
|
||||||
import { createUser } from '../../../../shared/extra-utils/users/users'
|
import { createUser } from '../../../../shared/extra-utils/users/users'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -58,11 +59,11 @@ describe('Test follow constraints', function () {
|
||||||
describe('With an unlogged user', function () {
|
describe('With an unlogged user', function () {
|
||||||
|
|
||||||
it('Should get the local video', async function () {
|
it('Should get the local video', async function () {
|
||||||
await getVideo(servers[0].url, video1UUID, 200)
|
await getVideo(servers[0].url, video1UUID, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should get the remote video', async function () {
|
it('Should get the remote video', async function () {
|
||||||
await getVideo(servers[0].url, video2UUID, 200)
|
await getVideo(servers[0].url, video2UUID, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should list local account videos', async function () {
|
it('Should list local account videos', async function () {
|
||||||
|
@ -98,11 +99,11 @@ describe('Test follow constraints', function () {
|
||||||
|
|
||||||
describe('With a logged user', function () {
|
describe('With a logged user', function () {
|
||||||
it('Should get the local video', async function () {
|
it('Should get the local video', async function () {
|
||||||
await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, 200)
|
await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should get the remote video', async function () {
|
it('Should get the remote video', async function () {
|
||||||
await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, 200)
|
await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should list local account videos', async function () {
|
it('Should list local account videos', async function () {
|
||||||
|
@ -148,11 +149,11 @@ describe('Test follow constraints', function () {
|
||||||
describe('With an unlogged user', function () {
|
describe('With an unlogged user', function () {
|
||||||
|
|
||||||
it('Should get the local video', async function () {
|
it('Should get the local video', async function () {
|
||||||
await getVideo(servers[0].url, video1UUID, 200)
|
await getVideo(servers[0].url, video1UUID, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not get the remote video', async function () {
|
it('Should not get the remote video', async function () {
|
||||||
await getVideo(servers[0].url, video2UUID, 403)
|
await getVideo(servers[0].url, video2UUID, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should list local account videos', async function () {
|
it('Should list local account videos', async function () {
|
||||||
|
@ -188,11 +189,11 @@ describe('Test follow constraints', function () {
|
||||||
|
|
||||||
describe('With a logged user', function () {
|
describe('With a logged user', function () {
|
||||||
it('Should get the local video', async function () {
|
it('Should get the local video', async function () {
|
||||||
await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, 200)
|
await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should get the remote video', async function () {
|
it('Should get the remote video', async function () {
|
||||||
await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, 200)
|
await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should list local account videos', async function () {
|
it('Should list local account videos', async function () {
|
||||||
|
|
|
@ -33,6 +33,7 @@ import {
|
||||||
getVideoCommentThreads,
|
getVideoCommentThreads,
|
||||||
getVideoThreadComments
|
getVideoThreadComments
|
||||||
} from '../../../../shared/extra-utils/videos/video-comments'
|
} from '../../../../shared/extra-utils/videos/video-comments'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -352,7 +353,7 @@ describe('Test handle downs', function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const id of videoIdsServer1) {
|
for (const id of videoIdsServer1) {
|
||||||
await getVideo(servers[1].url, id, 403)
|
await getVideo(servers[1].url, id, HttpStatusCode.FORBIDDEN_403)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'mocha'
|
||||||
import * as request from 'supertest'
|
import * as request from 'supertest'
|
||||||
import { ServerInfo } from '../../../../shared/extra-utils'
|
import { ServerInfo } from '../../../../shared/extra-utils'
|
||||||
import { cleanupTests, flushAndRunServer } from '../../../../shared/extra-utils/server/servers'
|
import { cleanupTests, flushAndRunServer } from '../../../../shared/extra-utils/server/servers'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
describe('Start and stop server without web client routes', function () {
|
describe('Start and stop server without web client routes', function () {
|
||||||
let server: ServerInfo
|
let server: ServerInfo
|
||||||
|
@ -16,7 +17,7 @@ describe('Start and stop server without web client routes', function () {
|
||||||
const req = request(server.url)
|
const req = request(server.url)
|
||||||
.get('/')
|
.get('/')
|
||||||
|
|
||||||
return req.expect(404)
|
return req.expect(HttpStatusCode.NOT_FOUND_404)
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'mocha'
|
||||||
import * as chai from 'chai'
|
import * as chai from 'chai'
|
||||||
import { cleanupTests, getVideo, registerUser, uploadVideo, userLogin, viewVideo, wait } from '../../../../shared/extra-utils'
|
import { cleanupTests, getVideo, registerUser, uploadVideo, userLogin, viewVideo, wait } from '../../../../shared/extra-utils'
|
||||||
import { flushAndRunServer, setAccessTokensToServers } from '../../../../shared/extra-utils/index'
|
import { flushAndRunServer, setAccessTokensToServers } from '../../../../shared/extra-utils/index'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -56,8 +57,8 @@ describe('Test application behind a reverse proxy', function () {
|
||||||
it('Should view a video 2 times with the X-Forwarded-For header set', async function () {
|
it('Should view a video 2 times with the X-Forwarded-For header set', async function () {
|
||||||
this.timeout(20000)
|
this.timeout(20000)
|
||||||
|
|
||||||
await viewVideo(server.url, videoId, 204, '0.0.0.1,127.0.0.1')
|
await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.1,127.0.0.1')
|
||||||
await viewVideo(server.url, videoId, 204, '0.0.0.2,127.0.0.1')
|
await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.2,127.0.0.1')
|
||||||
|
|
||||||
// Wait the repeatable job
|
// Wait the repeatable job
|
||||||
await wait(8000)
|
await wait(8000)
|
||||||
|
@ -69,8 +70,8 @@ describe('Test application behind a reverse proxy', function () {
|
||||||
it('Should view a video only once with the same client IP in the X-Forwarded-For header', async function () {
|
it('Should view a video only once with the same client IP in the X-Forwarded-For header', async function () {
|
||||||
this.timeout(20000)
|
this.timeout(20000)
|
||||||
|
|
||||||
await viewVideo(server.url, videoId, 204, '0.0.0.4,0.0.0.3,::ffff:127.0.0.1')
|
await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.4,0.0.0.3,::ffff:127.0.0.1')
|
||||||
await viewVideo(server.url, videoId, 204, '0.0.0.5,0.0.0.3,127.0.0.1')
|
await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.5,0.0.0.3,127.0.0.1')
|
||||||
|
|
||||||
// Wait the repeatable job
|
// Wait the repeatable job
|
||||||
await wait(8000)
|
await wait(8000)
|
||||||
|
@ -82,8 +83,8 @@ describe('Test application behind a reverse proxy', function () {
|
||||||
it('Should view a video two times with a different client IP in the X-Forwarded-For header', async function () {
|
it('Should view a video two times with a different client IP in the X-Forwarded-For header', async function () {
|
||||||
this.timeout(20000)
|
this.timeout(20000)
|
||||||
|
|
||||||
await viewVideo(server.url, videoId, 204, '0.0.0.8,0.0.0.6,127.0.0.1')
|
await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.8,0.0.0.6,127.0.0.1')
|
||||||
await viewVideo(server.url, videoId, 204, '0.0.0.8,0.0.0.7,127.0.0.1')
|
await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.8,0.0.0.7,127.0.0.1')
|
||||||
|
|
||||||
// Wait the repeatable job
|
// Wait the repeatable job
|
||||||
await wait(8000)
|
await wait(8000)
|
||||||
|
@ -96,10 +97,10 @@ describe('Test application behind a reverse proxy', function () {
|
||||||
const user = { username: 'root', password: 'fail' }
|
const user = { username: 'root', password: 'fail' }
|
||||||
|
|
||||||
for (let i = 0; i < 19; i++) {
|
for (let i = 0; i < 19; i++) {
|
||||||
await userLogin(server, user, 400)
|
await userLogin(server, user, HttpStatusCode.BAD_REQUEST_400)
|
||||||
}
|
}
|
||||||
|
|
||||||
await userLogin(server, user, 429)
|
await userLogin(server, user, HttpStatusCode.TOO_MANY_REQUESTS_429)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should rate limit signup', async function () {
|
it('Should rate limit signup', async function () {
|
||||||
|
@ -111,7 +112,7 @@ describe('Test application behind a reverse proxy', function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await registerUser(server.url, 'test42', 'password', 429)
|
await registerUser(server.url, 'test42', 'password', HttpStatusCode.TOO_MANY_REQUESTS_429)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not rate limit failed signup', async function () {
|
it('Should not rate limit failed signup', async function () {
|
||||||
|
@ -120,10 +121,10 @@ describe('Test application behind a reverse proxy', function () {
|
||||||
await wait(7000)
|
await wait(7000)
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
await registerUser(server.url, 'test' + i, 'password', 409)
|
await registerUser(server.url, 'test' + i, 'password', HttpStatusCode.CONFLICT_409)
|
||||||
}
|
}
|
||||||
|
|
||||||
await registerUser(server.url, 'test43', 'password', 204)
|
await registerUser(server.url, 'test43', 'password', HttpStatusCode.NO_CONTENT_204)
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -140,7 +141,7 @@ describe('Test application behind a reverse proxy', function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await getVideo(server.url, videoId, 429)
|
await getVideo(server.url, videoId, HttpStatusCode.TOO_MANY_REQUESTS_429)
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -41,6 +41,7 @@ import {
|
||||||
findCommentId
|
findCommentId
|
||||||
} from '../../../../shared/extra-utils/videos/video-comments'
|
} from '../../../../shared/extra-utils/videos/video-comments'
|
||||||
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -999,7 +1000,7 @@ describe('Test multiple servers', function () {
|
||||||
expect(res.body.downloadEnabled).to.be.false
|
expect(res.body.downloadEnabled).to.be.false
|
||||||
|
|
||||||
const text = 'my super forbidden comment'
|
const text = 'my super forbidden comment'
|
||||||
await addVideoCommentThread(server.url, server.accessToken, videoUUID, text, 409)
|
await addVideoCommentThread(server.url, server.accessToken, videoUUID, text, HttpStatusCode.CONFLICT_409)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1021,7 +1022,7 @@ describe('Test multiple servers', function () {
|
||||||
const filePath = join(__dirname, '..', '..', 'fixtures', 'video_short.webm')
|
const filePath = join(__dirname, '..', '..', 'fixtures', 'video_short.webm')
|
||||||
|
|
||||||
await req.attach('videofile', filePath)
|
await req.attach('videofile', filePath)
|
||||||
.expect(200)
|
.expect(HttpStatusCode.OK_200)
|
||||||
|
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
||||||
import { User } from '../../../../shared/models/users'
|
import { User } from '../../../../shared/models/users'
|
||||||
import { VideoDetails } from '../../../../shared/models/videos'
|
import { VideoDetails } from '../../../../shared/models/videos'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -140,7 +141,7 @@ describe('Test video change ownership - nominal', function () {
|
||||||
it('Should not be possible to refuse the change of ownership from first user', async function () {
|
it('Should not be possible to refuse the change of ownership from first user', async function () {
|
||||||
this.timeout(10000)
|
this.timeout(10000)
|
||||||
|
|
||||||
await refuseChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, 403)
|
await refuseChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should be possible to refuse the change of ownership from second user', async function () {
|
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 () {
|
||||||
const secondUserInformationResponse = await getMyUserInformation(servers[0].url, secondUserAccessToken)
|
const secondUserInformationResponse = await getMyUserInformation(servers[0].url, secondUserAccessToken)
|
||||||
const secondUserInformation: User = secondUserInformationResponse.body
|
const secondUserInformation: User = secondUserInformationResponse.body
|
||||||
const channelId = secondUserInformation.videoChannels[0].id
|
const channelId = secondUserInformation.videoChannels[0].id
|
||||||
await acceptChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, channelId, 403)
|
await acceptChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, channelId, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should be possible to accept the change of ownership from second user', async function () {
|
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 () {
|
||||||
const secondUserInformationResponse = await getMyUserInformation(server.url, secondUserAccessToken)
|
const secondUserInformationResponse = await getMyUserInformation(server.url, secondUserAccessToken)
|
||||||
const secondUserInformation: User = secondUserInformationResponse.body
|
const secondUserInformation: User = secondUserInformationResponse.body
|
||||||
const channelId = secondUserInformation.videoChannels[0].id
|
const channelId = secondUserInformation.videoChannels[0].id
|
||||||
await acceptChangeOwnership(server.url, secondUserAccessToken, lastRequestChangeOwnershipId, channelId, 403)
|
|
||||||
|
await acceptChangeOwnership(
|
||||||
|
server.url,
|
||||||
|
secondUserAccessToken,
|
||||||
|
lastRequestChangeOwnershipId,
|
||||||
|
channelId,
|
||||||
|
HttpStatusCode.PAYLOAD_TOO_LARGE_413
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
import { VideoDetails } from '../../../../shared/models/videos'
|
import { VideoDetails } from '../../../../shared/models/videos'
|
||||||
import { VideoStreamingPlaylistType } from '../../../../shared/models/videos/video-streaming-playlist.type'
|
import { VideoStreamingPlaylistType } from '../../../../shared/models/videos/video-streaming-playlist.type'
|
||||||
import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants'
|
import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -57,8 +58,8 @@ async function checkHlsPlaylist (servers: ServerInfo[], videoUUID: string, hlsOn
|
||||||
)
|
)
|
||||||
expect(file.resolution.label).to.equal(resolution + 'p')
|
expect(file.resolution.label).to.equal(resolution + 'p')
|
||||||
|
|
||||||
await makeRawRequest(file.torrentUrl, 200)
|
await makeRawRequest(file.torrentUrl, HttpStatusCode.OK_200)
|
||||||
await makeRawRequest(file.fileUrl, 200)
|
await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200)
|
||||||
|
|
||||||
const torrent = await webtorrentAdd(file.magnetUri, true)
|
const torrent = await webtorrentAdd(file.magnetUri, true)
|
||||||
expect(torrent.files).to.be.an('array')
|
expect(torrent.files).to.be.an('array')
|
||||||
|
@ -144,8 +145,8 @@ describe('Test HLS videos', function () {
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await getVideo(server.url, videoUUID, 404)
|
await getVideo(server.url, videoUUID, HttpStatusCode.NOT_FOUND_404)
|
||||||
await getVideo(server.url, videoAudioUUID, 404)
|
await getVideo(server.url, videoAudioUUID, HttpStatusCode.NOT_FOUND_404)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@ import {
|
||||||
removeServerFromAccountBlocklist,
|
removeServerFromAccountBlocklist,
|
||||||
removeServerFromServerBlocklist
|
removeServerFromServerBlocklist
|
||||||
} from '../../../../shared/extra-utils/users/blocklist'
|
} from '../../../../shared/extra-utils/users/blocklist'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -1091,7 +1092,7 @@ describe('Test video playlists', function () {
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await getVideoPlaylist(server.url, videoPlaylistIds.uuid, 200)
|
await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.OK_200)
|
||||||
}
|
}
|
||||||
|
|
||||||
const playlistAttrs = { privacy: VideoPlaylistPrivacy.PRIVATE }
|
const playlistAttrs = { privacy: VideoPlaylistPrivacy.PRIVATE }
|
||||||
|
@ -1100,11 +1101,11 @@ describe('Test video playlists', function () {
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
for (const server of [ servers[1], servers[2] ]) {
|
for (const server of [ servers[1], servers[2] ]) {
|
||||||
await getVideoPlaylist(server.url, videoPlaylistIds.uuid, 404)
|
await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.NOT_FOUND_404)
|
||||||
}
|
}
|
||||||
await getVideoPlaylist(servers[0].url, videoPlaylistIds.uuid, 401)
|
await getVideoPlaylist(servers[0].url, videoPlaylistIds.uuid, HttpStatusCode.UNAUTHORIZED_401)
|
||||||
|
|
||||||
await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistIds.uuid, 200)
|
await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistIds.uuid, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1118,7 +1119,7 @@ describe('Test video playlists', function () {
|
||||||
await waitJobs(servers)
|
await waitJobs(servers)
|
||||||
|
|
||||||
for (const server of servers) {
|
for (const server of servers) {
|
||||||
await getVideoPlaylist(server.url, playlistServer1UUID, 404)
|
await getVideoPlaylist(server.url, playlistServer1UUID, HttpStatusCode.NOT_FOUND_404)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1178,7 +1179,7 @@ describe('Test video playlists', function () {
|
||||||
expect(res3.body.displayName).to.equal('channel playlist')
|
expect(res3.body.displayName).to.equal('channel playlist')
|
||||||
expect(res3.body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
|
expect(res3.body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
|
||||||
|
|
||||||
await getVideoPlaylist(servers[1].url, videoPlaylistUUID, 404)
|
await getVideoPlaylist(servers[1].url, videoPlaylistUUID, HttpStatusCode.NOT_FOUND_404)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should delete an account and delete its playlists', async function () {
|
it('Should delete an account and delete its playlists', async function () {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { createUser } from '../../../../shared/extra-utils/users/users'
|
||||||
import { getMyVideos, getVideo, getVideoWithToken, updateVideo } from '../../../../shared/extra-utils/videos/videos'
|
import { getMyVideos, getVideo, getVideoWithToken, updateVideo } from '../../../../shared/extra-utils/videos/videos'
|
||||||
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
|
||||||
import { Video } from '@shared/models'
|
import { Video } from '@shared/models'
|
||||||
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -110,8 +111,8 @@ describe('Test video privacy', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not be able to watch the private/internal video with non authenticated user', async function () {
|
it('Should not be able to watch the private/internal video with non authenticated user', async function () {
|
||||||
await getVideo(servers[0].url, privateVideoUUID, 401)
|
await getVideo(servers[0].url, privateVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
|
||||||
await getVideo(servers[0].url, internalVideoUUID, 401)
|
await getVideo(servers[0].url, internalVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not be able to watch the private video with another user', async function () {
|
it('Should not be able to watch the private video with another user', async function () {
|
||||||
|
@ -124,15 +125,15 @@ describe('Test video privacy', function () {
|
||||||
await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
|
await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
|
||||||
|
|
||||||
anotherUserToken = await userLogin(servers[0], user)
|
anotherUserToken = await userLogin(servers[0], user)
|
||||||
await getVideoWithToken(servers[0].url, anotherUserToken, privateVideoUUID, 403)
|
await getVideoWithToken(servers[0].url, anotherUserToken, privateVideoUUID, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should be able to watch the internal video with another user', async function () {
|
it('Should be able to watch the internal video with another user', async function () {
|
||||||
await getVideoWithToken(servers[0].url, anotherUserToken, internalVideoUUID, 200)
|
await getVideoWithToken(servers[0].url, anotherUserToken, internalVideoUUID, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should be able to watch the private video with the correct user', async function () {
|
it('Should be able to watch the private video with the correct user', async function () {
|
||||||
await getVideoWithToken(servers[0].url, servers[0].accessToken, privateVideoUUID, 200)
|
await getVideoWithToken(servers[0].url, servers[0].accessToken, privateVideoUUID, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should upload an unlisted video on server 2', async function () {
|
it('Should upload an unlisted video on server 2', async function () {
|
||||||
|
@ -202,7 +203,7 @@ describe('Test video privacy', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not be able to get non-federated unlisted video from federated server', async function () {
|
it('Should not be able to get non-federated unlisted video from federated server', async function () {
|
||||||
await getVideo(servers[1].url, nonFederatedUnlistedVideoUUID, 404)
|
await getVideo(servers[1].url, nonFederatedUnlistedVideoUUID, HttpStatusCode.NOT_FOUND_404)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should update the private and internal videos to public on server 1', async function () {
|
it('Should update the private and internal videos to public on server 1', async function () {
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
} from '../../../../shared/extra-utils'
|
} from '../../../../shared/extra-utils'
|
||||||
import { Video, VideoDetails } from '../../../../shared/models/videos'
|
import { Video, VideoDetails } from '../../../../shared/models/videos'
|
||||||
import { listMyVideosHistory, removeMyVideosHistory, userWatchVideo } from '../../../../shared/extra-utils/videos/video-history'
|
import { listMyVideosHistory, removeMyVideosHistory, userWatchVideo } from '../../../../shared/extra-utils/videos/video-history'
|
||||||
|
import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -171,7 +172,7 @@ describe('Test videos history', function () {
|
||||||
videosHistoryEnabled: false
|
videosHistoryEnabled: false
|
||||||
})
|
})
|
||||||
|
|
||||||
await userWatchVideo(server.url, server.accessToken, video2UUID, 8, 409)
|
await userWatchVideo(server.url, server.accessToken, video2UUID, 8, HttpStatusCode.CONFLICT_409)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should re-enable videos history', async function () {
|
it('Should re-enable videos history', async function () {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
ServerInfo,
|
ServerInfo,
|
||||||
setAccessTokensToServers
|
setAccessTokensToServers
|
||||||
} from '../../../shared/extra-utils'
|
} from '../../../shared/extra-utils'
|
||||||
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
describe('Test reset password scripts', function () {
|
describe('Test reset password scripts', function () {
|
||||||
let server: ServerInfo
|
let server: ServerInfo
|
||||||
|
@ -28,7 +29,7 @@ describe('Test reset password scripts', function () {
|
||||||
const env = getEnvCli(server)
|
const env = getEnvCli(server)
|
||||||
await execCLI(`echo coucou | ${env} npm run reset-password -- -u user_1`)
|
await execCLI(`echo coucou | ${env} npm run reset-password -- -u user_1`)
|
||||||
|
|
||||||
await login(server.url, server.client, { username: 'user_1', password: 'coucou' }, 200)
|
await login(server.url, server.client, { username: 'user_1', password: 'coucou' }, HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
after(async function () {
|
after(async function () {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import {
|
||||||
import { waitJobs } from '../../../shared/extra-utils/server/jobs'
|
import { waitJobs } from '../../../shared/extra-utils/server/jobs'
|
||||||
import { addVideoCommentThread } from '../../../shared/extra-utils/videos/video-comments'
|
import { addVideoCommentThread } from '../../../shared/extra-utils/videos/video-comments'
|
||||||
import { User } from '../../../shared/models/users'
|
import { User } from '../../../shared/models/users'
|
||||||
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
chai.use(require('chai-xml'))
|
chai.use(require('chai-xml'))
|
||||||
chai.use(require('chai-json-schema'))
|
chai.use(require('chai-json-schema'))
|
||||||
|
@ -330,11 +331,16 @@ describe('Test syndication feeds', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with an invalid token', async function () {
|
it('Should fail with an invalid token', async function () {
|
||||||
await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: 'toto' }, 403)
|
await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: 'toto' }, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should fail with a token of another user', async function () {
|
it('Should fail with a token of another user', async function () {
|
||||||
await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: userFeedToken }, 403)
|
await getJSONfeed(
|
||||||
|
servers[0].url,
|
||||||
|
'subscriptions',
|
||||||
|
{ accountId: feeduserAccountId, token: userFeedToken },
|
||||||
|
HttpStatusCode.FORBIDDEN_403
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should list no videos for a user with videos but no subscriptions', async function () {
|
it('Should list no videos for a user with videos but no subscriptions', async function () {
|
||||||
|
@ -382,7 +388,12 @@ describe('Test syndication feeds', () => {
|
||||||
it('Should renew the token, and so have an invalid old token', async function () {
|
it('Should renew the token, and so have an invalid old token', async function () {
|
||||||
await renewUserScopedTokens(servers[0].url, userAccessToken)
|
await renewUserScopedTokens(servers[0].url, userAccessToken)
|
||||||
|
|
||||||
await getJSONfeed(servers[0].url, 'subscriptions', { accountId: userAccountId, token: userFeedToken, version: 3 }, 403)
|
await getJSONfeed(
|
||||||
|
servers[0].url,
|
||||||
|
'subscriptions',
|
||||||
|
{ accountId: userAccountId, token: userFeedToken, version: 3 },
|
||||||
|
HttpStatusCode.FORBIDDEN_403
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should succeed with the new token', async function () {
|
it('Should succeed with the new token', async function () {
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { cleanupTests, flushAndRunMultipleServers, ServerInfo } from '../../../s
|
||||||
import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports'
|
import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports'
|
||||||
import { VideoDetails, VideoImport, VideoImportState, VideoPrivacy } from '../../../shared/models/videos'
|
import { VideoDetails, VideoImport, VideoImportState, VideoPrivacy } from '../../../shared/models/videos'
|
||||||
import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
|
import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
|
||||||
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should run filter:api.video.upload.accept.result', async function () {
|
it('Should run filter:api.video.upload.accept.result', async function () {
|
||||||
await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video with bad word' }, 403)
|
await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video with bad word' }, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should run filter:api.live-video.create.accept.result', async function () {
|
it('Should run filter:api.live-video.create.accept.result', async function () {
|
||||||
|
@ -137,7 +138,7 @@ describe('Test plugin filter hooks', function () {
|
||||||
channelId: servers[0].videoChannel.id
|
channelId: servers[0].videoChannel.id
|
||||||
}
|
}
|
||||||
|
|
||||||
await createLive(servers[0].url, servers[0].accessToken, attributes, 403)
|
await createLive(servers[0].url, servers[0].accessToken, attributes, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should run filter:api.video.pre-import-url.accept.result', async function () {
|
it('Should run filter:api.video.pre-import-url.accept.result', async function () {
|
||||||
|
@ -147,7 +148,7 @@ describe('Test plugin filter hooks', function () {
|
||||||
channelId: servers[0].videoChannel.id,
|
channelId: servers[0].videoChannel.id,
|
||||||
targetUrl: getGoodVideoUrl() + 'bad'
|
targetUrl: getGoodVideoUrl() + 'bad'
|
||||||
}
|
}
|
||||||
await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, 403)
|
await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should run filter:api.video.pre-import-torrent.accept.result', async function () {
|
it('Should run filter:api.video.pre-import-torrent.accept.result', async function () {
|
||||||
|
@ -157,7 +158,7 @@ describe('Test plugin filter hooks', function () {
|
||||||
channelId: servers[0].videoChannel.id,
|
channelId: servers[0].videoChannel.id,
|
||||||
torrentfile: 'video-720p.torrent' as any
|
torrentfile: 'video-720p.torrent' as any
|
||||||
}
|
}
|
||||||
await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, 403)
|
await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should run filter:api.video.post-import-url.accept.result', async function () {
|
it('Should run filter:api.video.post-import-url.accept.result', async function () {
|
||||||
|
@ -219,15 +220,22 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should run filter:api.video-thread.create.accept.result', async function () {
|
it('Should run filter:api.video-thread.create.accept.result', async function () {
|
||||||
await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment with bad word', 403)
|
await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment with bad word', HttpStatusCode.FORBIDDEN_403)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should run filter:api.video-comment-reply.create.accept.result', async function () {
|
it('Should run filter:api.video-comment-reply.create.accept.result', async function () {
|
||||||
const res = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'thread')
|
const res = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'thread')
|
||||||
threadId = res.body.comment.id
|
threadId = res.body.comment.id
|
||||||
|
|
||||||
await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'comment with bad word', 403)
|
await addVideoCommentReply(
|
||||||
await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'comment with good word', 200)
|
servers[0].url,
|
||||||
|
servers[0].accessToken,
|
||||||
|
videoUUID,
|
||||||
|
threadId,
|
||||||
|
'comment with bad word',
|
||||||
|
HttpStatusCode.FORBIDDEN_403
|
||||||
|
)
|
||||||
|
await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'comment with good word', HttpStatusCode.OK_200)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should run filter:api.video-threads.list.params', async function () {
|
it('Should run filter:api.video-threads.list.params', async function () {
|
||||||
|
@ -326,7 +334,7 @@ describe('Test plugin filter hooks', function () {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not allow a signup', async function () {
|
it('Should not allow a signup', async function () {
|
||||||
const res = await registerUser(servers[0].url, 'jma', 'password', 403)
|
const res = await registerUser(servers[0].url, 'jma', 'password', HttpStatusCode.FORBIDDEN_403)
|
||||||
|
|
||||||
expect(res.body.error).to.equal('No jma')
|
expect(res.body.error).to.equal('No jma')
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
uploadVideo
|
uploadVideo
|
||||||
} from '../../../shared/extra-utils'
|
} from '../../../shared/extra-utils'
|
||||||
import { VideoDetails, VideoPlaylistPrivacy } from '../../../shared/models/videos'
|
import { VideoDetails, VideoPlaylistPrivacy } from '../../../shared/models/videos'
|
||||||
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
|
|
||||||
|
@ -89,12 +90,17 @@ describe('Test plugin altering video constants', function () {
|
||||||
|
|
||||||
it('Should not be able to create a video with this privacy', async function () {
|
it('Should not be able to create a video with this privacy', async function () {
|
||||||
const attrs = { name: 'video', privacy: 2 }
|
const attrs = { name: 'video', privacy: 2 }
|
||||||
await uploadVideo(server.url, server.accessToken, attrs, 400)
|
await uploadVideo(server.url, server.accessToken, attrs, HttpStatusCode.BAD_REQUEST_400)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should not be able to create a video with this privacy', async function () {
|
it('Should not be able to create a video with this privacy', async function () {
|
||||||
const attrs = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE }
|
const attrs = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE }
|
||||||
await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs: attrs, expectedStatus: 400 })
|
await createVideoPlaylist({
|
||||||
|
url: server.url,
|
||||||
|
token: server.accessToken,
|
||||||
|
playlistAttrs: attrs,
|
||||||
|
expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('Should be able to upload a video with these values', async function () {
|
it('Should be able to upload a video with these values', async function () {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import * as program from 'commander'
|
||||||
import { getAdminTokenOrDie, getServerCredentials } from './cli'
|
import { getAdminTokenOrDie, getServerCredentials } from './cli'
|
||||||
import { VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
|
import { VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
|
||||||
import { addVideoRedundancy, listVideoRedundancies, removeVideoRedundancy } from '@shared/extra-utils/server/redundancy'
|
import { addVideoRedundancy, listVideoRedundancies, removeVideoRedundancy } from '@shared/extra-utils/server/redundancy'
|
||||||
|
import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
|
||||||
import validator from 'validator'
|
import validator from 'validator'
|
||||||
import * as CliTable3 from 'cli-table3'
|
import * as CliTable3 from 'cli-table3'
|
||||||
import { URL } from 'url'
|
import { URL } from 'url'
|
||||||
|
@ -124,9 +125,9 @@ async function addRedundancyCLI (options: { videoId: number }) {
|
||||||
|
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.message.includes(409)) {
|
if (err.message.includes(HttpStatusCode.CONFLICT_409)) {
|
||||||
console.error('This video is already duplicated by your instance.')
|
console.error('This video is already duplicated by your instance.')
|
||||||
} else if (err.message.includes(404)) {
|
} else if (err.message.includes(HttpStatusCode.NOT_FOUND_404)) {
|
||||||
console.error('This video id does not exist.')
|
console.error('This video id does not exist.')
|
||||||
} else {
|
} else {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* Hypertext Transfer Protocol (HTTP) response status codes.
|
* Hypertext Transfer Protocol (HTTP) response status codes.
|
||||||
* @see {@link https://en.wikipedia.org/wiki/List_of_HTTP_status_codes}
|
* @see {@link https://en.wikipedia.org/wiki/List_of_HTTP_status_codes}
|
||||||
|
*
|
||||||
|
* WebDAV and other codes useless with regards to PeerTube are not listed.
|
||||||
*/
|
*/
|
||||||
export enum HttpStatusCode {
|
export enum HttpStatusCode {
|
||||||
|
|
||||||
|
@ -47,15 +49,6 @@ export enum HttpStatusCode {
|
||||||
*/
|
*/
|
||||||
ACCEPTED_202 = 202,
|
ACCEPTED_202 = 202,
|
||||||
|
|
||||||
/**
|
|
||||||
* Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.4
|
|
||||||
*
|
|
||||||
* SINCE HTTP/1.1
|
|
||||||
* The server is a transforming proxy that received a 200 OK from its origin,
|
|
||||||
* but is returning a modified version of the origin's response.
|
|
||||||
*/
|
|
||||||
NON_AUTHORITATIVE_INFORMATION_203 = 203,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.5
|
* Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.5
|
||||||
*
|
*
|
||||||
|
@ -77,18 +70,6 @@ export enum HttpStatusCode {
|
||||||
*/
|
*/
|
||||||
PARTIAL_CONTENT_206 = 206,
|
PARTIAL_CONTENT_206 = 206,
|
||||||
|
|
||||||
/**
|
|
||||||
* The message body that follows is an XML message and can contain a number of separate response codes,
|
|
||||||
* depending on how many sub-requests were made.
|
|
||||||
*/
|
|
||||||
MULTI_STATUS_207 = 207,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The server has fulfilled a request for the resource,
|
|
||||||
* and the response is a representation of the result of one or more instance-manipulations applied to the current instance.
|
|
||||||
*/
|
|
||||||
IM_USED_226 = 226,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates multiple options for the resource from which the client may choose (via agent-driven content negotiation).
|
* Indicates multiple options for the resource from which the client may choose (via agent-driven content negotiation).
|
||||||
* For example, this code could be used to present multiple video format options,
|
* For example, this code could be used to present multiple video format options,
|
||||||
|
@ -128,20 +109,6 @@ export enum HttpStatusCode {
|
||||||
*/
|
*/
|
||||||
NOT_MODIFIED_304 = 304,
|
NOT_MODIFIED_304 = 304,
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated
|
|
||||||
* SINCE HTTP/1.1
|
|
||||||
* The requested resource is available only through a proxy, the address for which is provided in the response.
|
|
||||||
* Many HTTP clients (such as Mozilla and Internet Explorer) do not correctly handle responses with this status
|
|
||||||
* code, primarily for security reasons.
|
|
||||||
*/
|
|
||||||
USE_PROXY_305 = 305,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* No longer used. Originally meant "Subsequent requests should use the specified proxy."
|
|
||||||
*/
|
|
||||||
SWITCH_PROXY_306 = 306,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SINCE HTTP/1.1
|
* SINCE HTTP/1.1
|
||||||
* In this case, the request should be repeated with another URI; however, future requests should still use the original URI.
|
* In this case, the request should be repeated with another URI; however, future requests should still use the original URI.
|
||||||
|
@ -175,6 +142,8 @@ export enum HttpStatusCode {
|
||||||
UNAUTHORIZED_401 = 401,
|
UNAUTHORIZED_401 = 401,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.2
|
||||||
|
*
|
||||||
* Reserved for future use. The original intention was that this code might be used as part of some form of digital
|
* Reserved for future use. The original intention was that this code might be used as part of some form of digital
|
||||||
* cash or micro payment scheme, but that has not happened, and this code is not usually used.
|
* cash or micro payment scheme, but that has not happened, and this code is not usually used.
|
||||||
* Google Developers API uses this status if a particular developer has exceeded the daily limit on requests.
|
* Google Developers API uses this status if a particular developer has exceeded the daily limit on requests.
|
||||||
|
@ -210,11 +179,6 @@ export enum HttpStatusCode {
|
||||||
*/
|
*/
|
||||||
NOT_ACCEPTABLE_406 = 406,
|
NOT_ACCEPTABLE_406 = 406,
|
||||||
|
|
||||||
/**
|
|
||||||
* The client must first authenticate itself with the proxy.
|
|
||||||
*/
|
|
||||||
PROXY_AUTHENTICATION_REQUIRED_407 = 407,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.7
|
* Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.7
|
||||||
*
|
*
|
||||||
|
@ -222,10 +186,14 @@ export enum HttpStatusCode {
|
||||||
* It means that the server would like to shut down this unused connection. This response is used much more since
|
* It means that the server would like to shut down this unused connection. This response is used much more since
|
||||||
* some browsers, like Chrome, Firefox 27+, or IE9, use HTTP pre-connection mechanisms to speed up surfing. Also
|
* some browsers, like Chrome, Firefox 27+, or IE9, use HTTP pre-connection mechanisms to speed up surfing. Also
|
||||||
* note that some servers merely shut down the connection without sending this message.
|
* note that some servers merely shut down the connection without sending this message.
|
||||||
|
*
|
||||||
|
* @
|
||||||
*/
|
*/
|
||||||
REQUEST_TIMEOUT_408 = 408,
|
REQUEST_TIMEOUT_408 = 408,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.8
|
||||||
|
*
|
||||||
* Indicates that the request could not be processed because of conflict in the request,
|
* Indicates that the request could not be processed because of conflict in the request,
|
||||||
* such as an edit conflict between multiple simultaneous updates.
|
* such as an edit conflict between multiple simultaneous updates.
|
||||||
*/
|
*/
|
||||||
|
@ -284,52 +252,39 @@ export enum HttpStatusCode {
|
||||||
RANGE_NOT_SATISFIABLE_416 = 416,
|
RANGE_NOT_SATISFIABLE_416 = 416,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The server cannot meet the requirements of the Expect request-header field.
|
* The server cannot meet the requirements of the `Expect` request-header field.
|
||||||
*/
|
*/
|
||||||
EXPECTATION_FAILED_417 = 417,
|
EXPECTATION_FAILED_417 = 417,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Official Documentation @ https://tools.ietf.org/html/rfc2324
|
||||||
|
*
|
||||||
* This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol,
|
* This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol,
|
||||||
* and is not expected to be implemented by actual HTTP servers. The RFC specifies this code should be returned by
|
* and is not expected to be implemented by actual HTTP servers. The RFC specifies this code should be returned by
|
||||||
* teapots requested to brew coffee. This HTTP status is used as an Easter egg in some websites, including PeerTube instances ;-).
|
* teapots requested to brew coffee. This HTTP status is used as an Easter egg in some websites, including PeerTube instances ;-).
|
||||||
*/
|
*/
|
||||||
I_AM_A_TEAPOT_418 = 418,
|
I_AM_A_TEAPOT_418 = 418,
|
||||||
|
|
||||||
/**
|
|
||||||
* The request was directed at a server that is not able to produce a response (for example because a connection reuse).
|
|
||||||
*/
|
|
||||||
MISDIRECTED_REQUEST_421 = 421,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.3
|
* Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.3
|
||||||
*
|
*
|
||||||
* The request was well-formed but was unable to be followed due to semantic errors.
|
* The request was well-formed but was unable to be followed due to semantic errors.
|
||||||
|
*
|
||||||
|
* @see HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415 if the `Content-Type` was not supported.
|
||||||
|
* @see HttpStatusCode.BAD_REQUEST_400 if the request was not parsable (broken JSON, XML)
|
||||||
*/
|
*/
|
||||||
UNPROCESSABLE_ENTITY_422 = 422,
|
UNPROCESSABLE_ENTITY_422 = 422,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The resource that is being accessed is locked.
|
* Official Documentation @ https://tools.ietf.org/html/rfc4918#section-11.3
|
||||||
|
*
|
||||||
|
* The resource that is being accessed is locked. WebDAV-specific but used by some HTTP services.
|
||||||
|
*
|
||||||
|
* @deprecated use `If-Match` / `If-None-Match` instead
|
||||||
|
* @see {@link https://evertpot.com/http/423-locked}
|
||||||
*/
|
*/
|
||||||
LOCKED_423 = 423,
|
LOCKED_423 = 423,
|
||||||
|
|
||||||
/**
|
|
||||||
* The request failed due to failure of a previous request (e.g., a PROPPATCH).
|
|
||||||
*/
|
|
||||||
FAILED_DEPENDENCY_424 = 424,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header field.
|
|
||||||
*/
|
|
||||||
UPGRADE_REQUIRED_426 = 426,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The origin server requires the request to be conditional.
|
|
||||||
* Intended to prevent "the 'lost update' problem, where a client
|
|
||||||
* GETs a resource's state, modifies it, and PUTs it back to the server,
|
|
||||||
* when meanwhile a third party has modified the state on the server, leading to a conflict."
|
|
||||||
*/
|
|
||||||
PRECONDITION_REQUIRED_428 = 428,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Official Documentation @ https://tools.ietf.org/html/rfc6585#section-4
|
* Official Documentation @ https://tools.ietf.org/html/rfc6585#section-4
|
||||||
*
|
*
|
||||||
|
@ -359,6 +314,8 @@ export enum HttpStatusCode {
|
||||||
INTERNAL_SERVER_ERROR_500 = 500,
|
INTERNAL_SERVER_ERROR_500 = 500,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.6.2
|
||||||
|
*
|
||||||
* The server either does not recognize the request method, or it lacks the ability to fulfill the request.
|
* The server either does not recognize the request method, or it lacks the ability to fulfill the request.
|
||||||
* Usually this implies future availability (e.g., a new feature of a web-service API).
|
* Usually this implies future availability (e.g., a new feature of a web-service API).
|
||||||
*/
|
*/
|
||||||
|
@ -385,11 +342,6 @@ export enum HttpStatusCode {
|
||||||
*/
|
*/
|
||||||
HTTP_VERSION_NOT_SUPPORTED_505 = 505,
|
HTTP_VERSION_NOT_SUPPORTED_505 = 505,
|
||||||
|
|
||||||
/**
|
|
||||||
* Transparent content negotiation for the request results in a circular reference.
|
|
||||||
*/
|
|
||||||
VARIANT_ALSO_NEGOTIATES_506 = 506,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.6
|
* Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.6
|
||||||
*
|
*
|
||||||
|
@ -397,23 +349,8 @@ export enum HttpStatusCode {
|
||||||
* server is unable to store the representation needed to successfully complete the request. This condition is
|
* server is unable to store the representation needed to successfully complete the request. This condition is
|
||||||
* considered to be temporary. If the request which received this status code was the result of a user action,
|
* considered to be temporary. If the request which received this status code was the result of a user action,
|
||||||
* the request MUST NOT be repeated until it is requested by a separate user action.
|
* the request MUST NOT be repeated until it is requested by a separate user action.
|
||||||
|
*
|
||||||
|
* @see HttpStatusCode.PAYLOAD_TOO_LARGE_413 for quota errors
|
||||||
*/
|
*/
|
||||||
INSUFFICIENT_STORAGE_507 = 507,
|
INSUFFICIENT_STORAGE_507 = 507,
|
||||||
|
|
||||||
/**
|
|
||||||
* The server detected an infinite loop while processing the request.
|
|
||||||
*/
|
|
||||||
LOOP_DETECTED_508 = 508,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Further extensions to the request are required for the server to fulfill it.
|
|
||||||
*/
|
|
||||||
NOT_EXTENDED_510 = 510,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The client needs to authenticate to gain network access.
|
|
||||||
* Intended for use by intercepting proxies used to control access to the network (e.g., "captive portals" used
|
|
||||||
* to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot).
|
|
||||||
*/
|
|
||||||
NETWORK_AUTHENTICATION_REQUIRED_511 = 511
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import * as request from 'supertest'
|
import * as request from 'supertest'
|
||||||
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
function makeActivityPubGetRequest (url: string, path: string, expectedStatus = 200) {
|
function makeActivityPubGetRequest (url: string, path: string, expectedStatus = HttpStatusCode.OK_200) {
|
||||||
return request(url)
|
return request(url)
|
||||||
.get(path)
|
.get(path)
|
||||||
.set('Accept', 'application/activity+json,text/html;q=0.9,\\*/\\*;q=0.8')
|
.set('Accept', 'application/activity+json,text/html;q=0.9,\\*/\\*;q=0.8')
|
||||||
|
|
|
@ -2,7 +2,13 @@ import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequ
|
||||||
import { VideoRedundanciesTarget } from '@shared/models'
|
import { VideoRedundanciesTarget } from '@shared/models'
|
||||||
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
function updateRedundancy (url: string, accessToken: string, host: string, redundancyAllowed: boolean, expectedStatus = 204) {
|
function updateRedundancy (
|
||||||
|
url: string,
|
||||||
|
accessToken: string,
|
||||||
|
host: string,
|
||||||
|
redundancyAllowed: boolean,
|
||||||
|
expectedStatus = HttpStatusCode.NO_CONTENT_204
|
||||||
|
) {
|
||||||
const path = '/api/v1/server/redundancy/' + host
|
const path = '/api/v1/server/redundancy/' + host
|
||||||
|
|
||||||
return makePutBodyRequest({
|
return makePutBodyRequest({
|
||||||
|
|
|
@ -2,12 +2,13 @@ import * as request from 'supertest'
|
||||||
|
|
||||||
import { ServerInfo } from '../server/servers'
|
import { ServerInfo } from '../server/servers'
|
||||||
import { getClient } from '../server/clients'
|
import { getClient } from '../server/clients'
|
||||||
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
type Client = { id: string, secret: string }
|
type Client = { id: string, secret: string }
|
||||||
type User = { username: string, password: string }
|
type User = { username: string, password: string }
|
||||||
type Server = { url: string, client: Client, user: User }
|
type Server = { url: string, client: Client, user: User }
|
||||||
|
|
||||||
function login (url: string, client: Client, user: User, expectedStatus = 200) {
|
function login (url: string, client: Client, user: User, expectedStatus = HttpStatusCode.OK_200) {
|
||||||
const path = '/api/v1/users/token'
|
const path = '/api/v1/users/token'
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
|
@ -27,7 +28,7 @@ function login (url: string, client: Client, user: User, expectedStatus = 200) {
|
||||||
.expect(expectedStatus)
|
.expect(expectedStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
function logout (url: string, token: string, expectedStatus = 200) {
|
function logout (url: string, token: string, expectedStatus = HttpStatusCode.OK_200) {
|
||||||
const path = '/api/v1/users/revoke-token'
|
const path = '/api/v1/users/revoke-token'
|
||||||
|
|
||||||
return request(url)
|
return request(url)
|
||||||
|
@ -38,12 +39,12 @@ function logout (url: string, token: string, expectedStatus = 200) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function serverLogin (server: Server) {
|
async function serverLogin (server: Server) {
|
||||||
const res = await login(server.url, server.client, server.user, 200)
|
const res = await login(server.url, server.client, server.user, HttpStatusCode.OK_200)
|
||||||
|
|
||||||
return res.body.access_token as string
|
return res.body.access_token as string
|
||||||
}
|
}
|
||||||
|
|
||||||
function refreshToken (server: ServerInfo, refreshToken: string, expectedStatus = 200) {
|
function refreshToken (server: ServerInfo, refreshToken: string, expectedStatus = HttpStatusCode.OK_200) {
|
||||||
const path = '/api/v1/users/token'
|
const path = '/api/v1/users/token'
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
|
@ -61,7 +62,7 @@ function refreshToken (server: ServerInfo, refreshToken: string, expectedStatus
|
||||||
.expect(expectedStatus)
|
.expect(expectedStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function userLogin (server: Server, user: User, expectedStatus = 200) {
|
async function userLogin (server: Server, user: User, expectedStatus = HttpStatusCode.OK_200) {
|
||||||
const res = await login(server.url, server.client, user, expectedStatus)
|
const res = await login(server.url, server.client, user, expectedStatus)
|
||||||
|
|
||||||
return res.body.access_token as string
|
return res.body.access_token as string
|
||||||
|
@ -95,7 +96,7 @@ function setAccessTokensToServers (servers: ServerInfo[]) {
|
||||||
return Promise.all(tasks)
|
return Promise.all(tasks)
|
||||||
}
|
}
|
||||||
|
|
||||||
function loginUsingExternalToken (server: Server, username: string, externalAuthToken: string, expectedStatus = 200) {
|
function loginUsingExternalToken (server: Server, username: string, externalAuthToken: string, expectedStatus = HttpStatusCode.OK_200) {
|
||||||
const path = '/api/v1/users/token'
|
const path = '/api/v1/users/token'
|
||||||
|
|
||||||
const body = {
|
const body = {
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
import { makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
|
import { makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
|
||||||
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
|
||||||
|
|
||||||
function userWatchVideo (url: string, token: string, videoId: number | string, currentTime: number, statusCodeExpected = 204) {
|
function userWatchVideo (
|
||||||
|
url: string,
|
||||||
|
token: string,
|
||||||
|
videoId: number | string,
|
||||||
|
currentTime: number,
|
||||||
|
statusCodeExpected = HttpStatusCode.NO_CONTENT_204
|
||||||
|
) {
|
||||||
const path = '/api/v1/videos/' + videoId + '/watching'
|
const path = '/api/v1/videos/' + videoId + '/watching'
|
||||||
const fields = { currentTime }
|
const fields = { currentTime }
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ function getVideosListWithToken (url: string, token: string, query: { nsfw?: boo
|
||||||
.set('Authorization', 'Bearer ' + token)
|
.set('Authorization', 'Bearer ' + token)
|
||||||
.query(immutableAssign(query, { sort: 'name' }))
|
.query(immutableAssign(query, { sort: 'name' }))
|
||||||
.set('Accept', 'application/json')
|
.set('Accept', 'application/json')
|
||||||
.expect(200)
|
.expect(HttpStatusCode.OK_200)
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ function getLocalVideos (url: string) {
|
||||||
.get(path)
|
.get(path)
|
||||||
.query({ sort: 'name', filter: 'local' })
|
.query({ sort: 'name', filter: 'local' })
|
||||||
.set('Accept', 'application/json')
|
.set('Accept', 'application/json')
|
||||||
.expect(200)
|
.expect(HttpStatusCode.OK_200)
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1312,20 +1312,24 @@ paths:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/VideoUploadResponse'
|
$ref: '#/components/schemas/VideoUploadResponse'
|
||||||
|
'400':
|
||||||
|
description: invalid file field, schedule date or parameter
|
||||||
'403':
|
'403':
|
||||||
description: user video quota is exceeded with this video
|
description: video didn't pass upload filter
|
||||||
'408':
|
'408':
|
||||||
description: upload has timed out
|
description: upload has timed out
|
||||||
'413':
|
'413':
|
||||||
description: video file too large
|
description: video file too large, due to quota or max body size limit set by the reverse-proxy
|
||||||
headers:
|
headers:
|
||||||
X-File-Maximum-Size:
|
X-File-Maximum-Size:
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
format: Nginx size
|
format: Nginx size
|
||||||
description: Maximum file size for the video
|
description: Maximum file size for the video
|
||||||
|
'415':
|
||||||
|
description: video type unsupported
|
||||||
'422':
|
'422':
|
||||||
description: invalid input file
|
description: video unreadable
|
||||||
requestBody:
|
requestBody:
|
||||||
content:
|
content:
|
||||||
multipart/form-data:
|
multipart/form-data:
|
||||||
|
@ -1534,10 +1538,12 @@ paths:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/VideoUploadResponse'
|
$ref: '#/components/schemas/VideoUploadResponse'
|
||||||
'409':
|
|
||||||
description: HTTP or Torrent/magnetURI import not enabled
|
|
||||||
'400':
|
'400':
|
||||||
description: '`magnetUri` or `targetUrl` or a torrent file missing'
|
description: '`magnetUri` or `targetUrl` or a torrent file missing'
|
||||||
|
'403':
|
||||||
|
description: video didn't pass pre-import filter
|
||||||
|
'409':
|
||||||
|
description: HTTP or Torrent/magnetURI import not enabled
|
||||||
|
|
||||||
/videos/live:
|
/videos/live:
|
||||||
post:
|
post:
|
||||||
|
@ -3572,7 +3578,7 @@ components:
|
||||||
name: name
|
name: name
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: The name of the account
|
description: The username or handle of the account
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
example: chocobozzz | chocobozzz@example.org
|
example: chocobozzz | chocobozzz@example.org
|
||||||
|
@ -5175,7 +5181,7 @@ components:
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
description: The name for the default channel
|
description: The username for the default channel
|
||||||
pattern: '/^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_.:]+$/'
|
pattern: '/^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_.:]+$/'
|
||||||
displayName:
|
displayName:
|
||||||
type: string
|
type: string
|
||||||
|
|
Loading…
Reference in New Issue
Block a user