Init commit

This commit is contained in:
ShreejitPanchal
2026-05-19 19:56:02 +08:00
commit 6601501eff
4047 changed files with 2185372 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
export * from './jobs.js'
export * from './registration-token.js'
export * from './runners.js'

View File

@@ -0,0 +1,60 @@
import express from 'express'
import { param } from 'express-validator'
import { basename } from 'path'
import { isSafeFilename } from '@server/helpers/custom-validators/misc.js'
import { hasVideoStudioTaskFile, HttpStatusCode, RunnerJobStudioTranscodingPayload } from '@peertube/peertube-models'
import { areValidationErrors, doesVideoExist, isValidVideoIdParam } from '../shared/index.js'
const tags = [ 'runner' ]
export const runnerJobGetVideoTranscodingFileValidator = [
isValidVideoIdParam('videoId'),
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
if (!await doesVideoExist(req.params.videoId, res, 'all')) return
const runnerJob = res.locals.runnerJob
if (runnerJob.privatePayload.videoUUID !== res.locals.videoAll.uuid) {
return res.fail({
status: HttpStatusCode.FORBIDDEN_403,
message: 'Job is not associated to this video',
tags: [ ...tags, res.locals.videoAll.uuid ]
})
}
return next()
}
]
export const runnerJobGetVideoStudioTaskFileValidator = [
param('filename').custom(v => isSafeFilename(v)),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res)) return
const filename = req.params.filename
const payload = res.locals.runnerJob.payload as RunnerJobStudioTranscodingPayload
const found = Array.isArray(payload?.tasks) && payload.tasks.some(t => {
if (hasVideoStudioTaskFile(t)) {
return basename(t.options.file) === filename
}
return false
})
if (!found) {
return res.fail({
status: HttpStatusCode.BAD_REQUEST_400,
message: 'File is not associated to this edition task',
tags: [ ...tags, res.locals.videoAll.uuid ]
})
}
return next()
}
]

View File

@@ -0,0 +1,200 @@
import { arrayify } from '@peertube/peertube-core-utils'
import {
HttpStatusCode,
RunnerJobState,
RunnerJobStateType,
RunnerJobSuccessBody,
RunnerJobUpdateBody,
ServerErrorCode
} from '@peertube/peertube-models'
import { exists, isUUIDValid } from '@server/helpers/custom-validators/misc.js'
import {
isRunnerJobAbortReasonValid,
isRunnerJobArrayOfStateValid,
isRunnerJobErrorMessageValid,
isRunnerJobProgressValid,
isRunnerJobSuccessPayloadValid,
isRunnerJobTokenValid,
isRunnerJobUpdatePayloadValid
} from '@server/helpers/custom-validators/runners/jobs.js'
import { isRunnerTokenValid } from '@server/helpers/custom-validators/runners/runners.js'
import { cleanUpReqFiles } from '@server/helpers/express-utils.js'
import { runnerJobCanBeCancelled } from '@server/lib/runners/index.js'
import { RunnerJobModel } from '@server/models/runner/runner-job.js'
import express from 'express'
import { body, param, query } from 'express-validator'
import { areValidationErrors } from '../shared/index.js'
const tags = [ 'runner' ]
export const acceptRunnerJobValidator = [
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (res.locals.runnerJob.state !== RunnerJobState.PENDING) {
return res.fail({
status: HttpStatusCode.BAD_REQUEST_400,
message: 'This runner job is not in pending state',
tags
})
}
return next()
}
]
export const abortRunnerJobValidator = [
body('reason').custom(isRunnerJobAbortReasonValid),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res, { tags })) return
return next()
}
]
export const updateRunnerJobValidator = [
body('progress').optional().custom(isRunnerJobProgressValid),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res, { tags })) return cleanUpReqFiles(req)
const body = req.body as RunnerJobUpdateBody
const job = res.locals.runnerJob
if (isRunnerJobUpdatePayloadValid(body.payload, job.type, req.files) !== true) {
cleanUpReqFiles(req)
return res.fail({
status: HttpStatusCode.BAD_REQUEST_400,
message: 'Payload is invalid',
tags
})
}
return next()
}
]
export const errorRunnerJobValidator = [
body('message').custom(isRunnerJobErrorMessageValid),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res, { tags })) return
return next()
}
]
export const successRunnerJobValidator = [
(req: express.Request, res: express.Response, next: express.NextFunction) => {
const body = req.body as RunnerJobSuccessBody
if (isRunnerJobSuccessPayloadValid(body.payload, res.locals.runnerJob.type, req.files) !== true) {
cleanUpReqFiles(req)
return res.fail({
status: HttpStatusCode.BAD_REQUEST_400,
message: 'Payload is invalid',
tags
})
}
return next()
}
]
export const cancelRunnerJobValidator = [
(req: express.Request, res: express.Response, next: express.NextFunction) => {
const runnerJob = res.locals.runnerJob
if (runnerJobCanBeCancelled(runnerJob) !== true) {
return res.fail({
status: HttpStatusCode.BAD_REQUEST_400,
message: 'Cannot cancel this job that is not in "pending", "processing" or "waiting for parent job" state',
tags
})
}
return next()
}
]
export const listRunnerJobsValidator = [
query('search')
.optional()
.custom(exists),
query('stateOneOf')
.optional()
.customSanitizer(arrayify)
.custom(isRunnerJobArrayOfStateValid),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
return next()
}
]
export const runnerJobGetValidator = [
param('jobUUID').custom(isUUIDValid),
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res, { tags })) return
const runnerJob = await RunnerJobModel.loadWithRunner(req.params.jobUUID)
if (!runnerJob) {
return res.fail({
status: HttpStatusCode.NOT_FOUND_404,
message: 'Unknown runner job',
tags
})
}
res.locals.runnerJob = runnerJob
return next()
}
]
export function jobOfRunnerGetValidatorFactory (allowedStates: RunnerJobStateType[]) {
return [
param('jobUUID').custom(isUUIDValid),
body('runnerToken').custom(isRunnerTokenValid),
body('jobToken').custom(isRunnerJobTokenValid),
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res, { tags })) return cleanUpReqFiles(req)
const runnerJob = await RunnerJobModel.loadByRunnerAndJobTokensWithRunner({
uuid: req.params.jobUUID,
runnerToken: req.body.runnerToken,
jobToken: req.body.jobToken
})
if (!runnerJob) {
cleanUpReqFiles(req)
return res.fail({
status: HttpStatusCode.NOT_FOUND_404,
message: 'Unknown runner job',
tags
})
}
if (!allowedStates.includes(runnerJob.state)) {
cleanUpReqFiles(req)
return res.fail({
status: HttpStatusCode.BAD_REQUEST_400,
type: ServerErrorCode.RUNNER_JOB_NOT_IN_PROCESSING_STATE,
message: 'Job is not in "processing" state',
tags
})
}
res.locals.runnerJob = runnerJob
return next()
}
]
}

