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