ThreadCount Community edition

Uniform stock management for healthcare linen rooms. Licensed under the GNU AGPL v3.
This commit is contained in:
ThreadCount
2026-09-13 08:45:19 +10:00
commit 1bc2de655a
505 changed files with 56223 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
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} />;
}