]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Optimize SQL requests of videos AP endpoints
authorChocobozzz <me@florianbigard.com>
Wed, 19 Sep 2018 08:16:44 +0000 (10:16 +0200)
committerChocobozzz <me@florianbigard.com>
Wed, 19 Sep 2018 08:20:38 +0000 (10:20 +0200)
server/controllers/activitypub/client.ts
server/helpers/custom-validators/videos.ts
server/lib/activitypub/videos.ts
server/middlewares/validators/video-comments.ts
server/middlewares/validators/videos.ts
server/models/video/video-format-utils.ts
server/models/video/video.ts

index 2e168ea78812c6876fa158e685ca60f09f72daa7..6229c44aa0b5f144a8a0016efbd4417a6edcbb10 100644 (file)
@@ -6,7 +6,13 @@ import { CONFIG, ROUTE_CACHE_LIFETIME } from '../../initializers'
 import { buildAnnounceWithVideoAudience } from '../../lib/activitypub/send'
 import { audiencify, getAudience } from '../../lib/activitypub/audience'
 import { buildCreateActivity } from '../../lib/activitypub/send/send-create'
-import { asyncMiddleware, executeIfActivityPub, localAccountValidator, localVideoChannelValidator } from '../../middlewares'
+import {
+  asyncMiddleware,
+  executeIfActivityPub,
+  localAccountValidator,
+  localVideoChannelValidator,
+  videosCustomGetValidator
+} from '../../middlewares'
 import { videosGetValidator, videosShareValidator } from '../../middlewares/validators'
 import { videoCommentGetValidator } from '../../middlewares/validators/video-comments'
 import { AccountModel } from '../../models/account/account'
