mirror of
				https://github.com/Chocobozzz/PeerTube.git
				synced 2025-02-25 18:55:32 -06:00 
			
		
		
		
	Protect all video related AP endpoints
This commit is contained in:
		@@ -16,6 +16,7 @@ import { isHostValid } from '../../helpers/custom-validators/servers.js'
 | 
			
		||||
import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy.js'
 | 
			
		||||
import { ServerModel } from '../../models/server/server.js'
 | 
			
		||||
import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from './shared/index.js'
 | 
			
		||||
import { canVideoBeFederated } from '@server/lib/activitypub/videos/federate.js'
 | 
			
		||||
 | 
			
		||||
const videoFileRedundancyGetValidator = [
 | 
			
		||||
  isValidVideoIdParam('videoId'),
 | 
			
		||||
@@ -31,6 +32,7 @@ const videoFileRedundancyGetValidator = [
 | 
			
		||||
  async (req: express.Request, res: express.Response, next: express.NextFunction) => {
 | 
			
		||||
    if (areValidationErrors(req, res)) return
 | 
			
		||||
    if (!await doesVideoExist(req.params.videoId, res)) return
 | 
			
		||||
    if (!canVideoBeFederated(res.locals.onlyVideo)) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
 | 
			
		||||
 | 
			
		||||
    const video = res.locals.videoAll
 | 
			
		||||
 | 
			
		||||
@@ -72,6 +74,7 @@ const videoPlaylistRedundancyGetValidator = [
 | 
			
		||||
  async (req: express.Request, res: express.Response, next: express.NextFunction) => {
 | 
			
		||||
    if (areValidationErrors(req, res)) return
 | 
			
		||||
    if (!await doesVideoExist(req.params.videoId, res)) return
 | 
			
		||||
    if (!canVideoBeFederated(res.locals.onlyVideo)) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
 | 
			
		||||
 | 
			
		||||
    const video = res.locals.videoAll
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ import {
 | 
			
		||||
  MVideoFullLight,
 | 
			
		||||
  MVideoId,
 | 
			
		||||
  MVideoImmutable,
 | 
			
		||||
  MVideoThumbnail,
 | 
			
		||||
  MVideoThumbnailBlacklist,
 | 
			
		||||
  MVideoUUID,
 | 
			
		||||
  MVideoWithRights
 | 
			
		||||
} from '@server/types/models/index.js'
 | 
			
		||||
@@ -56,7 +56,7 @@ export async function doesVideoExist (id: number | string, res: Response, fetchT
 | 
			
		||||
      break
 | 
			
		||||
 | 
			
		||||
    case 'only-video-and-blacklist':
 | 
			
		||||
      res.locals.onlyVideo = video as MVideoThumbnail
 | 
			
		||||
      res.locals.onlyVideo = video as MVideoThumbnailBlacklist
 | 
			
		||||
      break
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,19 @@
 | 
			
		||||
import { HttpStatusCode } from '@peertube/peertube-models'
 | 
			
		||||
import { exists, isSafePeerTubeFilenameWithoutExtension, isUUIDValid, toBooleanOrNull } from '@server/helpers/custom-validators/misc.js'
 | 
			
		||||
import { logger } from '@server/helpers/logger.js'
 | 
			
		||||
import { LRU_CACHE } from '@server/initializers/constants.js'
 | 
			
		||||
import { VideoFileModel } from '@server/models/video/video-file.js'
 | 
			
		||||
import { VideoModel } from '@server/models/video/video.js'
 | 
			
		||||
import { MStreamingPlaylist, MVideoFile, MVideoThumbnailBlacklist } from '@server/types/models/index.js'
 | 
			
		||||
import express from 'express'
 | 
			
		||||
import { query } from 'express-validator'
 | 
			
		||||
import { LRUCache } from 'lru-cache'
 | 
			
		||||
import { basename, dirname } from 'path'
 | 
			
		||||
import { exists, isSafePeerTubeFilenameWithoutExtension, isUUIDValid, toBooleanOrNull } from '@server/helpers/custom-validators/misc.js'
 | 
			
		||||
import { logger } from '@server/helpers/logger.js'
 | 
			
		||||
import { LRU_CACHE } from '@server/initializers/constants.js'
 | 
			
		||||
import { VideoModel } from '@server/models/video/video.js'
 | 
			
		||||
import { VideoFileModel } from '@server/models/video/video-file.js'
 | 
			
		||||
import { MStreamingPlaylist, MVideoFile, MVideoThumbnail } from '@server/types/models/index.js'
 | 
			
		||||
import { HttpStatusCode } from '@peertube/peertube-models'
 | 
			
		||||
import { areValidationErrors, checkCanAccessVideoStaticFiles, isValidVideoPasswordHeader } from './shared/index.js'
 | 
			
		||||
 | 
			
		||||
type LRUValue = {
 | 
			
		||||
  allowed: boolean
 | 
			
		||||
  video?: MVideoThumbnail
 | 
			
		||||
  video?: MVideoThumbnailBlacklist
 | 
			
		||||
  file?: MVideoFile
 | 
			
		||||
  playlist?: MStreamingPlaylist }
 | 
			
		||||
 | 
			
		||||
@@ -122,8 +122,7 @@ const ensureCanAccessPrivateVideoHLSFiles = [
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
  ensureCanAccessVideoPrivateWebVideoFiles,
 | 
			
		||||
  ensureCanAccessPrivateVideoHLSFiles
 | 
			
		||||
  ensureCanAccessPrivateVideoHLSFiles, ensureCanAccessVideoPrivateWebVideoFiles
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ---------------------------------------------------------------------------
 | 
			
		||||
@@ -139,7 +138,7 @@ async function isWebVideoAllowed (req: express.Request, res: express.Response) {
 | 
			
		||||
    return { allowed: false }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const video = await VideoModel.load(file.getVideo().id)
 | 
			
		||||
  const video = await VideoModel.loadWithBlacklist(file.getVideo().id)
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    file,
 | 
			
		||||
@@ -151,7 +150,7 @@ async function isWebVideoAllowed (req: express.Request, res: express.Response) {
 | 
			
		||||
async function isHLSAllowed (req: express.Request, res: express.Response, videoUUID: string) {
 | 
			
		||||
  const filename = basename(req.path)
 | 
			
		||||
 | 
			
		||||
  const video = await VideoModel.loadWithFiles(videoUUID)
 | 
			
		||||
  const video = await VideoModel.loadAndPopulateAccountAndFiles(videoUUID)
 | 
			
		||||
 | 
			
		||||
  if (!video) {
 | 
			
		||||
    logger.debug('Unknown static file %s to serve', req.originalUrl, { videoUUID })
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ import {
 | 
			
		||||
  isValidVideoIdParam,
 | 
			
		||||
  isValidVideoPasswordHeader
 | 
			
		||||
} from '../shared/index.js'
 | 
			
		||||
import { canVideoBeFederated } from '@server/lib/activitypub/videos/federate.js'
 | 
			
		||||
 | 
			
		||||
const listVideoCommentsValidator = [
 | 
			
		||||
  query('isLocal')
 | 
			
		||||
@@ -132,8 +133,11 @@ const videoCommentGetValidator = [
 | 
			
		||||
 | 
			
		||||
  async (req: express.Request, res: express.Response, next: express.NextFunction) => {
 | 
			
		||||
    if (areValidationErrors(req, res)) return
 | 
			
		||||
    if (!await doesVideoExist(req.params.videoId, res, 'id')) return
 | 
			
		||||
    if (!await doesVideoCommentExist(req.params.commentId, res.locals.videoId, res)) return
 | 
			
		||||
    if (!await doesVideoExist(req.params.videoId, res, 'only-video-and-blacklist')) return
 | 
			
		||||
 | 
			
		||||
    if (!canVideoBeFederated(res.locals.onlyVideo)) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
 | 
			
		||||
 | 
			
		||||
    if (!await doesVideoCommentExist(req.params.commentId, res.locals.onlyVideo, res)) return
 | 
			
		||||
 | 
			
		||||
    return next()
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,12 @@
 | 
			
		||||
import { HttpStatusCode } from '@peertube/peertube-models'
 | 
			
		||||
import { canVideoBeFederated } from '@server/lib/activitypub/videos/federate.js'
 | 
			
		||||
import express from 'express'
 | 
			
		||||
import { param } from 'express-validator'
 | 
			
		||||
import { HttpStatusCode } from '@peertube/peertube-models'
 | 
			
		||||
import { isIdValid } from '../../../helpers/custom-validators/misc.js'
 | 
			
		||||
import { VideoShareModel } from '../../../models/video/video-share.js'
 | 
			
		||||
import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from '../shared/index.js'
 | 
			
		||||
 | 
			
		||||
const videosShareValidator = [
 | 
			
		||||
export const videosShareValidator = [
 | 
			
		||||
  isValidVideoIdParam('id'),
 | 
			
		||||
 | 
			
		||||
  param('actorId')
 | 
			
		||||
@@ -16,20 +17,12 @@ const videosShareValidator = [
 | 
			
		||||
    if (!await doesVideoExist(req.params.id, res)) return
 | 
			
		||||
 | 
			
		||||
    const video = res.locals.videoAll
 | 
			
		||||
    if (!canVideoBeFederated(video)) res.sendStatus(HttpStatusCode.NOT_FOUND_404)
 | 
			
		||||
 | 
			
		||||
    const share = await VideoShareModel.load(req.params.actorId, video.id)
 | 
			
		||||
    if (!share) {
 | 
			
		||||
      return res.status(HttpStatusCode.NOT_FOUND_404)
 | 
			
		||||
                .end()
 | 
			
		||||
    }
 | 
			
		||||
    if (!share) return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
 | 
			
		||||
 | 
			
		||||
    res.locals.videoShare = share
 | 
			
		||||
    return next()
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
// ---------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
  videosShareValidator
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1392,6 +1392,12 @@ export class VideoModel extends SequelizeModel<VideoModel> {
 | 
			
		||||
    return queryBuilder.queryVideo({ id, transaction, type: 'thumbnails-blacklist' })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static loadAndPopulateAccountAndFiles (id: number | string, transaction?: Transaction): Promise<MVideoAccountLightBlacklistAllFiles> {
 | 
			
		||||
    const queryBuilder = new VideoModelGetQueryBuilder(VideoModel.sequelize)
 | 
			
		||||
 | 
			
		||||
    return queryBuilder.queryVideo({ id, transaction, type: 'account-blacklist-files' })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static loadImmutableAttributes (id: number | string, t?: Transaction): Promise<MVideoImmutable> {
 | 
			
		||||
    const fun = () => {
 | 
			
		||||
      const query = {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								server/core/types/express.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								server/core/types/express.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -20,7 +20,8 @@ import {
 | 
			
		||||
  MVideoLiveFormattable,
 | 
			
		||||
  MVideoPassword,
 | 
			
		||||
  MVideoPlaylistFull,
 | 
			
		||||
  MVideoPlaylistFullSummary
 | 
			
		||||
  MVideoPlaylistFullSummary,
 | 
			
		||||
  MVideoThumbnailBlacklist
 | 
			
		||||
} from '@server/types/models/index.js'
 | 
			
		||||
import { MOAuthTokenUser } from '@server/types/models/oauth/oauth-token.js'
 | 
			
		||||
import { MPlugin, MServer, MServerBlocklist } from '@server/types/models/server.js'
 | 
			
		||||
@@ -44,8 +45,7 @@ import {
 | 
			
		||||
  MVideoCaptionVideo,
 | 
			
		||||
  MVideoFullLight,
 | 
			
		||||
  MVideoRedundancyVideo,
 | 
			
		||||
  MVideoShareActor,
 | 
			
		||||
  MVideoThumbnail
 | 
			
		||||
  MVideoShareActor
 | 
			
		||||
} from './models/index.js'
 | 
			
		||||
import { MRunner, MRunnerJobRunner, MRunnerRegistrationToken } from './models/runners/index.js'
 | 
			
		||||
import { MVideoSource } from './models/video/video-source.js'
 | 
			
		||||
@@ -135,7 +135,7 @@ declare module 'express' {
 | 
			
		||||
      videoAPI?: MVideoFormattableDetails
 | 
			
		||||
      videoAll?: MVideoFullLight
 | 
			
		||||
      onlyImmutableVideo?: MVideoImmutable
 | 
			
		||||
      onlyVideo?: MVideoThumbnail
 | 
			
		||||
      onlyVideo?: MVideoThumbnailBlacklist
 | 
			
		||||
      videoId?: MVideoId
 | 
			
		||||
 | 
			
		||||
      videoLive?: MVideoLiveFormattable
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user