Cleanup helpers
[oweals/peertube.git] / server / helpers / custom-validators / videos.ts
1 import * as Bluebird from 'bluebird'
2 import { Response } from 'express'
3 import 'express-validator'
4 import { values } from 'lodash'
5 import 'multer'
6 import * as validator from 'validator'
7 import { VideoRateType } from '../../../shared'
8 import { CONSTRAINTS_FIELDS, VIDEO_CATEGORIES, VIDEO_LANGUAGES, VIDEO_LICENCES, VIDEO_RATE_TYPES } from '../../initializers'
9 import { database as db } from '../../initializers/database'
10 import { VideoInstance } from '../../models/video/video-interface'
11 import { logger } from '../logger'
12 import { isActivityPubUrlValid } from './activitypub/misc'
13 import { exists, isArray } from './misc'
14 import { VIDEO_PRIVACIES } from '../../initializers/constants'
15
16 const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
17 const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
18
19 function isVideoCategoryValid (value: number) {
20   return VIDEO_CATEGORIES[value] !== undefined
21 }
22
23 function isVideoUrlValid (value: string) {
24   return isActivityPubUrlValid(value)
25 }
26
27 function isVideoLicenceValid (value: number) {
28   return VIDEO_LICENCES[value] !== undefined
29 }
30
31 function isVideoLanguageValid (value: number) {
32   return value === null || VIDEO_LANGUAGES[value] !== undefined
33 }
34
35 function isVideoNSFWValid (value: any) {
36   return typeof value === 'boolean' || (typeof value === 'string' && validator.isBoolean(value))
37 }
38
39 function isVideoDurationValid (value: string) {
40   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
41 }
42
43 function isVideoTruncatedDescriptionValid (value: string) {
44   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.TRUNCATED_DESCRIPTION)
45 }
46
47 function isVideoDescriptionValid (value: string) {
48   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION)
49 }
50
51 function isVideoNameValid (value: string) {
52   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
53 }
54
55 function isVideoTagValid (tag: string) {
56   return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
57 }
58
59 function isVideoTagsValid (tags: string[]) {
60   return isArray(tags) &&
61          validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
62          tags.every(tag => isVideoTagValid(tag))
63 }
64
65 function isVideoAbuseReasonValid (value: string) {
66   return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
67 }
68
69 function isVideoViewsValid (value: string) {
70   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
71 }
72
73 function isVideoRatingTypeValid (value: string) {
74   return values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
75 }
76
77 function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
78   // Should have files
79   if (!files) return false
80   if (isArray(files)) return false
81
82   // Should have videofile file
83   const videofile = files['videofile']
84   if (!videofile || videofile.length === 0) return false
85
86   // The file should exist
87   const file = videofile[0]
88   if (!file || !file.originalname) return false
89
90   return new RegExp('^video/(webm|mp4|ogg)$', 'i').test(file.mimetype)
91 }
92
93 function isVideoFileInfoHashValid (value: string) {
94   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
95 }
96
97 function isVideoPrivacyValid (value: string) {
98   return VIDEO_PRIVACIES[value] !== undefined
99 }
100
101 function checkVideoExists (id: string, res: Response, callback: () => void) {
102   let promise: Bluebird<VideoInstance>
103   if (validator.isInt(id)) {
104     promise = db.Video.loadAndPopulateAccountAndServerAndTags(+id)
105   } else { // UUID
106     promise = db.Video.loadByUUIDAndPopulateAccountAndServerAndTags(id)
107   }
108
109   promise.then(video => {
110     if (!video) {
111       return res.status(404)
112         .json({ error: 'Video not found' })
113         .end()
114     }
115
116     res.locals.video = video
117     callback()
118   })
119     .catch(err => {
120       logger.error('Error in video request validator.', err)
121       return res.sendStatus(500)
122     })
123 }
124
125 // ---------------------------------------------------------------------------
126
127 export {
128   isVideoCategoryValid,
129   isVideoLicenceValid,
130   isVideoLanguageValid,
131   isVideoNSFWValid,
132   isVideoTruncatedDescriptionValid,
133   isVideoDescriptionValid,
134   isVideoFileInfoHashValid,
135   isVideoNameValid,
136   isVideoTagsValid,
137   isVideoAbuseReasonValid,
138   isVideoFile,
139   isVideoViewsValid,
140   isVideoRatingTypeValid,
141   isVideoDurationValid,
142   isVideoTagValid,
143   isVideoUrlValid,
144   isVideoPrivacyValid,
145   checkVideoExists
146 }