45 lines · 1.8 KB
import { env } from "cloudflare:workers";
import { timingSafeEqualStrings } from "./crypto";
import { isLocalDev } from "./deployment";

export type BootstrapVars = {
  ADMIN_EMAIL?: string;
  BOOTSTRAP_TOKEN?: string;
  GITFOR_LOCAL?: string;
  PUBLIC_URL?: string;
};

const MIN_BOOTSTRAP_TOKEN_LENGTH = 16;

export function isAdminEmail(email: string, vars: BootstrapVars = env): boolean {
  const configured = (vars.ADMIN_EMAIL ?? "").trim().toLowerCase();
  return configured !== "" && email.trim().toLowerCase() === configured;
}

/** A one-time BOOTSTRAP_TOKEN secret; too-short values are ignored so a placeholder can't be guessed. */
export function validBootstrapToken(presented: string | null | undefined, vars: BootstrapVars = env): boolean {
  const secret = vars.BOOTSTRAP_TOKEN ?? "";
  if (secret.length < MIN_BOOTSTRAP_TOKEN_LENGTH || !presented) return false;
  return timingSafeEqualStrings(presented, secret);
}

/**
 * Who may become the instance's first admin at signup (DEPLOY-P3 / AUTH-P5): whoever presents the
 * BOOTSTRAP_TOKEN, or on loopback dev only, simply the first account. ADMIN_EMAIL is not trusted here because
 * the address is unverified at signup; `promoteAdminEmailOnVerify` grants it once the address is proven.
 */
export function mayBootstrapAdminAtSignup(
  bootstrapToken: string | null | undefined,
  vars: BootstrapVars = env,
): boolean {
  return validBootstrapToken(bootstrapToken, vars) || isLocalDev(vars);
}

/**
 * Which first signup may bypass SIGNUPS_ENABLED=false: only one that could become admin right away. ADMIN_EMAIL
 * does not qualify, since anyone can type it and would then hold the single bootstrap slot unverified.