import React from 'react'; import { redirect } from 'next/navigation'; import { msg } from '@lingui/macro'; import { useLingui } from '@lingui/react'; import { DateTime } from 'luxon'; import { match } from 'ts-pattern'; import { UAParser } from 'ua-parser-js'; import { setupI18nSSR } from '@documenso/lib/client-only/providers/i18n.server'; import { APP_I18N_OPTIONS, ZSupportedLanguageCodeSchema } from '@documenso/lib/constants/i18n'; import { RECIPIENT_ROLES_DESCRIPTION, RECIPIENT_ROLE_SIGNING_REASONS, } from '@documenso/lib/constants/recipient-roles'; import { getEntireDocument } from '@documenso/lib/server-only/admin/get-entire-document'; import { decryptSecondaryData } from '@documenso/lib/server-only/crypto/decrypt'; import { getDocumentCertificateAuditLogs } from '@documenso/lib/server-only/document/get-document-certificate-audit-logs'; import { DOCUMENT_AUDIT_LOG_TYPE } from '@documenso/lib/types/document-audit-logs'; import { extractDocumentAuthMethods } from '@documenso/lib/utils/document-auth'; import { dynamicActivate } from '@documenso/lib/utils/i18n'; import { FieldType } from '@documenso/prisma/client'; import { Card, CardContent } from '@documenso/ui/primitives/card'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@documenso/ui/primitives/table'; import { Logo } from '~/components/branding/logo'; type SigningCertificateProps = { searchParams: { d: string; }; }; const FRIENDLY_SIGNING_REASONS = { ['__OWNER__']: msg`I am the owner of this document`, ...RECIPIENT_ROLE_SIGNING_REASONS, }; /** * DO NOT USE TRANS. YOU MUST USE _ FOR THIS FILE AND ALL CHILDREN COMPONENTS. * * Cannot use dynamicActivate by itself to translate this specific page and all * children components because `not-found.tsx` page runs and overrides the i18n. */ export default async function SigningCertificate({ searchParams }: SigningCertificateProps) { const { i18n } = await setupI18nSSR(); const { _ } = useLingui(); const { d } = searchParams; if (typeof d !== 'string' || !d) { return redirect('/'); } const rawDocumentId = decryptSecondaryData(d); if (!rawDocumentId || isNaN(Number(rawDocumentId))) { return redirect('/'); } const documentId = Number(rawDocumentId); const document = await getEntireDocument({ id: documentId, }).catch(() => null); if (!document) { return redirect('/'); } const documentLanguage = ZSupportedLanguageCodeSchema.parse(document.documentMeta?.language); await dynamicActivate(i18n, documentLanguage); const auditLogs = await getDocumentCertificateAuditLogs({ id: documentId, }); const isOwner = (email: string) => { return email.toLowerCase() === document.user.email.toLowerCase(); }; const getDevice = (userAgent?: string | null) => { if (!userAgent) { return 'Unknown'; } const parser = new UAParser(userAgent); parser.setUA(userAgent); const result = parser.getResult(); return `${result.os.name} - ${result.browser.name} ${result.browser.version}`; }; const getAuthenticationLevel = (recipientId: number) => { const recipient = document.recipients.find((recipient) => recipient.id === recipientId); if (!recipient) { return 'Unknown'; } const extractedAuthMethods = extractDocumentAuthMethods({ documentAuth: document.authOptions, recipientAuth: recipient.authOptions, }); let authLevel = match(extractedAuthMethods.derivedRecipientActionAuth) .with('ACCOUNT', () => _(msg`Account Re-Authentication`)) .with('TWO_FACTOR_AUTH', () => _(msg`Two-Factor Re-Authentication`)) .with('PASSKEY', () => _(msg`Passkey Re-Authentication`)) .with('EXPLICIT_NONE', () => _(msg`Email`)) .with(null, () => null) .exhaustive(); if (!authLevel) { authLevel = match(extractedAuthMethods.derivedRecipientAccessAuth) .with('ACCOUNT', () => _(msg`Account Authentication`)) .with(null, () => _(msg`Email`)) .exhaustive(); } return authLevel; }; const getRecipientAuditLogs = (recipientId: number) => { return { [DOCUMENT_AUDIT_LOG_TYPE.EMAIL_SENT]: auditLogs[DOCUMENT_AUDIT_LOG_TYPE.EMAIL_SENT].filter( (log) => log.type === DOCUMENT_AUDIT_LOG_TYPE.EMAIL_SENT && log.data.recipientId === recipientId, ), [DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_OPENED]: auditLogs[ DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_OPENED ].filter( (log) => log.type === DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_OPENED && log.data.recipientId === recipientId, ), [DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_COMPLETED]: auditLogs[ DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_COMPLETED ].filter( (log) => log.type === DOCUMENT_AUDIT_LOG_TYPE.DOCUMENT_RECIPIENT_COMPLETED && log.data.recipientId === recipientId, ), }; }; const getRecipientSignatureField = (recipientId: number) => { return document.recipients .find((recipient) => recipient.id === recipientId) ?.fields.find( (field) => field.type === FieldType.SIGNATURE || field.type === FieldType.FREE_SIGNATURE, ); }; return (
{_(msg`Signing certificate provided by`)}: