From f1c956a361539592d00836488181b69218798600 Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Sat, 5 Oct 2024 17:14:59 +0000 Subject: [PATCH] feature(web): Async validate JWT account and sign out the user if they no longer exist --- apps/web/app/dashboard/layout.tsx | 2 ++ .../components/utils/ValidAccountCheck.tsx | 26 +++++++++++++++++++ packages/trpc/routers/users.ts | 13 ++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 apps/web/components/utils/ValidAccountCheck.tsx diff --git a/apps/web/app/dashboard/layout.tsx b/apps/web/app/dashboard/layout.tsx index 23c379cb..b0ac1f7d 100644 --- a/apps/web/app/dashboard/layout.tsx +++ b/apps/web/app/dashboard/layout.tsx @@ -2,6 +2,7 @@ import MobileSidebar from "@/components/dashboard/sidebar/ModileSidebar"; import Sidebar from "@/components/dashboard/sidebar/Sidebar"; import DemoModeBanner from "@/components/DemoModeBanner"; import { Separator } from "@/components/ui/separator"; +import ValidAccountCheck from "@/components/utils/ValidAccountCheck"; import serverConfig from "@hoarder/shared/config"; @@ -14,6 +15,7 @@ export default async function Dashboard({ }>) { return (
+
diff --git a/apps/web/components/utils/ValidAccountCheck.tsx b/apps/web/components/utils/ValidAccountCheck.tsx new file mode 100644 index 00000000..12c11087 --- /dev/null +++ b/apps/web/components/utils/ValidAccountCheck.tsx @@ -0,0 +1,26 @@ +"use client"; + +import { api } from "@/lib/trpc"; +import { signOut } from "next-auth/react"; + +/** + * This component is used to address a confusion when the JWT token exists but the user no longer exists in the database. + * So this component synchronusly checks if the user is still valid and if not, signs out the user. + */ +export default function ValidAccountCheck() { + const { error } = api.users.whoami.useQuery(undefined, { + retry: (_failureCount, error) => { + if (error.data?.code === "UNAUTHORIZED") { + return false; + } + return true; + }, + }); + if (error?.data?.code === "UNAUTHORIZED") { + signOut({ + callbackUrl: "/", + }); + } + + return <>; +} diff --git a/packages/trpc/routers/users.ts b/packages/trpc/routers/users.ts index 51f9429e..ba1aee24 100644 --- a/packages/trpc/routers/users.ts +++ b/packages/trpc/routers/users.ts @@ -1,5 +1,5 @@ import { TRPCError } from "@trpc/server"; -import { count, eq } from "drizzle-orm"; +import { and, count, eq } from "drizzle-orm"; import invariant from "tiny-invariant"; import { z } from "zod"; @@ -138,7 +138,16 @@ export const usersAppRouter = router({ email: z.string().nullish(), }), ) - .query(({ ctx }) => { + .query(async ({ ctx }) => { + if (!ctx.user.email) { + throw new TRPCError({ code: "UNAUTHORIZED" }); + } + const userDb = await ctx.db.query.users.findFirst({ + where: and(eq(users.id, ctx.user.id), eq(users.email, ctx.user.email)), + }); + if (!userDb) { + throw new TRPCError({ code: "UNAUTHORIZED" }); + } return { id: ctx.user.id, name: ctx.user.name, email: ctx.user.email }; }), });