Merge pull request 'gitea: the package team may read code, and its units are reconciled' (#72) from fix/gitea-package-team-reads-code into main
This commit was merged in pull request #72.
This commit is contained in:
+24
-14
@@ -352,24 +352,34 @@ export class GiteaAdmin {
|
|||||||
GiteaAdmin.fail("/orgs", res);
|
GiteaAdmin.fail("/orgs", res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Ensure the org's package team exists, granting read+write on packages, and return its id. The
|
/** Ensure the org's package team exists with exactly these units, and return its id. Found or
|
||||||
* team is found by name if it is already there, created otherwise; a lost create race is resolved
|
* created, the units are applied either way — a team is configuration the reconcile loop owns,
|
||||||
* by re-listing. */
|
* the same as a user's password, so a unit this code gains reaches a team that already exists
|
||||||
|
* rather than only the next mesh raised from scratch. A lost create race is resolved by
|
||||||
|
* re-listing. */
|
||||||
async ensureTeam(org: string, team: string, packageWrite: boolean): Promise<number> {
|
async ensureTeam(org: string, team: string, packageWrite: boolean): Promise<number> {
|
||||||
|
// The units a consumer needs, and no more. `units_map` is exhaustive — a unit not named is a
|
||||||
|
// unit the team does not have — so code read must be said here: without it gitea answers a
|
||||||
|
// member's clone of a private repository with "not found", which is how the builder's first
|
||||||
|
// credentialed clone failed against a team that named only packages.
|
||||||
|
const units = {
|
||||||
|
permission: "read",
|
||||||
|
units_map: { "repo.code": "read", "repo.packages": packageWrite ? "write" : "read" },
|
||||||
|
includes_all_repositories: true,
|
||||||
|
can_create_org_repo: false,
|
||||||
|
};
|
||||||
const found = await this.findTeam(org, team);
|
const found = await this.findTeam(org, team);
|
||||||
if (found !== null) return found;
|
if (found !== null) {
|
||||||
|
const patch = await this.request(`/teams/${found}`, {
|
||||||
|
method: "PATCH",
|
||||||
|
body: JSON.stringify({ name: team, ...units }),
|
||||||
|
});
|
||||||
|
if (patch.status === 200) return found;
|
||||||
|
GiteaAdmin.fail(`/teams/${found}`, patch);
|
||||||
|
}
|
||||||
const res = await this.request(`/orgs/${encodeURIComponent(org)}/teams`, {
|
const res = await this.request(`/orgs/${encodeURIComponent(org)}/teams`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({ name: team, ...units }),
|
||||||
name: team,
|
|
||||||
permission: "read",
|
|
||||||
// Package access is a per-unit grant; the team needs write on the packages unit and nothing
|
|
||||||
// else. includes_all_repositories keeps the team's repo view whole without widening its
|
|
||||||
// repo permission beyond read.
|
|
||||||
units_map: { "repo.packages": packageWrite ? "write" : "read" },
|
|
||||||
includes_all_repositories: true,
|
|
||||||
can_create_org_repo: false,
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
if (res.status === 201) return Number(res.body?.id);
|
if (res.status === 201) return Number(res.body?.id);
|
||||||
if (res.status === 422 || res.status === 409) {
|
if (res.status === 422 || res.status === 409) {
|
||||||
|
|||||||
Reference in New Issue
Block a user