123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import express from 'express'
- import { query } from 'express-validator'
- import { join } from 'path'
- import { loadVideo } from '@server/lib/model-loaders'
- import { VideoPlaylistModel } from '@server/models/video/video-playlist'
- import { VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models'
- import { HttpStatusCode } from '../../../shared/models/http/http-error-codes'
- import { isTestOrDevInstance } from '../../helpers/core-utils'
- import { isIdOrUUIDValid, isUUIDValid, toCompleteUUID } from '../../helpers/custom-validators/misc'
- import { WEBSERVER } from '../../initializers/constants'
- import { areValidationErrors } from './shared'
- const playlistPaths = [
- join('videos', 'watch', 'playlist'),
- join('w', 'p')
- ]
- const videoPaths = [
- join('videos', 'watch'),
- 'w'
- ]
- function buildUrls (paths: string[]) {
- return paths.map(p => WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, p) + '/')
- }
- const startPlaylistURLs = buildUrls(playlistPaths)
- const startVideoURLs = buildUrls(videoPaths)
- const isURLOptions = {
- require_host: true,
- require_tld: true
- }
- // We validate 'localhost', so we don't have the top level domain
- if (isTestOrDevInstance()) {
- isURLOptions.require_tld = false
- }
- const oembedValidator = [
- query('url')
- .isURL(isURLOptions),
- query('maxwidth')
- .optional()
- .isInt(),
- query('maxheight')
- .optional()
- .isInt(),
- query('format')
- .optional()
- .isIn([ 'xml', 'json' ]),
- async (req: express.Request, res: express.Response, next: express.NextFunction) => {
- if (areValidationErrors(req, res)) return
- if (req.query.format !== undefined && req.query.format !== 'json') {
- return res.fail({
- status: HttpStatusCode.NOT_IMPLEMENTED_501,
- message: 'Requested format is not implemented on server.',
- data: {
- format: req.query.format
- }
- })
- }
- const url = req.query.url as string
- let urlPath: string
- try {
- urlPath = new URL(url).pathname
- } catch (err) {
- return res.fail({
- status: HttpStatusCode.BAD_REQUEST_400,
- message: err.message,
- data: {
- url
- }
- })
- }
- const isPlaylist = startPlaylistURLs.some(u => url.startsWith(u))
- const isVideo = isPlaylist ? false : startVideoURLs.some(u => url.startsWith(u))
- const startIsOk = isVideo || isPlaylist
- const parts = urlPath.split('/')
- if (startIsOk === false || parts.length === 0) {
- return res.fail({
- status: HttpStatusCode.BAD_REQUEST_400,
- message: 'Invalid url.',
- data: {
- url
- }
- })
- }
- const elementId = toCompleteUUID(parts.pop())
- if (isIdOrUUIDValid(elementId) === false) {
- return res.fail({ message: 'Invalid video or playlist id.' })
- }
- if (isVideo) {
- const video = await loadVideo(elementId, 'all')
- if (!video) {
- return res.fail({
- status: HttpStatusCode.NOT_FOUND_404,
- message: 'Video not found'
- })
- }
- if (
- video.privacy === VideoPrivacy.PUBLIC ||
- (video.privacy === VideoPrivacy.UNLISTED && isUUIDValid(elementId) === true)
- ) {
- res.locals.videoAll = video
- return next()
- }
- return res.fail({
- status: HttpStatusCode.FORBIDDEN_403,
- message: 'Video is not publicly available'
- })
- }
- // Is playlist
- const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannelSummary(elementId, undefined)
- if (!videoPlaylist) {
- return res.fail({
- status: HttpStatusCode.NOT_FOUND_404,
- message: 'Video playlist not found'
- })
- }
- if (
- videoPlaylist.privacy === VideoPlaylistPrivacy.PUBLIC ||
- (videoPlaylist.privacy === VideoPlaylistPrivacy.UNLISTED && isUUIDValid(elementId))
- ) {
- res.locals.videoPlaylistSummary = videoPlaylist
- return next()
- }
- return res.fail({
- status: HttpStatusCode.FORBIDDEN_403,
- message: 'Playlist is not public'
- })
- }
- ]
- // ---------------------------------------------------------------------------
- export {
- oembedValidator
- }
|