diff --git a/apps/web/src/pages/api/jobs/[[...handler]].ts b/apps/web/src/pages/api/jobs/[[...handler]].ts index 7b4d1087f..13d082d66 100644 --- a/apps/web/src/pages/api/jobs/[[...handler]].ts +++ b/apps/web/src/pages/api/jobs/[[...handler]].ts @@ -1,5 +1,4 @@ import { jobsClient } from '@documenso/lib/jobs/client'; -import '@documenso/lib/jobs/definitions'; export const config = { maxDuration: 300, diff --git a/packages/lib/jobs/client/_internal/job.ts b/packages/lib/jobs/client/_internal/job.ts index c2bee58c5..7e0a202bf 100644 --- a/packages/lib/jobs/client/_internal/job.ts +++ b/packages/lib/jobs/client/_internal/job.ts @@ -5,16 +5,14 @@ import type { Json } from './json'; export const ZTriggerJobOptionsSchema = z.object({ id: z.string().optional(), name: z.string(), - payload: z.any().refine((x) => x !== undefined, { message: 'payload is required' }), + payload: z.unknown().refine((x) => x !== undefined, { message: 'payload is required' }), timestamp: z.number().optional(), }); // The Omit is a temporary workaround for a "bug" in the zod library // @see: https://github.com/colinhacks/zod/issues/2966 export type TriggerJobOptions = Omit, 'payload'> & { - // Don't tell the feds - // eslint-disable-next-line @typescript-eslint/no-explicit-any - payload: any; + payload: unknown; }; // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/packages/lib/jobs/client/local.ts b/packages/lib/jobs/client/local.ts index e48e69f5d..6a7f99c60 100644 --- a/packages/lib/jobs/client/local.ts +++ b/packages/lib/jobs/client/local.ts @@ -9,7 +9,12 @@ import { BackgroundJobStatus, Prisma } from '@documenso/prisma/client'; import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app'; import { sign } from '../../server-only/crypto/sign'; import { verify } from '../../server-only/crypto/verify'; -import type { JobDefinition, JobRunIO, TriggerJobOptions } from './_internal/job'; +import { + type JobDefinition, + type JobRunIO, + type TriggerJobOptions, + ZTriggerJobOptionsSchema, +} from './_internal/job'; import type { Json } from './_internal/json'; import { BaseJobProvider } from './base'; @@ -59,7 +64,8 @@ export class LocalJobProvider extends BaseJobProvider { jobId: job.id, name: job.name, version: job.version, - payload: options.payload, + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + payload: options.payload as Prisma.InputJsonValue, }, }); @@ -80,7 +86,16 @@ export class LocalJobProvider extends BaseJobProvider { const isRetry = req.headers['x-job-retry'] !== undefined; // eslint-disable-next-line @typescript-eslint/consistent-type-assertions - const options = (await json(req)) as TriggerJobOptions; + const options = await json(req) + .then(async (data) => ZTriggerJobOptionsSchema.parseAsync(data)) + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions + .then((data) => data as TriggerJobOptions) + .catch(() => null); + + if (!options) { + res.status(400).send('Bad request'); + return; + } const definition = this._jobDefinitions[options.name];