+ Delete Account
+
+ Delete your account and all its contents, including completed documents. This action is
+ irreversible and will cancel your subscription, so proceed with caution.
+
+
);
}
diff --git a/apps/web/src/components/forms/profile.tsx b/apps/web/src/components/forms/profile.tsx
index 8a7e2ff3f..c3f8eca37 100644
--- a/apps/web/src/components/forms/profile.tsx
+++ b/apps/web/src/components/forms/profile.tsx
@@ -3,7 +3,6 @@
import { useRouter } from 'next/navigation';
import { zodResolver } from '@hookform/resolvers/zod';
-import { signOut } from 'next-auth/react';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
@@ -11,18 +10,7 @@ import type { User } from '@documenso/prisma/client';
import { TRPCClientError } from '@documenso/trpc/client';
import { trpc } from '@documenso/trpc/react';
import { cn } from '@documenso/ui/lib/utils';
-import { Alert, AlertDescription } from '@documenso/ui/primitives/alert';
import { Button } from '@documenso/ui/primitives/button';
-import { Card, CardContent, CardFooter } from '@documenso/ui/primitives/card';
-import {
- Dialog,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogTitle,
- DialogTrigger,
-} from '@documenso/ui/primitives/dialog';
import {
Form,
FormControl,
@@ -105,36 +93,6 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => {
}
};
- const onDeleteAccount = async () => {
- try {
- await deleteAccount();
-
- toast({
- title: 'Account deleted',
- description: 'Your account has been deleted successfully.',
- duration: 5000,
- });
-
- return await signOut({ callbackUrl: '/' });
- } catch (err) {
- if (err instanceof TRPCClientError && err.data?.code === 'BAD_REQUEST') {
- toast({
- title: 'An error occurred',
- description: err.message,
- variant: 'destructive',
- });
- } else {
- toast({
- title: 'An unknown error occurred',
- variant: 'destructive',
- description:
- err.message ??
- 'We encountered an unknown error while attempting to delete your account. Please try again later.',
- });
- }
- }
- };
-
return (
-
-
-
-
-
- Delete your account and all its contents, including completed documents. This action is
- irreversible and will cancel your subscription, so proceed with caution.
-
-
-
-
-
-
);
};
diff --git a/packages/lib/server-only/user/delete-user.ts b/packages/lib/server-only/user/delete-user.ts
index 65a74ac42..d6d4284b4 100644
--- a/packages/lib/server-only/user/delete-user.ts
+++ b/packages/lib/server-only/user/delete-user.ts
@@ -1,11 +1,13 @@
import { prisma } from '@documenso/prisma';
import { DocumentStatus } from '@documenso/prisma/client';
+import { deletedAccountServiceAccount } from './service-accounts/deleted-account';
+
export type DeleteUserOptions = {
email: string;
};
-export const deletedServiceAccount = async ({ email }: DeleteUserOptions) => {
+export const deleteUser = async ({ email }: DeleteUserOptions) => {
const user = await prisma.user.findFirst({
where: {
email: {
@@ -14,20 +16,13 @@ export const deletedServiceAccount = async ({ email }: DeleteUserOptions) => {
},
});
- const defaultDeleteUser = await prisma.user.findFirst({
- where: {
- email: 'deleted@documenso.com',
- },
- });
-
if (!user) {
throw new Error(`User with email ${email} not found`);
}
- if (!defaultDeleteUser) {
- throw new Error(`Default delete account not found`);
- }
+ const serviceAccount = await deletedAccountServiceAccount();
+ // TODO: Send out cancellations for all pending docs
await prisma.document.updateMany({
where: {
userId: user.id,
@@ -36,7 +31,7 @@ export const deletedServiceAccount = async ({ email }: DeleteUserOptions) => {
},
},
data: {
- userId: defaultDeleteUser.id,
+ userId: serviceAccount.id,
deletedAt: new Date(),
},
});
diff --git a/packages/lib/server-only/user/service-accounts/deleted-account.ts b/packages/lib/server-only/user/service-accounts/deleted-account.ts
new file mode 100644
index 000000000..6bfd6d25f
--- /dev/null
+++ b/packages/lib/server-only/user/service-accounts/deleted-account.ts
@@ -0,0 +1,17 @@
+import { prisma } from '@documenso/prisma';
+
+export const deletedAccountServiceAccount = async () => {
+ const serviceAccount = await prisma.user.findFirst({
+ where: {
+ email: 'deleted-account@documenso.com',
+ },
+ });
+
+ if (!serviceAccount) {
+ throw new Error(
+ 'Deleted account service account not found, have you ran the appropriate migrations?',
+ );
+ }
+
+ return serviceAccount;
+};
diff --git a/packages/prisma/migrations/20240205120648_create_delete_account/migration.sql b/packages/prisma/migrations/20240205120648_create_delete_account/migration.sql
index bfb9c2c83..d001bc4ae 100644
--- a/packages/prisma/migrations/20240205120648_create_delete_account/migration.sql
+++ b/packages/prisma/migrations/20240205120648_create_delete_account/migration.sql
@@ -1,7 +1,7 @@
-- Create deleted@documenso.com
DO $$
BEGIN
- IF NOT EXISTS (SELECT 1 FROM "public"."User" WHERE "email" = 'deleted@documenso.com') THEN
+ IF NOT EXISTS (SELECT 1 FROM "public"."User" WHERE "email" = 'deleted-account@documenso.com') THEN
INSERT INTO
"public"."User" (
"email",
@@ -16,7 +16,7 @@ BEGIN
)
VALUES
(
- 'deleted@documenso.com',
+ 'deleted-account@documenso.com',
NOW(),
NULL,
NOW(),
diff --git a/packages/trpc/server/profile-router/router.ts b/packages/trpc/server/profile-router/router.ts
index 56a6eea29..2f636d87d 100644
--- a/packages/trpc/server/profile-router/router.ts
+++ b/packages/trpc/server/profile-router/router.ts
@@ -1,6 +1,6 @@
import { TRPCError } from '@trpc/server';
-import { deletedServiceAccount } from '@documenso/lib/server-only/user/delete-user';
+import { deleteUser } from '@documenso/lib/server-only/user/delete-user';
import { findUserSecurityAuditLogs } from '@documenso/lib/server-only/user/find-user-security-audit-logs';
import { forgotPassword } from '@documenso/lib/server-only/user/forgot-password';
import { getUserById } from '@documenso/lib/server-only/user/get-user-by-id';
@@ -161,7 +161,7 @@ export const profileRouter = router({
try {
const user = ctx.user;
- return await deletedServiceAccount(user);
+ return await deleteUser(user);
} catch (err) {
let message = 'We were unable to delete your account. Please try again.';