diff options
author | Chocobozzz <me@florianbigard.com> | 2022-02-11 10:51:33 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2022-02-28 10:42:19 +0100 |
commit | c729caf6cc34630877a0e5a1bda1719384cd0c8a (patch) | |
tree | 1d2e13722e518c73d2c9e6f0969615e29d51cf8c /server/helpers/custom-validators | |
parent | a24bf4dc659cebb65d887862bf21d7a35e9ec791 (diff) | |
download | PeerTube-c729caf6cc34630877a0e5a1bda1719384cd0c8a.tar.gz PeerTube-c729caf6cc34630877a0e5a1bda1719384cd0c8a.tar.zst PeerTube-c729caf6cc34630877a0e5a1bda1719384cd0c8a.zip |
Add basic video editor support
Diffstat (limited to 'server/helpers/custom-validators')
-rw-r--r-- | server/helpers/custom-validators/actor-images.ts | 11 | ||||
-rw-r--r-- | server/helpers/custom-validators/misc.ts | 79 | ||||
-rw-r--r-- | server/helpers/custom-validators/video-captions.ts | 12 | ||||
-rw-r--r-- | server/helpers/custom-validators/video-editor.ts | 52 | ||||
-rw-r--r-- | server/helpers/custom-validators/video-imports.ts | 11 | ||||
-rw-r--r-- | server/helpers/custom-validators/videos.ts | 27 |
6 files changed, 121 insertions, 71 deletions
diff --git a/server/helpers/custom-validators/actor-images.ts b/server/helpers/custom-validators/actor-images.ts index 4fb0b7c70..89f5a2262 100644 --- a/server/helpers/custom-validators/actor-images.ts +++ b/server/helpers/custom-validators/actor-images.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | 1 | ||
2 | import { UploadFilesForCheck } from 'express' | ||
2 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | 3 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' |
3 | import { isFileValid } from './misc' | 4 | import { isFileValid } from './misc' |
4 | 5 | ||
@@ -6,8 +7,14 @@ const imageMimeTypes = CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME | |||
6 | .map(v => v.replace('.', '')) | 7 | .map(v => v.replace('.', '')) |
7 | .join('|') | 8 | .join('|') |
8 | const imageMimeTypesRegex = `image/(${imageMimeTypes})` | 9 | const imageMimeTypesRegex = `image/(${imageMimeTypes})` |
9 | function isActorImageFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], fieldname: string) { | 10 | |
10 | return isFileValid(files, imageMimeTypesRegex, fieldname, CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max) | 11 | function isActorImageFile (files: UploadFilesForCheck, fieldname: string) { |
12 | return isFileValid({ | ||
13 | files, | ||
14 | mimeTypeRegex: imageMimeTypesRegex, | ||
15 | field: fieldname, | ||
16 | maxSize: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max | ||
17 | }) | ||
11 | } | 18 | } |
12 | 19 | ||
13 | // --------------------------------------------------------------------------- | 20 | // --------------------------------------------------------------------------- |
diff --git a/server/helpers/custom-validators/misc.ts b/server/helpers/custom-validators/misc.ts index 81a60ee66..c80c86193 100644 --- a/server/helpers/custom-validators/misc.ts +++ b/server/helpers/custom-validators/misc.ts | |||
@@ -61,75 +61,43 @@ function isIntOrNull (value: any) { | |||
61 | 61 | ||
62 | // --------------------------------------------------------------------------- | 62 | // --------------------------------------------------------------------------- |
63 | 63 | ||
64 | function isFileFieldValid ( | 64 | function isFileValid (options: { |
65 | files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], | 65 | files: UploadFilesForCheck |
66 | field: string, | ||
67 | optional = false | ||
68 | ) { | ||
69 | // Should have files | ||
70 | if (!files) return optional | ||
71 | if (isArray(files)) return optional | ||
72 | 66 | ||
73 | // Should have a file | 67 | maxSize: number | null |
74 | const fileArray = files[field] | 68 | mimeTypeRegex: string | null |
75 | if (!fileArray || fileArray.length === 0) { | ||
76 | return optional | ||
77 | } | ||
78 | 69 | ||
79 | // The file should exist | 70 | field?: string |
80 | const file = fileArray[0] | ||
81 | if (!file || !file.originalname) return false | ||
82 | return file | ||
83 | } | ||
84 | 71 | ||
85 | function isFileMimeTypeValid ( | 72 | optional?: boolean // Default false |
86 | files: UploadFilesForCheck, | 73 | }) { |
87 | mimeTypeRegex: string, | 74 | const { files, mimeTypeRegex, field, maxSize, optional = false } = options |
88 | field: string, | ||
89 | optional = false | ||
90 | ) { | ||
91 | // Should have files | ||
92 | if (!files) return optional | ||
93 | if (isArray(files)) return optional | ||
94 | 75 | ||
95 | // Should have a file | ||
96 | const fileArray = files[field] | ||
97 | if (!fileArray || fileArray.length === 0) { | ||
98 | return optional | ||
99 | } | ||
100 | |||
101 | // The file should exist | ||
102 | const file = fileArray[0] | ||
103 | if (!file || !file.originalname) return false | ||
104 | |||
105 | return new RegExp(`^${mimeTypeRegex}$`, 'i').test(file.mimetype) | ||
106 | } | ||
107 | |||
108 | function isFileValid ( | ||
109 | files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], | ||
110 | mimeTypeRegex: string, | ||
111 | field: string, | ||
112 | maxSize: number | null, | ||
113 | optional = false | ||
114 | ) { | ||
115 | // Should have files | 76 | // Should have files |
116 | if (!files) return optional | 77 | if (!files) return optional |
117 | if (isArray(files)) return optional | ||
118 | 78 | ||
119 | // Should have a file | 79 | const fileArray = isArray(files) |
120 | const fileArray = files[field] | 80 | ? files |
121 | if (!fileArray || fileArray.length === 0) { | 81 | : files[field] |
82 | |||
83 | if (!fileArray || !isArray(fileArray) || fileArray.length === 0) { | ||
122 | return optional | 84 | return optional |
123 | } | 85 | } |
124 | 86 | ||
125 | // The file should exist | 87 | // The file exists |
126 | const file = fileArray[0] | 88 | const file = fileArray[0] |
127 | if (!file || !file.originalname) return false | 89 | if (!file || !file.originalname) return false |
128 | 90 | ||
129 | // Check size | 91 | // Check size |
130 | if ((maxSize !== null) && file.size > maxSize) return false | 92 | if ((maxSize !== null) && file.size > maxSize) return false |
131 | 93 | ||
132 | return new RegExp(`^${mimeTypeRegex}$`, 'i').test(file.mimetype) | 94 | if (mimeTypeRegex === null) return true |
95 | |||
96 | return checkMimetypeRegex(file.mimetype, mimeTypeRegex) | ||
97 | } | ||
98 | |||
99 | function checkMimetypeRegex (fileMimeType: string, mimeTypeRegex: string) { | ||
100 | return new RegExp(`^${mimeTypeRegex}$`, 'i').test(fileMimeType) | ||
133 | } | 101 | } |
134 | 102 | ||
135 | // --------------------------------------------------------------------------- | 103 | // --------------------------------------------------------------------------- |
@@ -204,7 +172,6 @@ export { | |||
204 | areUUIDsValid, | 172 | areUUIDsValid, |
205 | toArray, | 173 | toArray, |
206 | toIntArray, | 174 | toIntArray, |
207 | isFileFieldValid, | 175 | isFileValid, |
208 | isFileMimeTypeValid, | 176 | checkMimetypeRegex |
209 | isFileValid | ||
210 | } | 177 | } |
diff --git a/server/helpers/custom-validators/video-captions.ts b/server/helpers/custom-validators/video-captions.ts index 4cc7dcaf4..59ba005fe 100644 --- a/server/helpers/custom-validators/video-captions.ts +++ b/server/helpers/custom-validators/video-captions.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { getFileSize } from '@shared/extra-utils' | 1 | import { UploadFilesForCheck } from 'express' |
2 | import { readFile } from 'fs-extra' | 2 | import { readFile } from 'fs-extra' |
3 | import { getFileSize } from '@shared/extra-utils' | ||
3 | import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_LANGUAGES } from '../../initializers/constants' | 4 | import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_LANGUAGES } from '../../initializers/constants' |
4 | import { exists, isFileValid } from './misc' | 5 | import { exists, isFileValid } from './misc' |
5 | 6 | ||
@@ -11,8 +12,13 @@ const videoCaptionTypesRegex = Object.keys(MIMETYPES.VIDEO_CAPTIONS.MIMETYPE_EXT | |||
11 | .concat([ 'application/octet-stream' ]) // MacOS sends application/octet-stream | 12 | .concat([ 'application/octet-stream' ]) // MacOS sends application/octet-stream |
12 | .map(m => `(${m})`) | 13 | .map(m => `(${m})`) |
13 | .join('|') | 14 | .join('|') |
14 | function isVideoCaptionFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) { | 15 | function isVideoCaptionFile (files: UploadFilesForCheck, field: string) { |
15 | return isFileValid(files, videoCaptionTypesRegex, field, CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max) | 16 | return isFileValid({ |
17 | files, | ||
18 | mimeTypeRegex: videoCaptionTypesRegex, | ||
19 | field, | ||
20 | maxSize: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max | ||
21 | }) | ||
16 | } | 22 | } |
17 | 23 | ||
18 | async function isVTTFileValid (filePath: string) { | 24 | async function isVTTFileValid (filePath: string) { |
diff --git a/server/helpers/custom-validators/video-editor.ts b/server/helpers/custom-validators/video-editor.ts new file mode 100644 index 000000000..09238675e --- /dev/null +++ b/server/helpers/custom-validators/video-editor.ts | |||
@@ -0,0 +1,52 @@ | |||
1 | import validator from 'validator' | ||
2 | import { CONSTRAINTS_FIELDS } from '@server/initializers/constants' | ||
3 | import { buildTaskFileFieldname } from '@server/lib/video-editor' | ||
4 | import { VideoEditorTask } from '@shared/models' | ||
5 | import { isArray } from './misc' | ||
6 | import { isVideoFileMimeTypeValid, isVideoImageValid } from './videos' | ||
7 | |||
8 | function isValidEditorTasksArray (tasks: any) { | ||
9 | if (!isArray(tasks)) return false | ||
10 | |||
11 | return tasks.length >= CONSTRAINTS_FIELDS.VIDEO_EDITOR.TASKS.min && | ||
12 | tasks.length <= CONSTRAINTS_FIELDS.VIDEO_EDITOR.TASKS.max | ||
13 | } | ||
14 | |||
15 | function isEditorCutTaskValid (task: VideoEditorTask) { | ||
16 | if (task.name !== 'cut') return false | ||
17 | if (!task.options) return false | ||
18 | |||
19 | const { start, end } = task.options | ||
20 | if (!start && !end) return false | ||
21 | |||
22 | if (start && !validator.isInt(start + '', CONSTRAINTS_FIELDS.VIDEO_EDITOR.CUT_TIME)) return false | ||
23 | if (end && !validator.isInt(end + '', CONSTRAINTS_FIELDS.VIDEO_EDITOR.CUT_TIME)) return false | ||
24 | |||
25 | if (!start || !end) return true | ||
26 | |||
27 | return parseInt(start + '') < parseInt(end + '') | ||
28 | } | ||
29 | |||
30 | function isEditorTaskAddIntroOutroValid (task: VideoEditorTask, indice: number, files: Express.Multer.File[]) { | ||
31 | const file = files.find(f => f.fieldname === buildTaskFileFieldname(indice, 'file')) | ||
32 | |||
33 | return (task.name === 'add-intro' || task.name === 'add-outro') && | ||
34 | file && isVideoFileMimeTypeValid([ file ], null) | ||
35 | } | ||
36 | |||
37 | function isEditorTaskAddWatermarkValid (task: VideoEditorTask, indice: number, files: Express.Multer.File[]) { | ||
38 | const file = files.find(f => f.fieldname === buildTaskFileFieldname(indice, 'file')) | ||
39 | |||
40 | return task.name === 'add-watermark' && | ||
41 | file && isVideoImageValid([ file ], null, true) | ||
42 | } | ||
43 | |||
44 | // --------------------------------------------------------------------------- | ||
45 | |||
46 | export { | ||
47 | isValidEditorTasksArray, | ||
48 | |||
49 | isEditorCutTaskValid, | ||
50 | isEditorTaskAddIntroOutroValid, | ||
51 | isEditorTaskAddWatermarkValid | ||
52 | } | ||
diff --git a/server/helpers/custom-validators/video-imports.ts b/server/helpers/custom-validators/video-imports.ts index dbf6a3504..af93aea56 100644 --- a/server/helpers/custom-validators/video-imports.ts +++ b/server/helpers/custom-validators/video-imports.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import 'multer' | 1 | import 'multer' |
2 | import { UploadFilesForCheck } from 'express' | ||
2 | import validator from 'validator' | 3 | import validator from 'validator' |
3 | import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_IMPORT_STATES } from '../../initializers/constants' | 4 | import { CONSTRAINTS_FIELDS, MIMETYPES, VIDEO_IMPORT_STATES } from '../../initializers/constants' |
4 | import { exists, isFileValid } from './misc' | 5 | import { exists, isFileValid } from './misc' |
@@ -25,8 +26,14 @@ const videoTorrentImportRegex = Object.keys(MIMETYPES.TORRENT.MIMETYPE_EXT) | |||
25 | .concat([ 'application/octet-stream' ]) // MacOS sends application/octet-stream | 26 | .concat([ 'application/octet-stream' ]) // MacOS sends application/octet-stream |
26 | .map(m => `(${m})`) | 27 | .map(m => `(${m})`) |
27 | .join('|') | 28 | .join('|') |
28 | function isVideoImportTorrentFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) { | 29 | function isVideoImportTorrentFile (files: UploadFilesForCheck) { |
29 | return isFileValid(files, videoTorrentImportRegex, 'torrentfile', CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_FILE.FILE_SIZE.max, true) | 30 | return isFileValid({ |
31 | files, | ||
32 | mimeTypeRegex: videoTorrentImportRegex, | ||
33 | field: 'torrentfile', | ||
34 | maxSize: CONSTRAINTS_FIELDS.VIDEO_IMPORTS.TORRENT_FILE.FILE_SIZE.max, | ||
35 | optional: true | ||
36 | }) | ||
30 | } | 37 | } |
31 | 38 | ||
32 | // --------------------------------------------------------------------------- | 39 | // --------------------------------------------------------------------------- |
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts index e526c4284..ca5f70fdc 100644 --- a/server/helpers/custom-validators/videos.ts +++ b/server/helpers/custom-validators/videos.ts | |||
@@ -13,7 +13,7 @@ import { | |||
13 | VIDEO_RATE_TYPES, | 13 | VIDEO_RATE_TYPES, |
14 | VIDEO_STATES | 14 | VIDEO_STATES |
15 | } from '../../initializers/constants' | 15 | } from '../../initializers/constants' |
16 | import { exists, isArray, isDateValid, isFileMimeTypeValid, isFileValid } from './misc' | 16 | import { exists, isArray, isDateValid, isFileValid } from './misc' |
17 | 17 | ||
18 | const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS | 18 | const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS |
19 | 19 | ||
@@ -66,7 +66,7 @@ function isVideoTagValid (tag: string) { | |||
66 | return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG) | 66 | return exists(tag) && validator.isLength(tag, VIDEOS_CONSTRAINTS_FIELDS.TAG) |
67 | } | 67 | } |
68 | 68 | ||
69 | function isVideoTagsValid (tags: string[]) { | 69 | function areVideoTagsValid (tags: string[]) { |
70 | return tags === null || ( | 70 | return tags === null || ( |
71 | isArray(tags) && | 71 | isArray(tags) && |
72 | validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) && | 72 | validator.isInt(tags.length.toString(), VIDEOS_CONSTRAINTS_FIELDS.TAGS) && |
@@ -86,8 +86,13 @@ function isVideoFileExtnameValid (value: string) { | |||
86 | return exists(value) && (value === VIDEO_LIVE.EXTENSION || MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined) | 86 | return exists(value) && (value === VIDEO_LIVE.EXTENSION || MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined) |
87 | } | 87 | } |
88 | 88 | ||
89 | function isVideoFileMimeTypeValid (files: UploadFilesForCheck) { | 89 | function isVideoFileMimeTypeValid (files: UploadFilesForCheck, field = 'videofile') { |
90 | return isFileMimeTypeValid(files, MIMETYPES.VIDEO.MIMETYPES_REGEX, 'videofile') | 90 | return isFileValid({ |
91 | files, | ||
92 | mimeTypeRegex: MIMETYPES.VIDEO.MIMETYPES_REGEX, | ||
93 | field, | ||
94 | maxSize: null | ||
95 | }) | ||
91 | } | 96 | } |
92 | 97 | ||
93 | const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME | 98 | const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME |
@@ -95,8 +100,14 @@ const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME | |||
95 | .join('|') | 100 | .join('|') |
96 | const videoImageTypesRegex = `image/(${videoImageTypes})` | 101 | const videoImageTypesRegex = `image/(${videoImageTypes})` |
97 | 102 | ||
98 | function isVideoImage (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[], field: string) { | 103 | function isVideoImageValid (files: UploadFilesForCheck, field: string, optional = true) { |
99 | return isFileValid(files, videoImageTypesRegex, field, CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max, true) | 104 | return isFileValid({ |
105 | files, | ||
106 | mimeTypeRegex: videoImageTypesRegex, | ||
107 | field, | ||
108 | maxSize: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max, | ||
109 | optional | ||
110 | }) | ||
100 | } | 111 | } |
101 | 112 | ||
102 | function isVideoPrivacyValid (value: number) { | 113 | function isVideoPrivacyValid (value: number) { |
@@ -144,7 +155,7 @@ export { | |||
144 | isVideoDescriptionValid, | 155 | isVideoDescriptionValid, |
145 | isVideoFileInfoHashValid, | 156 | isVideoFileInfoHashValid, |
146 | isVideoNameValid, | 157 | isVideoNameValid, |
147 | isVideoTagsValid, | 158 | areVideoTagsValid, |
148 | isVideoFPSResolutionValid, | 159 | isVideoFPSResolutionValid, |
149 | isScheduleVideoUpdatePrivacyValid, | 160 | isScheduleVideoUpdatePrivacyValid, |
150 | isVideoOriginallyPublishedAtValid, | 161 | isVideoOriginallyPublishedAtValid, |
@@ -160,7 +171,7 @@ export { | |||
160 | isVideoPrivacyValid, | 171 | isVideoPrivacyValid, |
161 | isVideoFileResolutionValid, | 172 | isVideoFileResolutionValid, |
162 | isVideoFileSizeValid, | 173 | isVideoFileSizeValid, |
163 | isVideoImage, | 174 | isVideoImageValid, |
164 | isVideoSupportValid, | 175 | isVideoSupportValid, |
165 | isVideoFilterValid | 176 | isVideoFilterValid |
166 | } | 177 | } |