aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2022-10-19 10:43:53 +0200
committerChocobozzz <chocobozzz@cpy.re>2022-10-24 14:48:24 +0200
commit9ab330b90decf4edf152ff8e1d2948c065766b2c (patch)
tree29d924f50f7307e8e828a57ecb9ea78623487ce0 /server/controllers
parent3545e72c686ff1725bbdfd8d16d693e2f4aa75a3 (diff)
downloadPeerTube-9ab330b90decf4edf152ff8e1d2948c065766b2c.tar.gz
PeerTube-9ab330b90decf4edf152ff8e1d2948c065766b2c.tar.zst
PeerTube-9ab330b90decf4edf152ff8e1d2948c065766b2c.zip
Use private ACL for private videos in s3
Diffstat (limited to 'server/controllers')
-rw-r--r--server/controllers/download.ts22
-rw-r--r--server/controllers/index.ts11
-rw-r--r--server/controllers/object-storage-proxy.ts78
3 files changed, 104 insertions, 7 deletions
diff --git a/server/controllers/download.ts b/server/controllers/download.ts
index abd1df26f..d9f34109f 100644
--- a/server/controllers/download.ts
+++ b/server/controllers/download.ts
@@ -5,6 +5,7 @@ import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache
5import { Hooks } from '@server/lib/plugins/hooks' 5import { Hooks } from '@server/lib/plugins/hooks'
6import { VideoPathManager } from '@server/lib/video-path-manager' 6import { VideoPathManager } from '@server/lib/video-path-manager'
7import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models' 7import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
8import { addQueryParams } from '@shared/core-utils'
8import { HttpStatusCode, VideoStorage, VideoStreamingPlaylistType } from '@shared/models' 9import { HttpStatusCode, VideoStorage, VideoStreamingPlaylistType } from '@shared/models'
9import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants' 10import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants'
10import { asyncMiddleware, optionalAuthenticate, videosDownloadValidator } from '../middlewares' 11import { asyncMiddleware, optionalAuthenticate, videosDownloadValidator } from '../middlewares'
@@ -84,7 +85,7 @@ async function downloadVideoFile (req: express.Request, res: express.Response) {
84 if (!checkAllowResult(res, allowParameters, allowedResult)) return 85 if (!checkAllowResult(res, allowParameters, allowedResult)) return
85 86
86 if (videoFile.storage === VideoStorage.OBJECT_STORAGE) { 87 if (videoFile.storage === VideoStorage.OBJECT_STORAGE) {
87 return res.redirect(videoFile.getObjectStorageUrl()) 88 return redirectToObjectStorage({ req, res, video, file: videoFile })
88 } 89 }
89 90
90 await VideoPathManager.Instance.makeAvailableVideoFile(videoFile.withVideoOrPlaylist(video), path => { 91 await VideoPathManager.Instance.makeAvailableVideoFile(videoFile.withVideoOrPlaylist(video), path => {
@@ -120,7 +121,7 @@ async function downloadHLSVideoFile (req: express.Request, res: express.Response
120 if (!checkAllowResult(res, allowParameters, allowedResult)) return 121 if (!checkAllowResult(res, allowParameters, allowedResult)) return
121 122
122 if (videoFile.storage === VideoStorage.OBJECT_STORAGE) { 123 if (videoFile.storage === VideoStorage.OBJECT_STORAGE) {
123 return res.redirect(videoFile.getObjectStorageUrl()) 124 return redirectToObjectStorage({ req, res, video, file: videoFile })
124 } 125 }
125 126
126 await VideoPathManager.Instance.makeAvailableVideoFile(videoFile.withVideoOrPlaylist(streamingPlaylist), path => { 127 await VideoPathManager.Instance.makeAvailableVideoFile(videoFile.withVideoOrPlaylist(streamingPlaylist), path => {
@@ -174,3 +175,20 @@ function checkAllowResult (res: express.Response, allowParameters: any, result?:
174 175
175 return true 176 return true
176} 177}
178
179function redirectToObjectStorage (options: {
180 req: express.Request
181 res: express.Response
182 video: MVideo
183 file: MVideoFile
184}) {
185 const { req, res, video, file } = options
186
187 const baseUrl = file.getObjectStorageUrl(video)
188
189 const url = video.hasPrivateStaticPath() && req.query.videoFileToken
190 ? addQueryParams(baseUrl, { videoFileToken: req.query.videoFileToken })
191 : baseUrl
192
193 return res.redirect(url)
194}
diff --git a/server/controllers/index.ts b/server/controllers/index.ts
index 8574a9e7b..eaa2dd7c8 100644
--- a/server/controllers/index.ts
+++ b/server/controllers/index.ts
@@ -1,14 +1,15 @@
1export * from './activitypub' 1export * from './activitypub'
2export * from './api' 2export * from './api'
3export * from './bots'
3export * from './client' 4export * from './client'
4export * from './download' 5export * from './download'
5export * from './feeds' 6export * from './feeds'
6export * from './services'
7export * from './static'
8export * from './lazy-static' 7export * from './lazy-static'
9export * from './misc' 8export * from './misc'
10export * from './webfinger' 9export * from './object-storage-proxy'
11export * from './tracker'
12export * from './bots'
13export * from './plugins' 10export * from './plugins'
11export * from './services'
12export * from './static'
13export * from './tracker'
14export * from './webfinger'
14export * from './well-known' 15export * from './well-known'
diff --git a/server/controllers/object-storage-proxy.ts b/server/controllers/object-storage-proxy.ts
new file mode 100644
index 000000000..6fedcfd8f
--- /dev/null
+++ b/server/controllers/object-storage-proxy.ts
@@ -0,0 +1,78 @@
1import cors from 'cors'
2import express from 'express'
3import { OBJECT_STORAGE_PROXY_PATHS } from '@server/initializers/constants'
4import { getHLSFileReadStream, getWebTorrentFileReadStream } from '@server/lib/object-storage'
5import {
6 asyncMiddleware,
7 ensureCanAccessPrivateVideoHLSFiles,
8 ensureCanAccessVideoPrivateWebTorrentFiles,
9 optionalAuthenticate
10} from '@server/middlewares'
11import { HttpStatusCode } from '@shared/models'
12
13const objectStorageProxyRouter = express.Router()
14
15objectStorageProxyRouter.use(cors())
16
17objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.PRIVATE_WEBSEED + ':filename',
18 optionalAuthenticate,
19 asyncMiddleware(ensureCanAccessVideoPrivateWebTorrentFiles),
20 asyncMiddleware(proxifyWebTorrent)
21)
22
23objectStorageProxyRouter.get(OBJECT_STORAGE_PROXY_PATHS.STREAMING_PLAYLISTS.PRIVATE_HLS + ':videoUUID/:filename',
24 optionalAuthenticate,
25 asyncMiddleware(ensureCanAccessPrivateVideoHLSFiles),
26 asyncMiddleware(proxifyHLS)
27)
28
29// ---------------------------------------------------------------------------
30
31export {
32 objectStorageProxyRouter
33}
34
35async function proxifyWebTorrent (req: express.Request, res: express.Response) {
36 const filename = req.params.filename
37
38 try {
39 const stream = await getWebTorrentFileReadStream({
40 filename,
41 rangeHeader: req.header('range')
42 })
43
44 return stream.pipe(res)
45 } catch (err) {
46 return handleObjectStorageFailure(res, err)
47 }
48}
49
50async function proxifyHLS (req: express.Request, res: express.Response) {
51 const playlist = res.locals.videoStreamingPlaylist
52 const video = res.locals.onlyVideo
53 const filename = req.params.filename
54
55 try {
56 const stream = await getHLSFileReadStream({
57 playlist: playlist.withVideo(video),
58 filename,
59 rangeHeader: req.header('range')
60 })
61
62 return stream.pipe(res)
63 } catch (err) {
64 return handleObjectStorageFailure(res, err)
65 }
66}
67
68function handleObjectStorageFailure (res: express.Response, err: Error) {
69 if (err.name === 'NoSuchKey') {
70 return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
71 }
72
73 return res.fail({
74 status: HttpStatusCode.INTERNAL_SERVER_ERROR_500,
75 message: err.message,
76 type: err.name
77 })
78}