feat: add auth middleware for write endpoint protection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-03 13:22:00 +02:00
parent 7c4fa9d9d2
commit 8138458d8d
2 changed files with 124 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
import { beforeEach, describe, expect, test } from "bun:test";
import { Hono } from "hono";
import { requireAuth } from "../../src/server/middleware/auth";
import {
createApiKey,
createSession,
createUser,
} from "../../src/server/services/auth.service";
import { createTestDb } from "../helpers/db";
let db: ReturnType<typeof createTestDb>;
beforeEach(() => {
db = createTestDb();
});
function createApp() {
const app = new Hono<{ Variables: { db?: any } }>();
app.use("*", async (c, next) => {
c.set("db", db);
await next();
});
// Public GET
app.get("/items", (c) => c.json({ ok: true }));
// Protected POST
app.post("/items", requireAuth, (c) => c.json({ ok: true }));
return app;
}
describe("auth middleware", () => {
test("allows GET requests without auth (middleware not applied to GET)", async () => {
const app = createApp();
const res = await app.request("/items");
expect(res.status).toBe(200);
});
test("returns 403 setup_required when no users exist", async () => {
const app = createApp();
const res = await app.request("/items", { method: "POST" });
expect(res.status).toBe(403);
const body = await res.json();
expect(body.error).toBe("setup_required");
});
test("rejects POST without auth when users exist", async () => {
const app = createApp();
await createUser(db, "admin", "pass");
const res = await app.request("/items", { method: "POST" });
expect(res.status).toBe(401);
});
test("allows POST with valid session cookie", async () => {
const app = createApp();
const user = await createUser(db, "admin", "pass");
const session = createSession(db, user.id);
const res = await app.request("/items", {
method: "POST",
headers: { Cookie: `gearbox_session=${session.id}` },
});
expect(res.status).toBe(200);
});
test("allows POST with valid API key", async () => {
const app = createApp();
await createUser(db, "admin", "pass");
const key = await createApiKey(db, "test");
const res = await app.request("/items", {
method: "POST",
headers: { "X-API-Key": key.rawKey },
});
expect(res.status).toBe(200);
});
test("rejects POST with invalid API key", async () => {
const app = createApp();
await createUser(db, "admin", "pass");
const res = await app.request("/items", {
method: "POST",
headers: { "X-API-Key": "invalid" },
});
expect(res.status).toBe(401);
});
});