182 lines · 8.6 KB
import { createServerFn } from "@tanstack/react-start";
import { isTakenDown } from "~/lib/account-disable";
import type { Viewer } from "~/lib/types";
import { z } from "zod";
import { requireViewer, viewerMiddleware } from "./middleware";
import { all, batch, first, run, stmt } from "~/server/db";
import { assertBelowCap, CAPS, enforceRateLimit, limitBrowse, limitWrite, limitAccountWrite } from "~/server/limits";
import { assertOwnerNotDisabled, canAdministerAccount, requireRepoAccess } from "~/server/repos";
import { assertCanTransfer } from "~/server/fork-policy";
import { accountNameTaken } from "~/server/accounts";
import { profileReadme } from "~/server/profiles";
import { recordActivity } from "~/server/events/emit";
import { repoMoveStatements } from "~/server/redirects";
import { disableRepoConfigOnTransfer, repoOwnershipChangeStatements } from "~/server/integrations/ownership";
import { rebillRepoLfs } from "~/server/lfs/objects";
import { syncHostingForRepo, syncSitesForOwner } from "~/server/sites/sync";
import { confirmPassword } from "~/server/account-security";
import { badRequest, conflict, forbidden, notFoundError } from "~/server/errors";
import { accountName, repoRef } from "~/lib/validation";
import { userChanged } from "~/server/user-row";
import { isSupporter } from "~/server/supporter";

const FOLLOW_PAGE = 100;

async function accountByName(name: string, viewer: Viewer | null) {
  const account = await first<{
    id: string;
    name: string;
    kind: "user" | "org";
    avatar_key: string | null;
    disabled_at: number | null;
    disabled_reason: string | null;
  }>("SELECT id, name, kind, avatar_key, disabled_at, disabled_reason FROM accounts WHERE name = ?", name);
  if (!account || (isTakenDown(account) && !viewer?.isAdmin)) throw notFoundError("Account not found");
  return account;
}

export const getProfileExtras = createServerFn({ method: "GET" })
  .middleware([viewerMiddleware])
  .validator(z.object({ name: z.string().min(1).max(64) }))