gitea_team_rights: refuse a forge user that does not exist; keep ForgeRepository's doc comment on it (issue 1563)
mesh/delivery merged: source.main moved to novox/mesh-catalog@bf94af0a820f
mesh/check checking 36d59933239e on bf94af0a820f
mesh/delivery merged: source.main moved to novox/mesh-catalog@bf94af0a820f
mesh/check checking 36d59933239e on bf94af0a820f
This commit is contained in:
@@ -9,6 +9,7 @@ import { ConfiguredToken, MintedToken, type TokenSource } from "./token.js";
|
||||
import { MAIN_BRANCH, mainRuleBody, protectionBody, type BranchProtection, type ProtectionWanted } from "./protection.js";
|
||||
import { Refused, checkSentPath, ruleCovers, pathSegment, pathSegments } from "./guard.js";
|
||||
import { isCommit } from "./checks.js";
|
||||
import type { ForgeTeam } from "./teamrights.js";
|
||||
|
||||
/** A repository's path on the forge, its owner and name each one segment (guard.ts pathSegment): uniform for every
|
||||
* call, whether the names came from a caller or from the forge's own answer. */
|
||||
@@ -930,8 +931,6 @@ interface AdminResponse {
|
||||
}
|
||||
|
||||
/** A repository as the site administrator sees it: what saying why an account cannot read it needs (readall.ts). */
|
||||
import type { ForgeTeam } from "./teamrights.js";
|
||||
|
||||
export interface ForgeRepository {
|
||||
full_name: string;
|
||||
owner: string;
|
||||
|
||||
@@ -24,6 +24,7 @@ export interface ForgeTeam {
|
||||
export interface TeamForge {
|
||||
teams(org: string): Promise<ForgeTeam[]>;
|
||||
teamMembers(teamId: number): Promise<string[]>;
|
||||
accountExists(user: string): Promise<boolean>;
|
||||
everyRepository(): Promise<{ full_name: string; owner: string; name: string }[]>;
|
||||
repositoryPermission(owner: string, repo: string, user: string): Promise<string>;
|
||||
}
|
||||
@@ -74,6 +75,7 @@ export interface UserRights {
|
||||
* in and its effective right on every repository (or on those named), as the forge says it. Only reads. */
|
||||
export async function readTeamRights(forge: TeamForge, org: string, opts: { team?: string; user?: string; repositories?: string[]; list?: boolean } = {}):
|
||||
Promise<{ organisation: string; teams: TeamRights[]; user?: UserRights }> {
|
||||
if (opts.user && !(await forge.accountExists(opts.user))) throw new Error(`no forge user ${opts.user}`);
|
||||
const all = await forge.teams(org);
|
||||
const named = opts.team ? all.filter((t) => t.name === opts.team) : all;
|
||||
if (opts.team && !named.length) throw new Error(`no team "${opts.team}" in ${org}: it holds ${all.map((t) => t.name).join(", ") || "none"}`);
|
||||
|
||||
@@ -42,6 +42,8 @@ const server = createServer((req, res) => {
|
||||
if (path === "/orgs/novox/teams") return send(200, teams);
|
||||
const m = path.match(/^\/teams\/(\d+)\/members$/);
|
||||
if (m) return send(200, (members[m[1]] ?? []).map(user));
|
||||
const u = path.match(/^\/users\/([^/]+)$/);
|
||||
if (u) return send(u[1] === "nobody" ? 404 : 200, u[1] === "nobody" ? { message: "not found" } : user(u[1]));
|
||||
if (path === "/repos/search") return send(200, { ok: true, data: repos });
|
||||
const r = path.match(/^\/repos\/([^/]+)\/([^/]+)$/);
|
||||
if (r) {
|
||||
@@ -94,3 +96,7 @@ test("the tools' own token is refused the teams, which is why the administrator'
|
||||
const res = await fetch(`${url}/api/v1/orgs/novox/teams`, { headers: { Authorization: "token tools-token" } });
|
||||
assert.equal(res.status, 403);
|
||||
});
|
||||
|
||||
test("a user the forge does not know is refused, not answered as writing nowhere", async () => {
|
||||
await assert.rejects(run({ user: "nobody" }), /no forge user nobody/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user