Skip to content

Instantly share code, notes, and snippets.

@m5r
Created December 14, 2021 22:05
Show Gist options
  • Save m5r/1c53b693762aac9fcfdf9f15b144f5aa to your computer and use it in GitHub Desktop.
Save m5r/1c53b693762aac9fcfdf9f15b144f5aa to your computer and use it in GitHub Desktop.

Revisions

  1. m5r created this gist Dec 14, 2021.
    34 changes: 34 additions & 0 deletions delete-account-form.tsx
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,34 @@
    import type { ActionFunction } from "remix";
    import { Form, redirect, useTransition } from "remix";

    import { enqueueDeleteUserData } from "~/app/routes/queues/delete-user-data";
    import authenticator from "~/app/auth/authenticator";
    import { destroySession, getSession } from "~/utils/session.server";
    import db from "~/utils/db.server";

    export const action: ActionFunction = async ({ request }) => {
    const user = await authenticator.isAuthenticated(request, { failureRedirect: "/auth/sign-in" });
    await db.user.update({
    where: { id: user.id },
    data: { hashedPassword: "pending deletion" },
    });
    enqueueDeleteUserData({ userId: user.id });

    return redirect("/", {
    headers: {
    "Set-Cookie": await destroySession(await getSession(request)),
    },
    });
    };

    export default function DeleteAccountForm() {
    const isSubmitting = useTransition().state === "submitting";

    return (
    <Form method="post">
    <button type="submit" disabled={isSubmitting}>
    Delete my account
    </button>
    </Form>
    );
    }
    22 changes: 22 additions & 0 deletions delete-user-data.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,22 @@
    import type { ActionFunction } from "remix";

    import { enqueue } from "./enqueue";
    import db from "~/utils/db.server";

    type Payload = {
    userId: string;
    };

    export const action: ActionFunction = async ({ request }) => {
    const { userId } = await request.json();
    await db.user.delete({ where: { id: userId } })

    return null;
    };

    export function enqueueDeleteUserData(payload: Payload) {
    enqueue({
    route: "/queues/delete-user-data",
    payload,
    });
    }
    45 changes: 45 additions & 0 deletions enqueue.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,45 @@
    import type { ActionFunction } from "remix";

    import serverConfig from "~/config/config.server";

    export const action: ActionFunction = async ({ request }) => {
    const { route, payload } = await request.json();
    const req = new Request(`${serverConfig.app.baseUrl}${route}`, {
    method: "POST",
    body: JSON.stringify(payload),
    headers: {
    "Content-Type": "application/json",
    },
    credentials: "omit",
    });

    // don't await to return ASAP and handle the promise resolution without blocking
    fetch(req)
    .then(response => {
    if (!response.ok) {
    console.log("something wrong happened"); // TODO: implement retry mechanic
    return;
    }
    })
    .catch(error => console.error("error", error));

    return null;
    };

    type EnqueueParams = {
    route: string;
    payload: unknown;
    }

    export function enqueue(params: EnqueueParams) {
    const req = new Request(`${serverConfig.app.baseUrl}/queues/enqueue`, {
    method: "POST",
    body: JSON.stringify(params),
    headers: {
    "Content-Type": "application/json",
    },
    credentials: "omit",
    });

    fetch(req);
    }