fix: add logging for errors on sign or complete (#3149)

This commit is contained in:
Lucas Smith
2026-08-05 08:12:55 +10:00
committed by GitHub
parent 9c27ce6d18
commit 8bfcec8ee6
2 changed files with 94 additions and 60 deletions
+47 -24
View File
@@ -1,3 +1,4 @@
import { AppError } from '@documenso/lib/errors/app-error';
import { createEnvelopeFields } from '@documenso/lib/server-only/field/create-envelope-fields'; import { createEnvelopeFields } from '@documenso/lib/server-only/field/create-envelope-fields';
import { deleteDocumentField } from '@documenso/lib/server-only/field/delete-document-field'; import { deleteDocumentField } from '@documenso/lib/server-only/field/delete-document-field';
import { deleteTemplateField } from '@documenso/lib/server-only/field/delete-template-field'; import { deleteTemplateField } from '@documenso/lib/server-only/field/delete-template-field';
@@ -613,23 +614,34 @@ export const fieldRouter = router({
* @private * @private
*/ */
signFieldWithToken: procedure.input(ZSignFieldWithTokenMutationSchema).mutation(async ({ input, ctx }) => { signFieldWithToken: procedure.input(ZSignFieldWithTokenMutationSchema).mutation(async ({ input, ctx }) => {
const { token, fieldId, value, isBase64, authOptions } = input; try {
const { token, fieldId, value, isBase64, authOptions } = input;
ctx.logger.info({ ctx.logger.info({
input: { input: {
fieldId,
},
});
return await signFieldWithToken({
token,
fieldId, fieldId,
}, value: value ?? '',
}); isBase64,
userId: ctx.user?.id,
authOptions,
requestMetadata: ctx.metadata.requestMetadata,
});
} catch (err) {
// Log the error for debugging purposes.
ctx.logger.error({
message: 'Error signing field with token',
error: err instanceof AppError ? `[${err.code}]: ${err.message}` : err,
});
return await signFieldWithToken({ // Rethrow the error so that the client receives the appropriate error response.
token, throw err;
fieldId, }
value: value ?? '',
isBase64,
userId: ctx.user?.id,
authOptions,
requestMetadata: ctx.metadata.requestMetadata,
});
}), }),
/** /**
@@ -638,18 +650,29 @@ export const fieldRouter = router({
removeSignedFieldWithToken: procedure removeSignedFieldWithToken: procedure
.input(ZRemovedSignedFieldWithTokenMutationSchema) .input(ZRemovedSignedFieldWithTokenMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
const { token, fieldId } = input; try {
const { token, fieldId } = input;
ctx.logger.info({ ctx.logger.info({
input: { input: {
fieldId,
},
});
return await removeSignedFieldWithToken({
token,
fieldId, fieldId,
}, requestMetadata: ctx.metadata.requestMetadata,
}); });
} catch (err) {
// Log the error for debugging purposes.
ctx.logger.error({
message: 'Error removing signed field with token',
error: err instanceof AppError ? `[${err.code}]: ${err.message}` : err,
});
return await removeSignedFieldWithToken({ // Rethrow the error so that the client receives the appropriate error response.
token, throw err;
fieldId, }
requestMetadata: ctx.metadata.requestMetadata,
});
}), }),
}); });
+47 -36
View File
@@ -1,4 +1,5 @@
import { prepareCscRecipientSigning } from '@documenso/ee/server-only/signing/csc/prepare-recipient-signing'; import { prepareCscRecipientSigning } from '@documenso/ee/server-only/signing/csc/prepare-recipient-signing';
import { AppError } from '@documenso/lib/errors/app-error';
import { completeDocumentWithToken } from '@documenso/lib/server-only/document/complete-document-with-token'; import { completeDocumentWithToken } from '@documenso/lib/server-only/document/complete-document-with-token';
import { rejectDocumentWithToken } from '@documenso/lib/server-only/document/reject-document-with-token'; import { rejectDocumentWithToken } from '@documenso/lib/server-only/document/reject-document-with-token';
import { createEnvelopeRecipients } from '@documenso/lib/server-only/recipient/create-envelope-recipients'; import { createEnvelopeRecipients } from '@documenso/lib/server-only/recipient/create-envelope-recipients';
@@ -11,7 +12,6 @@ import { isTspEnvelope } from '@documenso/lib/types/signature-level';
import { unsafeBuildEnvelopeIdQuery } from '@documenso/lib/utils/envelope'; import { unsafeBuildEnvelopeIdQuery } from '@documenso/lib/utils/envelope';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import { EnvelopeType } from '@prisma/client'; import { EnvelopeType } from '@prisma/client';
import { ZGenericSuccessResponse, ZSuccessResponseSchema } from '../schema'; import { ZGenericSuccessResponse, ZSuccessResponseSchema } from '../schema';
import { authenticatedProcedure, procedure, router } from '../trpc'; import { authenticatedProcedure, procedure, router } from '../trpc';
import { findRecipientSuggestionsRoute } from './find-recipient-suggestions'; import { findRecipientSuggestionsRoute } from './find-recipient-suggestions';
@@ -590,47 +590,58 @@ export const recipientRouter = router({
.input(ZCompleteDocumentWithTokenMutationSchema) .input(ZCompleteDocumentWithTokenMutationSchema)
.output(ZCompleteDocumentWithTokenResponseSchema) .output(ZCompleteDocumentWithTokenResponseSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
const { token, documentId, accessAuthOptions, nextSigner, recipientOverride } = input; try {
const { token, documentId, accessAuthOptions, nextSigner, recipientOverride } = input;
ctx.logger.info({ ctx.logger.info({
input: { input: {
documentId, documentId,
}, },
}); });
// Branch on TSP envelopes before any SES side effects: TSP recipients // Branch on TSP envelopes before any SES side effects: TSP recipients
// can't complete via this route — they go through the CSC sync sign // can't complete via this route — they go through the CSC sync sign
// flow (`enterprise.csc.signEnvelope`). This route returns the redirect URL // flow (`enterprise.csc.signEnvelope`). This route returns the redirect URL
// for the credential-scope OAuth round-trip. // for the credential-scope OAuth round-trip.
const envelope = await prisma.envelope.findFirstOrThrow({ const envelope = await prisma.envelope.findFirstOrThrow({
where: { where: {
...unsafeBuildEnvelopeIdQuery({ type: 'documentId', id: documentId }, EnvelopeType.DOCUMENT), ...unsafeBuildEnvelopeIdQuery({ type: 'documentId', id: documentId }, EnvelopeType.DOCUMENT),
recipients: { some: { token } }, recipients: { some: { token } },
}, },
select: { signatureLevel: true, internalVersion: true }, select: { signatureLevel: true, internalVersion: true },
}); });
if (isTspEnvelope(envelope)) { if (isTspEnvelope(envelope)) {
return await prepareCscRecipientSigning({ return await prepareCscRecipientSigning({
recipientToken: token, recipientToken: token,
requestMetadata: ctx.metadata.requestMetadata,
});
}
await completeDocumentWithToken({
token,
id: {
type: 'documentId',
id: documentId,
},
accessAuthOptions,
nextSigner,
recipientOverride,
userId: ctx.user?.id,
requestMetadata: ctx.metadata.requestMetadata, requestMetadata: ctx.metadata.requestMetadata,
}); });
return { status: 'SIGNED' as const };
} catch (err) {
// Log the error for debugging purposes.
ctx.logger.error({
message: 'Error completing document with token',
error: err instanceof AppError ? `[${err.code}]: ${err.message}` : err,
});
// Rethrow the error so that the client receives the appropriate error response.
throw err;
} }
await completeDocumentWithToken({
token,
id: {
type: 'documentId',
id: documentId,
},
accessAuthOptions,
nextSigner,
recipientOverride,
userId: ctx.user?.id,
requestMetadata: ctx.metadata.requestMetadata,
});
return { status: 'SIGNED' as const };
}), }),
/** /**