111 lines · 4.5 KB
import { z } from "zod";
import {
  canListOrgMembers,
  createOrg,
  listMyOrgInvitations,
  listOrgInvitations,
  respondToOrgInvitation,
  setOrgMember,
} from "../accounts";
import { all, first } from "../db";
import { setCollaborator } from "../collaborators";
import { notFoundError } from "../errors";
import { limitWrite, limitAccountWrite } from "../limits";
import { accountNameFormat, displayName } from "~/lib/validation";
import { noContent, readJson, requireAccountScope, requireScopedRepo } from "./http";
import type { ApiContext } from "./http";

async function loadOrg(name: string): Promise<{ id: string; name: string }> {
  const org = await first<{ id: string; name: string }>(
    "SELECT id, name FROM accounts WHERE name = ? AND kind = 'org'",
    name,
  );
  if (!org) throw notFoundError("Organization not found");
  return org;
}

const orgInput = z.object({ name: accountNameFormat, display_name: displayName.default(null) });

/** Mirrors fn:account.createOrganization. */
export async function createOrgApi(ctx: ApiContext): Promise<Response> {
  requireAccountScope(ctx);
  const data = await readJson(ctx.request, orgInput);
  await limitWrite(ctx.viewer);
  await createOrg(data.name, data.display_name, ctx.viewer.id, ctx.viewer);
  return Response.json({ name: data.name }, { status: 201 });
}

/** Org profiles are public. */
export async function getOrgApi(_ctx: ApiContext, orgName: string): Promise<Response> {
  const org = await loadOrg(orgName);