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'
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 import { isActivityPubUrlValid } from './activitypub/misc'
24 const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
25 const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
26 const VIDEO_EVENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_EVENTS
28 function isVideoCategoryValid (value: number) {
29 return VIDEO_CATEGORIES[value] !== undefined
32 // Maybe we don't know the remote category, but that doesn't matter
33 function isRemoteVideoCategoryValid (value: string) {
34 return validator.isInt('' + value)
37 function isVideoUrlValid (value: string) {
38 return isActivityPubUrlValid(value)
41 function isVideoLicenceValid (value: number) {
42 return VIDEO_LICENCES[value] !== undefined
45 function isVideoPrivacyValid (value: string) {
46 return VIDEO_PRIVACIES[value] !== undefined
49 // Maybe we don't know the remote privacy setting, but that doesn't matter
50 function isRemoteVideoPrivacyValid (value: string) {
51 return validator.isInt('' + value)
54 // Maybe we don't know the remote licence, but that doesn't matter
55 function isRemoteVideoLicenceValid (value: string) {
56 return validator.isInt('' + value)
59 function isVideoLanguageValid (value: number) {
60 return value === null || VIDEO_LANGUAGES[value] !== undefined
63 // Maybe we don't know the remote language, but that doesn't matter
64 function isRemoteVideoLanguageValid (value: string) {
65 return validator.isInt('' + value)
68 function isVideoNSFWValid (value: any) {
69 return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
72 function isVideoDurationValid (value: string) {
73 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
76 function isVideoTruncatedDescriptionValid (value: string) {
77 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.TRUNCATED_DESCRIPTION)
80 function isVideoDescriptionValid (value: string) {
81 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION)
84 function isVideoNameValid (value: string) {
85 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
88 function isVideoTagValid (tag: string) {
89 return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
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))
98 function isVideoThumbnailValid (value: string) {
99 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL)
102 function isVideoThumbnailDataValid (value: string) {
103 return exists(value) && validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL_DATA)
106 function isVideoAbuseReasonValid (value: string) {
107 return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
110 function isVideoViewsValid (value: string) {
111 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
114 function isVideoLikesValid (value: string) {
115 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.LIKES)
118 function isVideoDislikesValid (value: string) {
119 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DISLIKES)
122 function isVideoEventCountValid (value: string) {
123 return exists(value) && validator.isInt(value + '', VIDEO_EVENTS_CONSTRAINTS_FIELDS.COUNT)
126 function isVideoRatingTypeValid (value: string) {
127 return values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
130 function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
132 if (!files) return false
133 if (isArray(files)) return false
135 // Should have videofile file
136 const videofile = files['videofile']
137 if (!videofile || videofile.length === 0) return false
139 // The file should exist
140 const file = videofile[0]
141 if (!file || !file.originalname) return false
143 return new RegExp('^video/(webm|mp4|ogg)$', 'i').test(file.mimetype)
146 function isVideoFileSizeValid (value: string) {
147 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
150 function isVideoFileResolutionValid (value: string) {
151 return exists(value) && validator.isInt(value + '')
154 function isVideoFileExtnameValid (value: string) {
155 return VIDEOS_CONSTRAINTS_FIELDS.EXTNAME.indexOf(value) !== -1
158 function isVideoFileInfoHashValid (value: string) {
159 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
162 function checkVideoExists (id: string, res: express.Response, callback: () => void) {
163 let promise: Promise<VideoInstance>
164 if (validator.isInt(id)) {
165 promise = db.Video.loadAndPopulateAccountAndServerAndTags(+id)
167 promise = db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(id)
170 promise.then(video => {
172 return res.status(404)
173 .json({ error: 'Video not found' })
177 res.locals.video = video
181 logger.error('Error in video request validator.', err)
182 return res.sendStatus(500)
186 // ---------------------------------------------------------------------------
189 isVideoCategoryValid,
191 isVideoLanguageValid,
193 isVideoTruncatedDescriptionValid,
194 isVideoDescriptionValid,
195 isVideoFileInfoHashValid,
198 isVideoThumbnailValid,
199 isVideoThumbnailDataValid,
200 isVideoFileExtnameValid,
201 isVideoAbuseReasonValid,
205 isVideoRatingTypeValid,
206 isVideoDislikesValid,
207 isVideoEventCountValid,
208 isVideoFileSizeValid,
210 isRemoteVideoPrivacyValid,
211 isVideoDurationValid,
212 isVideoFileResolutionValid,
215 isRemoteVideoCategoryValid,
216 isRemoteVideoLicenceValid,
218 isRemoteVideoLanguageValid