403 lines · 18.8 KB
import { all, batch, first, run, stmt } from "./db";
import { accountDb, repoDb, type ScopedValue } from "./scoped-db";
import { forgetLocator, type LocatorKind } from "./scoped-db/locators";
import { revokeAccessTokensWhere } from "./access-token-store";
import { revokeAllDeployTokensCreatedBy } from "./deploy-token-index";
import { forEachScope } from "./account-scope";
import { invitationOrgs } from "./invitation-index";
import { hashPassword, passwordNeedsRehash, randomToken, verifyPassword } from "./crypto";
import { consumeAuthToken, findAuthToken, storeAuthToken } from "./auth-tokens";
import { deleteUserSessions, sessionCreatedAt } from "./auth";
import { enforceHourlyLimit, enforceRateLimit, HOURLY } from "./limits";
import { emailTemplates, queueEmail } from "./email";
import { publicUrl } from "./events/emit";
import { badRequest, conflict } from "./errors";
import { promoteAdminEmailOnVerify, reclaimUnverifiedEmail } from "./accounts";
import { invalidateUserSignatures } from "./security/signatures";
import { dropMcpAccess } from "./access-revocation";
import { recordAdminAction } from "./admin-audit";
import { userChanged } from "./user-row";

const VERIFY_TTL_SECONDS = 60 * 60 * 24;
const RESET_TTL_SECONDS = 60 * 60;

type VerifyPayload = { email: string };
type SpentReason = "used" | "superseded";
/** `viaPrimary` is false when the link went to one of the user's other verified addresses. */
type ResetPayload = { passwordHash: string | null; viaPrimary: boolean };

function parseVerify(raw: string): VerifyPayload {
  const parsed: unknown = JSON.parse(raw);
  const email = typeof parsed === "object" && parsed !== null && "email" in parsed ? parsed.email : null;
  if (typeof email !== "string") throw badRequest("This verification link is invalid");
  return { email };
}

function parseReset(raw: string): ResetPayload {
  const parsed: unknown = JSON.parse(raw);
  const hash = typeof parsed === "object" && parsed !== null && "passwordHash" in parsed ? parsed.passwordHash : null;
  const viaPrimary =
    typeof parsed === "object" && parsed !== null && "viaPrimary" in parsed ? parsed.viaPrimary !== false : true;