]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/helpers/custom-validators/videos.ts
Import torrents with webtorrent
[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
23const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
0b697522 24
9d3ef9fe 25function isVideoCategoryValid (value: any) {
2186386c
C
26 return value === null || VIDEO_CATEGORIES[ value ] !== undefined
27}
28
29function isVideoStateValid (value: any) {
30 return exists(value) && VIDEO_STATES[ value ] !== undefined
6e07c3de
C
31}
32
9d3ef9fe 33function isVideoLicenceValid (value: any) {
2186386c 34 return value === null || VIDEO_LICENCES[ value ] !== undefined
6f0c39e2
C
35}
36
9d3ef9fe
C
37function isVideoLanguageValid (value: any) {
38 return value === null ||
39 (typeof value === 'string' && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.LANGUAGE))
3092476e
C
40}
41
8e10cf1a
C
42function isVideoDurationValid (value: string) {
43 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
44}
45
9567011b
C
46function isVideoTruncatedDescriptionValid (value: string) {
47 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.TRUNCATED_DESCRIPTION)
48}
49
69818c93 50function isVideoDescriptionValid (value: string) {
f595d394 51 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION))
be587647
C
52}
53
2422c46b
C
54function isVideoSupportValid (value: string) {
55 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.SUPPORT))
56}
57
69818c93
C
58function isVideoNameValid (value: string) {
59 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
be587647
C
60}
61
0d0e8dd0
C
62function isVideoTagValid (tag: string) {
63 return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
64}
65
69818c93 66function isVideoTagsValid (tags: string[]) {
2efd32f6
C
67 return tags === null || (
68 isArray(tags) &&
69 validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
70 tags.every(tag => isVideoTagValid(tag))
71 )
be587647
C
72}
73
69818c93
C
74function isVideoAbuseReasonValid (value: string) {
75 return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
e4c55619
C
76}
77
69818c93
C
78function isVideoViewsValid (value: string) {
79 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
9e167724
C
80}
81
69818c93 82function isVideoRatingTypeValid (value: string) {
57a49263 83 return value === 'none' || values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
d38b8281
C
84}
85
ac81d1a0
C
86const videoFileTypes = Object.keys(VIDEO_MIMETYPE_EXT).map(m => `(${m})`)
87const videoFileTypesRegex = videoFileTypes.join('|')
2186386c 88
b60e5f38 89function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
0c237b19 90 return isFileValid(files, videoFileTypesRegex, 'videofile', null)
ac81d1a0 91}
f6f7dfee 92
ac81d1a0 93const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
2186386c
C
94 .map(v => v.replace('.', ''))
95 .join('|')
ac81d1a0 96const videoImageTypesRegex = `image/(${videoImageTypes})`
2186386c 97
ac81d1a0 98function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) {
0c237b19 99 return isFileValid(files, videoImageTypesRegex, field, CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max, true)
f6f7dfee
C
100}
101
2baea0c7 102function isVideoPrivacyValid (value: number) {
2186386c 103 return validator.isInt(value + '') && VIDEO_PRIVACIES[ value ] !== undefined
d4f1e94c
C
104}
105
2baea0c7
C
106function isScheduleVideoUpdatePrivacyValid (value: number) {
107 return validator.isInt(value + '') &&
108 (
109 value === VideoPrivacy.UNLISTED ||
110 value === VideoPrivacy.PUBLIC
111 )
112}
113
2cebd797 114function isVideoFileInfoHashValid (value: string | null | undefined) {
93e1258c
C
115 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
116}
117
d4f1e94c
C
118function isVideoFileResolutionValid (value: string) {
119 return exists(value) && validator.isInt(value + '')
120}
121
3a6f351b
C
122function isVideoFPSResolutionValid (value: string) {
123 return value === null || validator.isInt(value + '')
124}
125
d4f1e94c
C
126function isVideoFileSizeValid (value: string) {
127 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
8d468a16
C
128}
129
ce33919c
C
130function isVideoMagnetUriValid (value: string) {
131 if (!exists(value)) return false
132
133 const parsed = magnetUtil.decode(value)
134 return parsed && isVideoFileInfoHashValid(parsed.infoHash)
135}
136
40e87e9e
C
137function checkUserCanManageVideo (user: UserModel, video: VideoModel, right: UserRight, res: Response) {
138 // Retrieve the user who did the request
139 if (video.isOwned() === false) {
140 res.status(403)
141 .json({ error: 'Cannot manage a video of another server.' })
142 .end()
143 return false
144 }
145
146 // Check if the user can delete the video
147 // The user can delete it if he has the right
148 // Or if s/he is the video's account
149 const account = video.VideoChannel.Account
150 if (user.hasRight(right) === false && account.userId !== user.id) {
151 res.status(403)
152 .json({ error: 'Cannot manage a video of another user.' })
153 .end()
154 return false
155 }
156
157 return true
158}
159
a2431b7d 160async function isVideoExist (id: string, res: Response) {
c1e791ba 161 let video: VideoModel | null
4e50b6a1
C
162
163 if (validator.isInt(id)) {
3fd3ab2d 164 video = await VideoModel.loadAndPopulateAccountAndServerAndTags(+id)
4e50b6a1 165 } else { // UUID
3fd3ab2d 166 video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(id)
4e50b6a1
C
167 }
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
177 res.locals.video = video
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
C
185 res.status(400)
186 .json({ error: 'Unknown video video channel on this instance.' })
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
C
198 res.status(400)
199 .json({ error: 'Unknown video video channel for this account.' })
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 isVideoAbuseReasonValid,
65fcc311 224 isVideoFile,
ce33919c 225 isVideoMagnetUriValid,
2186386c 226 isVideoStateValid,
65fcc311 227 isVideoViewsValid,
65fcc311 228 isVideoRatingTypeValid,
8e10cf1a 229 isVideoDurationValid,
0d0e8dd0 230 isVideoTagValid,
8d468a16 231 isVideoPrivacyValid,
d4f1e94c
C
232 isVideoFileResolutionValid,
233 isVideoFileSizeValid,
ac81d1a0 234 isVideoExist,
2422c46b 235 isVideoImage,
0f320037 236 isVideoChannelOfAccountExist,
2422c46b 237 isVideoSupportValid
65fcc311 238}