diff options
Diffstat (limited to 'server/middlewares/validators/oembed.ts')
-rw-r--r-- | server/middlewares/validators/oembed.ts | 65 |
1 files changed, 50 insertions, 15 deletions
diff --git a/server/middlewares/validators/oembed.ts b/server/middlewares/validators/oembed.ts index ab4dbb4d1..c9f9ea0c0 100644 --- a/server/middlewares/validators/oembed.ts +++ b/server/middlewares/validators/oembed.ts | |||
@@ -1,15 +1,19 @@ | |||
1 | import * as express from 'express' | 1 | import * as express from 'express' |
2 | import { query } from 'express-validator' | 2 | import { query } from 'express-validator' |
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import { fetchVideo } from '@server/helpers/video' | ||
5 | import { VideoPlaylistModel } from '@server/models/video/video-playlist' | ||
6 | import { VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models' | ||
4 | import { isTestInstance } from '../../helpers/core-utils' | 7 | import { isTestInstance } from '../../helpers/core-utils' |
5 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' | 8 | import { isIdOrUUIDValid } from '../../helpers/custom-validators/misc' |
6 | import { logger } from '../../helpers/logger' | 9 | import { logger } from '../../helpers/logger' |
7 | import { areValidationErrors } from './utils' | ||
8 | import { WEBSERVER } from '../../initializers/constants' | 10 | import { WEBSERVER } from '../../initializers/constants' |
9 | import { doesVideoExist } from '../../helpers/middlewares' | 11 | import { areValidationErrors } from './utils' |
10 | 12 | ||
11 | const urlShouldStartWith = WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, 'videos', 'watch') + '/' | 13 | const startVideoPlaylistsURL = WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, 'videos', 'watch', 'playlist') + '/' |
12 | const videoWatchRegex = new RegExp('([^/]+)$') | 14 | const startVideosURL = WEBSERVER.SCHEME + '://' + join(WEBSERVER.HOST, 'videos', 'watch') + '/' |
15 | |||
16 | const watchRegex = new RegExp('([^/]+)$') | ||
13 | const isURLOptions = { | 17 | const isURLOptions = { |
14 | require_host: true, | 18 | require_host: true, |
15 | require_tld: true | 19 | require_tld: true |
@@ -33,32 +37,63 @@ const oembedValidator = [ | |||
33 | 37 | ||
34 | if (req.query.format !== undefined && req.query.format !== 'json') { | 38 | if (req.query.format !== undefined && req.query.format !== 'json') { |
35 | return res.status(501) | 39 | return res.status(501) |
36 | .json({ error: 'Requested format is not implemented on server.' }) | 40 | .json({ error: 'Requested format is not implemented on server.' }) |
37 | .end() | ||
38 | } | 41 | } |
39 | 42 | ||
40 | const url = req.query.url as string | 43 | const url = req.query.url as string |
41 | 44 | ||
42 | const startIsOk = url.startsWith(urlShouldStartWith) | 45 | const isPlaylist = url.startsWith(startVideoPlaylistsURL) |
43 | const matches = videoWatchRegex.exec(url) | 46 | const isVideo = isPlaylist ? false : url.startsWith(startVideosURL) |
47 | |||
48 | const startIsOk = isVideo || isPlaylist | ||
49 | |||
50 | const matches = watchRegex.exec(url) | ||
44 | 51 | ||
45 | if (startIsOk === false || matches === null) { | 52 | if (startIsOk === false || matches === null) { |
46 | return res.status(400) | 53 | return res.status(400) |
47 | .json({ error: 'Invalid url.' }) | 54 | .json({ error: 'Invalid url.' }) |
48 | .end() | ||
49 | } | 55 | } |
50 | 56 | ||
51 | const videoId = matches[1] | 57 | const elementId = matches[1] |
52 | if (isIdOrUUIDValid(videoId) === false) { | 58 | if (isIdOrUUIDValid(elementId) === false) { |
53 | return res.status(400) | 59 | return res.status(400) |
54 | .json({ error: 'Invalid video id.' }) | 60 | .json({ error: 'Invalid video or playlist id.' }) |
55 | .end() | ||
56 | } | 61 | } |
57 | 62 | ||
58 | if (!await doesVideoExist(videoId, res)) return | 63 | if (isVideo) { |
64 | const video = await fetchVideo(elementId, 'all') | ||
65 | |||
66 | if (!video) { | ||
67 | return res.status(404) | ||
68 | .json({ error: 'Video not found' }) | ||
69 | } | ||
59 | 70 | ||
71 | if (video.privacy !== VideoPrivacy.PUBLIC) { | ||
72 | return res.status(403) | ||
73 | .json({ error: 'Video is not public' }) | ||
74 | } | ||
75 | |||
76 | res.locals.videoAll = video | ||
77 | return next() | ||
78 | } | ||
79 | |||
80 | // Is playlist | ||
81 | |||
82 | const videoPlaylist = await VideoPlaylistModel.loadWithAccountAndChannelSummary(elementId, undefined) | ||
83 | if (!videoPlaylist) { | ||
84 | return res.status(404) | ||
85 | .json({ error: 'Video playlist not found' }) | ||
86 | } | ||
87 | |||
88 | if (videoPlaylist.privacy !== VideoPlaylistPrivacy.PUBLIC) { | ||
89 | return res.status(403) | ||
90 | .json({ error: 'Playlist is not public' }) | ||
91 | } | ||
92 | |||
93 | res.locals.videoPlaylistSummary = videoPlaylist | ||
60 | return next() | 94 | return next() |
61 | } | 95 | } |
96 | |||
62 | ] | 97 | ] |
63 | 98 | ||
64 | // --------------------------------------------------------------------------- | 99 | // --------------------------------------------------------------------------- |