diff --git a/packages/trpc/server/admin-router/router.ts b/packages/trpc/server/admin-router/router.ts index b37510be7..05ee84736 100644 --- a/packages/trpc/server/admin-router/router.ts +++ b/packages/trpc/server/admin-router/router.ts @@ -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.', diff --git a/packages/trpc/server/api-token-router/router.ts b/packages/trpc/server/api-token-router/router.ts index 14e75e001..55129f029 100644 --- a/packages/trpc/server/api-token-router/router.ts +++ b/packages/trpc/server/api-token-router/router.ts @@ -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.', diff --git a/packages/trpc/server/document-router/router.ts b/packages/trpc/server/document-router/router.ts index 4a6f11e60..6e7e8764f 100644 --- a/packages/trpc/server/document-router/router.ts +++ b/packages/trpc/server/document-router/router.ts @@ -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.', diff --git a/packages/trpc/server/field-router/router.ts b/packages/trpc/server/field-router/router.ts index 4b299b6a1..354e937a5 100644 --- a/packages/trpc/server/field-router/router.ts +++ b/packages/trpc/server/field-router/router.ts @@ -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 diff --git a/packages/trpc/server/profile-router/router.ts b/packages/trpc/server/profile-router/router.ts index 542ac2807..eb5f54274 100644 --- a/packages/trpc/server/profile-router/router.ts +++ b/packages/trpc/server/profile-router/router.ts @@ -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) { diff --git a/packages/trpc/server/singleplayer-router/router.ts b/packages/trpc/server/singleplayer-router/router.ts index 2095d7d42..33b125110 100644 --- a/packages/trpc/server/singleplayer-router/router.ts +++ b/packages/trpc/server/singleplayer-router/router.ts @@ -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; + } }), }); diff --git a/packages/trpc/server/template-router/router.ts b/packages/trpc/server/template-router/router.ts index 2dd4d51c8..4ed567b2b 100644 --- a/packages/trpc/server/template-router/router.ts +++ b/packages/trpc/server/template-router/router.ts @@ -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.', diff --git a/packages/trpc/server/webhook-router/router.ts b/packages/trpc/server/webhook-router/router.ts index 08b1b9bce..d1479457b 100644 --- a/packages/trpc/server/webhook-router/router.ts +++ b/packages/trpc/server/webhook-router/router.ts @@ -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.',