Add ability to update a video channel
[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 import { VideoChannelModel } from '../../models/video/video-channel'
18
19 const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
20 const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
21
22 function isVideoCategoryValid (value: any) {
23   return value === null || VIDEO_CATEGORIES[value] !== undefined
24 }
25
26 function isVideoLicenceValid (value: any) {
27   return value === null || VIDEO_LICENCES[value] !== undefined
28 }
29
30 function isVideoLanguageValid (value: any) {
31   return value === null ||
32     (typeof value === 'string' && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.LANGUAGE))
33 }
34
35 function isVideoDurationValid (value: string) {
36   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
37 }
38
39 function isVideoTruncatedDescriptionValid (value: string) {
40   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.TRUNCATED_DESCRIPTION)
41 }
42
43 function isVideoDescriptionValid (value: string) {
44   return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION))
45 }
46
47 function isVideoSupportValid (value: string) {
48   return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.SUPPORT))
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 value === 'none' || values(VIDEO_RATE_TYPES).indexOf(value as VideoRateType) !== -1
75 }
76
77 const videoFileTypes = Object.keys(VIDEO_MIMETYPE_EXT).map(m => `(${m})`)
78 const videoFileTypesRegex = videoFileTypes.join('|')
79 function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
80   return isFileValid(files, videoFileTypesRegex, 'videofile')
81 }
82
83 const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
84   .map(v => v.replace('.', ''))
85   .join('|')
86 const videoImageTypesRegex = `image/(${videoImageTypes})`
87 function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) {
88   return isFileValid(files, videoImageTypesRegex, field, true)
89 }
90
91 function isVideoPrivacyValid (value: string) {
92   return validator.isInt(value + '') && VIDEO_PRIVACIES[value] !== undefined
93 }
94
95 function isVideoFileInfoHashValid (value: string) {
96   return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
97 }
98
99 function isVideoFileResolutionValid (value: string) {
100   return exists(value) && validator.isInt(value + '')
101 }
102
103 function isVideoFileSizeValid (value: string) {
104   return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
105 }
106
107 async function isVideoExist (id: string, res: Response) {
108   let video: VideoModel
109
110   if (validator.isInt(id)) {
111     video = await VideoModel.loadAndPopulateAccountAndServerAndTags(+id)
112   } else { // UUID
113     video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(id)
114   }
115
116   if (!video) {
117     res.status(404)
118       .json({ error: 'Video not found' })
119       .end()
120
121     return false
122   }
123
124   res.locals.video = video
125   return true
126 }
127
128 async function isVideoChannelOfAccountExist (channelId: number, accountId: number, res: Response) {
129   const videoChannel = await VideoChannelModel.loadByIdAndAccount(channelId, accountId)
130   if (!videoChannel) {
131     res.status(400)
132        .json({ error: 'Unknown video video channel for this account.' })
133        .end()
134
135     return false
136   }
137
138   res.locals.videoChannel = videoChannel
139   return true
140 }
141
142 // ---------------------------------------------------------------------------
143
144 export {
145   isVideoCategoryValid,
146   isVideoLicenceValid,
147   isVideoLanguageValid,
148   isVideoTruncatedDescriptionValid,
149   isVideoDescriptionValid,
150   isVideoFileInfoHashValid,
151   isVideoNameValid,
152   isVideoTagsValid,
153   isVideoAbuseReasonValid,
154   isVideoFile,
155   isVideoViewsValid,
156   isVideoRatingTypeValid,
157   isVideoDurationValid,
158   isVideoTagValid,
159   isVideoPrivacyValid,
160   isVideoFileResolutionValid,
161   isVideoFileSizeValid,
162   isVideoExist,
163   isVideoImage,
164   isVideoChannelOfAccountExist,
165   isVideoSupportValid
166 }