mirror of
https://github.com/documenso/documenso.git
synced 2025-11-10 04:22:32 +10:00
fix: improve error log coverage
This commit is contained in:
@ -29,6 +29,8 @@ export const adminRouter = router({
|
||||
try {
|
||||
return await findDocuments({ term, page, perPage });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to retrieve the documents. Please try again.',
|
||||
@ -44,6 +46,8 @@ export const adminRouter = router({
|
||||
try {
|
||||
return await updateUser({ id, name, email, roles });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to retrieve the specified account. Please try again.',
|
||||
@ -59,6 +63,8 @@ export const adminRouter = router({
|
||||
try {
|
||||
return await updateRecipient({ id, name, email });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to update the recipient provided.',
|
||||
@ -79,6 +85,8 @@ export const adminRouter = router({
|
||||
userId: ctx.user.id,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to update the site setting provided.',
|
||||
@ -95,6 +103,7 @@ export const adminRouter = router({
|
||||
return await sealDocument({ documentId: id, isResealing: true });
|
||||
} catch (err) {
|
||||
console.log('resealDocument error', err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to reseal the document provided.',
|
||||
|
||||
@ -16,7 +16,9 @@ export const apiTokenRouter = router({
|
||||
getTokens: authenticatedProcedure.query(async ({ ctx }) => {
|
||||
try {
|
||||
return await getUserTokens({ userId: ctx.user.id });
|
||||
} catch (e) {
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to find your API tokens. Please try again.',
|
||||
@ -34,7 +36,9 @@ export const apiTokenRouter = router({
|
||||
id,
|
||||
userId: ctx.user.id,
|
||||
});
|
||||
} catch (e) {
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to find this API token. Please try again.',
|
||||
@ -54,7 +58,9 @@ export const apiTokenRouter = router({
|
||||
tokenName,
|
||||
expiresIn: expirationDate,
|
||||
});
|
||||
} catch (e) {
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to create an API token. Please try again.',
|
||||
@ -73,7 +79,9 @@ export const apiTokenRouter = router({
|
||||
teamId,
|
||||
userId: ctx.user.id,
|
||||
});
|
||||
} catch (e) {
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to delete this API Token. Please try again.',
|
||||
|
||||
@ -115,6 +115,8 @@ export const documentRouter = router({
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
if (err instanceof TRPCError) {
|
||||
throw err;
|
||||
}
|
||||
@ -222,13 +224,19 @@ export const documentRouter = router({
|
||||
|
||||
const userId = ctx.user.id;
|
||||
|
||||
return await updateTitle({
|
||||
title,
|
||||
userId,
|
||||
teamId,
|
||||
documentId,
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
try {
|
||||
return await updateTitle({
|
||||
title,
|
||||
userId,
|
||||
teamId,
|
||||
documentId,
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw err;
|
||||
}
|
||||
}),
|
||||
|
||||
setPasswordForDocument: authenticatedProcedure
|
||||
@ -347,7 +355,9 @@ export const documentRouter = router({
|
||||
userId: ctx.user.id,
|
||||
});
|
||||
return documents;
|
||||
} catch (error) {
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We are unable to search for documents. Please try again later.',
|
||||
|
||||
@ -52,20 +52,26 @@ export const fieldRouter = router({
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
const { templateId, fields } = input;
|
||||
|
||||
await setFieldsForTemplate({
|
||||
userId: ctx.user.id,
|
||||
templateId,
|
||||
fields: fields.map((field) => ({
|
||||
id: field.nativeId,
|
||||
signerEmail: field.signerEmail,
|
||||
type: field.type,
|
||||
pageNumber: field.pageNumber,
|
||||
pageX: field.pageX,
|
||||
pageY: field.pageY,
|
||||
pageWidth: field.pageWidth,
|
||||
pageHeight: field.pageHeight,
|
||||
})),
|
||||
});
|
||||
try {
|
||||
await setFieldsForTemplate({
|
||||
userId: ctx.user.id,
|
||||
templateId,
|
||||
fields: fields.map((field) => ({
|
||||
id: field.nativeId,
|
||||
signerEmail: field.signerEmail,
|
||||
type: field.type,
|
||||
pageNumber: field.pageNumber,
|
||||
pageX: field.pageX,
|
||||
pageY: field.pageY,
|
||||
pageWidth: field.pageWidth,
|
||||
pageHeight: field.pageHeight,
|
||||
})),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw err;
|
||||
}
|
||||
}),
|
||||
|
||||
signFieldWithToken: procedure
|
||||
|
||||
@ -37,6 +37,8 @@ export const profileRouter = router({
|
||||
...input,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to find user security audit logs. Please try again.',
|
||||
@ -50,6 +52,8 @@ export const profileRouter = router({
|
||||
|
||||
return await getUserById({ id });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to retrieve the specified account. Please try again.',
|
||||
@ -108,6 +112,8 @@ export const profileRouter = router({
|
||||
|
||||
return { success: true, url: user.url };
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
const error = AppError.parseError(err);
|
||||
|
||||
if (error.code !== AppErrorCode.UNKNOWN_ERROR) {
|
||||
@ -135,6 +141,8 @@ export const profileRouter = router({
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
let message =
|
||||
'We were unable to update your profile. Please review the information you provided and try again.';
|
||||
|
||||
@ -171,6 +179,8 @@ export const profileRouter = router({
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
let message = 'We were unable to reset your password. Please try again.';
|
||||
|
||||
if (err instanceof Error) {
|
||||
@ -192,6 +202,8 @@ export const profileRouter = router({
|
||||
|
||||
return await sendConfirmationToken({ email });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
let message = 'We were unable to send a confirmation email. Please try again.';
|
||||
|
||||
if (err instanceof Error) {
|
||||
@ -211,6 +223,8 @@ export const profileRouter = router({
|
||||
id: ctx.user.id,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
let message = 'We were unable to delete your account. Please try again.';
|
||||
|
||||
if (err instanceof Error) {
|
||||
|
||||
@ -29,151 +29,157 @@ export const singleplayerRouter = router({
|
||||
createSinglePlayerDocument: procedure
|
||||
.input(ZCreateSinglePlayerDocumentMutationSchema)
|
||||
.mutation(async ({ input }) => {
|
||||
const { signer, fields, documentData, documentName } = input;
|
||||
try {
|
||||
const { signer, fields, documentData, documentName } = input;
|
||||
|
||||
const document = await getFile({
|
||||
data: documentData.data,
|
||||
type: documentData.type,
|
||||
});
|
||||
|
||||
const doc = await PDFDocument.load(document);
|
||||
|
||||
const createdAt = new Date();
|
||||
|
||||
const isBase64 = signer.signature.startsWith('data:image/png;base64,');
|
||||
const signatureImageAsBase64 = isBase64 ? signer.signature : null;
|
||||
const typedSignature = !isBase64 ? signer.signature : null;
|
||||
|
||||
// Update the document with the fields inserted.
|
||||
for (const field of fields) {
|
||||
const isSignatureField = field.type === FieldType.SIGNATURE;
|
||||
|
||||
await insertFieldInPDF(doc, {
|
||||
...mapField(field, signer),
|
||||
Signature: isSignatureField
|
||||
? {
|
||||
created: createdAt,
|
||||
signatureImageAsBase64,
|
||||
typedSignature,
|
||||
// Dummy data.
|
||||
id: -1,
|
||||
recipientId: -1,
|
||||
fieldId: -1,
|
||||
}
|
||||
: null,
|
||||
// Dummy data.
|
||||
id: -1,
|
||||
secondaryId: '-1',
|
||||
documentId: -1,
|
||||
templateId: null,
|
||||
recipientId: -1,
|
||||
const document = await getFile({
|
||||
data: documentData.data,
|
||||
type: documentData.type,
|
||||
});
|
||||
}
|
||||
|
||||
const unsignedPdfBytes = await doc.save();
|
||||
const doc = await PDFDocument.load(document);
|
||||
|
||||
const signedPdfBuffer = await signPdf({ pdf: Buffer.from(unsignedPdfBytes) });
|
||||
const createdAt = new Date();
|
||||
|
||||
const { token } = await prisma.$transaction(
|
||||
async (tx) => {
|
||||
const token = alphaid();
|
||||
const isBase64 = signer.signature.startsWith('data:image/png;base64,');
|
||||
const signatureImageAsBase64 = isBase64 ? signer.signature : null;
|
||||
const typedSignature = !isBase64 ? signer.signature : null;
|
||||
|
||||
// Fetch service user who will be the owner of the document.
|
||||
const serviceUser = await tx.user.findFirstOrThrow({
|
||||
where: {
|
||||
email: SERVICE_USER_EMAIL,
|
||||
},
|
||||
// Update the document with the fields inserted.
|
||||
for (const field of fields) {
|
||||
const isSignatureField = field.type === FieldType.SIGNATURE;
|
||||
|
||||
await insertFieldInPDF(doc, {
|
||||
...mapField(field, signer),
|
||||
Signature: isSignatureField
|
||||
? {
|
||||
created: createdAt,
|
||||
signatureImageAsBase64,
|
||||
typedSignature,
|
||||
// Dummy data.
|
||||
id: -1,
|
||||
recipientId: -1,
|
||||
fieldId: -1,
|
||||
}
|
||||
: null,
|
||||
// Dummy data.
|
||||
id: -1,
|
||||
secondaryId: '-1',
|
||||
documentId: -1,
|
||||
templateId: null,
|
||||
recipientId: -1,
|
||||
});
|
||||
}
|
||||
|
||||
const { id: documentDataId } = await putFile({
|
||||
name: `${documentName}.pdf`,
|
||||
type: 'application/pdf',
|
||||
arrayBuffer: async () => Promise.resolve(signedPdfBuffer),
|
||||
});
|
||||
const unsignedPdfBytes = await doc.save();
|
||||
|
||||
// Create document.
|
||||
const document = await tx.document.create({
|
||||
data: {
|
||||
title: documentName,
|
||||
status: DocumentStatus.COMPLETED,
|
||||
documentDataId,
|
||||
userId: serviceUser.id,
|
||||
createdAt,
|
||||
},
|
||||
});
|
||||
const signedPdfBuffer = await signPdf({ pdf: Buffer.from(unsignedPdfBytes) });
|
||||
|
||||
// Create recipient.
|
||||
const recipient = await tx.recipient.create({
|
||||
data: {
|
||||
documentId: document.id,
|
||||
name: signer.name,
|
||||
email: signer.email,
|
||||
token,
|
||||
signedAt: createdAt,
|
||||
readStatus: ReadStatus.OPENED,
|
||||
signingStatus: SigningStatus.SIGNED,
|
||||
sendStatus: SendStatus.SENT,
|
||||
},
|
||||
});
|
||||
const { token } = await prisma.$transaction(
|
||||
async (tx) => {
|
||||
const token = alphaid();
|
||||
|
||||
// Create fields and signatures.
|
||||
await Promise.all(
|
||||
fields.map(async (field) => {
|
||||
const insertedField = await tx.field.create({
|
||||
data: {
|
||||
documentId: document.id,
|
||||
recipientId: recipient.id,
|
||||
...mapField(field, signer),
|
||||
},
|
||||
});
|
||||
// Fetch service user who will be the owner of the document.
|
||||
const serviceUser = await tx.user.findFirstOrThrow({
|
||||
where: {
|
||||
email: SERVICE_USER_EMAIL,
|
||||
},
|
||||
});
|
||||
|
||||
if (field.type === FieldType.SIGNATURE || field.type === FieldType.FREE_SIGNATURE) {
|
||||
await tx.signature.create({
|
||||
const { id: documentDataId } = await putFile({
|
||||
name: `${documentName}.pdf`,
|
||||
type: 'application/pdf',
|
||||
arrayBuffer: async () => Promise.resolve(signedPdfBuffer),
|
||||
});
|
||||
|
||||
// Create document.
|
||||
const document = await tx.document.create({
|
||||
data: {
|
||||
title: documentName,
|
||||
status: DocumentStatus.COMPLETED,
|
||||
documentDataId,
|
||||
userId: serviceUser.id,
|
||||
createdAt,
|
||||
},
|
||||
});
|
||||
|
||||
// Create recipient.
|
||||
const recipient = await tx.recipient.create({
|
||||
data: {
|
||||
documentId: document.id,
|
||||
name: signer.name,
|
||||
email: signer.email,
|
||||
token,
|
||||
signedAt: createdAt,
|
||||
readStatus: ReadStatus.OPENED,
|
||||
signingStatus: SigningStatus.SIGNED,
|
||||
sendStatus: SendStatus.SENT,
|
||||
},
|
||||
});
|
||||
|
||||
// Create fields and signatures.
|
||||
await Promise.all(
|
||||
fields.map(async (field) => {
|
||||
const insertedField = await tx.field.create({
|
||||
data: {
|
||||
fieldId: insertedField.id,
|
||||
signatureImageAsBase64,
|
||||
typedSignature,
|
||||
documentId: document.id,
|
||||
recipientId: recipient.id,
|
||||
...mapField(field, signer),
|
||||
},
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
return { document, token };
|
||||
},
|
||||
{
|
||||
maxWait: 5000,
|
||||
timeout: 30000,
|
||||
},
|
||||
);
|
||||
if (field.type === FieldType.SIGNATURE || field.type === FieldType.FREE_SIGNATURE) {
|
||||
await tx.signature.create({
|
||||
data: {
|
||||
fieldId: insertedField.id,
|
||||
signatureImageAsBase64,
|
||||
typedSignature,
|
||||
recipientId: recipient.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
const template = createElement(DocumentSelfSignedEmailTemplate, {
|
||||
documentName: documentName,
|
||||
assetBaseUrl: NEXT_PUBLIC_WEBAPP_URL() || 'http://localhost:3000',
|
||||
});
|
||||
return { document, token };
|
||||
},
|
||||
{
|
||||
maxWait: 5000,
|
||||
timeout: 30000,
|
||||
},
|
||||
);
|
||||
|
||||
const [html, text] = await Promise.all([
|
||||
renderAsync(template),
|
||||
renderAsync(template, { plainText: true }),
|
||||
]);
|
||||
const template = createElement(DocumentSelfSignedEmailTemplate, {
|
||||
documentName: documentName,
|
||||
assetBaseUrl: NEXT_PUBLIC_WEBAPP_URL() || 'http://localhost:3000',
|
||||
});
|
||||
|
||||
// Send email to signer.
|
||||
await mailer.sendMail({
|
||||
to: {
|
||||
address: signer.email,
|
||||
name: signer.name,
|
||||
},
|
||||
from: {
|
||||
name: FROM_NAME,
|
||||
address: FROM_ADDRESS,
|
||||
},
|
||||
subject: 'Document signed',
|
||||
html,
|
||||
text,
|
||||
attachments: [{ content: signedPdfBuffer, filename: documentName }],
|
||||
});
|
||||
const [html, text] = await Promise.all([
|
||||
renderAsync(template),
|
||||
renderAsync(template, { plainText: true }),
|
||||
]);
|
||||
|
||||
return token;
|
||||
// Send email to signer.
|
||||
await mailer.sendMail({
|
||||
to: {
|
||||
address: signer.email,
|
||||
name: signer.name,
|
||||
},
|
||||
from: {
|
||||
name: FROM_NAME,
|
||||
address: FROM_ADDRESS,
|
||||
},
|
||||
subject: 'Document signed',
|
||||
html,
|
||||
text,
|
||||
attachments: [{ content: signedPdfBuffer, filename: documentName }],
|
||||
});
|
||||
|
||||
return token;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw err;
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
||||
@ -56,6 +56,8 @@ export const templateRouter = router({
|
||||
recipients: input.recipients,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to create this document. Please try again later.',
|
||||
|
||||
@ -21,6 +21,8 @@ export const webhookRouter = router({
|
||||
try {
|
||||
return await getWebhooksByUserId(ctx.user.id);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to fetch your webhooks. Please try again later.',
|
||||
@ -36,6 +38,8 @@ export const webhookRouter = router({
|
||||
try {
|
||||
return await getWebhooksByTeamId(teamId, ctx.user.id);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to fetch your webhooks. Please try again later.',
|
||||
@ -55,6 +59,8 @@ export const webhookRouter = router({
|
||||
teamId,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to fetch your webhook. Please try again later.',
|
||||
@ -77,6 +83,8 @@ export const webhookRouter = router({
|
||||
userId: ctx.user.id,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to create this webhook. Please try again later.',
|
||||
@ -96,6 +104,8 @@ export const webhookRouter = router({
|
||||
userId: ctx.user.id,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to create this webhook. Please try again later.',
|
||||
@ -116,6 +126,8 @@ export const webhookRouter = router({
|
||||
teamId,
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to create this webhook. Please try again later.',
|
||||
|
||||
Reference in New Issue
Block a user