Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/openstatus. ๐ซ Status page with uptime monitoring & API monitoring as code ๐ซ openstatus.dev
bun drizzle-orm monitoring monitoring-as-code nextjs observability on-call open-source shadcn-ui status-page statuspage synthetic-monitoring tinybird turso uptime uptime-checker uptime-monitor
Something went wrong. Try again.
3.0 kB ยท 86 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687import type { Scope } from "@openstatus/db/src/schema";import { expect } from "@std/expect";import { describe, test } from "@std/testing/bdd";import { Hono } from "hono";
import type { Variables } from "@/types";
import { requireWriteScope } from "./require-scope";
/** * Spin up a minimal Hono app, pre-populate `apiKey` (simulating * `authMiddleware` having already run), mount `requireWriteScope`, * and exercise it with a real `app.request`. Closer to the production * shape than calling the middleware function directly with a mock * context. */function makeApp(scopes: Scope[] | undefined): Hono<{ Variables: Variables }> { const app = new Hono<{ Variables: Variables }>(); app.use("*", async (c, next) => { if (scopes !== undefined) { c.set("apiKey", { id: "test-key", createdById: 1, scopes, }); } await next(); }); app.use("*", requireWriteScope()); app.get("/r", (c) => c.text("ok-get")); app.post("/r", (c) => c.text("ok-post")); app.put("/r", (c) => c.text("ok-put")); app.delete("/r", (c) => c.text("ok-delete")); return app;}
describe("requireWriteScope", () => { test("GET passes for read-only key", async () => { const res = await makeApp(["read"]).request("/r", { method: "GET" }); expect(res.status).toBe(200); });
test("HEAD passes for read-only key", async () => { const res = await makeApp(["read"]).request("/r", { method: "HEAD" }); expect(res.status).toBe(200); });
test("POST returns 403 for read-only key", async () => { const res = await makeApp(["read"]).request("/r", { method: "POST" }); expect(res.status).toBe(403); });
test("PUT returns 403 for read-only key", async () => { const res = await makeApp(["read"]).request("/r", { method: "PUT" }); expect(res.status).toBe(403); });
test("DELETE returns 403 for read-only key", async () => { const res = await makeApp(["read"]).request("/r", { method: "DELETE" }); expect(res.status).toBe(403); });
test("POST passes for write key", async () => { const res = await makeApp(["write"]).request("/r", { method: "POST" }); expect(res.status).toBe(200); });
test("POST passes for super-admin '*' key", async () => { const res = await makeApp(["*"]).request("/r", { method: "POST" }); expect(res.status).toBe(200); });
test("POST returns 403 for empty scopes (fail-closed)", async () => { const res = await makeApp([]).request("/r", { method: "POST" }); expect(res.status).toBe(403); });
test("missing apiKey defers to upstream (no 403, would be 401 in prod)", async () => { // `requireWriteScope` is not the auth gate โ when `apiKey` isn't // set, it must let the request flow on so `authMiddleware` (in // prod) can return its own 401 instead of this layer returning a // confusing 403. const res = await makeApp(undefined).request("/r", { method: "POST" }); expect(res.status).toBe(200); });});