]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/middlewares/validators/shared/videos.ts
Clearer video creation from API regarding rates
[github/Chocobozzz/PeerTube.git] / server / middlewares / validators / shared / videos.ts
CommitLineData
795212f7 1import { Request, Response } from 'express'
868fce62 2import { loadVideo, VideoLoadType } from '@server/lib/model-loaders'
c729caf6 3import { isAbleToUploadVideo } from '@server/lib/user'
795212f7
C
4import { authenticatePromiseIfNeeded } from '@server/middlewares/auth'
5import { VideoModel } from '@server/models/video/video'
10363c74
C
6import { VideoChannelModel } from '@server/models/video/video-channel'
7import { VideoFileModel } from '@server/models/video/video-file'
7eba5e1f
C
8import {
9 MUser,
10 MUserAccountId,
c729caf6 11 MUserId,
795212f7 12 MVideo,
7eba5e1f 13 MVideoAccountLight,
ca4b4b2e 14 MVideoFormattableDetails,
7eba5e1f 15 MVideoFullLight,
71d4af1e 16 MVideoId,
7eba5e1f 17 MVideoImmutable,
795212f7
C
18 MVideoThumbnail,
19 MVideoWithRights
26d6bf65 20} from '@server/types/models'
c729caf6 21import { HttpStatusCode, ServerErrorCode, UserRight } from '@shared/models'
3e753302 22
868fce62 23async function doesVideoExist (id: number | string, res: Response, fetchType: VideoLoadType = 'all') {
3e753302
C
24 const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined
25
868fce62 26 const video = await loadVideo(id, fetchType, userId)
3e753302
C
27
28 if (video === null) {
76148b27
RK
29 res.fail({
30 status: HttpStatusCode.NOT_FOUND_404,
31 message: 'Video not found'
32 })
3e753302
C
33 return false
34 }
35
453e83ea 36 switch (fetchType) {
ca4b4b2e
C
37 case 'for-api':
38 res.locals.videoAPI = video as MVideoFormattableDetails
39 break
40
453e83ea
C
41 case 'all':
42 res.locals.videoAll = video as MVideoFullLight
43 break
44
7eba5e1f
C
45 case 'only-immutable-attributes':
46 res.locals.onlyImmutableVideo = video as MVideoImmutable
47 break
48
453e83ea 49 case 'id':
71d4af1e 50 res.locals.videoId = video as MVideoId
453e83ea
C
51 break
52
53 case 'only-video':
0283eaac 54 res.locals.onlyVideo = video as MVideoThumbnail
453e83ea 55 break
453e83ea
C
56 }
57
3e753302
C
58 return true
59}
60
8319d6ae
RK
61async function doesVideoFileOfVideoExist (id: number, videoIdOrUUID: number | string, res: Response) {
62 if (!await VideoFileModel.doesVideoExistForVideoFile(id, videoIdOrUUID)) {
76148b27
RK
63 res.fail({
64 status: HttpStatusCode.NOT_FOUND_404,
65 message: 'VideoFile matching Video not found'
66 })
8319d6ae
RK
67 return false
68 }
69
70 return true
71}
72
453e83ea 73async function doesVideoChannelOfAccountExist (channelId: number, user: MUserAccountId, res: Response) {
2cb03dc1 74 const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId)
3e753302 75
2cb03dc1 76 if (videoChannel === null) {
76148b27 77 res.fail({ message: 'Unknown video "video channel" for this instance.' })
2cb03dc1
C
78 return false
79 }
80
81 // Don't check account id if the user can update any video
82 if (user.hasRight(UserRight.UPDATE_ANY_VIDEO) === true) {
3e753302
C
83 res.locals.videoChannel = videoChannel
84 return true
85 }
86
2cb03dc1 87 if (videoChannel.Account.id !== user.Account.id) {
76148b27
RK
88 res.fail({
89 message: 'Unknown video "video channel" for this account.'
90 })
3e753302
C
91 return false
92 }
93
94 res.locals.videoChannel = videoChannel
95 return true
96}
97
795212f7
C
98async function checkCanSeeVideoIfPrivate (req: Request, res: Response, video: MVideo, authenticateInQuery = false) {
99 if (!video.requiresAuth()) return true
100
101 const videoWithRights = await VideoModel.loadAndPopulateAccountAndServerAndTags(video.id)
102
103 return checkCanSeePrivateVideo(req, res, videoWithRights, authenticateInQuery)
104}
105
106async function checkCanSeePrivateVideo (req: Request, res: Response, video: MVideoWithRights, authenticateInQuery = false) {
107 await authenticatePromiseIfNeeded(req, res, authenticateInQuery)
108
109 const user = res.locals.oauth ? res.locals.oauth.token.User : null
110
111 // Only the owner or a user that have blocklist rights can see the video
112 if (!user || !user.canGetVideo(video)) {
c729caf6
C
113 res.fail({
114 status: HttpStatusCode.FORBIDDEN_403,
115 message: 'Cannot fetch information of private/internal/blocklisted video'
116 })
117
795212f7
C
118 return false
119 }
120
121 return true
122}
123
af4ae64f 124function checkUserCanManageVideo (user: MUser, video: MVideoAccountLight, right: UserRight, res: Response, onlyOwned = true) {
3e753302 125 // Retrieve the user who did the request
af4ae64f 126 if (onlyOwned && video.isOwned() === false) {
76148b27
RK
127 res.fail({
128 status: HttpStatusCode.FORBIDDEN_403,
129 message: 'Cannot manage a video of another server.'
130 })
3e753302
C
131 return false
132 }
133
134 // Check if the user can delete the video
135 // The user can delete it if he has the right
136 // Or if s/he is the video's account
137 const account = video.VideoChannel.Account
138 if (user.hasRight(right) === false && account.userId !== user.id) {
76148b27
RK
139 res.fail({
140 status: HttpStatusCode.FORBIDDEN_403,
141 message: 'Cannot manage a video of another user.'
142 })
3e753302
C
143 return false
144 }
145
146 return true
147}
148
c729caf6
C
149async function checkUserQuota (user: MUserId, videoFileSize: number, res: Response) {
150 if (await isAbleToUploadVideo(user.id, videoFileSize) === false) {
151 res.fail({
152 status: HttpStatusCode.PAYLOAD_TOO_LARGE_413,
153 message: 'The user video quota is exceeded with this video.',
154 type: ServerErrorCode.QUOTA_REACHED
155 })
156 return false
157 }
158
159 return true
160}
161
3e753302
C
162// ---------------------------------------------------------------------------
163
164export {
165 doesVideoChannelOfAccountExist,
166 doesVideoExist,
8319d6ae 167 doesVideoFileOfVideoExist,
c729caf6 168
795212f7
C
169 checkUserCanManageVideo,
170 checkCanSeeVideoIfPrivate,
c729caf6
C
171 checkCanSeePrivateVideo,
172 checkUserQuota
3e753302 173}