fix: unwrap webhook payload before test and resend (#2710)

This commit is contained in:
Ephraim Duncan
2026-04-22 05:42:16 +00:00
committed by GitHub
parent d38d703fd3
commit e5da5bca38
3 changed files with 29 additions and 18 deletions
@@ -32,7 +32,7 @@ export const triggerTestWebhook = async ({
try {
await triggerWebhook({
event,
data: samplePayload,
data: samplePayload.payload,
userId,
teamId,
});
+22 -16
View File
@@ -1,4 +1,4 @@
import type { DocumentMeta, Envelope, Recipient, WebhookTriggerEvents } from '@prisma/client';
import type { DocumentMeta, Envelope, Recipient } from '@prisma/client';
import {
DocumentDistributionMethod,
DocumentSigningOrder,
@@ -10,6 +10,7 @@ import {
RecipientRole,
SendStatus,
SigningStatus,
WebhookTriggerEvents,
} from '@prisma/client';
import { z } from 'zod';
@@ -25,10 +26,10 @@ export const ZWebhookRecipientSchema = z.object({
email: z.string(),
name: z.string(),
token: z.string(),
documentDeletedAt: z.date().nullable(),
expiresAt: z.date().nullable(),
expirationNotifiedAt: z.date().nullable(),
signedAt: z.date().nullable(),
documentDeletedAt: z.coerce.date().nullable(),
expiresAt: z.coerce.date().nullable(),
expirationNotifiedAt: z.coerce.date().nullable(),
signedAt: z.coerce.date().nullable(),
authOptions: z.any().nullable(),
signingOrder: z.number().nullable(),
rejectionReason: z.string().nullable(),
@@ -70,10 +71,10 @@ export const ZWebhookDocumentSchema = z.object({
visibility: z.nativeEnum(DocumentVisibility),
title: z.string(),
status: z.nativeEnum(DocumentStatus),
createdAt: z.date(),
updatedAt: z.date(),
completedAt: z.date().nullable(),
deletedAt: z.date().nullable(),
createdAt: z.coerce.date(),
updatedAt: z.coerce.date(),
completedAt: z.coerce.date().nullable(),
deletedAt: z.coerce.date().nullable(),
teamId: z.number().nullable(),
templateId: z.number().nullable(),
source: z.nativeEnum(DocumentSource),
@@ -86,15 +87,20 @@ export const ZWebhookDocumentSchema = z.object({
Recipient: z.array(ZWebhookRecipientSchema),
});
/**
* Schema for the full webhook delivery envelope (what receivers see on the wire
* and what is persisted to `WebhookCall.requestBody`).
*/
export const ZWebhookPayloadSchema = z.object({
event: z.nativeEnum(WebhookTriggerEvents),
payload: ZWebhookDocumentSchema,
createdAt: z.string(),
webhookEndpoint: z.string(),
});
export type TWebhookRecipient = z.infer<typeof ZWebhookRecipientSchema>;
export type TWebhookDocument = z.infer<typeof ZWebhookDocumentSchema>;
export type WebhookPayload = {
event: WebhookTriggerEvents;
payload: TWebhookDocument;
createdAt: string;
webhookEndpoint: string;
};
export type WebhookPayload = z.infer<typeof ZWebhookPayloadSchema>;
export const mapEnvelopeToWebhookDocumentPayload = (
envelope: Envelope & {
@@ -1,6 +1,7 @@
import { TEAM_MEMBER_ROLE_PERMISSIONS_MAP } from '@documenso/lib/constants/teams';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { jobs } from '@documenso/lib/jobs/client';
import { ZWebhookPayloadSchema } from '@documenso/lib/types/webhook-payload';
import { buildTeamWhereQuery } from '@documenso/lib/utils/teams';
import { prisma } from '@documenso/prisma';
@@ -39,12 +40,16 @@ export const resendWebhookCallRoute = authenticatedProcedure
throw new AppError(AppErrorCode.NOT_FOUND);
}
// `requestBody` stores the full delivery envelope; unwrap to the inner
// document so the handler doesn't wrap it a second time.
const { payload: data } = ZWebhookPayloadSchema.parse(webhookCall.requestBody);
await jobs.triggerJob({
name: 'internal.execute-webhook',
payload: {
event: webhookCall.event,
webhookId,
data: webhookCall.requestBody,
data,
},
});
});