From 0861beea8b9a7cc9006ac8b3ba2e234f335f0ca3 Mon Sep 17 00:00:00 2001 From: ghost <49853598+JSONbored@users.noreply.github.com> Date: Tue, 9 Jun 2026 11:19:04 -0600 Subject: [PATCH] fix(api): allow maintainer settings preview sessions --- src/api/routes.ts | 14 ++++++++++++-- test/integration/api.test.ts | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/api/routes.ts b/src/api/routes.ts index 085a029ec5..b675282780 100644 --- a/src/api/routes.ts +++ b/src/api/routes.ts @@ -1647,12 +1647,17 @@ export function createApp() { }); app.post("/v1/repos/:owner/:repo/settings-preview", async (c) => { + const identity = await authenticateRequestIdentity(c); const fullName = `${c.req.param("owner")}/${c.req.param("repo")}`; const body = (await c.req.json().catch(() => null)) ?? {}; const parsed = settingsPreviewSchema.safeParse(body); if (!parsed.success) return c.json({ error: "invalid_settings_preview_request", issues: parsed.error.issues }, 400); - const [repo, settings, issues, pullRequests] = await Promise.all([ - getRepository(c.env, fullName), + const repo = await getRepository(c.env, fullName); + if (identity?.kind === "session") { + const unauthorized = await requireSessionRepoAccess(c, identity, fullName, repo); + if (unauthorized) return unauthorized; + } + const [settings, issues, pullRequests] = await Promise.all([ getRepositorySettings(c.env, fullName), listIssues(c.env, fullName), listPullRequests(c.env, fullName), @@ -3564,12 +3569,17 @@ function canSessionAccessPath(env: Env, identity: Extract { expect((await app.request("/v1/app/operator-dashboard", { headers: ownerHeaders }, ownerEnv)).status).toBe(403); expect((await app.request("/v1/app/analytics/daily-rollups", { headers: ownerHeaders }, ownerEnv)).status).toBe(403); expect((await app.request("/v1/app/analytics/mcp-compatibility", { headers: ownerHeaders }, ownerEnv)).status).toBe(403); + const ownerSettingsPreview = await app.request( + "/v1/repos/repo-owner/owned-repo/settings-preview", + { method: "POST", headers: ownerHeaders, body: JSON.stringify({ sample: { authorLogin: "oktofeesh1", minerStatus: "confirmed" } }) }, + ownerEnv, + ); + expect(ownerSettingsPreview.status).toBe(200); + await expect(ownerSettingsPreview.json()).resolves.toMatchObject({ repoFullName: "repo-owner/owned-repo" }); + const forbiddenVictimSettingsPreview = await app.request( + "/v1/repos/victim-org/secret-repo/settings-preview", + { method: "POST", headers: ownerHeaders, body: JSON.stringify({ sample: { authorLogin: "oktofeesh1", minerStatus: "confirmed" } }) }, + ownerEnv, + ); + expect(forbiddenVictimSettingsPreview.status).toBe(403); + await expect(forbiddenVictimSettingsPreview.json()).resolves.toMatchObject({ error: "forbidden_repo" }); const ownerWeeklyReport = await app.request("/v1/app/analytics/weekly-value-report", { headers: ownerHeaders }, ownerEnv); expect(ownerWeeklyReport.status).toBe(200); const ownerWeeklyReportBody = await ownerWeeklyReport.json();