diff --git a/src/server/plugin/Config.ts b/src/server/plugin/Config.ts index 00f6951..a4d5d2f 100644 --- a/src/server/plugin/Config.ts +++ b/src/server/plugin/Config.ts @@ -173,59 +173,73 @@ export class ParsedPluginConfig { * Returns all permission groups used in the Verdacio config. */ private parseConfiguredPackageGroups() { - Object.values(this.config.packages || {}).forEach((packageConfig) => { - ;["access", "publish", "unpublish"] - .flatMap((key) => packageConfig[key]) - .forEach((group) => { - if (typeof group !== "string") { - return - } - - const [providerId, key1, value1, key2, value2, key3] = - group.split("/") + const configuredGroups = Object.values(this.config.packages || {}).flatMap( + (packageConfig) => { + return ["access", "publish", "unpublish"].flatMap((action) => { + const allowedGroups = packageConfig[action] - if (providerId !== "github") { - return null + if (typeof allowedGroups === "string") { + return allowedGroups } - if (key1 === "user" && !key2) { - const parsedUser: ParsedUser = { - group, - user: value1, - } - this.parsedUsers.push(parsedUser) - this.configuredGroupsMap[group] = true + if ( + Array.isArray(allowedGroups) && + allowedGroups.every((group) => typeof group === "string") + ) { + return allowedGroups as string[] } - if (key1 === "org" && key2 === "team" && !key3) { - const parsedTeam: ParsedTeam = { - group, - org: value1, - team: value2, - } - this.parsedTeams.push(parsedTeam) - this.configuredGroupsMap[group] = true - } - - if ((key1 === "org" || key1 === "user") && key2 === "repo" && !key3) { - const parsedRepo: ParsedRepo = { - group, - owner: value1, - repo: value2, - } - this.parsedRepos.push(parsedRepo) - this.configuredGroupsMap[group] = true - } - - if (key1 === "org" && !key2) { - const parsedOrg: ParsedOrg = { - group, - org: value1, - } - this.parsedOrgs.push(parsedOrg) - this.configuredGroupsMap[group] = true - } + return [] }) + }, + ) + + const configuredGroupsDeduped = [...new Set(configuredGroups)] + + configuredGroupsDeduped.forEach((group) => { + const [providerId, key1, value1, key2, value2, key3] = group.split("/") + + if (providerId !== "github") { + return null + } + + if (key1 === "user" && !key2) { + const parsedUser: ParsedUser = { + group, + user: value1, + } + this.parsedUsers.push(parsedUser) + this.configuredGroupsMap[group] = true + } + + if (key1 === "org" && key2 === "team" && !key3) { + const parsedTeam: ParsedTeam = { + group, + org: value1, + team: value2, + } + this.parsedTeams.push(parsedTeam) + this.configuredGroupsMap[group] = true + } + + if ((key1 === "org" || key1 === "user") && key2 === "repo" && !key3) { + const parsedRepo: ParsedRepo = { + group, + owner: value1, + repo: value2, + } + this.parsedRepos.push(parsedRepo) + this.configuredGroupsMap[group] = true + } + + if (key1 === "org" && !key2) { + const parsedOrg: ParsedOrg = { + group, + org: value1, + } + this.parsedOrgs.push(parsedOrg) + this.configuredGroupsMap[group] = true + } }) } } diff --git a/test/server/plugin/Config/ParsedPluginConfig.test.ts b/test/server/plugin/Config/ParsedPluginConfig.test.ts index bb73872..78d958a 100644 --- a/test/server/plugin/Config/ParsedPluginConfig.test.ts +++ b/test/server/plugin/Config/ParsedPluginConfig.test.ts @@ -164,4 +164,93 @@ describe("ParsedPluginConfig", () => { } `) }) + + it("deduplicates package groups", () => { + const enabledPluginConfig = { + enabled: true, + } as any + + const minimalPluginConfig: PluginConfig = { + "client-id": "clientId", + "client-secret": "clientSecret", + token: "token", + "enterprise-origin": "enterpriseOrigin", + } + + const config: Config = { + middlewares: { [pluginKey]: enabledPluginConfig }, + auth: { [pluginKey]: minimalPluginConfig }, + url_prefix: "/verdaccio/", + packages: { + package1a: { access: "$authenticated" }, + package1b: { access: "$authenticated" }, + + package2a: { access: "github/user/TEST_USER" }, + package2b: { access: "github/user/TEST_USER" }, + + package3a: { access: "github/user/TEST_USER/repo/TEST_REPO" }, + package3b: { access: "github/user/TEST_USER/repo/TEST_REPO" }, + + package4a: { access: "github/org/TEST_ORG" }, + package4b: { access: "github/org/TEST_ORG" }, + + package5a: { access: "github/org/TEST_ORG/team/TEST_TEAM" }, + package5b: { access: "github/org/TEST_ORG/team/TEST_TEAM" }, + + package6a: { access: "github/org/TEST_ORG/repo/TEST_REPO" }, + package6b: { access: "github/org/TEST_ORG/repo/TEST_REPO" }, + }, + } as any + + const parsedPluginConfig = new ParsedPluginConfig(config) + + expect(parsedPluginConfig.configuredGroupsMap).toMatchInlineSnapshot(` + { + "github/org/TEST_ORG": true, + "github/org/TEST_ORG/repo/TEST_REPO": true, + "github/org/TEST_ORG/team/TEST_TEAM": true, + "github/user/TEST_USER": true, + "github/user/TEST_USER/repo/TEST_REPO": true, + } + `) + expect(parsedPluginConfig.parsedOrgs).toMatchInlineSnapshot(` + [ + { + "group": "github/org/TEST_ORG", + "org": "TEST_ORG", + }, + ] + `) + expect(parsedPluginConfig.parsedRepos).toMatchInlineSnapshot(` + [ + { + "group": "github/user/TEST_USER/repo/TEST_REPO", + "owner": "TEST_USER", + "repo": "TEST_REPO", + }, + { + "group": "github/org/TEST_ORG/repo/TEST_REPO", + "owner": "TEST_ORG", + "repo": "TEST_REPO", + }, + ] + `) + expect(parsedPluginConfig.parsedTeams).toMatchInlineSnapshot(` + [ + { + "group": "github/org/TEST_ORG/team/TEST_TEAM", + "org": "TEST_ORG", + "team": "TEST_TEAM", + }, + ] + `) + expect(parsedPluginConfig.parsedUsers).toMatchInlineSnapshot(` + [ + { + "group": "github/user/TEST_USER", + "user": "TEST_USER", + }, + ] + `) + }) })