]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/helpers/custom-validators/videos.ts
Fix trending days display on first load
[github/Chocobozzz/PeerTube.git] / server / helpers / custom-validators / videos.ts
CommitLineData
8d468a16 1import { Response } from 'express'
fdbda9e3 2import 'express-validator'
79d5caf9 3import { values } from 'lodash'
1840c2f7 4import 'multer'
79d5caf9 5import * as validator from 'validator'
1cd3facc 6import { UserRight, VideoFilter, VideoPrivacy, VideoRateType } from '../../../shared'
3fd3ab2d 7import {
14e2014a 8 CONSTRAINTS_FIELDS, MIMETYPES,
3fd3ab2d 9 VIDEO_CATEGORIES,
28be8916 10 VIDEO_LICENCES,
3fd3ab2d 11 VIDEO_PRIVACIES,
2186386c
C
12 VIDEO_RATE_TYPES,
13 VIDEO_STATES
3fd3ab2d
C
14} from '../../initializers'
15import { VideoModel } from '../../models/video/video'
ac81d1a0 16import { exists, isArray, isFileValid } from './misc'
0f320037 17import { VideoChannelModel } from '../../models/video/video-channel'
6200d8d9 18import { UserModel } from '../../models/account/user'
ce33919c 19import * as magnetUtil from 'magnet-uri'
4157cdb1 20import { fetchVideo, VideoFetchType } from '../video'
65fcc311
C
21
22const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
0b697522 23
1cd3facc
C
24function isVideoFilterValid (filter: VideoFilter) {
25 return filter === 'local' || filter === 'all-local'
26}
27
9d3ef9fe 28function isVideoCategoryValid (value: any) {
2186386c
C
29 return value === null || VIDEO_CATEGORIES[ value ] !== undefined
30}
31
32function isVideoStateValid (value: any) {
33 return exists(value) && VIDEO_STATES[ value ] !== undefined
6e07c3de
C
34}
35
9d3ef9fe 36function isVideoLicenceValid (value: any) {
2186386c 37 return value === null || VIDEO_LICENCES[ value ] !== undefined
6f0c39e2
C
38}
39
9d3ef9fe
C
40function isVideoLanguageValid (value: any) {
41 return value === null ||
42 (typeof value === 'string' && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.LANGUAGE))
3092476e
C
43}
44
8e10cf1a
C
45function isVideoDurationValid (value: string) {
46 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
47}
48
9567011b
C
49function isVideoTruncatedDescriptionValid (value: string) {
50 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.TRUNCATED_DESCRIPTION)
51}
52
69818c93 53function isVideoDescriptionValid (value: string) {
f595d394 54 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION))
be587647
C
55}
56
2422c46b
C
57function isVideoSupportValid (value: string) {
58 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.SUPPORT))
59}
60
69818c93
C
61function isVideoNameValid (value: string) {
62 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
be587647
C
63}
64
0d0e8dd0
C
65function isVideoTagValid (tag: string) {
66 return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
67}
68
69818c93 69function isVideoTagsValid (tags: string[]) {
2efd32f6
C
70 return tags === null || (
71 isArray(tags) &&
72 validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
73 tags.every(tag => isVideoTagValid(tag))
74 )
be587647
C
75}
76
69818c93
C
77function isVideoViewsValid (value: string) {
78 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
9e167724
C
79}
80
69818c93 81function isVideoRatingTypeValid (value: string) {
57a49263 82 return value === 'none' || values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
d38b8281
C
83}
84
14e2014a
C
85function isVideoFileExtnameValid (value: string) {
86 return exists(value) && MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined
87}
2186386c 88
b60e5f38 89function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
14e2014a
C
90 const videoFileTypesRegex = Object.keys(MIMETYPES.VIDEO.MIMETYPE_EXT)
91 .map(m => `(${m})`)
92 .join('|')
93
0c237b19 94 return isFileValid(files, videoFileTypesRegex, 'videofile', null)
ac81d1a0 95}
f6f7dfee 96
ac81d1a0 97const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
2186386c
C
98 .map(v => v.replace('.', ''))
99 .join('|')
ac81d1a0 100const videoImageTypesRegex = `image/(${videoImageTypes})`
2186386c 101
ac81d1a0 102function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) {
0c237b19 103 return isFileValid(files, videoImageTypesRegex, field, CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max, true)
f6f7dfee
C
104}
105
2baea0c7 106function isVideoPrivacyValid (value: number) {
2186386c 107 return validator.isInt(value + '') && VIDEO_PRIVACIES[ value ] !== undefined
d4f1e94c
C
108}
109
2baea0c7
C
110function isScheduleVideoUpdatePrivacyValid (value: number) {
111 return validator.isInt(value + '') &&
112 (
113 value === VideoPrivacy.UNLISTED ||
114 value === VideoPrivacy.PUBLIC
115 )
116}
117
2cebd797 118function isVideoFileInfoHashValid (value: string | null | undefined) {
93e1258c
C
119 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
120}
121
d4f1e94c
C
122function isVideoFileResolutionValid (value: string) {
123 return exists(value) && validator.isInt(value + '')
124}
125
3a6f351b
C
126function isVideoFPSResolutionValid (value: string) {
127 return value === null || validator.isInt(value + '')
128}
129
d4f1e94c
C
130function isVideoFileSizeValid (value: string) {
131 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
8d468a16
C
132}
133
ce33919c
C
134function isVideoMagnetUriValid (value: string) {
135 if (!exists(value)) return false
136
137 const parsed = magnetUtil.decode(value)
138 return parsed && isVideoFileInfoHashValid(parsed.infoHash)
139}
140
40e87e9e
C
141function checkUserCanManageVideo (user: UserModel, video: VideoModel, right: UserRight, res: Response) {
142 // Retrieve the user who did the request
143 if (video.isOwned() === false) {
144 res.status(403)
145 .json({ error: 'Cannot manage a video of another server.' })
146 .end()
147 return false
148 }
149
150 // Check if the user can delete the video
151 // The user can delete it if he has the right
152 // Or if s/he is the video's account
153 const account = video.VideoChannel.Account
154 if (user.hasRight(right) === false && account.userId !== user.id) {
155 res.status(403)
156 .json({ error: 'Cannot manage a video of another user.' })
157 .end()
158 return false
159 }
160
161 return true
162}
163
96f29c0f 164async function isVideoExist (id: string, res: Response, fetchType: VideoFetchType = 'all') {
6e46de09
C
165 const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined
166
167 const video = await fetchVideo(id, fetchType, userId)
4e50b6a1 168
2cebd797 169 if (video === null) {
4e50b6a1 170 res.status(404)
2186386c
C
171 .json({ error: 'Video not found' })
172 .end()
4e50b6a1
C
173
174 return false
175 }
176
627621c1 177 if (fetchType !== 'none') res.locals.video = video
4e50b6a1
C
178 return true
179}
180
6200d8d9
C
181async function isVideoChannelOfAccountExist (channelId: number, user: UserModel, res: Response) {
182 if (user.hasRight(UserRight.UPDATE_ANY_VIDEO) === true) {
183 const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId)
2cebd797 184 if (videoChannel === null) {
6200d8d9 185 res.status(400)
e78980eb 186 .json({ error: 'Unknown video `video channel` on this instance.' })
6200d8d9
C
187 .end()
188
189 return false
190 }
191
192 res.locals.videoChannel = videoChannel
193 return true
194 }
195
196 const videoChannel = await VideoChannelModel.loadByIdAndAccount(channelId, user.Account.id)
2cebd797 197 if (videoChannel === null) {
0f320037 198 res.status(400)
e78980eb 199 .json({ error: 'Unknown video `video channel` for this account.' })
0f320037
C
200 .end()
201
202 return false
203 }
204
205 res.locals.videoChannel = videoChannel
206 return true
207}
208
55fa55a9
C
209// ---------------------------------------------------------------------------
210
65fcc311 211export {
65fcc311 212 isVideoCategoryValid,
40e87e9e 213 checkUserCanManageVideo,
65fcc311
C
214 isVideoLicenceValid,
215 isVideoLanguageValid,
9567011b 216 isVideoTruncatedDescriptionValid,
65fcc311 217 isVideoDescriptionValid,
93e1258c 218 isVideoFileInfoHashValid,
65fcc311
C
219 isVideoNameValid,
220 isVideoTagsValid,
3a6f351b 221 isVideoFPSResolutionValid,
2baea0c7 222 isScheduleVideoUpdatePrivacyValid,
65fcc311 223 isVideoFile,
ce33919c 224 isVideoMagnetUriValid,
2186386c 225 isVideoStateValid,
65fcc311 226 isVideoViewsValid,
65fcc311 227 isVideoRatingTypeValid,
14e2014a 228 isVideoFileExtnameValid,
8e10cf1a 229 isVideoDurationValid,
0d0e8dd0 230 isVideoTagValid,
8d468a16 231 isVideoPrivacyValid,
d4f1e94c
C
232 isVideoFileResolutionValid,
233 isVideoFileSizeValid,
ac81d1a0 234 isVideoExist,
2422c46b 235 isVideoImage,
0f320037 236 isVideoChannelOfAccountExist,
1cd3facc
C
237 isVideoSupportValid,
238 isVideoFilterValid
65fcc311 239}