import { headers } from 'next/headers'; import { notFound, redirect } from 'next/navigation'; import { match } from 'ts-pattern'; import { DOCUMENSO_ENCRYPTION_KEY } from '@documenso/lib/constants/crypto'; import { DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/constants/date-formats'; import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer'; import { DEFAULT_DOCUMENT_TIME_ZONE } from '@documenso/lib/constants/time-zones'; import { getServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session'; import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token'; import { viewedDocument } from '@documenso/lib/server-only/document/viewed-document'; import { getFieldsForToken } from '@documenso/lib/server-only/field/get-fields-for-token'; import { getRecipientByToken } from '@documenso/lib/server-only/recipient/get-recipient-by-token'; import { getRecipientSignatures } from '@documenso/lib/server-only/recipient/get-recipient-signatures'; import { symmetricDecrypt } from '@documenso/lib/universal/crypto'; import { extractNextHeaderRequestMetadata } from '@documenso/lib/universal/extract-request-metadata'; import { DocumentStatus, FieldType, RecipientRole, SigningStatus } from '@documenso/prisma/client'; import { Card, CardContent } from '@documenso/ui/primitives/card'; import { ElementVisible } from '@documenso/ui/primitives/element-visible'; import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer'; import { truncateTitle } from '~/helpers/truncate-title'; import { DateField } from './date-field'; import { EmailField } from './email-field'; import { SigningForm } from './form'; import { NameField } from './name-field'; import { NoLongerAvailable } from './no-longer-available'; import { SigningProvider } from './provider'; import { SignatureField } from './signature-field'; import { TextField } from './text-field'; export type SigningPageProps = { params: { token?: string; }; }; export default async function SigningPage({ params: { token } }: SigningPageProps) { if (!token) { return notFound(); } const requestHeaders = Object.fromEntries(headers().entries()); const requestMetadata = extractNextHeaderRequestMetadata(requestHeaders); const [document, fields, recipient] = await Promise.all([ getDocumentAndSenderByToken({ token, }).catch(() => null), getFieldsForToken({ token }), getRecipientByToken({ token }).catch(() => null), viewedDocument({ token, requestMetadata }).catch(() => null), ]); if (!document || !document.documentData || !recipient) { return notFound(); } const truncatedTitle = truncateTitle(document.title); const { documentData, documentMeta } = document; const { user } = await getServerComponentSession(); if ( document.status === DocumentStatus.COMPLETED || recipient.signingStatus === SigningStatus.SIGNED ) { documentMeta?.redirectUrl ? redirect(documentMeta.redirectUrl) : redirect(`/sign/${token}/complete`); } if (documentMeta?.password) { const key = DOCUMENSO_ENCRYPTION_KEY; if (!key) { throw new Error('Missing DOCUMENSO_ENCRYPTION_KEY'); } const securePassword = Buffer.from( symmetricDecrypt({ key, data: documentMeta.password, }), ).toString('utf-8'); documentMeta.password = securePassword; } const [recipientSignature] = await getRecipientSignatures({ recipientId: recipient.id }); if (document.deletedAt) { return ( ); } return ( {truncatedTitle} {document.User.name} ({document.User.email}) has invited you to{' '} {recipient.role === RecipientRole.VIEWER && 'view'} {recipient.role === RecipientRole.SIGNER && 'sign'} {recipient.role === RecipientRole.APPROVER && 'approve'} this document. {fields.map((field) => match(field.type) .with(FieldType.SIGNATURE, () => ( )) .with(FieldType.NAME, () => ( )) .with(FieldType.DATE, () => ( )) .with(FieldType.EMAIL, () => ( )) .with(FieldType.TEXT, () => ( )) .otherwise(() => null), )} ); }
{document.User.name} ({document.User.email}) has invited you to{' '} {recipient.role === RecipientRole.VIEWER && 'view'} {recipient.role === RecipientRole.SIGNER && 'sign'} {recipient.role === RecipientRole.APPROVER && 'approve'} this document.