Move video file metadata in their own table
[oweals/peertube.git] / server / helpers / custom-validators / videos.ts
1 import { values } from 'lodash'
2 import * as validator from 'validator'
3 import 'multer'
4
5 import {
6   CONSTRAINTS_FIELDS,
7   VIDEO_CATEGORIES,
8   VIDEO_LICENCES,
9   VIDEO_LANGUAGES,
10   VIDEO_RATE_TYPES,
11   VIDEO_FILE_RESOLUTIONS
12 } from '../../initializers'
13 import { isUserUsernameValid } from './users'
14 import { isArray, exists } from './misc'
15 import { VideoRateType } from '../../../shared'
16
17 const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
18 const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
19 const VIDEO_EVENTS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_EVENTS
20
21 function isVideoIdOrUUIDValid (value: string) {
22   return validator.isInt(value) || isVideoUUIDValid(value)
23 }
24
25 function isVideoAuthorValid (value: string) {
26   return isUserUsernameValid(value)
27 }
28
29 function isVideoDateValid (value: string) {
30   return exists(value) && validator.isISO8601(value)
31 }
32
33 function isVideoCategoryValid (value: number) {
34   return VIDEO_CATEGORIES[value] !== undefined
35 }
36
37 function isVideoLicenceValid (value: number) {
38   return VIDEO_LICENCES[value] !== undefined
39 }
40
41 function isVideoLanguageValid (value: number) {
42   return value === null || VIDEO_LANGUAGES[value] !== undefined
43 }
44
45 function isVideoNSFWValid (value: any) {
46   return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
47 }
48
49 function isVideoDescriptionValid (value: string) {
50   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION)
51 }
52
53 function isVideoDurationValid (value: string) {
54   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
55 }
56
57 function isVideoNameValid (value: string) {
58   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
59 }
60
61 function isVideoTagsValid (tags: string[]) {
62   return isArray(tags) &&
63          validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
64          tags.every(tag => {
65            return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
66          })
67 }
68
69 function isVideoThumbnailValid (value: string) {
70   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL)
71 }
72
73 function isVideoThumbnailDataValid (value: string) {
74   return exists(value) && validator.isByteLength(value, VIDEOS_CONSTRAINTS_FIELDS.THUMBNAIL_DATA)
75 }
76
77 function isVideoUUIDValid (value: string) {
78   return exists(value) && validator.isUUID('' + value, 4)
79 }
80
81 function isVideoAbuseReasonValid (value: string) {
82   return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
83 }
84
85 function isVideoAbuseReporterUsernameValid (value: string) {
86   return isUserUsernameValid(value)
87 }
88
89 function isVideoViewsValid (value: string) {
90   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
91 }
92
93 function isVideoLikesValid (value: string) {
94   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.LIKES)
95 }
96
97 function isVideoDislikesValid (value: string) {
98   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DISLIKES)
99 }
100
101 function isVideoEventCountValid (value: string) {
102   return exists(value) && validator.isInt(value + '', VIDEO_EVENTS_CONSTRAINTS_FIELDS.COUNT)
103 }
104
105 function isVideoRatingTypeValid (value: string) {
106   return values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
107 }
108
109 function isVideoFile (value: string, files: { [ fieldname: string ]: Express.Multer.File[] }) {
110   // Should have files
111   if (!files) return false
112
113   // Should have videofile file
114   const videofile = files.videofile
115   if (!videofile || videofile.length === 0) return false
116
117   // The file should exist
118   const file = videofile[0]
119   if (!file || !file.originalname) return false
120
121   return new RegExp('^video/(webm|mp4|ogg)$', 'i').test(file.mimetype)
122 }
123
124 function isVideoFileSizeValid (value: string) {
125   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
126 }
127
128 function isVideoFileResolutionValid (value: string) {
129   return VIDEO_FILE_RESOLUTIONS[value] !== undefined
130 }
131
132 function isVideoFileExtnameValid (value: string) {
133   return VIDEOS_CONSTRAINTS_FIELDS.EXTNAME.indexOf(value) !== -1
134 }
135
136 function isVideoFileInfoHashValid (value: string) {
137   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
138 }
139
140 // ---------------------------------------------------------------------------
141
142 export {
143   isVideoIdOrUUIDValid,
144   isVideoAuthorValid,
145   isVideoDateValid,
146   isVideoCategoryValid,
147   isVideoLicenceValid,
148   isVideoLanguageValid,
149   isVideoNSFWValid,
150   isVideoDescriptionValid,
151   isVideoDurationValid,
152   isVideoFileInfoHashValid,
153   isVideoNameValid,
154   isVideoTagsValid,
155   isVideoThumbnailValid,
156   isVideoThumbnailDataValid,
157   isVideoFileExtnameValid,
158   isVideoUUIDValid,
159   isVideoAbuseReasonValid,
160   isVideoAbuseReporterUsernameValid,
161   isVideoFile,
162   isVideoViewsValid,
163   isVideoLikesValid,
164   isVideoRatingTypeValid,
165   isVideoDislikesValid,
166   isVideoEventCountValid,
167   isVideoFileSizeValid,
168   isVideoFileResolutionValid
169 }
170
171 declare global {
172   namespace ExpressValidator {
173     export interface Validator {
174       isVideoIdOrUUIDValid,
175       isVideoAuthorValid,
176       isVideoDateValid,
177       isVideoCategoryValid,
178       isVideoLicenceValid,
179       isVideoLanguageValid,
180       isVideoNSFWValid,
181       isVideoDescriptionValid,
182       isVideoDurationValid,
183       isVideoInfoHashValid,
184       isVideoNameValid,
185       isVideoTagsValid,
186       isVideoThumbnailValid,
187       isVideoThumbnailDataValid,
188       isVideoExtnameValid,
189       isVideoUUIDValid,
190       isVideoAbuseReasonValid,
191       isVideoAbuseReporterUsernameValid,
192       isVideoFile,
193       isVideoViewsValid,
194       isVideoLikesValid,
195       isVideoRatingTypeValid,
196       isVideoDislikesValid,
197       isVideoEventCountValid,
198       isVideoFileSizeValid,
199       isVideoFileResolutionValid
200     }
201   }
202 }