]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/helpers/custom-validators/videos.ts
Add ability to search on followers/following
[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'
4157cdb1 21import { fetchVideo, VideoFetchType } from '../video'
65fcc311
C
22
23const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
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 isVideoViewsValid (value: string) {
75 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
9e167724
C
76}
77
69818c93 78function isVideoRatingTypeValid (value: string) {
57a49263 79 return value === 'none' || values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
d38b8281
C
80}
81
ac81d1a0
C
82const videoFileTypes = Object.keys(VIDEO_MIMETYPE_EXT).map(m => `(${m})`)
83const videoFileTypesRegex = videoFileTypes.join('|')
2186386c 84
b60e5f38 85function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
0c237b19 86 return isFileValid(files, videoFileTypesRegex, 'videofile', null)
ac81d1a0 87}
f6f7dfee 88
ac81d1a0 89const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
2186386c
C
90 .map(v => v.replace('.', ''))
91 .join('|')
ac81d1a0 92const videoImageTypesRegex = `image/(${videoImageTypes})`
2186386c 93
ac81d1a0 94function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) {
0c237b19 95 return isFileValid(files, videoImageTypesRegex, field, CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max, true)
f6f7dfee
C
96}
97
2baea0c7 98function isVideoPrivacyValid (value: number) {
2186386c 99 return validator.isInt(value + '') && VIDEO_PRIVACIES[ value ] !== undefined
d4f1e94c
C
100}
101
2baea0c7
C
102function isScheduleVideoUpdatePrivacyValid (value: number) {
103 return validator.isInt(value + '') &&
104 (
105 value === VideoPrivacy.UNLISTED ||
106 value === VideoPrivacy.PUBLIC
107 )
108}
109
2cebd797 110function isVideoFileInfoHashValid (value: string | null | undefined) {
93e1258c
C
111 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
112}
113
d4f1e94c
C
114function isVideoFileResolutionValid (value: string) {
115 return exists(value) && validator.isInt(value + '')
116}
117
3a6f351b
C
118function isVideoFPSResolutionValid (value: string) {
119 return value === null || validator.isInt(value + '')
120}
121
d4f1e94c
C
122function isVideoFileSizeValid (value: string) {
123 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
8d468a16
C
124}
125
ce33919c
C
126function isVideoMagnetUriValid (value: string) {
127 if (!exists(value)) return false
128
129 const parsed = magnetUtil.decode(value)
130 return parsed && isVideoFileInfoHashValid(parsed.infoHash)
131}
132
40e87e9e
C
133function checkUserCanManageVideo (user: UserModel, video: VideoModel, right: UserRight, res: Response) {
134 // Retrieve the user who did the request
135 if (video.isOwned() === false) {
136 res.status(403)
137 .json({ error: 'Cannot manage a video of another server.' })
138 .end()
139 return false
140 }
141
142 // Check if the user can delete the video
143 // The user can delete it if he has the right
144 // Or if s/he is the video's account
145 const account = video.VideoChannel.Account
146 if (user.hasRight(right) === false && account.userId !== user.id) {
147 res.status(403)
148 .json({ error: 'Cannot manage a video of another user.' })
149 .end()
150 return false
151 }
152
153 return true
154}
155
96f29c0f 156async function isVideoExist (id: string, res: Response, fetchType: VideoFetchType = 'all') {
6e46de09
C
157 const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined
158
159 const video = await fetchVideo(id, fetchType, userId)
4e50b6a1 160
2cebd797 161 if (video === null) {
4e50b6a1 162 res.status(404)
2186386c
C
163 .json({ error: 'Video not found' })
164 .end()
4e50b6a1
C
165
166 return false
167 }
168
627621c1 169 if (fetchType !== 'none') res.locals.video = video
4e50b6a1
C
170 return true
171}
172
6200d8d9
C
173async function isVideoChannelOfAccountExist (channelId: number, user: UserModel, res: Response) {
174 if (user.hasRight(UserRight.UPDATE_ANY_VIDEO) === true) {
175 const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId)
2cebd797 176 if (videoChannel === null) {
6200d8d9 177 res.status(400)
e78980eb 178 .json({ error: 'Unknown video `video channel` on this instance.' })
6200d8d9
C
179 .end()
180
181 return false
182 }
183
184 res.locals.videoChannel = videoChannel
185 return true
186 }
187
188 const videoChannel = await VideoChannelModel.loadByIdAndAccount(channelId, user.Account.id)
2cebd797 189 if (videoChannel === null) {
0f320037 190 res.status(400)
e78980eb 191 .json({ error: 'Unknown video `video channel` for this account.' })
0f320037
C
192 .end()
193
194 return false
195 }
196
197 res.locals.videoChannel = videoChannel
198 return true
199}
200
55fa55a9
C
201// ---------------------------------------------------------------------------
202
65fcc311 203export {
65fcc311 204 isVideoCategoryValid,
40e87e9e 205 checkUserCanManageVideo,
65fcc311
C
206 isVideoLicenceValid,
207 isVideoLanguageValid,
9567011b 208 isVideoTruncatedDescriptionValid,
65fcc311 209 isVideoDescriptionValid,
93e1258c 210 isVideoFileInfoHashValid,
65fcc311
C
211 isVideoNameValid,
212 isVideoTagsValid,
3a6f351b 213 isVideoFPSResolutionValid,
2baea0c7 214 isScheduleVideoUpdatePrivacyValid,
65fcc311 215 isVideoFile,
ce33919c 216 isVideoMagnetUriValid,
2186386c 217 isVideoStateValid,
65fcc311 218 isVideoViewsValid,
65fcc311 219 isVideoRatingTypeValid,
8e10cf1a 220 isVideoDurationValid,
0d0e8dd0 221 isVideoTagValid,
8d468a16 222 isVideoPrivacyValid,
d4f1e94c
C
223 isVideoFileResolutionValid,
224 isVideoFileSizeValid,
ac81d1a0 225 isVideoExist,
2422c46b 226 isVideoImage,
0f320037 227 isVideoChannelOfAccountExist,
2422c46b 228 isVideoSupportValid
65fcc311 229}