33 lines
1.3 KiB
TypeScript
33 lines
1.3 KiB
TypeScript
import { z } from "zod";
|
|
|
|
type AuthMode = "cloudflare_access" | "local_noauth" | "hosted";
|
|
|
|
const authModeSchema = z
|
|
.enum(["cloudflare_access", "local_noauth", "hosted"])
|
|
.catch("cloudflare_access");
|
|
|
|
export function getAuthMode(value: string | null | undefined): AuthMode {
|
|
return authModeSchema.parse(value);
|
|
}
|
|
|
|
export function isHostedAuthMode(value: string | null | undefined) {
|
|
return getAuthMode(value) === "hosted";
|
|
}
|
|
|
|
export function isHostedClientAuthMode() {
|
|
// This is an explicit deploy-time contract: the operator must keep the
|
|
// client build-time AUTH_MODE aligned with the server runtime AUTH_MODE.
|
|
// We accept that tradeoff to avoid a startup round-trip just to ask the
|
|
// backend which auth UI to render. Hosted deployments must therefore set
|
|
// AUTH_MODE=hosted in both the client build environment and the runtime.
|
|
return isHostedAuthMode(import.meta.env.AUTH_MODE);
|
|
}
|
|
|
|
export function isEmailVerificationBypassed() {
|
|
// Local-dev escape hatch (BYPASS_EMAIL_VERIFICATION=true). The server skips
|
|
// verification and never marks users emailVerified, so the client must treat
|
|
// the session as verified too — otherwise route guards and /verify-email
|
|
// bounce each other in an infinite redirect loop.
|
|
return import.meta.env.BYPASS_EMAIL_VERIFICATION === "true";
|
|
}
|