aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/server/helpers/custom-validators/runners/jobs.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/server/helpers/custom-validators/runners/jobs.ts')
-rw-r--r--server/server/helpers/custom-validators/runners/jobs.ts197
1 files changed, 197 insertions, 0 deletions
diff --git a/server/server/helpers/custom-validators/runners/jobs.ts b/server/server/helpers/custom-validators/runners/jobs.ts
new file mode 100644
index 000000000..78c6c2e1e
--- /dev/null
+++ b/server/server/helpers/custom-validators/runners/jobs.ts
@@ -0,0 +1,197 @@
1import { UploadFilesForCheck } from 'express'
2import validator from 'validator'
3import { CONSTRAINTS_FIELDS, RUNNER_JOB_STATES } from '@server/initializers/constants.js'
4import {
5 LiveRTMPHLSTranscodingSuccess,
6 RunnerJobSuccessPayload,
7 RunnerJobType,
8 RunnerJobUpdatePayload,
9 VideoStudioTranscodingSuccess,
10 VODAudioMergeTranscodingSuccess,
11 VODHLSTranscodingSuccess,
12 VODWebVideoTranscodingSuccess
13} from '@peertube/peertube-models'
14import { exists, isArray, isFileValid, isSafeFilename } from '../misc.js'
15
16const RUNNER_JOBS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.RUNNER_JOBS
17
18const runnerJobTypes = new Set([ 'vod-hls-transcoding', 'vod-web-video-transcoding', 'vod-audio-merge-transcoding' ])
19function isRunnerJobTypeValid (value: RunnerJobType) {
20 return runnerJobTypes.has(value)
21}
22
23function isRunnerJobSuccessPayloadValid (value: RunnerJobSuccessPayload, type: RunnerJobType, files: UploadFilesForCheck) {
24 return isRunnerJobVODWebVideoResultPayloadValid(value as VODWebVideoTranscodingSuccess, type, files) ||
25 isRunnerJobVODHLSResultPayloadValid(value as VODHLSTranscodingSuccess, type, files) ||
26 isRunnerJobVODAudioMergeResultPayloadValid(value as VODHLSTranscodingSuccess, type, files) ||
27 isRunnerJobLiveRTMPHLSResultPayloadValid(value as LiveRTMPHLSTranscodingSuccess, type) ||
28 isRunnerJobVideoStudioResultPayloadValid(value as VideoStudioTranscodingSuccess, type, files)
29}
30
31// ---------------------------------------------------------------------------
32
33function isRunnerJobProgressValid (value: string) {
34 return validator.default.isInt(value + '', RUNNER_JOBS_CONSTRAINTS_FIELDS.PROGRESS)
35}
36
37function isRunnerJobUpdatePayloadValid (value: RunnerJobUpdatePayload, type: RunnerJobType, files: UploadFilesForCheck) {
38 return isRunnerJobVODWebVideoUpdatePayloadValid(value, type, files) ||
39 isRunnerJobVODHLSUpdatePayloadValid(value, type, files) ||
40 isRunnerJobVideoStudioUpdatePayloadValid(value, type, files) ||
41 isRunnerJobVODAudioMergeUpdatePayloadValid(value, type, files) ||
42 isRunnerJobLiveRTMPHLSUpdatePayloadValid(value, type, files)
43}
44
45// ---------------------------------------------------------------------------
46
47function isRunnerJobTokenValid (value: string) {
48 return exists(value) && validator.default.isLength(value, RUNNER_JOBS_CONSTRAINTS_FIELDS.TOKEN)
49}
50
51function isRunnerJobAbortReasonValid (value: string) {
52 return validator.default.isLength(value, RUNNER_JOBS_CONSTRAINTS_FIELDS.REASON)
53}
54
55function isRunnerJobErrorMessageValid (value: string) {
56 return validator.default.isLength(value, RUNNER_JOBS_CONSTRAINTS_FIELDS.ERROR_MESSAGE)
57}
58
59function isRunnerJobStateValid (value: any) {
60 return exists(value) && RUNNER_JOB_STATES[value] !== undefined
61}
62
63function isRunnerJobArrayOfStateValid (value: any) {
64 return isArray(value) && value.every(v => isRunnerJobStateValid(v))
65}
66
67// ---------------------------------------------------------------------------
68
69export {
70 isRunnerJobTypeValid,
71 isRunnerJobSuccessPayloadValid,
72 isRunnerJobUpdatePayloadValid,
73 isRunnerJobTokenValid,
74 isRunnerJobErrorMessageValid,
75 isRunnerJobProgressValid,
76 isRunnerJobAbortReasonValid,
77 isRunnerJobArrayOfStateValid,
78 isRunnerJobStateValid
79}
80
81// ---------------------------------------------------------------------------
82
83function isRunnerJobVODWebVideoResultPayloadValid (
84 _value: VODWebVideoTranscodingSuccess,
85 type: RunnerJobType,
86 files: UploadFilesForCheck
87) {
88 return type === 'vod-web-video-transcoding' &&
89 isFileValid({ files, field: 'payload[videoFile]', mimeTypeRegex: null, maxSize: null })
90}
91
92function isRunnerJobVODHLSResultPayloadValid (
93 _value: VODHLSTranscodingSuccess,
94 type: RunnerJobType,
95 files: UploadFilesForCheck
96) {
97 return type === 'vod-hls-transcoding' &&
98 isFileValid({ files, field: 'payload[videoFile]', mimeTypeRegex: null, maxSize: null }) &&
99 isFileValid({ files, field: 'payload[resolutionPlaylistFile]', mimeTypeRegex: null, maxSize: null })
100}
101
102function isRunnerJobVODAudioMergeResultPayloadValid (
103 _value: VODAudioMergeTranscodingSuccess,
104 type: RunnerJobType,
105 files: UploadFilesForCheck
106) {
107 return type === 'vod-audio-merge-transcoding' &&
108 isFileValid({ files, field: 'payload[videoFile]', mimeTypeRegex: null, maxSize: null })
109}
110
111function isRunnerJobLiveRTMPHLSResultPayloadValid (
112 value: LiveRTMPHLSTranscodingSuccess,
113 type: RunnerJobType
114) {
115 return type === 'live-rtmp-hls-transcoding' && (!value || (typeof value === 'object' && Object.keys(value).length === 0))
116}
117
118function isRunnerJobVideoStudioResultPayloadValid (
119 _value: VideoStudioTranscodingSuccess,
120 type: RunnerJobType,
121 files: UploadFilesForCheck
122) {
123 return type === 'video-studio-transcoding' &&
124 isFileValid({ files, field: 'payload[videoFile]', mimeTypeRegex: null, maxSize: null })
125}
126
127// ---------------------------------------------------------------------------
128
129function isRunnerJobVODWebVideoUpdatePayloadValid (
130 value: RunnerJobUpdatePayload,
131 type: RunnerJobType,
132 _files: UploadFilesForCheck
133) {
134 return type === 'vod-web-video-transcoding' &&
135 (!value || (typeof value === 'object' && Object.keys(value).length === 0))
136}
137
138function isRunnerJobVODHLSUpdatePayloadValid (
139 value: RunnerJobUpdatePayload,
140 type: RunnerJobType,
141 _files: UploadFilesForCheck
142) {
143 return type === 'vod-hls-transcoding' &&
144 (!value || (typeof value === 'object' && Object.keys(value).length === 0))
145}
146
147function isRunnerJobVODAudioMergeUpdatePayloadValid (
148 value: RunnerJobUpdatePayload,
149 type: RunnerJobType,
150 _files: UploadFilesForCheck
151) {
152 return type === 'vod-audio-merge-transcoding' &&
153 (!value || (typeof value === 'object' && Object.keys(value).length === 0))
154}
155
156function isRunnerJobLiveRTMPHLSUpdatePayloadValid (
157 value: RunnerJobUpdatePayload,
158 type: RunnerJobType,
159 files: UploadFilesForCheck
160) {
161 let result = type === 'live-rtmp-hls-transcoding' && !!value && !!files
162
163 result &&= isFileValid({ files, field: 'payload[masterPlaylistFile]', mimeTypeRegex: null, maxSize: null, optional: true })
164
165 result &&= isFileValid({
166 files,
167 field: 'payload[resolutionPlaylistFile]',
168 mimeTypeRegex: null,
169 maxSize: null,
170 optional: !value.resolutionPlaylistFilename
171 })
172
173 if (files['payload[resolutionPlaylistFile]']) {
174 result &&= isSafeFilename(value.resolutionPlaylistFilename, 'm3u8')
175 }
176
177 return result &&
178 isSafeFilename(value.videoChunkFilename, 'ts') &&
179 (
180 (
181 value.type === 'remove-chunk'
182 ) ||
183 (
184 value.type === 'add-chunk' &&
185 isFileValid({ files, field: 'payload[videoChunkFile]', mimeTypeRegex: null, maxSize: null })
186 )
187 )
188}
189
190function isRunnerJobVideoStudioUpdatePayloadValid (
191 value: RunnerJobUpdatePayload,
192 type: RunnerJobType,
193 _files: UploadFilesForCheck
194) {
195 return type === 'video-studio-transcoding' &&
196 (!value || (typeof value === 'object' && Object.keys(value).length === 0))
197}