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