Fix private video download
authorChocobozzz <me@florianbigard.com>
Tue, 3 Dec 2019 09:41:23 +0000 (10:41 +0100)
committerChocobozzz <me@florianbigard.com>
Tue, 3 Dec 2019 09:41:23 +0000 (10:41 +0100)
client/src/app/shared/video/modals/video-download.component.ts
server/controllers/static.ts
server/middlewares/oauth.ts
server/middlewares/validators/videos/videos.ts

index 0e9e44de7c7e52fea659f2ad5dc2eb507cf24e73..5849ee4586fc5093247de431772b4a11f8412419 100644 (file)
@@ -2,7 +2,8 @@ import { Component, ElementRef, ViewChild } from '@angular/core'
 import { VideoDetails } from '../../../shared/video/video-details.model'
 import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap'
 import { I18n } from '@ngx-translate/i18n-polyfill'
-import { Notifier } from '@app/core'
+import { AuthService, Notifier } from '@app/core'
+import { VideoPrivacy } from '@shared/models'
 
 @Component({
   selector: 'my-video-download',
@@ -21,6 +22,7 @@ export class VideoDownloadComponent {
   constructor (
     private notifier: Notifier,
     private modalService: NgbModal,
+    private auth: AuthService,
     private i18n: I18n
   ) { }
 
@@ -57,12 +59,16 @@ export class VideoDownloadComponent {
       return
     }
 
+    const suffix = this.video.privacy.id === VideoPrivacy.PRIVATE
+      ? '?access_token=' + this.auth.getAccessToken()
+      : ''
+
     switch (this.downloadType) {
       case 'direct':
-        return file.fileDownloadUrl
+        return file.fileDownloadUrl + suffix
 
       case 'torrent':
-        return file.torrentDownloadUrl
+        return file.torrentDownloadUrl + suffix
     }
   }
 
index 7c900be9268ec4e286db0b17959920535a80891c..0aab12756ad53fd56910bd97975c035f9fc65295 100644 (file)
@@ -10,7 +10,7 @@ import {
   WEBSERVER
 } from '../initializers/constants'
 import { cacheRoute } from '../middlewares/cache'
-import { asyncMiddleware, videosGetValidator } from '../middlewares'
+import { asyncMiddleware, videosDownloadValidator } from '../middlewares'
 import { VideoModel } from '../models/video/video'
 import { UserModel } from '../models/account/user'
 import { VideoCommentModel } from '../models/video/video-comment'
@@ -39,12 +39,12 @@ staticRouter.use(
 )
 staticRouter.use(
   STATIC_DOWNLOAD_PATHS.TORRENTS + ':id-:resolution([0-9]+).torrent',
-  asyncMiddleware(videosGetValidator),
+  asyncMiddleware(videosDownloadValidator),
   asyncMiddleware(downloadTorrent)
 )
 staticRouter.use(
   STATIC_DOWNLOAD_PATHS.TORRENTS + ':id-:resolution([0-9]+)-hls.torrent',
-  asyncMiddleware(videosGetValidator),
+  asyncMiddleware(videosDownloadValidator),
   asyncMiddleware(downloadHLSVideoFileTorrent)
 )
 
@@ -62,13 +62,13 @@ staticRouter.use(
 
 staticRouter.use(
   STATIC_DOWNLOAD_PATHS.VIDEOS + ':id-:resolution([0-9]+).:extension',
-  asyncMiddleware(videosGetValidator),
+  asyncMiddleware(videosDownloadValidator),
   asyncMiddleware(downloadVideoFile)
 )
 
 staticRouter.use(
   STATIC_DOWNLOAD_PATHS.HLS_VIDEOS + ':id-:resolution([0-9]+)-fragmented.:extension',
-  asyncMiddleware(videosGetValidator),
+  asyncMiddleware(videosDownloadValidator),
   asyncMiddleware(downloadHLSVideoFile)
 )
 
index 77fb305dd5247063b538a502def2aa3df3d2e7a0..bb90dac470db51df2e5b7f7fc4a7bb6b9a527bcb 100644 (file)
@@ -12,8 +12,10 @@ const oAuthServer = new OAuthServer({
   model: require('../lib/oauth-model')
 })
 
-function authenticate (req: express.Request, res: express.Response, next: express.NextFunction) {
-  oAuthServer.authenticate()(req, res, err => {
+function authenticate (req: express.Request, res: express.Response, next: express.NextFunction, authenticateInQuery = false) {
+  const options = authenticateInQuery ? { allowBearerTokensInQueryString: true } : {}
+
+  oAuthServer.authenticate(options)(req, res, err => {
     if (err) {
       logger.warn('Cannot authenticate.', { err })
 
@@ -50,16 +52,14 @@ function authenticateSocket (socket: Socket, next: (err?: any) => void) {
     })
 }
 
-function authenticatePromiseIfNeeded (req: express.Request, res: express.Response) {
+function authenticatePromiseIfNeeded (req: express.Request, res: express.Response, authenticateInQuery = false) {
   return new Promise(resolve => {
     // Already authenticated? (or tried to)
     if (res.locals.oauth && res.locals.oauth.token.User) return resolve()
 
     if (res.locals.authenticated === false) return res.sendStatus(401)
 
-    authenticate(req, res, () => {
-      return resolve()
-    })
+    authenticate(req, res, () => resolve(), authenticateInQuery)
   })
 }
 
index 53a2f193d9db430ecdb772cd6bf454474627641a..ab984d84a98cdbbea881ded9a1d98d29b21ae036 100644 (file)
@@ -147,7 +147,7 @@ async function checkVideoFollowConstraints (req: express.Request, res: express.R
             })
 }
 
-const videosCustomGetValidator = (fetchType: 'all' | 'only-video' | 'only-video-with-rights') => {
+const videosCustomGetValidator = (fetchType: 'all' | 'only-video' | 'only-video-with-rights', authenticateInQuery = false) => {
   return [
     param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
 
@@ -162,7 +162,7 @@ const videosCustomGetValidator = (fetchType: 'all' | 'only-video' | 'only-video-
 
       // Video private or blacklisted
       if (video.privacy === VideoPrivacy.PRIVATE || videoAll.VideoBlacklist) {
-        await authenticatePromiseIfNeeded(req, res)
+        await authenticatePromiseIfNeeded(req, res, authenticateInQuery)
 
         const user = res.locals.oauth ? res.locals.oauth.token.User : null
 
@@ -193,6 +193,7 @@ const videosCustomGetValidator = (fetchType: 'all' | 'only-video' | 'only-video-
 }
 
 const videosGetValidator = videosCustomGetValidator('all')
+const videosDownloadValidator = videosCustomGetValidator('all', true)
 
 const videosRemoveValidator = [
   param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
@@ -407,6 +408,7 @@ export {
   videosAddValidator,
   videosUpdateValidator,
   videosGetValidator,
+  videosDownloadValidator,
   checkVideoFollowConstraints,
   videosCustomGetValidator,
   videosRemoveValidator,