diff options
author | Chocobozzz <me@florianbigard.com> | 2023-04-21 14:55:10 +0200 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2023-05-09 08:57:34 +0200 |
commit | 0c9668f77901e7540e2c7045eb0f2974a4842a69 (patch) | |
tree | 226d3dd1565b0bb56588897af3b8530e6216e96b /server/helpers/custom-validators | |
parent | 6bcb854cdea8688a32240bc5719c7d139806e00b (diff) | |
download | PeerTube-0c9668f77901e7540e2c7045eb0f2974a4842a69.tar.gz PeerTube-0c9668f77901e7540e2c7045eb0f2974a4842a69.tar.zst PeerTube-0c9668f77901e7540e2c7045eb0f2974a4842a69.zip |
Implement remote runner jobs in server
Move ffmpeg functions to @shared
Diffstat (limited to 'server/helpers/custom-validators')
-rw-r--r-- | server/helpers/custom-validators/misc.ts | 5 | ||||
-rw-r--r-- | server/helpers/custom-validators/runners/jobs.ts | 166 | ||||
-rw-r--r-- | server/helpers/custom-validators/runners/runners.ts | 30 |
3 files changed, 201 insertions, 0 deletions
diff --git a/server/helpers/custom-validators/misc.ts b/server/helpers/custom-validators/misc.ts index ebab4c6b2..fa0f469f6 100644 --- a/server/helpers/custom-validators/misc.ts +++ b/server/helpers/custom-validators/misc.ts | |||
@@ -15,6 +15,10 @@ function isSafePath (p: string) { | |||
15 | }) | 15 | }) |
16 | } | 16 | } |
17 | 17 | ||
18 | function isSafeFilename (filename: string, extension: string) { | ||
19 | return typeof filename === 'string' && !!filename.match(new RegExp(`^[a-z0-9-]+\\.${extension}$`)) | ||
20 | } | ||
21 | |||
18 | function isSafePeerTubeFilenameWithoutExtension (filename: string) { | 22 | function isSafePeerTubeFilenameWithoutExtension (filename: string) { |
19 | return filename.match(/^[a-z0-9-]+$/) | 23 | return filename.match(/^[a-z0-9-]+$/) |
20 | } | 24 | } |
@@ -177,5 +181,6 @@ export { | |||
177 | toIntArray, | 181 | toIntArray, |
178 | isFileValid, | 182 | isFileValid, |
179 | isSafePeerTubeFilenameWithoutExtension, | 183 | isSafePeerTubeFilenameWithoutExtension, |
184 | isSafeFilename, | ||
180 | checkMimetypeRegex | 185 | checkMimetypeRegex |
181 | } | 186 | } |
diff --git a/server/helpers/custom-validators/runners/jobs.ts b/server/helpers/custom-validators/runners/jobs.ts new file mode 100644 index 000000000..5f755d5bb --- /dev/null +++ b/server/helpers/custom-validators/runners/jobs.ts | |||
@@ -0,0 +1,166 @@ | |||
1 | import { UploadFilesForCheck } from 'express' | ||
2 | import validator from 'validator' | ||
3 | import { CONSTRAINTS_FIELDS } from '@server/initializers/constants' | ||
4 | import { | ||
5 | LiveRTMPHLSTranscodingSuccess, | ||
6 | RunnerJobSuccessPayload, | ||
7 | RunnerJobType, | ||
8 | RunnerJobUpdatePayload, | ||
9 | VODAudioMergeTranscodingSuccess, | ||
10 | VODHLSTranscodingSuccess, | ||
11 | VODWebVideoTranscodingSuccess | ||
12 | } from '@shared/models' | ||
13 | import { exists, isFileValid, isSafeFilename } from '../misc' | ||
14 | |||
15 | const RUNNER_JOBS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.RUNNER_JOBS | ||
16 | |||
17 | const runnerJobTypes = new Set([ 'vod-hls-transcoding', 'vod-web-video-transcoding', 'vod-audio-merge-transcoding' ]) | ||
18 | function isRunnerJobTypeValid (value: RunnerJobType) { | ||
19 | return runnerJobTypes.has(value) | ||
20 | } | ||
21 | |||
22 | function isRunnerJobSuccessPayloadValid (value: RunnerJobSuccessPayload, type: RunnerJobType, files: UploadFilesForCheck) { | ||
23 | return isRunnerJobVODWebVideoResultPayloadValid(value as VODWebVideoTranscodingSuccess, type, files) || | ||
24 | isRunnerJobVODHLSResultPayloadValid(value as VODHLSTranscodingSuccess, type, files) || | ||
25 | isRunnerJobVODAudioMergeResultPayloadValid(value as VODHLSTranscodingSuccess, type, files) || | ||
26 | isRunnerJobLiveRTMPHLSResultPayloadValid(value as LiveRTMPHLSTranscodingSuccess, type) | ||
27 | } | ||
28 | |||
29 | // --------------------------------------------------------------------------- | ||
30 | |||
31 | function isRunnerJobProgressValid (value: string) { | ||
32 | return validator.isInt(value + '', RUNNER_JOBS_CONSTRAINTS_FIELDS.PROGRESS) | ||
33 | } | ||
34 | |||
35 | function isRunnerJobUpdatePayloadValid (value: RunnerJobUpdatePayload, type: RunnerJobType, files: UploadFilesForCheck) { | ||
36 | return isRunnerJobVODWebVideoUpdatePayloadValid(value, type, files) || | ||
37 | isRunnerJobVODHLSUpdatePayloadValid(value, type, files) || | ||
38 | isRunnerJobVODAudioMergeUpdatePayloadValid(value, type, files) || | ||
39 | isRunnerJobLiveRTMPHLSUpdatePayloadValid(value, type, files) | ||
40 | } | ||
41 | |||
42 | // --------------------------------------------------------------------------- | ||
43 | |||
44 | function isRunnerJobTokenValid (value: string) { | ||
45 | return exists(value) && validator.isLength(value, RUNNER_JOBS_CONSTRAINTS_FIELDS.TOKEN) | ||
46 | } | ||
47 | |||
48 | function isRunnerJobAbortReasonValid (value: string) { | ||
49 | return validator.isLength(value, RUNNER_JOBS_CONSTRAINTS_FIELDS.REASON) | ||
50 | } | ||
51 | |||
52 | function isRunnerJobErrorMessageValid (value: string) { | ||
53 | return validator.isLength(value, RUNNER_JOBS_CONSTRAINTS_FIELDS.ERROR_MESSAGE) | ||
54 | } | ||
55 | |||
56 | // --------------------------------------------------------------------------- | ||
57 | |||
58 | export { | ||
59 | isRunnerJobTypeValid, | ||
60 | isRunnerJobSuccessPayloadValid, | ||
61 | isRunnerJobUpdatePayloadValid, | ||
62 | isRunnerJobTokenValid, | ||
63 | isRunnerJobErrorMessageValid, | ||
64 | isRunnerJobProgressValid, | ||
65 | isRunnerJobAbortReasonValid | ||
66 | } | ||
67 | |||
68 | // --------------------------------------------------------------------------- | ||
69 | |||
70 | function isRunnerJobVODWebVideoResultPayloadValid ( | ||
71 | _value: VODWebVideoTranscodingSuccess, | ||
72 | type: RunnerJobType, | ||
73 | files: UploadFilesForCheck | ||
74 | ) { | ||
75 | return type === 'vod-web-video-transcoding' && | ||
76 | isFileValid({ files, field: 'payload[videoFile]', mimeTypeRegex: null, maxSize: null }) | ||
77 | } | ||
78 | |||
79 | function isRunnerJobVODHLSResultPayloadValid ( | ||
80 | _value: VODHLSTranscodingSuccess, | ||
81 | type: RunnerJobType, | ||
82 | files: UploadFilesForCheck | ||
83 | ) { | ||
84 | return type === 'vod-hls-transcoding' && | ||
85 | isFileValid({ files, field: 'payload[videoFile]', mimeTypeRegex: null, maxSize: null }) && | ||
86 | isFileValid({ files, field: 'payload[resolutionPlaylistFile]', mimeTypeRegex: null, maxSize: null }) | ||
87 | } | ||
88 | |||
89 | function isRunnerJobVODAudioMergeResultPayloadValid ( | ||
90 | _value: VODAudioMergeTranscodingSuccess, | ||
91 | type: RunnerJobType, | ||
92 | files: UploadFilesForCheck | ||
93 | ) { | ||
94 | return type === 'vod-audio-merge-transcoding' && | ||
95 | isFileValid({ files, field: 'payload[videoFile]', mimeTypeRegex: null, maxSize: null }) | ||
96 | } | ||
97 | |||
98 | function isRunnerJobLiveRTMPHLSResultPayloadValid ( | ||
99 | value: LiveRTMPHLSTranscodingSuccess, | ||
100 | type: RunnerJobType | ||
101 | ) { | ||
102 | return type === 'live-rtmp-hls-transcoding' && (!value || (typeof value === 'object' && Object.keys(value).length === 0)) | ||
103 | } | ||
104 | |||
105 | // --------------------------------------------------------------------------- | ||
106 | |||
107 | function isRunnerJobVODWebVideoUpdatePayloadValid ( | ||
108 | value: RunnerJobUpdatePayload, | ||
109 | type: RunnerJobType, | ||
110 | _files: UploadFilesForCheck | ||
111 | ) { | ||
112 | return type === 'vod-web-video-transcoding' && | ||
113 | (!value || (typeof value === 'object' && Object.keys(value).length === 0)) | ||
114 | } | ||
115 | |||
116 | function isRunnerJobVODHLSUpdatePayloadValid ( | ||
117 | value: RunnerJobUpdatePayload, | ||
118 | type: RunnerJobType, | ||
119 | _files: UploadFilesForCheck | ||
120 | ) { | ||
121 | return type === 'vod-hls-transcoding' && | ||
122 | (!value || (typeof value === 'object' && Object.keys(value).length === 0)) | ||
123 | } | ||
124 | |||
125 | function isRunnerJobVODAudioMergeUpdatePayloadValid ( | ||
126 | value: RunnerJobUpdatePayload, | ||
127 | type: RunnerJobType, | ||
128 | _files: UploadFilesForCheck | ||
129 | ) { | ||
130 | return type === 'vod-audio-merge-transcoding' && | ||
131 | (!value || (typeof value === 'object' && Object.keys(value).length === 0)) | ||
132 | } | ||
133 | |||
134 | function isRunnerJobLiveRTMPHLSUpdatePayloadValid ( | ||
135 | value: RunnerJobUpdatePayload, | ||
136 | type: RunnerJobType, | ||
137 | files: UploadFilesForCheck | ||
138 | ) { | ||
139 | let result = type === 'live-rtmp-hls-transcoding' && !!value && !!files | ||
140 | |||
141 | result &&= isFileValid({ files, field: 'payload[masterPlaylistFile]', mimeTypeRegex: null, maxSize: null, optional: true }) | ||
142 | |||
143 | result &&= isFileValid({ | ||
144 | files, | ||
145 | field: 'payload[resolutionPlaylistFile]', | ||
146 | mimeTypeRegex: null, | ||
147 | maxSize: null, | ||
148 | optional: !value.resolutionPlaylistFilename | ||
149 | }) | ||
150 | |||
151 | if (files['payload[resolutionPlaylistFile]']) { | ||
152 | result &&= isSafeFilename(value.resolutionPlaylistFilename, 'm3u8') | ||
153 | } | ||
154 | |||
155 | return result && | ||
156 | isSafeFilename(value.videoChunkFilename, 'ts') && | ||
157 | ( | ||
158 | ( | ||
159 | value.type === 'remove-chunk' | ||
160 | ) || | ||
161 | ( | ||
162 | value.type === 'add-chunk' && | ||
163 | isFileValid({ files, field: 'payload[videoChunkFile]', mimeTypeRegex: null, maxSize: null }) | ||
164 | ) | ||
165 | ) | ||
166 | } | ||
diff --git a/server/helpers/custom-validators/runners/runners.ts b/server/helpers/custom-validators/runners/runners.ts new file mode 100644 index 000000000..953fac3b5 --- /dev/null +++ b/server/helpers/custom-validators/runners/runners.ts | |||
@@ -0,0 +1,30 @@ | |||
1 | import validator from 'validator' | ||
2 | import { CONSTRAINTS_FIELDS } from '@server/initializers/constants' | ||
3 | import { exists } from '../misc' | ||
4 | |||
5 | const RUNNERS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.RUNNERS | ||
6 | |||
7 | function isRunnerRegistrationTokenValid (value: string) { | ||
8 | return exists(value) && validator.isLength(value, RUNNERS_CONSTRAINTS_FIELDS.TOKEN) | ||
9 | } | ||
10 | |||
11 | function isRunnerTokenValid (value: string) { | ||
12 | return exists(value) && validator.isLength(value, RUNNERS_CONSTRAINTS_FIELDS.TOKEN) | ||
13 | } | ||
14 | |||
15 | function isRunnerNameValid (value: string) { | ||
16 | return exists(value) && validator.isLength(value, RUNNERS_CONSTRAINTS_FIELDS.NAME) | ||
17 | } | ||
18 | |||
19 | function isRunnerDescriptionValid (value: string) { | ||
20 | return exists(value) && validator.isLength(value, RUNNERS_CONSTRAINTS_FIELDS.DESCRIPTION) | ||
21 | } | ||
22 | |||
23 | // --------------------------------------------------------------------------- | ||
24 | |||
25 | export { | ||
26 | isRunnerRegistrationTokenValid, | ||
27 | isRunnerTokenValid, | ||
28 | isRunnerNameValid, | ||
29 | isRunnerDescriptionValid | ||
30 | } | ||