]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/helpers/custom-validators/videos.ts
Add ability to list all local videos
[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
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
1cd3facc
C
25function isVideoFilterValid (filter: VideoFilter) {
26 return filter === 'local' || filter === 'all-local'
27}
28
9d3ef9fe 29function isVideoCategoryValid (value: any) {
2186386c
C
30 return value === null || VIDEO_CATEGORIES[ value ] !== undefined
31}
32
33function isVideoStateValid (value: any) {
34 return exists(value) && VIDEO_STATES[ value ] !== undefined
6e07c3de
C
35}
36
9d3ef9fe 37function isVideoLicenceValid (value: any) {
2186386c 38 return value === null || VIDEO_LICENCES[ value ] !== undefined
6f0c39e2
C
39}
40
9d3ef9fe
C
41function isVideoLanguageValid (value: any) {
42 return value === null ||
43 (typeof value === 'string' && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.LANGUAGE))
3092476e
C
44}
45
8e10cf1a
C
46function isVideoDurationValid (value: string) {
47 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
48}
49
9567011b
C
50function isVideoTruncatedDescriptionValid (value: string) {
51 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.TRUNCATED_DESCRIPTION)
52}
53
69818c93 54function isVideoDescriptionValid (value: string) {
f595d394 55 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION))
be587647
C
56}
57
2422c46b
C
58function isVideoSupportValid (value: string) {
59 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.SUPPORT))
60}
61
69818c93
C
62function isVideoNameValid (value: string) {
63 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
be587647
C
64}
65
0d0e8dd0
C
66function isVideoTagValid (tag: string) {
67 return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
68}
69
69818c93 70function isVideoTagsValid (tags: string[]) {
2efd32f6
C
71 return tags === null || (
72 isArray(tags) &&
73 validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
74 tags.every(tag => isVideoTagValid(tag))
75 )
be587647
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
96f29c0f 160async function isVideoExist (id: string, res: Response, fetchType: VideoFetchType = 'all') {
6e46de09
C
161 const userId = res.locals.oauth ? res.locals.oauth.token.User.id : undefined
162
163 const video = await fetchVideo(id, fetchType, userId)
4e50b6a1 164
2cebd797 165 if (video === null) {
4e50b6a1 166 res.status(404)
2186386c
C
167 .json({ error: 'Video not found' })
168 .end()
4e50b6a1
C
169
170 return false
171 }
172
627621c1 173 if (fetchType !== 'none') res.locals.video = video
4e50b6a1
C
174 return true
175}
176
6200d8d9
C
177async function isVideoChannelOfAccountExist (channelId: number, user: UserModel, res: Response) {
178 if (user.hasRight(UserRight.UPDATE_ANY_VIDEO) === true) {
179 const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId)
2cebd797 180 if (videoChannel === null) {
6200d8d9 181 res.status(400)
e78980eb 182 .json({ error: 'Unknown video `video channel` on this instance.' })
6200d8d9
C
183 .end()
184
185 return false
186 }
187
188 res.locals.videoChannel = videoChannel
189 return true
190 }
191
192 const videoChannel = await VideoChannelModel.loadByIdAndAccount(channelId, user.Account.id)
2cebd797 193 if (videoChannel === null) {
0f320037 194 res.status(400)
e78980eb 195 .json({ error: 'Unknown video `video channel` for this account.' })
0f320037
C
196 .end()
197
198 return false
199 }
200
201 res.locals.videoChannel = videoChannel
202 return true
203}
204
55fa55a9
C
205// ---------------------------------------------------------------------------
206
65fcc311 207export {
65fcc311 208 isVideoCategoryValid,
40e87e9e 209 checkUserCanManageVideo,
65fcc311
C
210 isVideoLicenceValid,
211 isVideoLanguageValid,
9567011b 212 isVideoTruncatedDescriptionValid,
65fcc311 213 isVideoDescriptionValid,
93e1258c 214 isVideoFileInfoHashValid,
65fcc311
C
215 isVideoNameValid,
216 isVideoTagsValid,
3a6f351b 217 isVideoFPSResolutionValid,
2baea0c7 218 isScheduleVideoUpdatePrivacyValid,
65fcc311 219 isVideoFile,
ce33919c 220 isVideoMagnetUriValid,
2186386c 221 isVideoStateValid,
65fcc311 222 isVideoViewsValid,
65fcc311 223 isVideoRatingTypeValid,
8e10cf1a 224 isVideoDurationValid,
0d0e8dd0 225 isVideoTagValid,
8d468a16 226 isVideoPrivacyValid,
d4f1e94c
C
227 isVideoFileResolutionValid,
228 isVideoFileSizeValid,
ac81d1a0 229 isVideoExist,
2422c46b 230 isVideoImage,
0f320037 231 isVideoChannelOfAccountExist,
1cd3facc
C
232 isVideoSupportValid,
233 isVideoFilterValid
65fcc311 234}