import { forbidden } from "./errors";
import { canAdministerAccount, canCreateInAccount, hasPermission, repoPermission } from "./repos";
import type { RepoRow, Viewer } from "~/lib/types";
/**
* Who may fork `source` into `target` (GIT-A8 / AZ-A7). Public repositories fork like before. A private
* repository is only forkable by writers, or by readers when its owner enabled `allow_forking`; and the
* copy may only land in the forker's own account or in an organization they administer, so no plain org
* member can hand a private history to every member of an unrelated org.
*/
export async function assertCanFork(source: RepoRow, target: { id: string }, viewer: Viewer): Promise<void> {
if (!(await canCreateInAccount(target.id, viewer))) throw forbidden("You cannot create repositories here");
if (source.visibility === "public") return;
const permission = await repoPermission(source, viewer);
if (!hasPermission(permission, "write") && !(source.allow_forking === 1 && hasPermission(permission, "read"))) {
throw forbidden("Forking this private repository is not allowed");
}
if (target.id !== viewer.id && !(await canAdministerAccount(target.id, viewer))) {
throw forbidden("Private repositories can only be forked into your account or an organization you administer");
}
}