aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/download.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-03-23 11:54:08 +0100
committerChocobozzz <me@florianbigard.com>2021-03-24 18:18:41 +0100
commit4bc45da342597fb49593fc14c40f8dc5a97bb64e (patch)
tree9fa876e21995b27827fbc4467bd71b8d427312e2 /server/controllers/download.ts
parentc0ab041c2c749db05ce564d3078c2ad10d18f35f (diff)
downloadPeerTube-4bc45da342597fb49593fc14c40f8dc5a97bb64e.tar.gz
PeerTube-4bc45da342597fb49593fc14c40f8dc5a97bb64e.tar.zst
PeerTube-4bc45da342597fb49593fc14c40f8dc5a97bb64e.zip
Add hooks support for video download
Diffstat (limited to 'server/controllers/download.ts')
-rw-r--r--server/controllers/download.ts85
1 files changed, 74 insertions, 11 deletions
diff --git a/server/controllers/download.ts b/server/controllers/download.ts
index 27caa1518..fd44f10e9 100644
--- a/server/controllers/download.ts
+++ b/server/controllers/download.ts
@@ -1,8 +1,10 @@
1import * as cors from 'cors' 1import * as cors from 'cors'
2import * as express from 'express' 2import * as express from 'express'
3import { logger } from '@server/helpers/logger'
3import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache' 4import { VideosTorrentCache } from '@server/lib/files-cache/videos-torrent-cache'
5import { Hooks } from '@server/lib/plugins/hooks'
4import { getVideoFilePath } from '@server/lib/video-paths' 6import { getVideoFilePath } from '@server/lib/video-paths'
5import { MVideoFile, MVideoFullLight } from '@server/types/models' 7import { MStreamingPlaylist, MVideo, MVideoFile, MVideoFullLight } from '@server/types/models'
6import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' 8import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
7import { VideoStreamingPlaylistType } from '@shared/models' 9import { VideoStreamingPlaylistType } from '@shared/models'
8import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants' 10import { STATIC_DOWNLOAD_PATHS } from '../initializers/constants'
@@ -14,19 +16,19 @@ downloadRouter.use(cors())
14 16
15downloadRouter.use( 17downloadRouter.use(
16 STATIC_DOWNLOAD_PATHS.TORRENTS + ':filename', 18 STATIC_DOWNLOAD_PATHS.TORRENTS + ':filename',
17 downloadTorrent 19 asyncMiddleware(downloadTorrent)
18) 20)
19 21
20downloadRouter.use( 22downloadRouter.use(
21 STATIC_DOWNLOAD_PATHS.VIDEOS + ':id-:resolution([0-9]+).:extension', 23 STATIC_DOWNLOAD_PATHS.VIDEOS + ':id-:resolution([0-9]+).:extension',
22 asyncMiddleware(videosDownloadValidator), 24 asyncMiddleware(videosDownloadValidator),
23 downloadVideoFile 25 asyncMiddleware(downloadVideoFile)
24) 26)
25 27
26downloadRouter.use( 28downloadRouter.use(
27 STATIC_DOWNLOAD_PATHS.HLS_VIDEOS + ':id-:resolution([0-9]+)-fragmented.:extension', 29 STATIC_DOWNLOAD_PATHS.HLS_VIDEOS + ':id-:resolution([0-9]+)-fragmented.:extension',
28 asyncMiddleware(videosDownloadValidator), 30 asyncMiddleware(videosDownloadValidator),
29 downloadHLSVideoFile 31 asyncMiddleware(downloadHLSVideoFile)
30) 32)
31 33
32// --------------------------------------------------------------------------- 34// ---------------------------------------------------------------------------
@@ -41,28 +43,58 @@ async function downloadTorrent (req: express.Request, res: express.Response) {
41 const result = await VideosTorrentCache.Instance.getFilePath(req.params.filename) 43 const result = await VideosTorrentCache.Instance.getFilePath(req.params.filename)
42 if (!result) return res.sendStatus(HttpStatusCode.NOT_FOUND_404) 44 if (!result) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
43 45
46 const allowParameters = { torrentPath: result.path, downloadName: result.downloadName }
47
48 const allowedResult = await Hooks.wrapFun(
49 isTorrentDownloadAllowed,
50 allowParameters,
51 'filter:api.download.torrent.allowed.result'
52 )
53
54 if (!checkAllowResult(res, allowParameters, allowedResult)) return
55
44 return res.download(result.path, result.downloadName) 56 return res.download(result.path, result.downloadName)
45} 57}
46 58
47function downloadVideoFile (req: express.Request, res: express.Response) { 59async function downloadVideoFile (req: express.Request, res: express.Response) {
48 const video = res.locals.videoAll 60 const video = res.locals.videoAll
49 61
50 const videoFile = getVideoFile(req, video.VideoFiles) 62 const videoFile = getVideoFile(req, video.VideoFiles)
51 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).end() 63 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).end()
52 64
65 const allowParameters = { video, videoFile }
66
67 const allowedResult = await Hooks.wrapFun(
68 isVideoDownloadAllowed,
69 allowParameters,
70 'filter:api.download.video.allowed.result'
71 )
72
73 if (!checkAllowResult(res, allowParameters, allowedResult)) return
74
53 return res.download(getVideoFilePath(video, videoFile), `${video.name}-${videoFile.resolution}p${videoFile.extname}`) 75 return res.download(getVideoFilePath(video, videoFile), `${video.name}-${videoFile.resolution}p${videoFile.extname}`)
54} 76}
55 77
56function downloadHLSVideoFile (req: express.Request, res: express.Response) { 78async function downloadHLSVideoFile (req: express.Request, res: express.Response) {
57 const video = res.locals.videoAll 79 const video = res.locals.videoAll
58 const playlist = getHLSPlaylist(video) 80 const streamingPlaylist = getHLSPlaylist(video)
59 if (!playlist) return res.status(HttpStatusCode.NOT_FOUND_404).end 81 if (!streamingPlaylist) return res.status(HttpStatusCode.NOT_FOUND_404).end
60 82
61 const videoFile = getVideoFile(req, playlist.VideoFiles) 83 const videoFile = getVideoFile(req, streamingPlaylist.VideoFiles)
62 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).end() 84 if (!videoFile) return res.status(HttpStatusCode.NOT_FOUND_404).end()
63 85
64 const filename = `${video.name}-${videoFile.resolution}p-${playlist.getStringType()}${videoFile.extname}` 86 const allowParameters = { video, streamingPlaylist, videoFile }
65 return res.download(getVideoFilePath(playlist, videoFile), filename) 87
88 const allowedResult = await Hooks.wrapFun(
89 isVideoDownloadAllowed,
90 allowParameters,
91 'filter:api.download.video.allowed.result'
92 )
93
94 if (!checkAllowResult(res, allowParameters, allowedResult)) return
95
96 const filename = `${video.name}-${videoFile.resolution}p-${streamingPlaylist.getStringType()}${videoFile.extname}`
97 return res.download(getVideoFilePath(streamingPlaylist, videoFile), filename)
66} 98}
67 99
68function getVideoFile (req: express.Request, files: MVideoFile[]) { 100function getVideoFile (req: express.Request, files: MVideoFile[]) {
@@ -76,3 +108,34 @@ function getHLSPlaylist (video: MVideoFullLight) {
76 108
77 return Object.assign(playlist, { Video: video }) 109 return Object.assign(playlist, { Video: video })
78} 110}
111
112type AllowedResult = {
113 allowed: boolean
114 errorMessage?: string
115}
116
117function isTorrentDownloadAllowed (_object: {
118 torrentPath: string
119}): AllowedResult {
120 return { allowed: true }
121}
122
123function isVideoDownloadAllowed (_object: {
124 video: MVideo
125 videoFile: MVideoFile
126 streamingPlaylist?: MStreamingPlaylist
127}): AllowedResult {
128 return { allowed: true }
129}
130
131function checkAllowResult (res: express.Response, allowParameters: any, result?: AllowedResult) {
132 if (!result || result.allowed !== true) {
133 logger.info('Download is not allowed.', { result, allowParameters })
134 res.status(HttpStatusCode.FORBIDDEN_403)
135 .json({ error: result.errorMessage || 'Refused download' })
136
137 return false
138 }
139
140 return true
141}