fix: polish

This commit is contained in:
David Nguyen
2024-03-27 18:35:20 +08:00
parent 47916e3127
commit 3c0918963d
7 changed files with 40 additions and 34 deletions

View File

@ -1,7 +1,5 @@
import { useEffect, useState } from 'react';
import Link from 'next/link';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
@ -22,6 +20,8 @@ import {
} from '@documenso/ui/primitives/form/form';
import { Input } from '@documenso/ui/primitives/input';
import { EnableAuthenticatorAppDialog } from '~/components/forms/2fa/enable-authenticator-app-dialog';
import { useRequiredDocumentAuthContext } from './document-auth-provider';
export type DocumentActionAuth2FAProps = {
@ -58,6 +58,7 @@ export const DocumentActionAuth2FA = ({
},
});
const [is2FASetupSuccessful, setIs2FASetupSuccessful] = useState(false);
const [formErrorCode, setFormErrorCode] = useState<string | null>(null);
const onFormSubmit = async ({ token }: T2FAAuthFormSchema) => {
@ -87,17 +88,29 @@ export const DocumentActionAuth2FA = ({
token: '',
});
setIs2FASetupSuccessful(false);
setFormErrorCode(null);
}, [open, form]);
if (!user?.twoFactorEnabled) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open]);
if (!user?.twoFactorEnabled && !is2FASetupSuccessful) {
return (
<div className="space-y-4">
<Alert variant="warning">
<AlertDescription>
{recipient.role === RecipientRole.VIEWER && actionTarget === 'DOCUMENT'
? 'You need to setup 2FA to mark this document as viewed.'
: `You need to setup 2FA to ${actionVerb.toLowerCase()} this ${actionTarget.toLowerCase()}.`}
<p>
{recipient.role === RecipientRole.VIEWER && actionTarget === 'DOCUMENT'
? 'You need to setup 2FA to mark this document as viewed.'
: `You need to setup 2FA to ${actionVerb.toLowerCase()} this ${actionTarget.toLowerCase()}.`}
</p>
{user?.identityProvider === 'DOCUMENSO' && (
<p className="mt-2">
By enabling 2FA, you will be required to enter a code from your authenticator app
every time you sign in.
</p>
)}
</AlertDescription>
</Alert>
@ -106,9 +119,7 @@ export const DocumentActionAuth2FA = ({
Close
</Button>
<Button type="button" asChild>
<Link href="/settings/security">Setup 2FA</Link>
</Button>
<EnableAuthenticatorAppDialog onSuccess={() => setIs2FASetupSuccessful(true)} />
</DialogFooter>
</div>
);

View File

@ -49,7 +49,7 @@ export const DocumentActionAuthAccount = ({
return (
<fieldset disabled={isSigningOut} className="space-y-4">
<Alert>
<Alert variant="warning">
<AlertDescription>
{actionTarget === 'DOCUMENT' && recipient.role === RecipientRole.VIEWER ? (
<span>

View File

@ -137,10 +137,7 @@ export const DocumentActionAuthPasskey = ({
);
}
if (
passkeyData.isInitialLoading ||
(passkeyData.isRefetching && passkeyData.passkeys.length === 0)
) {
if (passkeyData.isInitialLoading || (passkeyData.isError && passkeyData.passkeys.length === 0)) {
return (
<div className="flex h-28 items-center justify-center">
<Loader className="text-muted-foreground h-6 w-6 animate-spin" />
@ -171,7 +168,7 @@ export const DocumentActionAuthPasskey = ({
if (passkeyData.passkeys.length === 0) {
return (
<div className="space-y-4">
<Alert>
<Alert variant="warning">
<AlertDescription>
{recipient.role === RecipientRole.VIEWER && actionTarget === 'DOCUMENT'
? 'You need to setup a passkey to mark this document as viewed.'

View File

@ -5,7 +5,6 @@ import { createContext, useContext, useEffect, useMemo, useState } from 'react';
import { match } from 'ts-pattern';
import { MAXIMUM_PASSKEYS } from '@documenso/lib/constants/auth';
import { DOCUMENT_AUTH_TYPES } from '@documenso/lib/constants/document-auth';
import type {
TDocumentAuthOptions,
TRecipientAccessAuthTypes,
@ -175,9 +174,11 @@ export const DocumentAuthProvider = ({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [passkeyData.passkeys]);
// Assume that a user must be logged in for any auth requirements.
const isAuthRedirectRequired = Boolean(
DOCUMENT_AUTH_TYPES[derivedRecipientActionAuth || '']?.isAuthRedirectRequired &&
!preCalculatedActionAuthOptions,
derivedRecipientActionAuth &&
derivedRecipientActionAuth !== DocumentAuth.EXPLICIT_NONE &&
user?.email !== recipient.email,
);
const refetchPasskeys = async () => {

View File

@ -42,10 +42,10 @@ export const SigningForm = ({ document, recipient, fields, redirectUrl }: Signin
const { mutateAsync: completeDocumentWithToken } =
trpc.recipient.completeDocumentWithToken.useMutation();
const {
handleSubmit,
formState: { isSubmitting },
} = useForm();
const { handleSubmit, formState } = useForm();
// Keep the loading state going if successful since the redirect may take some time.
const isSubmitting = formState.isSubmitting || formState.isSubmitSuccessful;
const uninsertedFields = useMemo(() => {
return sortFieldsByPosition(fields.filter((field) => !field.inserted));

View File

@ -41,8 +41,13 @@ export const ZEnable2FAForm = z.object({
export type TEnable2FAForm = z.infer<typeof ZEnable2FAForm>;
export const EnableAuthenticatorAppDialog = () => {
export type EnableAuthenticatorAppDialogProps = {
onSuccess?: () => void;
};
export const EnableAuthenticatorAppDialog = ({ onSuccess }: EnableAuthenticatorAppDialogProps) => {
const { toast } = useToast();
const router = useRouter();
const [isOpen, setIsOpen] = useState(false);
@ -79,6 +84,7 @@ export const EnableAuthenticatorAppDialog = () => {
const data = await enable2FA({ code: token });
setRecoveryCodes(data.recoveryCodes);
onSuccess?.();
toast({
title: 'Two-factor authentication enabled',
@ -89,7 +95,7 @@ export const EnableAuthenticatorAppDialog = () => {
toast({
title: 'Unable to setup two-factor authentication',
description:
'We were unable to setup two-factor authentication for your account. Please ensure that you have entered your password correctly and try again.',
'We were unable to setup two-factor authentication for your account. Please ensure that you have entered your code correctly and try again.',
variant: 'destructive',
});
}

View File

@ -4,21 +4,12 @@ import { DocumentAuth } from '../types/document-auth';
type DocumentAuthTypeData = {
key: TDocumentAuth;
value: string;
/**
* Whether this authentication event will require the user to halt and
* redirect.
*
* Defaults to false.
*/
isAuthRedirectRequired?: boolean;
};
export const DOCUMENT_AUTH_TYPES: Record<string, DocumentAuthTypeData> = {
[DocumentAuth.ACCOUNT]: {
key: DocumentAuth.ACCOUNT,
value: 'Require account',
isAuthRedirectRequired: true,
},
[DocumentAuth.PASSKEY]: {
key: DocumentAuth.PASSKEY,