@@ -54,7 +60,7 @@ activityPubClientRouter.get('/videos/watch/:id/activity',
   executeIfActivityPub(asyncMiddleware(videoController))
 )
 activityPubClientRouter.get('/videos/watch/:id/announces',
-  executeIfActivityPub(asyncMiddleware(videosGetValidator)),
+  executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video'))),
   executeIfActivityPub(asyncMiddleware(videoAnnouncesController))
 )
 activityPubClientRouter.get('/videos/watch/:id/announces/:accountId',
@@ -62,15 +68,15 @@ activityPubClientRouter.get('/videos/watch/:id/announces/:accountId',
   executeIfActivityPub(asyncMiddleware(videoAnnounceController))
 )
 activityPubClientRouter.get('/videos/watch/:id/likes',
-  executeIfActivityPub(asyncMiddleware(videosGetValidator)),
+  executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video'))),
   executeIfActivityPub(asyncMiddleware(videoLikesController))
 )
 activityPubClientRouter.get('/videos/watch/:id/dislikes',
-  executeIfActivityPub(asyncMiddleware(videosGetValidator)),
+  executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video'))),
   executeIfActivityPub(asyncMiddleware(videoDislikesController))
 )
 activityPubClientRouter.get('/videos/watch/:id/comments',
-  executeIfActivityPub(asyncMiddleware(videosGetValidator)),
+  executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video'))),
   executeIfActivityPub(asyncMiddleware(videoCommentsController))
 )
 activityPubClientRouter.get('/videos/watch/:videoId/comments/:commentId',
index dd207c7876d470cf2bada623eb9fb5d537919637..c9ef8445d2a69cd1934df579a8e7a24c5062ce83 100644 (file)
@@ -152,7 +152,8 @@ function checkUserCanManageVideo (user: UserModel, video: VideoModel, right: Use
   return true
 }
 
-async function isVideoExist (id: string, res: Response, fetchType: 'all' | 'only-video' | 'id' | 'none' = 'all') {
+export type VideoFetchType = 'all' | 'only-video' | 'id' | 'none'
+async function isVideoExist (id: string, res: Response, fetchType: VideoFetchType = 'all') {
   let video: VideoModel | null
 
   if (fetchType === 'all') {
index 783f78d3ec8417ec0bcee5b96835482e3e57b8fb..5150c9975d13c3f07dcc66822c8db78659be4e22 100644 (file)
@@ -61,7 +61,7 @@ function fetchRemoteVideoStaticFile (video: VideoModel, path: string, reject: Fu
 
 async function fetchRemoteVideoDescription (video: VideoModel) {
   const host = video.VideoChannel.Account.Actor.Server.host
-  const path = video.getDescriptionPath()
+  const path = video.getDescriptionAPIPath()
   const options = {
     uri: REMOTE_SCHEME.HTTP + '://' + host + path,
     json: true
index 4b15eed23006255fa657186f5b6b06f66ddb37c6..69385249923ce6214c44dfb8592930a8037dc820 100644 (file)
@@ -78,7 +78,7 @@ const videoCommentGetValidator = [
     logger.debug('Checking videoCommentGetValidator parameters.', { parameters: req.params })
 
     if (areValidationErrors(req, res)) return
-    if (!await isVideoExist(req.params.videoId, res)) return
+    if (!await isVideoExist(req.params.videoId, res, 'id')) return
     if (!await isVideoCommentExist(req.params.commentId, res.locals.video, res)) return
 
     return next()
index 9befbc9ee7e506d195c94b899f1ebc5e939bfe5b..8aa7b3a396630a78043046e2f424ac589bd83460 100644 (file)
@@ -26,7 +26,8 @@ import {
   isVideoPrivacyValid,
   isVideoRatingTypeValid,
   isVideoSupportValid,
-  isVideoTagsValid
+  isVideoTagsValid,
+  VideoFetchType
 } from '../../helpers/custom-validators/videos'
 import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils'
 import { logger } from '../../helpers/logger'
@@ -128,47 +129,49 @@ const videosUpdateValidator = getCommonVideoAttributes().concat([
   }
 ])
 
-const videosGetValidator = [
-  param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
-
-  async (req: express.Request, res: express.Response, next: express.NextFunction) => {
-    logger.debug('Checking videosGet parameters', { parameters: req.params })
+const videosCustomGetValidator = (fetchType: VideoFetchType) => {
+  return [
+    param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
 
-    if (areValidationErrors(req, res)) return
-    if (!await isVideoExist(req.params.id, res)) return
+    async (req: express.Request, res: express.Response, next: express.NextFunction) => {
+      logger.debug('Checking videosGet parameters', { parameters: req.params })
 
-    const video: VideoModel = res.locals.video
+      if (areValidationErrors(req, res)) return
+      if (!await isVideoExist(req.params.id, res, fetchType)) return
 
-    // Video private or blacklisted
-    if (video.privacy === VideoPrivacy.PRIVATE || video.VideoBlacklist) {
-      return authenticate(req, res, () => {
-        const user: UserModel = res.locals.oauth.token.User
+      const video: VideoModel = res.locals.video
 
-        // Only the owner or a user that have blacklist rights can see the video
-        if (video.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)) {
-          return res.status(403)
-                    .json({ error: 'Cannot get this private or blacklisted video.' })
-                    .end()
-        }
+      // Video private or blacklisted
+      if (video.privacy === VideoPrivacy.PRIVATE || video.VideoBlacklist) {
+        return authenticate(req, res, () => {
+          const user: UserModel = res.locals.oauth.token.User
 
-        return next()
-      })
+          // Only the owner or a user that have blacklist rights can see the video
+          if (video.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)) {
+            return res.status(403)
+                      .json({ error: 'Cannot get this private or blacklisted video.' })
+                      .end()
+          }
 
-      return
-    }
+          return next()
+        })
+      }
 
-    // Video is public, anyone can access it
-    if (video.privacy === VideoPrivacy.PUBLIC) return next()
+      // Video is public, anyone can access it
+      if (video.privacy === VideoPrivacy.PUBLIC) return next()
 
-    // Video is unlisted, check we used the uuid to fetch it
-    if (video.privacy === VideoPrivacy.UNLISTED) {
-      if (isUUIDValid(req.params.id)) return next()
+      // Video is unlisted, check we used the uuid to fetch it
+      if (video.privacy === VideoPrivacy.UNLISTED) {
+        if (isUUIDValid(req.params.id)) return next()
 
-      // Don't leak this unlisted video
-      return res.status(404).end()
+        // Don't leak this unlisted video
+        return res.status(404).end()
+      }
     }
-  }
-]
+  ]
+}
+
+const videosGetValidator = videosCustomGetValidator('all')
 
 const videosRemoveValidator = [
   param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
@@ -366,6 +369,7 @@ export {
   videosAddValidator,
   videosUpdateValidator,
   videosGetValidator,
+  videosCustomGetValidator,
   videosRemoveValidator,
   videosShareValidator,
 
index fae38507bdfef924979c68aaebb4a58eca2c787b..a9a58624dee16e1d7c75246fb21125205e7ecdf3 100644 (file)
@@ -112,12 +112,13 @@ function videoModelToFormattedDetailsJSON (video: VideoModel): VideoDetails {
     }
   })
 
+  const tags = video.Tags ? video.Tags.map(t => t.name) : []
   const detailsJson = {
     support: video.support,
-    descriptionPath: video.getDescriptionPath(),
+    descriptionPath: video.getDescriptionAPIPath(),
     channel: video.VideoChannel.toFormattedJSON(),
     account: video.VideoChannel.Account.toFormattedJSON(),
-    tags: video.Tags.map(t => t.name),
+    tags,
     commentsEnabled: video.commentsEnabled,
     waitTranscoding: video.waitTranscoding,
     state: {
index c7cd2890ca593f123408be4e0795a093c80acef1..ce2153f870f0d9e929caafe1192618cbbb8ccb22 100644 (file)
@@ -1406,7 +1406,7 @@ export class VideoModel extends Model<VideoModel> {
     return getVideoFileResolution(originalFilePath)
   }
 
-  getDescriptionPath () {
+  getDescriptionAPIPath () {
     return `/api/${API_VERSION}/videos/${this.uuid}/description`
   }