23d2d8ac6aa380af3e4c2f9818563a31e03b38f6
[oweals/peertube.git] / server / helpers / custom-validators / videos.ts
1 import { Response } from 'express'
2 import 'express-validator'
3 import { values } from 'lodash'
4 import 'multer'
5 import * as validator from 'validator'
6 import { VideoRateType } from '../../../shared'
7 import {
8   CONSTRAINTS_FIELDS,
9   VIDEO_CATEGORIES,
10   VIDEO_LANGUAGES,
11   VIDEO_LICENCES, VIDEO_MIMETYPE_EXT,
12   VIDEO_PRIVACIES,
13   VIDEO_RATE_TYPES
14 } from '../../initializers'
15 import { VideoModel } from '../../models/video/video'
16 import { exists, isArray, isFileValid } from './misc'
17
18 const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
19 const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
20
21 function isVideoCategoryValid (value: any) {
22   return value === null || VIDEO_CATEGORIES[value] !== undefined
23 }
24
25 function isVideoLicenceValid (value: any) {
26   return value === null || VIDEO_LICENCES[value] !== undefined
27 }
28
29 function isVideoLanguageValid (value: any) {
30   return value === null ||
31     (typeof value === 'string' && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.LANGUAGE))
32 }
33
34 function isVideoDurationValid (value: string) {
35   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
36 }
37
38 function isVideoTruncatedDescriptionValid (value: string) {
39   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.TRUNCATED_DESCRIPTION)
40 }
41
42 function isVideoDescriptionValid (value: string) {
43   return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION))
44 }
45
46 function isVideoSupportValid (value: string) {
47   return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.SUPPORT))
48 }
49
50 function isVideoNameValid (value: string) {
51   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
52 }
53
54 function isVideoTagValid (tag: string) {
55   return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
56 }
57
58 function isVideoTagsValid (tags: string[]) {
59   return isArray(tags) &&
60          validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
61          tags.every(tag => isVideoTagValid(tag))
62 }
63
64 function isVideoAbuseReasonValid (value: string) {
65   return exists(value) && validator.isLength(value, VIDEO_ABUSES_CONSTRAINTS_FIELDS.REASON)
66 }
67
68 function isVideoViewsValid (value: string) {
69   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
70 }
71
72 function isVideoRatingTypeValid (value: string) {
73   return value === 'none' || values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
74 }
75
76 const videoFileTypes = Object.keys(VIDEO_MIMETYPE_EXT).map(m => `(${m})`)
77 const videoFileTypesRegex = videoFileTypes.join('|')
78 function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
79   return isFileValid(files, videoFileTypesRegex, 'videofile')
80 }
81
82 const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
83   .map(v => v.replace('.', ''))
84   .join('|')
85 const videoImageTypesRegex = `image/(${videoImageTypes})`
86 function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) {
87   return isFileValid(files, videoImageTypesRegex, field, true)
88 }
89
90 function isVideoPrivacyValid (value: string) {
91   return validator.isInt(value + '') && VIDEO_PRIVACIES[value] !== undefined
92 }
93
94 function isVideoFileInfoHashValid (value: string) {
95   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
96 }
97
98 function isVideoFileResolutionValid (value: string) {
99   return exists(value) && validator.isInt(value + '')
100 }
101
102 function isVideoFileSizeValid (value: string) {
103   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
104 }
105
106 async function isVideoExist (id: string, res: Response) {
107   let video: VideoModel
108
109   if (validator.isInt(id)) {
110     video = await VideoModel.loadAndPopulateAccountAndServerAndTags(+id)
111   } else { // UUID
112     video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(id)
113   }
114
115   if (!video) {
116     res.status(404)
117       .json({ error: 'Video not found' })
118       .end()
119
120     return false
121   }
122
123   res.locals.video = video
124   return true
125 }
126
127 // ---------------------------------------------------------------------------
128
129 export {
130   isVideoCategoryValid,
131   isVideoLicenceValid,
132   isVideoLanguageValid,
133   isVideoTruncatedDescriptionValid,
134   isVideoDescriptionValid,
135   isVideoFileInfoHashValid,
136   isVideoNameValid,
137   isVideoTagsValid,
138   isVideoAbuseReasonValid,
139   isVideoFile,
140   isVideoViewsValid,
141   isVideoRatingTypeValid,
142   isVideoDurationValid,
143   isVideoTagValid,
144   isVideoPrivacyValid,
145   isVideoFileResolutionValid,
146   isVideoFileSizeValid,
147   isVideoExist,
148   isVideoImage,
149   isVideoSupportValid
150 }