aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-09-19 10:16:44 +0200
committerChocobozzz <me@florianbigard.com>2018-09-19 10:20:38 +0200
commit96f29c0f6d2e623fb088e88200934c5df8da9924 (patch)
treef11e52c12f56733bef70ac7bbde5179c5a5ecc40
parentad76628b17ff8f25d3402d6d669b274116bbf76c (diff)
downloadPeerTube-96f29c0f6d2e623fb088e88200934c5df8da9924.tar.gz
PeerTube-96f29c0f6d2e623fb088e88200934c5df8da9924.tar.zst
PeerTube-96f29c0f6d2e623fb088e88200934c5df8da9924.zip
Optimize SQL requests of videos AP endpoints
-rw-r--r--server/controllers/activitypub/client.ts16
-rw-r--r--server/helpers/custom-validators/videos.ts3
-rw-r--r--server/lib/activitypub/videos.ts2
-rw-r--r--server/middlewares/validators/video-comments.ts2
-rw-r--r--server/middlewares/validators/videos.ts68
-rw-r--r--server/models/video/video-format-utils.ts5
-rw-r--r--server/models/video/video.ts2
7 files changed, 55 insertions, 43 deletions
diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts
index 2e168ea78..6229c44aa 100644
--- a/server/controllers/activitypub/client.ts
+++ b/server/controllers/activitypub/client.ts
@@ -6,7 +6,13 @@ import { CONFIG, ROUTE_CACHE_LIFETIME } from '../../initializers'
6import { buildAnnounceWithVideoAudience } from '../../lib/activitypub/send' 6import { buildAnnounceWithVideoAudience } from '../../lib/activitypub/send'
7import { audiencify, getAudience } from '../../lib/activitypub/audience' 7import { audiencify, getAudience } from '../../lib/activitypub/audience'
8import { buildCreateActivity } from '../../lib/activitypub/send/send-create' 8import { buildCreateActivity } from '../../lib/activitypub/send/send-create'
9import { asyncMiddleware, executeIfActivityPub, localAccountValidator, localVideoChannelValidator } from '../../middlewares' 9import {
10 asyncMiddleware,
11 executeIfActivityPub,
12 localAccountValidator,
13 localVideoChannelValidator,
14 videosCustomGetValidator
15} from '../../middlewares'
10import { videosGetValidator, videosShareValidator } from '../../middlewares/validators' 16import { videosGetValidator, videosShareValidator } from '../../middlewares/validators'
11import { videoCommentGetValidator } from '../../middlewares/validators/video-comments' 17import { videoCommentGetValidator } from '../../middlewares/validators/video-comments'
12import { AccountModel } from '../../models/account/account' 18import { AccountModel } from '../../models/account/account'
@@ -54,7 +60,7 @@ activityPubClientRouter.get('/videos/watch/:id/activity',
54 executeIfActivityPub(asyncMiddleware(videoController)) 60 executeIfActivityPub(asyncMiddleware(videoController))
55) 61)
56activityPubClientRouter.get('/videos/watch/:id/announces', 62activityPubClientRouter.get('/videos/watch/:id/announces',
57 executeIfActivityPub(asyncMiddleware(videosGetValidator)), 63 executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video'))),
58 executeIfActivityPub(asyncMiddleware(videoAnnouncesController)) 64 executeIfActivityPub(asyncMiddleware(videoAnnouncesController))
59) 65)
60activityPubClientRouter.get('/videos/watch/:id/announces/:accountId', 66activityPubClientRouter.get('/videos/watch/:id/announces/:accountId',
@@ -62,15 +68,15 @@ activityPubClientRouter.get('/videos/watch/:id/announces/:accountId',
62 executeIfActivityPub(asyncMiddleware(videoAnnounceController)) 68 executeIfActivityPub(asyncMiddleware(videoAnnounceController))
63) 69)
64activityPubClientRouter.get('/videos/watch/:id/likes', 70activityPubClientRouter.get('/videos/watch/:id/likes',
65 executeIfActivityPub(asyncMiddleware(videosGetValidator)), 71 executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video'))),
66 executeIfActivityPub(asyncMiddleware(videoLikesController)) 72 executeIfActivityPub(asyncMiddleware(videoLikesController))
67) 73)
68activityPubClientRouter.get('/videos/watch/:id/dislikes', 74activityPubClientRouter.get('/videos/watch/:id/dislikes',
69 executeIfActivityPub(asyncMiddleware(videosGetValidator)), 75 executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video'))),
70 executeIfActivityPub(asyncMiddleware(videoDislikesController)) 76 executeIfActivityPub(asyncMiddleware(videoDislikesController))
71) 77)
72activityPubClientRouter.get('/videos/watch/:id/comments', 78activityPubClientRouter.get('/videos/watch/:id/comments',
73 executeIfActivityPub(asyncMiddleware(videosGetValidator)), 79 executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video'))),
74 executeIfActivityPub(asyncMiddleware(videoCommentsController)) 80 executeIfActivityPub(asyncMiddleware(videoCommentsController))
75) 81)
76activityPubClientRouter.get('/videos/watch/:videoId/comments/:commentId', 82activityPubClientRouter.get('/videos/watch/:videoId/comments/:commentId',
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts
index dd207c787..c9ef8445d 100644
--- a/server/helpers/custom-validators/videos.ts
+++ b/server/helpers/custom-validators/videos.ts
@@ -152,7 +152,8 @@ function checkUserCanManageVideo (user: UserModel, video: VideoModel, right: Use
152 return true 152 return true
153} 153}
154 154
155async function isVideoExist (id: string, res: Response, fetchType: 'all' | 'only-video' | 'id' | 'none' = 'all') { 155export type VideoFetchType = 'all' | 'only-video' | 'id' | 'none'
156async function isVideoExist (id: string, res: Response, fetchType: VideoFetchType = 'all') {
156 let video: VideoModel | null 157 let video: VideoModel | null
157 158
158 if (fetchType === 'all') { 159 if (fetchType === 'all') {
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
index 783f78d3e..5150c9975 100644
--- a/server/lib/activitypub/videos.ts
+++ b/server/lib/activitypub/videos.ts
@@ -61,7 +61,7 @@ function fetchRemoteVideoStaticFile (video: VideoModel, path: string, reject: Fu
61 61
62async function fetchRemoteVideoDescription (video: VideoModel) { 62async function fetchRemoteVideoDescription (video: VideoModel) {
63 const host = video.VideoChannel.Account.Actor.Server.host 63 const host = video.VideoChannel.Account.Actor.Server.host
64 const path = video.getDescriptionPath() 64 const path = video.getDescriptionAPIPath()
65 const options = { 65 const options = {
66 uri: REMOTE_SCHEME.HTTP + '://' + host + path, 66 uri: REMOTE_SCHEME.HTTP + '://' + host + path,
67 json: true 67 json: true
diff --git a/server/middlewares/validators/video-comments.ts b/server/middlewares/validators/video-comments.ts
index 4b15eed23..693852499 100644
--- a/server/middlewares/validators/video-comments.ts
+++ b/server/middlewares/validators/video-comments.ts
@@ -78,7 +78,7 @@ const videoCommentGetValidator = [
78 logger.debug('Checking videoCommentGetValidator parameters.', { parameters: req.params }) 78 logger.debug('Checking videoCommentGetValidator parameters.', { parameters: req.params })
79 79
80 if (areValidationErrors(req, res)) return 80 if (areValidationErrors(req, res)) return
81 if (!await isVideoExist(req.params.videoId, res)) return 81 if (!await isVideoExist(req.params.videoId, res, 'id')) return
82 if (!await isVideoCommentExist(req.params.commentId, res.locals.video, res)) return 82 if (!await isVideoCommentExist(req.params.commentId, res.locals.video, res)) return
83 83
84 return next() 84 return next()
diff --git a/server/middlewares/validators/videos.ts b/server/middlewares/validators/videos.ts
index 9befbc9ee..8aa7b3a39 100644
--- a/server/middlewares/validators/videos.ts
+++ b/server/middlewares/validators/videos.ts
@@ -26,7 +26,8 @@ import {
26 isVideoPrivacyValid, 26 isVideoPrivacyValid,
27 isVideoRatingTypeValid, 27 isVideoRatingTypeValid,
28 isVideoSupportValid, 28 isVideoSupportValid,
29 isVideoTagsValid 29 isVideoTagsValid,
30 VideoFetchType
30} from '../../helpers/custom-validators/videos' 31} from '../../helpers/custom-validators/videos'
31import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils' 32import { getDurationFromVideoFile } from '../../helpers/ffmpeg-utils'
32import { logger } from '../../helpers/logger' 33import { logger } from '../../helpers/logger'
@@ -128,47 +129,49 @@ const videosUpdateValidator = getCommonVideoAttributes().concat([
128 } 129 }
129]) 130])
130 131
131const videosGetValidator = [ 132const videosCustomGetValidator = (fetchType: VideoFetchType) => {
132 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 133 return [
133 134 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
134 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
135 logger.debug('Checking videosGet parameters', { parameters: req.params })
136 135
137 if (areValidationErrors(req, res)) return 136 async (req: express.Request, res: express.Response, next: express.NextFunction) => {
138 if (!await isVideoExist(req.params.id, res)) return 137 logger.debug('Checking videosGet parameters', { parameters: req.params })
139 138
140 const video: VideoModel = res.locals.video 139 if (areValidationErrors(req, res)) return
140 if (!await isVideoExist(req.params.id, res, fetchType)) return
141 141
142 // Video private or blacklisted 142 const video: VideoModel = res.locals.video
143 if (video.privacy === VideoPrivacy.PRIVATE || video.VideoBlacklist) {
144 return authenticate(req, res, () => {
145 const user: UserModel = res.locals.oauth.token.User
146 143
147 // Only the owner or a user that have blacklist rights can see the video 144 // Video private or blacklisted
148 if (video.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)) { 145 if (video.privacy === VideoPrivacy.PRIVATE || video.VideoBlacklist) {
149 return res.status(403) 146 return authenticate(req, res, () => {
150 .json({ error: 'Cannot get this private or blacklisted video.' }) 147 const user: UserModel = res.locals.oauth.token.User
151 .end()
152 }
153 148
154 return next() 149 // Only the owner or a user that have blacklist rights can see the video
155 }) 150 if (video.VideoChannel.Account.userId !== user.id && !user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)) {
151 return res.status(403)
152 .json({ error: 'Cannot get this private or blacklisted video.' })
153 .end()
154 }
156 155
157 return 156 return next()
158 } 157 })
158 }
159 159
160 // Video is public, anyone can access it 160 // Video is public, anyone can access it
161 if (video.privacy === VideoPrivacy.PUBLIC) return next() 161 if (video.privacy === VideoPrivacy.PUBLIC) return next()
162 162
163 // Video is unlisted, check we used the uuid to fetch it 163 // Video is unlisted, check we used the uuid to fetch it
164 if (video.privacy === VideoPrivacy.UNLISTED) { 164 if (video.privacy === VideoPrivacy.UNLISTED) {
165 if (isUUIDValid(req.params.id)) return next() 165 if (isUUIDValid(req.params.id)) return next()
166 166
167 // Don't leak this unlisted video 167 // Don't leak this unlisted video
168 return res.status(404).end() 168 return res.status(404).end()
169 }
169 } 170 }
170 } 171 ]
171] 172}
173
174const videosGetValidator = videosCustomGetValidator('all')
172 175
173const videosRemoveValidator = [ 176const videosRemoveValidator = [
174 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'), 177 param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
@@ -366,6 +369,7 @@ export {
366 videosAddValidator, 369 videosAddValidator,
367 videosUpdateValidator, 370 videosUpdateValidator,
368 videosGetValidator, 371 videosGetValidator,
372 videosCustomGetValidator,
369 videosRemoveValidator, 373 videosRemoveValidator,
370 videosShareValidator, 374 videosShareValidator,
371 375
diff --git a/server/models/video/video-format-utils.ts b/server/models/video/video-format-utils.ts
index fae38507b..a9a58624d 100644
--- a/server/models/video/video-format-utils.ts
+++ b/server/models/video/video-format-utils.ts
@@ -112,12 +112,13 @@ function videoModelToFormattedDetailsJSON (video: VideoModel): VideoDetails {
112 } 112 }
113 }) 113 })
114 114
115 const tags = video.Tags ? video.Tags.map(t => t.name) : []
115 const detailsJson = { 116 const detailsJson = {
116 support: video.support, 117 support: video.support,
117 descriptionPath: video.getDescriptionPath(), 118 descriptionPath: video.getDescriptionAPIPath(),
118 channel: video.VideoChannel.toFormattedJSON(), 119 channel: video.VideoChannel.toFormattedJSON(),
119 account: video.VideoChannel.Account.toFormattedJSON(), 120 account: video.VideoChannel.Account.toFormattedJSON(),
120 tags: video.Tags.map(t => t.name), 121 tags,
121 commentsEnabled: video.commentsEnabled, 122 commentsEnabled: video.commentsEnabled,
122 waitTranscoding: video.waitTranscoding, 123 waitTranscoding: video.waitTranscoding,
123 state: { 124 state: {
diff --git a/server/models/video/video.ts b/server/models/video/video.ts
index c7cd2890c..ce2153f87 100644
--- a/server/models/video/video.ts
+++ b/server/models/video/video.ts
@@ -1406,7 +1406,7 @@ export class VideoModel extends Model<VideoModel> {
1406 return getVideoFileResolution(originalFilePath) 1406 return getVideoFileResolution(originalFilePath)
1407 } 1407 }
1408 1408
1409 getDescriptionPath () { 1409 getDescriptionAPIPath () {
1410 return `/api/${API_VERSION}/videos/${this.uuid}/description` 1410 return `/api/${API_VERSION}/videos/${this.uuid}/description`
1411 } 1411 }
1412 1412