29 lines · 1.3 KB
import { first } from "../db";
import { forbidden, notFoundError } from "../errors";
import { canAdministerAccount, requireRepoAccess } from "../repos";
import type { Viewer } from "~/lib/types";

export type ScopeRef = { owner: string; repo: string | null };
export type ResolvedScope = { scopeType: "repo" | "org"; scopeId: string; label: string; settingsPath: string };

/** Repo integrations need repo admin; org integrations need org ownership. */
export async function requireIntegrationScope(ref: ScopeRef, viewer: Viewer | null): Promise<ResolvedScope> {
  if (!viewer) throw forbidden("Sign in to manage integrations");
  if (ref.repo) {
    const { repo } = await requireRepoAccess(ref.owner, ref.repo, viewer, "admin");
    return {
      scopeType: "repo",
      scopeId: repo.id,
      label: `${repo.owner_name}/${repo.name}`,
      settingsPath: `/${repo.owner_name}/${repo.name}/settings/integrations`,
    };
  }
  const org = await first<{ id: string; name: string }>(
    "SELECT id, name FROM accounts WHERE name = ? AND kind = 'org'",
    ref.owner,
  );
  if (!org) throw notFoundError("Organization not found");
  if (!(await canAdministerAccount(org.id, viewer))) throw forbidden();
  return { scopeType: "org", scopeId: org.id, label: org.name, settingsPath: `/orgs/${org.name}/integrations` };
}