From 6faae5fc852953bc236353863f3eedcdd65bcf26 Mon Sep 17 00:00:00 2001 From: mzhang Date: Mon, 24 Aug 2026 12:21:03 -0400 Subject: [PATCH] PR fixes --- apps/app-portal/src/app/(landing)/page.tsx | 12 +++++-- apps/app-portal/src/app/auth/signin/page.tsx | 11 +++++-- .../src/components/auth/SignInForm.tsx | 33 ++++++++++++++----- apps/app-portal/src/lib/auth/config.ts | 5 +++ apps/app-portal/src/middleware.ts | 21 +++++++++--- 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/apps/app-portal/src/app/(landing)/page.tsx b/apps/app-portal/src/app/(landing)/page.tsx index a6c3f9d9..7a7a730f 100644 --- a/apps/app-portal/src/app/(landing)/page.tsx +++ b/apps/app-portal/src/app/(landing)/page.tsx @@ -3,9 +3,17 @@ import Link from "next/link"; import Image from "next/image"; import icon from "@/app/icon.ico"; import TiledBackground from "@/components/ui/tiled-background"; +import {redirect} from "next/navigation"; +import {isAdminEmail} from "@/lib/auth/roles.ts"; +import {getSession} from "@/lib/auth/session.ts"; + +export default async function Page(): Promise { + + const session = await getSession(); + if (session?.user) { + redirect(isAdminEmail(session.user.email) ? "/admin" : "/dashboard"); + } -//TODO: update to redirect authed users to /dashboard -export default function Page(): JSX.Element { return (
diff --git a/apps/app-portal/src/app/auth/signin/page.tsx b/apps/app-portal/src/app/auth/signin/page.tsx index ac1c9ca7..23e4edb9 100644 --- a/apps/app-portal/src/app/auth/signin/page.tsx +++ b/apps/app-portal/src/app/auth/signin/page.tsx @@ -5,12 +5,19 @@ import { getSession } from "@/lib/auth/session"; import { SignInForm } from "@/components/auth/SignInForm"; import {isAdminEmail} from "@/lib/auth/roles.ts"; -export default async function Page(): Promise { +export default async function Page({ + searchParams, +}: { + searchParams: { callbackUrl?: string }; +}): Promise { // read cookie - see if valid session in DB - if so, automatically redir user to logged in part const session = await getSession(); if (session?.user) { redirect(isAdminEmail(session.user.email) ? "/admin" : "/dashboard"); } - return ; + // callbackUrl is only present when middleware bounced an unauthed user here + // from a protected route. The form uses it both to prompt "sign in first" and + // as the post-sign-in destination baked into the magic link. + return ; } diff --git a/apps/app-portal/src/components/auth/SignInForm.tsx b/apps/app-portal/src/components/auth/SignInForm.tsx index d2ef54aa..5651e006 100644 --- a/apps/app-portal/src/components/auth/SignInForm.tsx +++ b/apps/app-portal/src/components/auth/SignInForm.tsx @@ -12,7 +12,11 @@ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; //regex email checker type Status = "idle" | "loading" | "sent"; -export function SignInForm() { +export function SignInForm({ + callbackUrl, +}: { + callbackUrl?: string; +}) { const [dotCount, setDotCount] = useState(1); const [email, setEmail] = useState(""); const [status, setStatus] = useState("idle"); @@ -25,6 +29,14 @@ export function SignInForm() { return () => clearInterval(id); }, []); + // Prompt users who were bounced here from a protected route (callbackUrl set). + useEffect(() => { + if (callbackUrl) { + // stable id so StrictMode's double-invoke shows one toast, not two + toast.info("Sign in before accessing the portal!", { id: "auth-required" }); + } + }, [callbackUrl]); + async function handleSignIn() { // invalid email -> inline error, no request sent if (!EMAIL_RE.test(email.trim())) { @@ -37,12 +49,14 @@ export function SignInForm() { try { // signIn() handles CSRF, form-encoding, and the redirect for us. // redirect:false → we drive the UI state ourselves instead of navigating. - // The callbackUrl is baked into the magic link; the admin layout - // re-checks the role server-side, so this is routing, not authorization. + // The callbackUrl is baked into the magic link. If the user was bounced + // here from a protected route, send them back to it; otherwise fall back + // to their default landing. The admin layout re-checks the role + // server-side, so this is routing, not authorization. const res = await signIn("email", { email: email.trim(), redirect: false, - callbackUrl: isAdminEmail(email) ? "/admin" : "/dashboard", + callbackUrl: callbackUrl ?? (isAdminEmail(email) ? "/admin" : "/dashboard"), }); if (res?.error) { @@ -81,10 +95,14 @@ export function SignInForm() { setEmail(e.target.value); if (emailError) setEmailError(null); }} + onKeyDown={(e)=>{ + if (e.key === "Enter") document.getElementById("submit")?.click() + }} className={"w-full p-1 mt-4 border-2 rounded-md"} /> {/*confirm*/}