Add video privacy setting
[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   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   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
77 }
78
79 function isVideoNameValid (value: string) {
80   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
81 }
82
83 function isVideoTagsValid (tags: string[]) {
84   return isArray(tags) &&
85          validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
86          tags.every(tag => {
87            return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
88          })
89 }
90
91 function isVideoThumbnailValid (value: string) {
92   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL)
93 }
94
95 function isVideoThumbnailDataValid (value: string) {
96   return exists(value) && validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL_DATA)
97 }
98
99 function isVideoAbuseReasonValid (value: string) {
100   return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
101 }
102
103 function isVideoAbuseReporterUsernameValid (value: string) {
104   return isUserUsernameValid(value)
105 }
106
107 function isVideoViewsValid (value: string) {
108   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
109 }
110
111 function isVideoLikesValid (value: string) {
112   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.LIKES)
113 }
114
115 function isVideoDislikesValid (value: string) {
116   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DISLIKES)
117 }
118
119 function isVideoEventCountValid (value: string) {
120   return exists(value) && validator.isInt(value + '', VIDEO_EVENTS_CONSTRAINTS_FIELDS.COUNT)
121 }
122
123 function isVideoRatingTypeValid (value: string) {
124   return values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
125 }
126
127 function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
128   // Should have files
129   if (!files) return false
130   if (isArray(files)) return false
131
132   // Should have videofile file
133   const videofile = files['videofile']
134   if (!videofile || videofile.length === 0) return false
135
136   // The file should exist
137   const file = videofile[0]
138   if (!file || !file.originalname) return false
139
140   return new RegExp('^video/(webm|mp4|ogg)$', 'i').test(file.mimetype)
141 }
142
143 function isVideoFileSizeValid (value: string) {
144   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
145 }
146
147 function isVideoFileResolutionValid (value: string) {
148   return exists(value) && validator.isInt(value + '')
149 }
150
151 function isVideoFileExtnameValid (value: string) {
152   return VIDEOS_CONSTRAINTS_FIELDS.EXTNAME.indexOf(value) !== -1
153 }
154
155 function isVideoFileInfoHashValid (value: string) {
156   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
157 }
158
159 function checkVideoExists (id: string, res: express.Response, callback: () => void) {
160   let promise: Promise<VideoInstance>
161   if (validator.isInt(id)) {
162     promise = db.Video.loadAndPopulateAuthorAndPodAndTags(+id)
163   } else { // UUID
164     promise = db.Video.loadByUUIDAndPopulateAuthorAndPodAndTags(id)
165   }
166
167   promise.then(video => {
168     if (!video) {
169       return res.status(404)
170                 .json({ error: 'Video not found' })
171                 .end()
172     }
173
174     res.locals.video = video
175     callback()
176   })
177   .catch(err => {
178     logger.error('Error in video request validator.', err)
179     return res.sendStatus(500)
180   })
181 }
182
183 // ---------------------------------------------------------------------------
184
185 export {
186   isVideoCategoryValid,
187   isVideoLicenceValid,
188   isVideoLanguageValid,
189   isVideoNSFWValid,
190   isVideoTruncatedDescriptionValid,
191   isVideoDescriptionValid,
192   isVideoDurationValid,
193   isVideoFileInfoHashValid,
194   isVideoNameValid,
195   isVideoTagsValid,
196   isVideoThumbnailValid,
197   isVideoThumbnailDataValid,
198   isVideoFileExtnameValid,
199   isVideoAbuseReasonValid,
200   isVideoAbuseReporterUsernameValid,
201   isVideoFile,
202   isVideoViewsValid,
203   isVideoLikesValid,
204   isVideoRatingTypeValid,
205   isVideoDislikesValid,
206   isVideoEventCountValid,
207   isVideoFileSizeValid,
208   isVideoPrivacyValid,
209   isRemoteVideoPrivacyValid,
210   isVideoFileResolutionValid,
211   checkVideoExists,
212   isRemoteVideoCategoryValid,
213   isRemoteVideoLicenceValid,
214   isRemoteVideoLanguageValid
215 }