diff --git a/src/app/(dashboard)/layout.tsx b/src/app/(dashboard)/layout.tsx index dc20652..46aafe6 100644 --- a/src/app/(dashboard)/layout.tsx +++ b/src/app/(dashboard)/layout.tsx @@ -1,5 +1,6 @@ import { redirect } from "next/navigation"; import { getSession } from "@/lib/auth"; +import { db } from "@/lib/db"; import { Sidebar } from "@/components/layout/sidebar"; import { TopNav } from "@/components/layout/topnav"; import { Footer } from "@/components/layout/footer"; @@ -7,10 +8,18 @@ import { Footer } from "@/components/layout/footer"; export default async function DashboardLayout({ children }: { children: React.ReactNode }) { const session = await getSession(); if (!session) redirect("/login"); + // Force a password change before anything else (provisioned accounts ship with - // a known default + mustChangePassword=true). The target page is outside this - // layout group, so there's no redirect loop. - if (session.user.mustChangePassword) redirect("/change-password"); + // a known default + mustChangePassword=true). Read the flag from the DB, not the + // JWT: the cookie is only refreshed on re-login/update(), so trusting it would + // keep bouncing the user back here even after they've set a new password. The + // target page is outside this layout group, so there's no redirect loop. + const account = await db.user.findUnique({ + where: { id: session.user.id }, + select: { active: true, mustChangePassword: true }, + }); + if (!account || !account.active) redirect("/login"); + if (account.mustChangePassword) redirect("/change-password"); return (