aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/middlewares/validators/shared/videos.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/middlewares/validators/shared/videos.ts')
-rw-r--r--server/middlewares/validators/shared/videos.ts84
1 files changed, 68 insertions, 16 deletions
diff --git a/server/middlewares/validators/shared/videos.ts b/server/middlewares/validators/shared/videos.ts
index 8807435f6..39aab6df7 100644
--- a/server/middlewares/validators/shared/videos.ts
+++ b/server/middlewares/validators/shared/videos.ts
@@ -1,4 +1,5 @@
1import { Request, Response } from 'express' 1import { Request, Response } from 'express'
2import { isUUIDValid } from '@server/helpers/custom-validators/misc'
2import { loadVideo, VideoLoadType } from '@server/lib/model-loaders' 3import { loadVideo, VideoLoadType } from '@server/lib/model-loaders'
3import { isAbleToUploadVideo } from '@server/lib/user' 4import { isAbleToUploadVideo } from '@server/lib/user'
4import { authenticatePromiseIfNeeded } from '@server/middlewares/auth' 5import { authenticatePromiseIfNeeded } from '@server/middlewares/auth'
@@ -18,18 +19,19 @@ import {
18 MVideoThumbnail, 19 MVideoThumbnail,
19 MVideoWithRights 20 MVideoWithRights
20} from '@server/types/models' 21} from '@server/types/models'
21import { HttpStatusCode, ServerErrorCode, UserRight } from '@shared/models' 22import { HttpStatusCode, ServerErrorCode, UserRight, VideoPrivacy } from '@shared/models'
22 23
23async function doesVideoExist (id: number | string, res: Response, fetchType: VideoLoadType = 'all') { 24async function doesVideoExist (id: number | string, res: Response, fetchType: VideoLoadType = 'all') {
24 const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined 25 const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined
25 26
26 const video = await loadVideo(id, fetchType, userId) 27 const video = await loadVideo(id, fetchType, userId)
27 28
28 if (video === null) { 29 if (!video) {
29 res.fail({ 30 res.fail({
30 status: HttpStatusCode.NOT_FOUND_404, 31 status: HttpStatusCode.NOT_FOUND_404,
31 message: 'Video not found' 32 message: 'Video not found'
32 }) 33 })
34
33 return false 35 return false
34 } 36 }
35 37
@@ -58,6 +60,8 @@ async function doesVideoExist (id: number | string, res: Response, fetchType: Vi
58 return true 60 return true
59} 61}
60 62
63// ---------------------------------------------------------------------------
64
61async function doesVideoFileOfVideoExist (id: number, videoIdOrUUID: number | string, res: Response) { 65async function doesVideoFileOfVideoExist (id: number, videoIdOrUUID: number | string, res: Response) {
62 if (!await VideoFileModel.doesVideoExistForVideoFile(id, videoIdOrUUID)) { 66 if (!await VideoFileModel.doesVideoExistForVideoFile(id, videoIdOrUUID)) {
63 res.fail({ 67 res.fail({
@@ -70,6 +74,8 @@ async function doesVideoFileOfVideoExist (id: number, videoIdOrUUID: number | st
70 return true 74 return true
71} 75}
72 76
77// ---------------------------------------------------------------------------
78
73async function doesVideoChannelOfAccountExist (channelId: number, user: MUserAccountId, res: Response) { 79async function doesVideoChannelOfAccountExist (channelId: number, user: MUserAccountId, res: Response) {
74 const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId) 80 const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId)
75 81
@@ -95,32 +101,77 @@ async function doesVideoChannelOfAccountExist (channelId: number, user: MUserAcc
95 return true 101 return true
96} 102}
97 103
98async function checkCanSeeVideoIfPrivate (req: Request, res: Response, video: MVideo, authenticateInQuery = false) { 104// ---------------------------------------------------------------------------
99 if (!video.requiresAuth()) return true
100 105
101 const videoWithRights = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.id) 106async function checkCanSeeVideo (options: {
107 req: Request
108 res: Response
109 paramId: string
110 video: MVideo
111 authenticateInQuery?: boolean // default false
112}) {
113 const { req, res, video, paramId, authenticateInQuery = false } = options
114
115 if (video.requiresAuth()) {
116 return checkCanSeeAuthVideo(req, res, video, authenticateInQuery)
117 }
102 118
103 return checkCanSeePrivateVideo(req, res, videoWithRights, authenticateInQuery) 119 if (video.privacy === VideoPrivacy.UNLISTED) {
104} 120 if (isUUIDValid(paramId)) return true
105 121
106async function checkCanSeePrivateVideo (req: Request, res: Response, video: MVideoWithRights, authenticateInQuery = false) { 122 return checkCanSeeAuthVideo(req, res, video, authenticateInQuery)
107 await authenticatePromiseIfNeeded(req, res, authenticateInQuery) 123 }
108 124
109 const user = res.locals.oauth ? res.locals.oauth.token.User : null 125 if (video.privacy === VideoPrivacy.PUBLIC) return true
126
127 throw new Error('Fatal error when checking video right ' + video.url)
128}
110 129
111 // Only the owner or a user that have blocklist rights can see the video 130async function checkCanSeeAuthVideo (req: Request, res: Response, video: MVideoId | MVideoWithRights, authenticateInQuery = false) {
112 if (!user || !user.canGetVideo(video)) { 131 const fail = () => {
113 res.fail({ 132 res.fail({
114 status: HttpStatusCode.FORBIDDEN_403, 133 status: HttpStatusCode.FORBIDDEN_403,
115 message: 'Cannot fetch information of private/internal/blocklisted video' 134 message: 'Cannot fetch information of private/internal/blocked video'
116 }) 135 })
117 136
118 return false 137 return false
119 } 138 }
120 139
121 return true 140 await authenticatePromiseIfNeeded(req, res, authenticateInQuery)
141
142 const user = res.locals.oauth?.token.User
143 if (!user) return fail()
144
145 const videoWithRights = (video as MVideoWithRights).VideoChannel?.Account?.userId
146 ? video as MVideoWithRights
147 : await VideoModel.loadAndPopulateAccountAndServerAndTags(video.id)
148
149 const privacy = videoWithRights.privacy
150
151 if (privacy === VideoPrivacy.INTERNAL) {
152 // We know we have a user
153 return true
154 }
155
156 const isOwnedByUser = videoWithRights.VideoChannel.Account.userId === user.id
157 if (privacy === VideoPrivacy.PRIVATE || privacy === VideoPrivacy.UNLISTED) {
158 if (isOwnedByUser && user.hasRight(UserRight.SEE_ALL_VIDEOS)) return true
159
160 return fail()
161 }
162
163 if (videoWithRights.isBlacklisted()) {
164 if (isOwnedByUser || user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST)) return true
165
166 return fail()
167 }
168
169 // Should not happen
170 return fail()
122} 171}
123 172
173// ---------------------------------------------------------------------------
174
124function checkUserCanManageVideo (user: MUser, video: MVideoAccountLight, right: UserRight, res: Response, onlyOwned = true) { 175function checkUserCanManageVideo (user: MUser, video: MVideoAccountLight, right: UserRight, res: Response, onlyOwned = true) {
125 // Retrieve the user who did the request 176 // Retrieve the user who did the request
126 if (onlyOwned && video.isOwned() === false) { 177 if (onlyOwned && video.isOwned() === false) {
@@ -146,6 +197,8 @@ function checkUserCanManageVideo (user: MUser, video: MVideoAccountLight, right:
146 return true 197 return true
147} 198}
148 199
200// ---------------------------------------------------------------------------
201
149async function checkUserQuota (user: MUserId, videoFileSize: number, res: Response) { 202async function checkUserQuota (user: MUserId, videoFileSize: number, res: Response) {
150 if (await isAbleToUploadVideo(user.id, videoFileSize) === false) { 203 if (await isAbleToUploadVideo(user.id, videoFileSize) === false) {
151 res.fail({ 204 res.fail({
@@ -167,7 +220,6 @@ export {
167 doesVideoFileOfVideoExist, 220 doesVideoFileOfVideoExist,
168 221
169 checkUserCanManageVideo, 222 checkUserCanManageVideo,
170 checkCanSeeVideoIfPrivate, 223 checkCanSeeVideo,
171 checkCanSeePrivateVideo,
172 checkUserQuota 224 checkUserQuota
173} 225}