]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/helpers/custom-validators/videos.ts
487b3d6464205104a14960b51b99f49192de50a9
[github/Chocobozzz/PeerTube.git] / server / helpers / custom-validators / videos.ts
1 import { values } from 'lodash'
2 import * as validator from 'validator'
3 import * as Promise from 'bluebird'
4 import * as express from 'express'
5 import 'express-validator'
6 import 'multer'
7
8 import {
9 CONSTRAINTS_FIELDS,
10 VIDEO_CATEGORIES,
11 VIDEO_LICENCES,
12 VIDEO_LANGUAGES,
13 VIDEO_RATE_TYPES,
14 VIDEO_PRIVACIES,
15 database as db
16 } from '../../initializers'
17 import { isUserUsernameValid } from './users'
18 import { isArray, exists } from './misc'
19 import { VideoInstance } from '../../models'
20 import { logger } from '../../helpers'
21 import { VideoRateType } from '../../../shared'
22
23 const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
24 const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
25 const VIDEO_EVENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_EVENTS
26
27 function isVideoCategoryValid (value: number) {
28 return VIDEO_CATEGORIES[value] !== undefined
29 }
30
31 // Maybe we don't know the remote category, but that doesn't matter
32 function isRemoteVideoCategoryValid (value: string) {
33 return validator.isInt('' + value)
34 }
35
36 function isVideoLicenceValid (value: number) {
37 return VIDEO_LICENCES[value] !== undefined
38 }
39
40 function isVideoPrivacyValid (value: string) {
41 return VIDEO_PRIVACIES[value] !== undefined
42 }
43
44 // Maybe we don't know the remote privacy setting, but that doesn't matter
45 function isRemoteVideoPrivacyValid (value: string) {
46 return validator.isInt('' + value)
47 }
48
49 // Maybe we don't know the remote licence, but that doesn't matter
50 function isRemoteVideoLicenceValid (value: string) {
51 return validator.isInt('' + value)
52 }
53
54 function isVideoLanguageValid (value: number) {
55 return value === null || VIDEO_LANGUAGES[value] !== undefined
56 }
57
58 // Maybe we don't know the remote language, but that doesn't matter
59 function isRemoteVideoLanguageValid (value: string) {
60 return validator.isInt('' + value)
61 }
62
63 function isVideoNSFWValid (value: any) {
64 return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
65 }
66
67 function isVideoTruncatedDescriptionValid (value: string) {
68 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.TRUNCATED_DESCRIPTION)
69 }
70
71 function isVideoDescriptionValid (value: string) {
72 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION)
73 }
74
75 function isVideoDurationValid (value: string) {
76 // https://www.w3.org/TR/activitystreams-vocabulary/#dfn-duration
77 return exists(value) &&
78 typeof value === 'string' &&
79 value.startsWith('PT') &&
80 value.endsWith('S') &&
81 validator.isInt(value.replace(/[^0-9]+/, ''), VIDEOS_CONSTRAINTS_FIELDS.DURATION)
82 }
83
84 function isVideoNameValid (value: string) {
85 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
86 }
87
88 function isVideoTagValid (tag: string) {
89 return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
90 }
91
92 function isVideoTagsValid (tags: string[]) {
93 return isArray(tags) &&
94 validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
95 tags.every(tag => isVideoTagValid(tag))
96 }
97
98 function isVideoThumbnailValid (value: string) {
99 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL)
100 }
101
102 function isVideoThumbnailDataValid (value: string) {
103 return exists(value) && validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL_DATA)
104 }
105
106 function isVideoAbuseReasonValid (value: string) {
107 return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
108 }
109
110 function isVideoAbuseReporterUsernameValid (value: string) {
111 return isUserUsernameValid(value)
112 }
113
114 function isVideoViewsValid (value: string) {
115 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
116 }
117
118 function isVideoLikesValid (value: string) {
119 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.LIKES)
120 }
121
122 function isVideoDislikesValid (value: string) {
123 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DISLIKES)
124 }
125
126 function isVideoEventCountValid (value: string) {
127 return exists(value) && validator.isInt(value + '', VIDEO_EVENTS_CONSTRAINTS_FIELDS.COUNT)
128 }
129
130 function isVideoRatingTypeValid (value: string) {
131 return values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
132 }
133
134 function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
135 // Should have files
136 if (!files) return false
137 if (isArray(files)) return false
138
139 // Should have videofile file
140 const videofile = files['videofile']
141 if (!videofile || videofile.length === 0) return false
142
143 // The file should exist
144 const file = videofile[0]
145 if (!file || !file.originalname) return false
146
147 return new RegExp('^video/(webm|mp4|ogg)$', 'i').test(file.mimetype)
148 }
149
150 function isVideoFileSizeValid (value: string) {
151 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
152 }
153
154 function isVideoFileResolutionValid (value: string) {
155 return exists(value) && validator.isInt(value + '')
156 }
157
158 function isVideoFileExtnameValid (value: string) {
159 return VIDEOS_CONSTRAINTS_FIELDS.EXTNAME.indexOf(value) !== -1
160 }
161
162 function isVideoFileInfoHashValid (value: string) {
163 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
164 }
165
166 function checkVideoExists (id: string, res: express.Response, callback: () => void) {
167 let promise: Promise<VideoInstance>
168 if (validator.isInt(id)) {
169 promise = db.Video.loadAndPopulateAccountAndPodAndTags(+id)
170 } else { // UUID
171 promise = db.Video.loadByUUIDAndPopulateAccountAndPodAndTags(id)
172 }
173
174 promise.then(video => {
175 if (!video) {
176 return res.status(404)
177 .json({ error: 'Video not found' })
178 .end()
179 }
180
181 res.locals.video = video
182 callback()
183 })
184 .catch(err => {
185 logger.error('Error in video request validator.', err)
186 return res.sendStatus(500)
187 })
188 }
189
190 // ---------------------------------------------------------------------------
191
192 export {
193 isVideoCategoryValid,
194 isVideoLicenceValid,
195 isVideoLanguageValid,
196 isVideoNSFWValid,
197 isVideoTruncatedDescriptionValid,
198 isVideoDescriptionValid,
199 isVideoDurationValid,
200 isVideoFileInfoHashValid,
201 isVideoNameValid,
202 isVideoTagsValid,
203 isVideoThumbnailValid,
204 isVideoThumbnailDataValid,
205 isVideoFileExtnameValid,
206 isVideoAbuseReasonValid,
207 isVideoAbuseReporterUsernameValid,
208 isVideoFile,
209 isVideoViewsValid,
210 isVideoLikesValid,
211 isVideoRatingTypeValid,
212 isVideoDislikesValid,
213 isVideoEventCountValid,
214 isVideoFileSizeValid,
215 isVideoPrivacyValid,
216 isRemoteVideoPrivacyValid,
217 isVideoFileResolutionValid,
218 checkVideoExists,
219 isVideoTagValid,
220 isRemoteVideoCategoryValid,
221 isRemoteVideoLicenceValid,
222 isRemoteVideoLanguageValid
223 }