mirror of
https://github.com/documenso/documenso.git
synced 2025-11-14 16:51:38 +10:00
feat: request usee to disable 2fa before deleting account
This commit is contained in:
@ -7,7 +7,6 @@ import { signOut } from 'next-auth/react';
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { validateTwoFactorAuthentication } from '@documenso/lib/server-only/2fa/validate-2fa';
|
|
||||||
import type { User } from '@documenso/prisma/client';
|
import type { User } from '@documenso/prisma/client';
|
||||||
import { TRPCClientError } from '@documenso/trpc/client';
|
import { TRPCClientError } from '@documenso/trpc/client';
|
||||||
import { trpc } from '@documenso/trpc/react';
|
import { trpc } from '@documenso/trpc/react';
|
||||||
@ -67,13 +66,6 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => {
|
|||||||
resolver: zodResolver(ZProfileFormSchema),
|
resolver: zodResolver(ZProfileFormSchema),
|
||||||
});
|
});
|
||||||
|
|
||||||
const deleteAccountTwoFactorTokenForm = useForm<TTwoFactorAuthTokenSchema>({
|
|
||||||
defaultValues: {
|
|
||||||
token: '',
|
|
||||||
},
|
|
||||||
resolver: zodResolver(ZTwoFactorAuthTokenSchema),
|
|
||||||
});
|
|
||||||
|
|
||||||
const isSubmitting = form.formState.isSubmitting;
|
const isSubmitting = form.formState.isSubmitting;
|
||||||
const hasTwoFactorAuthentication = user.twoFactorEnabled;
|
const hasTwoFactorAuthentication = user.twoFactorEnabled;
|
||||||
|
|
||||||
@ -113,7 +105,8 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteAccoutAndSignOut = async () => {
|
const onDeleteAccount = async () => {
|
||||||
|
try {
|
||||||
await deleteAccount();
|
await deleteAccount();
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
@ -123,28 +116,6 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return await signOut({ callbackUrl: '/' });
|
return await signOut({ callbackUrl: '/' });
|
||||||
};
|
|
||||||
|
|
||||||
const onDeleteAccount = async (hasTwoFactorAuthentication: boolean) => {
|
|
||||||
try {
|
|
||||||
if (!hasTwoFactorAuthentication) {
|
|
||||||
return await deleteAccoutAndSignOut();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { token } = deleteAccountTwoFactorTokenForm.getValues();
|
|
||||||
|
|
||||||
if (!token) {
|
|
||||||
throw new Error('Please enter your Two Factor Authentication token.');
|
|
||||||
}
|
|
||||||
|
|
||||||
await validateTwoFactorAuthentication({
|
|
||||||
totpCode: token,
|
|
||||||
user,
|
|
||||||
}).catch(() => {
|
|
||||||
throw new Error('We were unable to validate your Two Factor Authentication token.');
|
|
||||||
});
|
|
||||||
|
|
||||||
await deleteAccoutAndSignOut();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof TRPCClientError && err.data?.code === 'BAD_REQUEST') {
|
if (err instanceof TRPCClientError && err.data?.code === 'BAD_REQUEST') {
|
||||||
toast({
|
toast({
|
||||||
@ -225,12 +196,6 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => {
|
|||||||
irreversible and will cancel your subscription, so proceed with caution.
|
irreversible and will cancel your subscription, so proceed with caution.
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardFooter className="justify-end pb-4 pr-4">
|
<CardFooter className="justify-end pb-4 pr-4">
|
||||||
<Form {...deleteAccountTwoFactorTokenForm}>
|
|
||||||
<form
|
|
||||||
onSubmit={deleteAccountTwoFactorTokenForm.handleSubmit(() => {
|
|
||||||
console.log('delete account');
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<Dialog>
|
<Dialog>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button variant="destructive">Delete Account</Button>
|
<Button variant="destructive">Delete Account</Button>
|
||||||
@ -240,9 +205,9 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => {
|
|||||||
<DialogTitle>Delete Account</DialogTitle>
|
<DialogTitle>Delete Account</DialogTitle>
|
||||||
<DialogDescription>
|
<DialogDescription>
|
||||||
Documenso will delete{' '}
|
Documenso will delete{' '}
|
||||||
<span className="font-semibold">all of your documents</span>, along with all
|
<span className="font-semibold">all of your documents</span>, along with all of
|
||||||
of your completed documents, signatures, and all other resources belonging
|
your completed documents, signatures, and all other resources belonging to your
|
||||||
to your Account.
|
Account.
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|
||||||
@ -253,38 +218,25 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => {
|
|||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
{hasTwoFactorAuthentication && (
|
{hasTwoFactorAuthentication && (
|
||||||
<div className="flex flex-col gap-y-4">
|
<Alert variant="destructive">
|
||||||
<FormField
|
<AlertDescription className="selection:bg-red-100">
|
||||||
name="token"
|
Disable Two Factor Authentication before deleting your account.
|
||||||
control={deleteAccountTwoFactorTokenForm.control}
|
</AlertDescription>
|
||||||
render={({ field }) => (
|
</Alert>
|
||||||
<FormItem>
|
|
||||||
<FormLabel className="text-muted-foreground">
|
|
||||||
Two Factor Authentication Token
|
|
||||||
</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input {...field} value={field.value ?? ''} />
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<Button
|
<Button
|
||||||
onClick={async () => onDeleteAccount(hasTwoFactorAuthentication)}
|
onClick={onDeleteAccount}
|
||||||
loading={isDeletingAccount}
|
loading={isDeletingAccount}
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
|
disabled={hasTwoFactorAuthentication}
|
||||||
>
|
>
|
||||||
{isDeletingAccount ? 'Deleting account...' : 'Delete Account'}
|
{isDeletingAccount ? 'Deleting account...' : 'Delete Account'}
|
||||||
</Button>
|
</Button>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</form>
|
|
||||||
</Form>
|
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -17,7 +17,6 @@ export const verifyTwoFactorAuthenticationToken = async ({
|
|||||||
user,
|
user,
|
||||||
totpCode,
|
totpCode,
|
||||||
}: VerifyTwoFactorAuthenticationTokenOptions) => {
|
}: VerifyTwoFactorAuthenticationTokenOptions) => {
|
||||||
// TODO: This is undefined and I can't figure out why.
|
|
||||||
const key = DOCUMENSO_ENCRYPTION_KEY;
|
const key = DOCUMENSO_ENCRYPTION_KEY;
|
||||||
|
|
||||||
if (!user.twoFactorSecret) {
|
if (!user.twoFactorSecret) {
|
||||||
|
|||||||
Reference in New Issue
Block a user