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