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