View File

@@ -0,0 +1,37 @@
import express from 'express'
import { param } from 'express-validator'
import { isIdValid } from '@server/helpers/custom-validators/misc.js'
import { RunnerRegistrationTokenModel } from '@server/models/runner/runner-registration-token.js'
import { forceNumber } from '@peertube/peertube-core-utils'
import { HttpStatusCode } from '@peertube/peertube-models'
import { areValidationErrors } from '../shared/utils.js'
const tags = [ 'runner' ]
const deleteRegistrationTokenValidator = [
param('id').custom(isIdValid),
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res, { tags })) return
const registrationToken = await RunnerRegistrationTokenModel.load(forceNumber(req.params.id))
if (!registrationToken) {
return res.fail({
status: HttpStatusCode.NOT_FOUND_404,
message: 'Registration token not found',
tags
})
}
res.locals.runnerRegistrationToken = registrationToken
return next()
}
]
// ---------------------------------------------------------------------------
export {
deleteRegistrationTokenValidator
}

View File

@@ -0,0 +1,108 @@
import { forceNumber } from '@peertube/peertube-core-utils'
import { HttpStatusCode, RegisterRunnerBody, ServerErrorCode } from '@peertube/peertube-models'
import { isIdValid, isStableOrUnstableVersionValid } from '@server/helpers/custom-validators/misc.js'
import {
isRunnerDescriptionValid,
isRunnerNameValid,
isRunnerRegistrationTokenValid,
isRunnerTokenValid
} from '@server/helpers/custom-validators/runners/runners.js'
import { RunnerRegistrationTokenModel } from '@server/models/runner/runner-registration-token.js'
import { RunnerModel } from '@server/models/runner/runner.js'
import express from 'express'
import { body, param } from 'express-validator'
import { areValidationErrors } from '../shared/utils.js'
const tags = [ 'runner' ]
export const registerRunnerValidator = [
body('registrationToken').custom(isRunnerRegistrationTokenValid),
body('name').custom(isRunnerNameValid),
body('description').optional().custom(isRunnerDescriptionValid),
body('version').optional().custom(isStableOrUnstableVersionValid),
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res, { tags })) return
const body: RegisterRunnerBody = req.body
const runnerRegistrationToken = await RunnerRegistrationTokenModel.loadByRegistrationToken(body.registrationToken)
if (!runnerRegistrationToken) {
return res.fail({
status: HttpStatusCode.NOT_FOUND_404,
message: 'Registration token is invalid',
tags
})
}
const existing = await RunnerModel.loadByName(body.name)
if (existing) {
return res.fail({
status: HttpStatusCode.BAD_REQUEST_400,
message: 'This runner name already exists on this instance',
tags
})
}
res.locals.runnerRegistrationToken = runnerRegistrationToken
return next()
}
]
export const deleteRunnerValidator = [
param('runnerId').custom(isIdValid),
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res, { tags })) return
const runner = await RunnerModel.load(forceNumber(req.params.runnerId))
if (!runner) {
return res.fail({
status: HttpStatusCode.NOT_FOUND_404,
message: 'Runner not found',
tags
})
}
res.locals.runner = runner
return next()
}
]
export const getRunnerFromTokenValidator = [
body('runnerToken').custom(isRunnerTokenValid),
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res, { tags })) return
const runner = await RunnerModel.loadByToken(req.body.runnerToken)
if (!runner) {
return res.fail({
status: HttpStatusCode.NOT_FOUND_404,
message: 'Unknown runner token',
type: ServerErrorCode.UNKNOWN_RUNNER_TOKEN,
tags
})
}
res.locals.runner = runner
return next()
}
]
export const requestRunnerJobValidator = [
body('version').optional().custom(isStableOrUnstableVersionValid),
body('jobTypes').optional().isArray(),
(req: express.Request, res: express.Response, next: express.NextFunction) => {
if (areValidationErrors(req, res, { tags })) return
return next()
}
]