chore: merge main, resolve biome formatting conflicts

Merge origin/main into feat/external-2fa-codes. Resolve formatting
conflicts caused by biome rollout; preserve both feature streams:
PR's external 2FA token + signing-session 2FA proof additions plus
main's RateLimit/RecipientExpired/signingReminders/date-auto-insert.

In complete-document-with-token.ts, drop the duplicate early
field-fetching block introduced when main moved that logic later
with date auto-insert support; keep the EXTERNAL_TWO_FACTOR_AUTH
check using derivedRecipientActionAuth.
This commit is contained in:
ephraimduncan
2026-05-12 11:46:11 +00:00
parent 9194884fbe
commit 138d663c25
1959 changed files with 93488 additions and 47038 deletions
@@ -1,13 +1,3 @@
import { useState } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';
import { flushSync } from 'react-dom';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { authClient } from '@documenso/auth/client';
import { useSession } from '@documenso/lib/client-only/providers/session';
import { Button } from '@documenso/ui/primitives/button';
@@ -20,17 +10,18 @@ import {
DialogTitle,
DialogTrigger,
} from '@documenso/ui/primitives/dialog';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@documenso/ui/primitives/form/form';
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form';
import { Input } from '@documenso/ui/primitives/input';
import { PinInput, PinInputGroup, PinInputSlot } from '@documenso/ui/primitives/pin-input';
import { useToast } from '@documenso/ui/primitives/use-toast';
import { zodResolver } from '@hookform/resolvers/zod';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';
import { useState } from 'react';
import { flushSync } from 'react-dom';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
export const ZDisable2FAForm = z.object({
totpCode: z.string().trim().optional(),
@@ -120,8 +111,8 @@ export const DisableAuthenticatorAppDialog = () => {
<DialogDescription>
<Trans>
Please provide a token from the authenticator, or a backup code. If you do not have a
backup code available, please contact support.
Please provide a token from the authenticator, or a backup code. If you do not have a backup code
available, please contact support.
</Trans>
</DialogDescription>
</DialogHeader>
@@ -171,11 +162,7 @@ export const DisableAuthenticatorAppDialog = () => {
)}
<DialogFooter>
<Button
type="button"
variant="secondary"
onClick={onToggleTwoFactorDisableMethodClick}
>
<Button type="button" variant="secondary" onClick={onToggleTwoFactorDisableMethodClick}>
{twoFactorDisableMethod === 'totp' ? (
<Trans>Use Backup Code</Trans>
) : (
@@ -1,13 +1,3 @@
import { useEffect, useState } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';
import { useForm } from 'react-hook-form';
import { renderSVG } from 'uqr';
import { z } from 'zod';
import { authClient } from '@documenso/auth/client';
import { downloadFile } from '@documenso/lib/client-only/download-file';
import { useSession } from '@documenso/lib/client-only/providers/session';
@@ -22,16 +12,17 @@ import {
DialogTitle,
DialogTrigger,
} from '@documenso/ui/primitives/dialog';
import {
Form,
FormControl,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@documenso/ui/primitives/form/form';
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@documenso/ui/primitives/form/form';
import { PinInput, PinInputGroup, PinInputSlot } from '@documenso/ui/primitives/pin-input';
import { useToast } from '@documenso/ui/primitives/use-toast';
import { zodResolver } from '@hookform/resolvers/zod';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Trans } from '@lingui/react/macro';
import { useEffect, useState } from 'react';
import { useForm } from 'react-hook-form';
import { renderSVG } from 'uqr';
import { z } from 'zod';
import { RecoveryCodeList } from './recovery-code-list';
@@ -100,9 +91,7 @@ export const EnableAuthenticatorAppDialog = ({ onSuccess }: EnableAuthenticatorA
toast({
title: _(msg`Two-factor authentication enabled`),
description: _(
msg`You will now be required to enter a code from your authenticator app when signing in.`,
),
description: _(msg`You will now be required to enter a code from your authenticator app when signing in.`),
});
} catch (_err) {
toast({
@@ -162,119 +151,112 @@ export const EnableAuthenticatorAppDialog = ({ onSuccess }: EnableAuthenticatorA
</DialogTrigger>
<DialogContent position="center">
{setup2FAData && (
<>
{recoveryCodes ? (
<div>
{setup2FAData &&
(recoveryCodes ? (
<div>
<DialogHeader>
<DialogTitle>
<Trans>Backup codes</Trans>
</DialogTitle>
<DialogDescription>
<Trans>Your recovery codes are listed below. Please store them in a safe place.</Trans>
</DialogDescription>
</DialogHeader>
<div className="mt-4">
<RecoveryCodeList recoveryCodes={recoveryCodes} />
</div>
<DialogFooter className="mt-4">
<DialogClose asChild>
<Button variant="secondary">
<Trans>Close</Trans>
</Button>
</DialogClose>
<Button onClick={downloadRecoveryCodes}>
<Trans>Download</Trans>
</Button>
</DialogFooter>
</div>
) : (
<Form {...enable2FAForm}>
<form onSubmit={enable2FAForm.handleSubmit(onEnable2FAFormSubmit)}>
<DialogHeader>
<DialogTitle>
<Trans>Backup codes</Trans>
<Trans>Enable Authenticator App</Trans>
</DialogTitle>
<DialogDescription>
<Trans>
Your recovery codes are listed below. Please store them in a safe place.
To enable two-factor authentication, scan the following QR code using your authenticator app.
</Trans>
</DialogDescription>
</DialogHeader>
<div className="mt-4">
<RecoveryCodeList recoveryCodes={recoveryCodes} />
</div>
<fieldset disabled={isEnabling2FA} className="mt-4 flex flex-col gap-y-4">
<div
className="flex h-36 justify-center"
dangerouslySetInnerHTML={{
__html: renderSVG(setup2FAData?.uri ?? ''),
}}
/>
<DialogFooter className="mt-4">
<DialogClose asChild>
<Button variant="secondary">
<Trans>Close</Trans>
</Button>
</DialogClose>
<p className="text-muted-foreground text-sm">
<Trans>
If your authenticator app does not support QR codes, you can use the following code instead:
</Trans>
</p>
<Button onClick={downloadRecoveryCodes}>
<Trans>Download</Trans>
</Button>
</DialogFooter>
</div>
) : (
<Form {...enable2FAForm}>
<form onSubmit={enable2FAForm.handleSubmit(onEnable2FAFormSubmit)}>
<DialogHeader>
<DialogTitle>
<Trans>Enable Authenticator App</Trans>
</DialogTitle>
<DialogDescription>
<Trans>
To enable two-factor authentication, scan the following QR code using your
authenticator app.
</Trans>
</DialogDescription>
</DialogHeader>
<p className="rounded-lg bg-muted/60 p-2 text-center font-mono text-muted-foreground tracking-widest">
{setup2FAData?.secret}
</p>
<fieldset disabled={isEnabling2FA} className="mt-4 flex flex-col gap-y-4">
<div
className="flex h-36 justify-center"
dangerouslySetInnerHTML={{
__html: renderSVG(setup2FAData?.uri ?? ''),
}}
/>
<p className="text-muted-foreground text-sm">
<Trans>
Once you have scanned the QR code or entered the code manually, enter the code provided by your
authenticator app below.
</Trans>
</p>
<p className="text-muted-foreground text-sm">
<Trans>
If your authenticator app does not support QR codes, you can use the
following code instead:
</Trans>
</p>
<FormField
name="token"
control={enable2FAForm.control}
render={({ field }) => (
<FormItem>
<FormLabel className="text-muted-foreground">
<Trans>Token</Trans>
</FormLabel>
<FormControl>
<PinInput {...field} value={field.value ?? ''} maxLength={6}>
{Array(6)
.fill(null)
.map((_, i) => (
<PinInputGroup key={i}>
<PinInputSlot index={i} />
</PinInputGroup>
))}
</PinInput>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<p className="bg-muted/60 text-muted-foreground rounded-lg p-2 text-center font-mono tracking-widest">
{setup2FAData?.secret}
</p>
<p className="text-muted-foreground text-sm">
<Trans>
Once you have scanned the QR code or entered the code manually, enter the
code provided by your authenticator app below.
</Trans>
</p>
<FormField
name="token"
control={enable2FAForm.control}
render={({ field }) => (
<FormItem>
<FormLabel className="text-muted-foreground">
<Trans>Token</Trans>
</FormLabel>
<FormControl>
<PinInput {...field} value={field.value ?? ''} maxLength={6}>
{Array(6)
.fill(null)
.map((_, i) => (
<PinInputGroup key={i}>
<PinInputSlot index={i} />
</PinInputGroup>
))}
</PinInput>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<DialogFooter>
<DialogClose asChild>
<Button variant="secondary">
<Trans>Cancel</Trans>
</Button>
</DialogClose>
<Button type="submit" loading={isEnabling2FA}>
<Trans>Enable 2FA</Trans>
<DialogFooter>
<DialogClose asChild>
<Button variant="secondary">
<Trans>Cancel</Trans>
</Button>
</DialogFooter>
</fieldset>
</form>
</Form>
)}
</>
)}
</DialogClose>
<Button type="submit" loading={isEnabling2FA}>
<Trans>Enable 2FA</Trans>
</Button>
</DialogFooter>
</fieldset>
</form>
</Form>
))}
</DialogContent>
</Dialog>
);
@@ -1,10 +1,9 @@
import { useCopyToClipboard } from '@documenso/lib/client-only/hooks/use-copy-to-clipboard';
import { useToast } from '@documenso/ui/primitives/use-toast';
import { msg } from '@lingui/core/macro';
import { useLingui } from '@lingui/react';
import { Copy } from 'lucide-react';
import { useCopyToClipboard } from '@documenso/lib/client-only/hooks/use-copy-to-clipboard';
import { useToast } from '@documenso/ui/primitives/use-toast';
export type RecoveryCodeListProps = {
recoveryCodes: string[];
};
@@ -29,9 +28,7 @@ export const RecoveryCodeList = ({ recoveryCodes }: RecoveryCodeListProps) => {
} catch (_err) {
toast({
title: _(msg`Unable to copy recovery code`),
description: _(
msg`We were unable to copy your recovery code to your clipboard. Please try again.`,
),
description: _(msg`We were unable to copy your recovery code to your clipboard. Please try again.`),
variant: 'destructive',
});
}
@@ -40,17 +37,11 @@ export const RecoveryCodeList = ({ recoveryCodes }: RecoveryCodeListProps) => {
return (
<div className="grid grid-cols-2 gap-4">
{recoveryCodes.map((code) => (
<div
key={code}
className="bg-muted text-muted-foreground relative rounded-lg p-4 font-mono md:text-center"
>
<div key={code} className="relative rounded-lg bg-muted p-4 font-mono text-muted-foreground md:text-center">
<span>{code}</span>
<div className="absolute inset-y-0 right-4 flex items-center justify-center">
<button
className="opacity-60 hover:opacity-80"
onClick={() => void onCopyRecoveryCodeClick(code)}
>
<button className="opacity-60 hover:opacity-80" onClick={() => void onCopyRecoveryCodeClick(code)}>
<Copy className="h-5 w-5" />
</button>
</div>
@@ -1,11 +1,3 @@
import { useState } from 'react';
import { zodResolver } from '@hookform/resolvers/zod';
import { Trans } from '@lingui/react/macro';
import { useForm } from 'react-hook-form';
import { match } from 'ts-pattern';
import { z } from 'zod';
import { authClient } from '@documenso/auth/client';
import { downloadFile } from '@documenso/lib/client-only/download-file';
import { AppError } from '@documenso/lib/errors/app-error';
@@ -21,14 +13,14 @@ import {
DialogTitle,
DialogTrigger,
} from '@documenso/ui/primitives/dialog';
import {
Form,
FormControl,
FormField,
FormItem,
FormMessage,
} from '@documenso/ui/primitives/form/form';
import { Form, FormControl, FormField, FormItem, FormMessage } from '@documenso/ui/primitives/form/form';
import { PinInput, PinInputGroup, PinInputSlot } from '@documenso/ui/primitives/pin-input';
import { zodResolver } from '@hookform/resolvers/zod';
import { Trans } from '@lingui/react/macro';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { match } from 'ts-pattern';
import { z } from 'zod';
import { RecoveryCodeList } from './recovery-code-list';
@@ -97,9 +89,7 @@ export const ViewRecoveryCodesDialog = () => {
</DialogTitle>
<DialogDescription>
<Trans>
Your recovery codes are listed below. Please store them in a safe place.
</Trans>
<Trans>Your recovery codes are listed below. Please store them in a safe place.</Trans>
</DialogDescription>
</DialogHeader>
@@ -156,9 +146,7 @@ export const ViewRecoveryCodesDialog = () => {
<Alert variant="destructive">
<AlertDescription>
{match(AppError.parseError(error).message)
.with('INCORRECT_TWO_FACTOR_CODE', () => (
<Trans>Invalid code. Please try again.</Trans>
))
.with('INCORRECT_TWO_FACTOR_CODE', () => <Trans>Invalid code. Please try again.</Trans>)
.otherwise(() => (
<Trans>Something went wrong. Please try again or contact support.</Trans>
))}