Files
threadcount-community/app/ops/login/page.tsx
T
ThreadCount 1bc2de655a ThreadCount Community edition
Uniform stock management for healthcare linen rooms. Licensed under the GNU AGPL v3.
2026-09-13 08:45:19 +10:00

26 lines
1.3 KiB
TypeScript

import { headers } from "next/headers";
import { redirect } from "next/navigation";
import { accessSsoConfigured } from "@/lib/ops/cfAccess";
import { currentOperator } from "@/lib/ops/session";
import LoginForm from "./LoginForm";
/* The sign-in page decides between the front door and the fire escape.
*
* Behind Cloudflare Access every request carries a signed assertion. When SSO is configured and
* one is present, hand off to the SSO route, which verifies it and mints the session — unless we
* just came back from a failed attempt (?sso=failed), which would loop. The route falls back here
* on any problem, so the password form is always reachable. Without the two Access variables
* there is no SSO at all and this page is simply the form. */
export const dynamic = "force-dynamic";
export default async function OpsLogin({ searchParams }: { searchParams: Promise<{ sso?: string; next?: string }> }) {
if (await currentOperator()) redirect("/ops");
const sp = await searchParams;
const ssoFailed = sp.sso === "failed";
if (!ssoFailed && accessSsoConfigured()) {
const h = await headers();
if (h.get("cf-access-jwt-assertion")) redirect("/api/ops/auth/sso" + (sp.next ? `?next=${encodeURIComponent(sp.next)}` : ""));
}
return <LoginForm ssoFailed={ssoFailed} />;
}