mirror of
https://github.com/documenso/documenso.git
synced 2026-07-26 01:45:08 +10:00
feat: validate signers have signature fields before distribution (#2411)
API users were inadvertently sending documents without signature fields, causing confusion for recipients and breaking their signing flows. - Add getRecipientsWithMissingFields helper in recipients.ts - Add server-side validation in sendDocument to block distribution - Fix v1 API to return 400 instead of 500 for validation errors - Consolidate UI signature field checks to use isSignatureFieldType - Add E2E tests for both v1 and v2 APIs
This commit is contained in:
@@ -2,9 +2,40 @@ import type { Envelope } from '@prisma/client';
|
||||
import { type Field, type Recipient, RecipientRole, SigningStatus } from '@prisma/client';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { isSignatureFieldType } from '@documenso/prisma/guards/is-signature-field';
|
||||
|
||||
import { NEXT_PUBLIC_WEBAPP_URL } from '../constants/app';
|
||||
import { extractLegacyIds } from '../universal/id';
|
||||
|
||||
/**
|
||||
* Roles that require fields to be assigned before a document can be distributed.
|
||||
*
|
||||
* Currently only SIGNER requires a signature field.
|
||||
*/
|
||||
export const RECIPIENT_ROLES_THAT_REQUIRE_FIELDS = [RecipientRole.SIGNER] as const;
|
||||
|
||||
/**
|
||||
* Returns recipients who are missing required fields for their role.
|
||||
*
|
||||
* Currently only SIGNERs are validated - they must have at least one signature field.
|
||||
*/
|
||||
export const getRecipientsWithMissingFields = <T extends Pick<Recipient, 'id' | 'role'>>(
|
||||
recipients: T[],
|
||||
fields: Pick<Field, 'type' | 'recipientId'>[],
|
||||
): T[] => {
|
||||
return recipients.filter((recipient) => {
|
||||
if (recipient.role === RecipientRole.SIGNER) {
|
||||
const hasSignatureField = fields.some(
|
||||
(field) => field.recipientId === recipient.id && isSignatureFieldType(field.type),
|
||||
);
|
||||
|
||||
return !hasSignatureField;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
export const formatSigningLink = (token: string) => `${NEXT_PUBLIC_WEBAPP_URL()}/sign/${token}`;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user