From 31378810c3a0536a5d7f62dabe66b4762dda4436 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 02:29:15 +0000 Subject: [PATCH 1/2] Initial plan From e1c4aab822c9af1a6a13b09898331467a97bc385 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 02:37:43 +0000 Subject: [PATCH 2/2] Add tests for requireWriteScope middleware Co-authored-by: rickyrombo <3690498+rickyrombo@users.noreply.github.com> --- api/auth_middleware_test.go | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/api/auth_middleware_test.go b/api/auth_middleware_test.go index 98d8d651..d7edebe7 100644 --- a/api/auth_middleware_test.go +++ b/api/auth_middleware_test.go @@ -315,6 +315,50 @@ func TestGetApiSignerWithApiAccessKey(t *testing.T) { "body %s should contain address %s", string(body), parentApiKey) } +func TestRequireWriteScope(t *testing.T) { + // requireWriteScope only reads c.Locals("oauthScope"), so no DB is needed. + app := &ApiServer{} + + // Create a dummy write route that chains requireWriteScope after a scope-setting middleware + testApp := fiber.New() + testApp.Post("/write", func(c *fiber.Ctx) error { + // Simulate what authMiddleware does: set oauthScope if a PKCE token was used + scope := c.Get("X-Test-Oauth-Scope") + if scope != "" { + c.Locals("oauthScope", scope) + } + return c.Next() + }, app.requireWriteScope, func(c *fiber.Ctx) error { + return c.SendStatus(fiber.StatusOK) + }) + + // PKCE token with scope=read should be rejected (403) + t.Run("read scope rejected", func(t *testing.T) { + req := httptest.NewRequest("POST", "/write", nil) + req.Header.Set("X-Test-Oauth-Scope", "read") + res, err := testApp.Test(req, -1) + assert.NoError(t, err) + assert.Equal(t, fiber.StatusForbidden, res.StatusCode) + }) + + // PKCE token with scope=write should be allowed (200) + t.Run("write scope allowed", func(t *testing.T) { + req := httptest.NewRequest("POST", "/write", nil) + req.Header.Set("X-Test-Oauth-Scope", "write") + res, err := testApp.Test(req, -1) + assert.NoError(t, err) + assert.Equal(t, fiber.StatusOK, res.StatusCode) + }) + + // Non-OAuth auth (no oauthScope set) should pass through (200) + t.Run("non-oauth auth passes through", func(t *testing.T) { + req := httptest.NewRequest("POST", "/write", nil) + res, err := testApp.Test(req, -1) + assert.NoError(t, err) + assert.Equal(t, fiber.StatusOK, res.StatusCode) + }) +} + // ensureApiKeysTables creates api_keys and api_access_keys if they do not exist. func ensureApiKeysTables(t *testing.T, app *ApiServer, ctx context.Context) { t.Helper()