aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/helpers/custom-validators/videos.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/helpers/custom-validators/videos.ts')
-rw-r--r--server/helpers/custom-validators/videos.ts218
1 files changed, 0 insertions, 218 deletions
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts
deleted file mode 100644
index 00c6deed4..000000000
--- a/server/helpers/custom-validators/videos.ts
+++ /dev/null
@@ -1,218 +0,0 @@
1import { Request, Response, UploadFilesForCheck } from 'express'
2import { decode as magnetUriDecode } from 'magnet-uri'
3import validator from 'validator'
4import { getVideoWithAttributes } from '@server/helpers/video'
5import { HttpStatusCode, VideoInclude, VideoPrivacy, VideoRateType } from '@shared/models'
6import {
7 CONSTRAINTS_FIELDS,
8 MIMETYPES,
9 VIDEO_CATEGORIES,
10 VIDEO_LICENCES,
11 VIDEO_LIVE,
12 VIDEO_PRIVACIES,
13 VIDEO_RATE_TYPES,
14 VIDEO_STATES
15} from '../../initializers/constants'
16import { exists, isArray, isDateValid, isFileValid } from './misc'
17
18const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
19
20function isVideoIncludeValid (include: VideoInclude) {
21 return exists(include) && validator.isInt('' + include)
22}
23
24function isVideoCategoryValid (value: any) {
25 return value === null || VIDEO_CATEGORIES[value] !== undefined
26}
27
28function isVideoStateValid (value: any) {
29 return exists(value) && VIDEO_STATES[value] !== undefined
30}
31
32function isVideoLicenceValid (value: any) {
33 return value === null || VIDEO_LICENCES[value] !== undefined
34}
35
36function isVideoLanguageValid (value: any) {
37 return value === null ||
38 (typeof value === 'string' && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.LANGUAGE))
39}
40
41function isVideoDurationValid (value: string) {
42 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.DURATION)
43}
44
45function isVideoDescriptionValid (value: string) {
46 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.DESCRIPTION))
47}
48
49function isVideoSupportValid (value: string) {
50 return value === null || (exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.SUPPORT))
51}
52
53function isVideoNameValid (value: string) {
54 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.NAME)
55}
56
57function isVideoTagValid (tag: string) {
58 return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG)
59}
60
61function areVideoTagsValid (tags: string[]) {
62 return tags === null || (
63 isArray(tags) &&
64 validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) &&
65 tags.every(tag => isVideoTagValid(tag))
66 )
67}
68
69function isVideoViewsValid (value: string) {
70 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.VIEWS)
71}
72
73const ratingTypes = new Set(Object.values(VIDEO_RATE_TYPES))
74function isVideoRatingTypeValid (value: string) {
75 return value === 'none' || ratingTypes.has(value as VideoRateType)
76}
77
78function isVideoFileExtnameValid (value: string) {
79 return exists(value) && (value === VIDEO_LIVE.EXTENSION || MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined)
80}
81
82function isVideoFileMimeTypeValid (files: UploadFilesForCheck, field = 'videofile') {
83 return isFileValid({
84 files,
85 mimeTypeRegex: MIMETYPES.VIDEO.MIMETYPES_REGEX,
86 field,
87 maxSize: null
88 })
89}
90
91const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
92 .map(v => v.replace('.', ''))
93 .join('|')
94const videoImageTypesRegex = `image/(${videoImageTypes})`
95
96function isVideoImageValid (files: UploadFilesForCheck, field: string, optional = true) {
97 return isFileValid({
98 files,
99 mimeTypeRegex: videoImageTypesRegex,
100 field,
101 maxSize: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max,
102 optional
103 })
104}
105
106function isVideoPrivacyValid (value: number) {
107 return VIDEO_PRIVACIES[value] !== undefined
108}
109
110function isVideoReplayPrivacyValid (value: number) {
111 return VIDEO_PRIVACIES[value] !== undefined && value !== VideoPrivacy.PASSWORD_PROTECTED
112}
113
114function isScheduleVideoUpdatePrivacyValid (value: number) {
115 return value === VideoPrivacy.UNLISTED || value === VideoPrivacy.PUBLIC || value === VideoPrivacy.INTERNAL
116}
117
118function isVideoOriginallyPublishedAtValid (value: string | null) {
119 return value === null || isDateValid(value)
120}
121
122function isVideoFileInfoHashValid (value: string | null | undefined) {
123 return exists(value) && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.INFO_HASH)
124}
125
126function isVideoFileResolutionValid (value: string) {
127 return exists(value) && validator.isInt(value + '')
128}
129
130function isVideoFPSResolutionValid (value: string) {
131 return value === null || validator.isInt(value + '')
132}
133
134function isVideoFileSizeValid (value: string) {
135 return exists(value) && validator.isInt(value + '', VIDEOS_CONSTRAINTS_FIELDS.FILE_SIZE)
136}
137
138function isVideoMagnetUriValid (value: string) {
139 if (!exists(value)) return false
140
141 const parsed = magnetUriDecode(value)
142 return parsed && isVideoFileInfoHashValid(parsed.infoHash)
143}
144
145function isPasswordValid (password: string) {
146 return password.length >= CONSTRAINTS_FIELDS.VIDEO_PASSWORD.LENGTH.min &&
147 password.length < CONSTRAINTS_FIELDS.VIDEO_PASSWORD.LENGTH.max
148}
149
150function isValidPasswordProtectedPrivacy (req: Request, res: Response) {
151 const fail = (message: string) => {
152 res.fail({
153 status: HttpStatusCode.BAD_REQUEST_400,
154 message
155 })
156 return false
157 }
158
159 let privacy: VideoPrivacy
160 const video = getVideoWithAttributes(res)
161
162 if (exists(req.body?.privacy)) privacy = req.body.privacy
163 else if (exists(video?.privacy)) privacy = video.privacy
164
165 if (privacy !== VideoPrivacy.PASSWORD_PROTECTED) return true
166
167 if (!exists(req.body.videoPasswords) && !exists(req.body.passwords)) return fail('Video passwords are missing.')
168
169 const passwords = req.body.videoPasswords || req.body.passwords
170
171 if (passwords.length === 0) return fail('At least one video password is required.')
172
173 if (new Set(passwords).size !== passwords.length) return fail('Duplicate video passwords are not allowed.')
174
175 for (const password of passwords) {
176 if (typeof password !== 'string') {
177 return fail('Video password should be a string.')
178 }
179
180 if (!isPasswordValid(password)) {
181 return fail('Invalid video password. Password length should be at least 2 characters and no more than 100 characters.')
182 }
183 }
184
185 return true
186}
187
188// ---------------------------------------------------------------------------
189
190export {
191 isVideoCategoryValid,
192 isVideoLicenceValid,
193 isVideoLanguageValid,
194 isVideoDescriptionValid,
195 isVideoFileInfoHashValid,
196 isVideoNameValid,
197 areVideoTagsValid,
198 isVideoFPSResolutionValid,
199 isScheduleVideoUpdatePrivacyValid,
200 isVideoOriginallyPublishedAtValid,
201 isVideoMagnetUriValid,
202 isVideoStateValid,
203 isVideoIncludeValid,
204 isVideoViewsValid,
205 isVideoRatingTypeValid,
206 isVideoFileExtnameValid,
207 isVideoFileMimeTypeValid,
208 isVideoDurationValid,
209 isVideoTagValid,
210 isVideoPrivacyValid,
211 isVideoReplayPrivacyValid,
212 isVideoFileResolutionValid,
213 isVideoFileSizeValid,
214 isVideoImageValid,
215 isVideoSupportValid,
216 isPasswordValid,
217 isValidPasswordProtectedPrivacy
218}