]>
Commit | Line | Data |
---|---|---|
795212f7 | 1 | import { Request, Response } from 'express' |
868fce62 | 2 | import { loadVideo, VideoLoadType } from '@server/lib/model-loaders' |
c729caf6 | 3 | import { isAbleToUploadVideo } from '@server/lib/user' |
795212f7 C |
4 | import { authenticatePromiseIfNeeded } from '@server/middlewares/auth' |
5 | import { VideoModel } from '@server/models/video/video' | |
10363c74 C |
6 | import { VideoChannelModel } from '@server/models/video/video-channel' |
7 | import { VideoFileModel } from '@server/models/video/video-file' | |
7eba5e1f C |
8 | import { |
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 | 21 | import { HttpStatusCode, ServerErrorCode, UserRight } from '@shared/models' |
3e753302 | 22 | |
868fce62 | 23 | async 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 |
61 | async 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 | 73 | async 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 |
98 | async 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 | ||
106 | async 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 | 124 | function 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 |
149 | async 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 | ||
164 | export { | |
165 | doesVideoChannelOfAccountExist, | |
166 | doesVideoExist, | |
8319d6ae | 167 | doesVideoFileOfVideoExist, |
c729caf6 | 168 | |
795212f7 C |
169 | checkUserCanManageVideo, |
170 | checkCanSeeVideoIfPrivate, | |
c729caf6 C |
171 | checkCanSeePrivateVideo, |
172 | checkUserQuota | |
3e753302 | 173 | } |