diff --git a/apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx b/apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx index 214c5af99..848ff17cc 100644 --- a/apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx +++ b/apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx @@ -57,7 +57,7 @@ export const DesktopNav = ({ className, ...props }: DesktopNavProps) => { )} > - API Token + API Tokens diff --git a/apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx b/apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx index ce61ba97d..7482c2f10 100644 --- a/apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx +++ b/apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx @@ -60,7 +60,7 @@ export const MobileNav = ({ className, ...props }: MobileNavProps) => { )} > - API Token + API Tokens diff --git a/apps/web/src/pages/api/v1/[...ts-rest].tsx b/apps/web/src/pages/api/v1/[...ts-rest].tsx index b8e36340b..96e1584a1 100644 --- a/apps/web/src/pages/api/v1/[...ts-rest].tsx +++ b/apps/web/src/pages/api/v1/[...ts-rest].tsx @@ -1,12 +1,14 @@ import type { NextApiRequest, NextApiResponse } from 'next'; -import { createDocumentData } from '@documenso/lib/server-only/document-data/create-document-data'; -import { createDocument } from '@documenso/lib/server-only/document/create-document'; +import { upsertDocumentMeta } from '@documenso/lib/server-only/document-meta/upsert-document-meta'; import { deleteDocument } from '@documenso/lib/server-only/document/delete-document'; +import { findDocuments } from '@documenso/lib/server-only/document/find-documents'; import { getDocumentById } from '@documenso/lib/server-only/document/get-document-by-id'; -import { getDocuments } from '@documenso/lib/server-only/public-api/get-documents'; +import { sendDocument } from '@documenso/lib/server-only/document/send-document'; +import { setFieldsForDocument } from '@documenso/lib/server-only/field/set-fields-for-document'; import { checkUserFromToken } from '@documenso/lib/server-only/public-api/get-user-by-token'; -import { putFile } from '@documenso/lib/universal/upload/put-file'; +import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document'; +import { getPresignPostUrl } from '@documenso/lib/universal/upload/server-actions'; import { contract } from '@documenso/trpc/api-contract/contract'; import { createNextRoute, createNextRouter } from '@documenso/trpc/server/public-api/ts-rest'; @@ -35,7 +37,7 @@ const router = createNextRoute(contract, { }; } - const { documents, totalPages } = await getDocuments({ page, perPage, userId: user.id }); + const { data: documents, totalPages } = await findDocuments({ page, perPage, userId: user.id }); return { status: 200, @@ -114,7 +116,30 @@ const router = createNextRoute(contract, { } }, createDocument: async (args) => { + const { body } = args; + + try { + const { url, key } = await getPresignPostUrl(body.fileName, body.contentType); + + return { + status: 200, + body: { + url, + key, + }, + }; + } catch (e) { + return { + status: 404, + body: { + message: 'An error has occured while uploading the file', + }, + }; + } + }, + sendDocumentForSigning: async (args) => { const { authorization } = args.headers; + const { id } = args.params; const { body } = args; const user = await validateUserToken(authorization); @@ -128,39 +153,72 @@ const router = createNextRoute(contract, { }; } + const document = await getDocumentById({ id: Number(id), userId: user.id }); + + if (!document) { + return { + status: 404, + body: { + message: 'Document not found', + }, + }; + } + + if (document.status === 'PENDING') { + return { + status: 400, + body: { + message: 'Document is already waiting for signing', + }, + }; + } + try { - const regexPattern = /filename="(.+?)"/; - const match = body.toString().match(regexPattern); - const documentTitle = match?.[1] ?? 'Untitled document'; - - const file = new Blob([body], { - type: 'application/pdf', + await setRecipientsForDocument({ + userId: user.id, + documentId: Number(id), + recipients: [ + { + email: body.signerEmail, + name: body.signerName ?? '', + }, + ], }); - const { type, data } = await putFile(file); - - const { id: documentDataId } = await createDocumentData({ - type, - data, + await setFieldsForDocument({ + documentId: Number(id), + userId: user.id, + fields: body.fields.map((field) => ({ + signerEmail: body.signerEmail, + type: field.fieldType, + pageNumber: field.pageNumber, + pageX: field.pageX, + pageY: field.pageY, + pageWidth: field.pageWidth, + pageHeight: field.pageHeight, + })), }); - const { id } = await createDocument({ - title: documentTitle, - documentDataId, + if (body.emailBody || body.emailSubject) { + await upsertDocumentMeta({ + documentId: Number(id), + subject: body.emailSubject ?? '', + message: body.emailBody ?? '', + }); + } + + await sendDocument({ + documentId: Number(id), userId: user.id, }); return { status: 200, body: { - uploadedFile: { - id, - message: 'Document uploaded successfuly', - }, + message: 'Document sent for signing successfully', }, }; } catch (e) { - console.error(e); return { status: 500, body: { diff --git a/packages/lib/server-only/public-api/delete-api-token-by-id.ts b/packages/lib/server-only/public-api/delete-api-token-by-id.ts index af176063f..398288006 100644 --- a/packages/lib/server-only/public-api/delete-api-token-by-id.ts +++ b/packages/lib/server-only/public-api/delete-api-token-by-id.ts @@ -6,7 +6,7 @@ export type DeleteTokenByIdOptions = { }; export const deleteTokenById = async ({ id, userId }: DeleteTokenByIdOptions) => { - return prisma.apiToken.delete({ + return await prisma.apiToken.delete({ where: { id, userId, diff --git a/packages/lib/server-only/public-api/get-documents.ts b/packages/lib/server-only/public-api/get-documents.ts deleted file mode 100644 index deea612e8..000000000 --- a/packages/lib/server-only/public-api/get-documents.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { prisma } from '@documenso/prisma'; - -type GetDocumentsProps = { - page: number; - perPage: number; - userId: number; -}; - -export const getDocuments = async ({ page = 1, perPage = 10, userId }: GetDocumentsProps) => { - const [documents, count] = await Promise.all([ - await prisma.document.findMany({ - where: { - userId, - }, - take: perPage, - skip: Math.max(page - 1, 0) * perPage, - }), - await prisma.document.count(), - ]); - - return { - documents, - totalPages: Math.ceil(count / perPage), - }; -}; diff --git a/packages/trpc/api-contract/schema.ts b/packages/trpc/api-contract/schema.ts index 504fa55b2..d62d50d52 100644 --- a/packages/trpc/api-contract/schema.ts +++ b/packages/trpc/api-contract/schema.ts @@ -38,10 +38,8 @@ export const SendDocumentForSigningMutationSchema = z.object({ }); export const UploadDocumentSuccessfulSchema = z.object({ - uploadedFile: z.object({ - url: z.string(), - key: z.string(), - }), + url: z.string(), + key: z.string(), }); export const CreateDocumentMutationSchema = z.object({ diff --git a/packages/trpc/server/api-token-router/router.ts b/packages/trpc/server/api-token-router/router.ts index 266c045d0..bae094456 100644 --- a/packages/trpc/server/api-token-router/router.ts +++ b/packages/trpc/server/api-token-router/router.ts @@ -23,6 +23,7 @@ export const apiTokenRouter = router({ }); } }), + getTokenById: authenticatedProcedure .input(ZGetApiTokenByIdQuerySchema) .query(async ({ input, ctx }) => { @@ -40,6 +41,7 @@ export const apiTokenRouter = router({ }); } }), + createToken: authenticatedProcedure .input(ZCreateTokenMutationSchema) .mutation(async ({ input, ctx }) => { @@ -56,6 +58,7 @@ export const apiTokenRouter = router({ }); } }), + deleteTokenById: authenticatedProcedure .input(ZDeleteTokenByIdMutationSchema) .mutation(async ({ input, ctx }) => {