diff --git a/README.md b/README.md index 4d7010b8..1473f24d 100644 --- a/README.md +++ b/README.md @@ -102,9 +102,14 @@ Set this if you are using GitHub Enterprise. Example: `https://github.example.co The following groups are added during login and can be used to configure package permissions: - `$authenticated` +- `github/owner/GITHUB_ORG` for every GitHub org the user is a member of +- `github/owner/GITHUB_ORG/team/GITHUB_TEAM` for every GitHub team the user is a member of +- `github/owner/GITHUB_ORG/repo/GITHUB_REPO` for every GitHub repository the user has access to + +These groups are deprecated but still work: + - `github/GITHUB_ORG` for every GitHub org the user is a member of -- `github/GITHUB_ORG/team/GITHUB_TEAM` for every GitHub team the user is a member of -- `github/GITHUB_ORG/repo/GITHUB_REPO` for every GitHub repository the user has access to +- `github/GITHUB_ORG/GITHUB_TEAM` for every GitHub team the user is a member of You can use these groups as shown below: @@ -115,13 +120,13 @@ packages: access: $authenticated # limit actions to org members - publish: github/GITHUB_ORG + publish: github/owner/GITHUB_ORG # limit actions to team members - unpublish: github/GITHUB_ORG/team/GITHUB_TEAM + unpublish: github/owner/GITHUB_ORG/team/GITHUB_TEAM bar: # limit actions to repository members (does not work for outside collaborators) - access: github/GITHUB_ORG/repo/GITHUB_REPO + access: github/owner/GITHUB_ORG/repo/GITHUB_REPO ``` See [Package Access](https://verdaccio.org/docs/en/packages) for more examples. diff --git a/src/server/github/AuthProvider.ts b/src/server/github/AuthProvider.ts index b67c031b..a5704a56 100644 --- a/src/server/github/AuthProvider.ts +++ b/src/server/github/AuthProvider.ts @@ -57,6 +57,26 @@ export class GitHubAuthProvider implements AuthProvider { return user.data.login } + createOwnerGroup(orgName: string) { + return `${this.getId()}/owner/${orgName}` + } + + createTeamGroup(orgName: string, teamName: string) { + return `${this.createOwnerGroup(orgName)}/team/${teamName}` + } + + createRepoGroup(ownerName: string, repoName: string) { + return `${this.createOwnerGroup(ownerName)}/repo/${repoName}` + } + + createLegacyOrgGroup(orgName: string) { + return `${this.getId()}/${orgName}` + } + + createLegacyTeamGroup(orgName: string, teamName: string) { + return `${this.createLegacyOrgGroup(orgName)}/team/${teamName}` + } + async getGroups(token: string) { const [orgs, teams, repos] = await Promise.all([ this.client.requestUserOrgs(token), @@ -64,17 +84,27 @@ export class GitHubAuthProvider implements AuthProvider { this.client.requestUserRepos(token), ]) - const orgGroups = orgs.map((org) => `github/${org.login}`) - const legacyTeamGroups = teams.map( - (team) => `github/${team.organization?.login}/${team.name}`, + const orgGroups = orgs.map((org) => this.createOwnerGroup(org.login)) + const teamGroups = teams.map((team) => + this.createTeamGroup(team.organization?.login, team.name), + ) + const repoGroups = repos.map((repo) => + this.createRepoGroup(repo.owner.login, repo.name), ) - const teamGroups = teams.map( - (team) => `github/${team.organization?.login}/team/${team.name}`, + const userGroup = this.createOwnerGroup(username) + const legacyOrgGroups = orgs.map((org) => + this.createLegacyOrgGroup(org.login), ) - const repoGroups = repos.map( - (repo) => `github/${repo.owner?.login}/repo/${repo.name}`, + const legacyTeamGroups = teams.map((team) => + this.createLegacyTeamGroup(team.organization.login, team.name), ) - return [...orgGroups, ...legacyTeamGroups, ...teamGroups, ...repoGroups] + return [ + ...orgGroups, + ...teamGroups, + ...repoGroups, + ...legacyOrgGroups, + ...legacyTeamGroups, + ] } } diff --git a/test/server/plugin/Core/createAuthenticatedUser.test.ts b/test/server/plugin/Core/createAuthenticatedUser.test.ts index 67f81773..741d3f47 100644 --- a/test/server/plugin/Core/createAuthenticatedUser.test.ts +++ b/test/server/plugin/Core/createAuthenticatedUser.test.ts @@ -51,12 +51,15 @@ describe("AuthCore", () => { }, }) - const user = await core.createAuthenticatedUser(username, providerGroups) + const user = await core.createAuthenticatedUser( + testUsername, + providerGroups, + ) expect(user.real_groups).toMatchInlineSnapshot(` Array [ + "github/owner/test-org", "test-username", - "github/test-org", ] `) }) diff --git a/test/utils.ts b/test/utils.ts index 5de06c06..837d8525 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -9,20 +9,39 @@ import { Verdaccio } from "src/server/verdaccio/Verdaccio" import timekeeper from "timekeeper" import Auth from "verdaccio/build/lib/auth" -export const testOrg = "github/TEST_ORG" -export const testLegacyTeam = "github/TEST_ORG/TEST_LEGACY_TEAM" -export const testTeam = "github/TEST_ORG/team/TEST_TEAM" -export const testRepo = "github/TEST_ORG/repo/TEST_REPO" +export const testLoginOrgName = "TEST_LOGIN_ORG" +export const testLoginOrgGroup = `github/owner/${testLoginOrgName}` +export const testOrgGroup = `github/owner/TEST_ORG` +export const testTeamGroup = `${testOrgGroup}/team/TEST_TEAM` +export const testRepoGroup = `${testOrgGroup}/repo/TEST_REPO` +export const testLegacyOrgGroup = "github/TEST_LEGACY_ORG" +export const testLegacyTeamGroup = "github/TEST_LEGACY_ORG/TEST_LEGACY_TEAM" + +export const unrelatedOrgGroup = "github/owner/another_org" +export const unrelatedTeamGroup = `${unrelatedOrgGroup}/team/another_team` +export const unrelatedRepoGroup = `${unrelatedOrgGroup}/repo/another_repo` +export const unrelatedLegacyOrgGroup = "github/another_legacy_org" +export const unrelatedLegacyTeamGroup = + "github/another_legacy_org/another_legacy_team" + export const testProviderGroups = [ - testOrg, - "another_org", - testLegacyTeam, - `${testOrg}/another_legacy_team`, - testTeam, - `${testOrg}/team/another_team`, - testRepo, - `${testOrg}/repo/another_repo`, + // regular groups + testLoginOrgGroup, + testOrgGroup, + testTeamGroup, + testRepoGroup, + // legacy groups + testLegacyOrgGroup, + testLegacyTeamGroup, + // unrelated regular groups + unrelatedOrgGroup, + unrelatedTeamGroup, + unrelatedRepoGroup, + // unrelated legacy groups + unrelatedLegacyOrgGroup, + unrelatedLegacyTeamGroup, ] + export const testClientId = "TEST_CLIENT_ID" export const testClientSecret = "TEST_CLIENT_SECRET" export const testUsername = "test-username"