import { env } from "cloudflare:workers";
import { all, first, run } from "./db";
import { forbidden, notFoundError } from "./errors";
import { disabledMessage } from "~/lib/account-disable";
import type { DisableReason, DisabledNotice } from "~/lib/account-disable";
import { userChanged } from "./user-row";
export type AccountDisableState = { reason: string; at: number; note: string | null };
export type DisabledAccount = {
id: string;
name: string;
kind: string;
reason: string;
note: string | null;
disabledAt: number;
};
/** SUPPORT_EMAIL, else the legal contact, so a forge without a dedicated inbox still shows a way back in. */
export function supportEmail(): string | null {
return env.SUPPORT_EMAIL?.trim() || env.LEGAL_CONTACT_EMAIL?.trim() || null;
}
export function disabledNotice(reason: string): DisabledNotice {
const email = supportEmail();
return { reason, message: disabledMessage(reason, email), supportEmail: email };
}
export async function accountDisableState(accountId: string): Promise<AccountDisableState | null> {
const row = await first<{ disabled_at: number | null; disabled_reason: string | null; disabled_note: string | null }>(
"SELECT disabled_at, disabled_reason, disabled_note FROM accounts WHERE id = ?",
accountId,
);
if (!row || row.disabled_at === null) return null;
return { reason: row.disabled_reason ?? "admin", at: row.disabled_at, note: row.disabled_note };
}
/** Refuses sign-in (and anything else that would hand out a credential) for a disabled account. */
export async function assertAccountActive(accountId: string): Promise<void> {
const state = await accountDisableState(accountId);