import { describe, test, expect, mock, beforeEach } from "bun:test"; import { Hono } from "hono"; // We test the authMiddleware in isolation by importing and mounting it on a // minimal Hono app, without touching the real session/user layer. // Mock the managers and modules that authMiddleware depends on mock.module("../../../src/managers/sessions", () => ({ sessions: { fetch: mock(), }, })); mock.module("../../../src/modules/globalEvents", () => ({ events: { emit: mock(), on: mock(), any: mock(), }, })); import { authMiddleware } from "../../../src/api/middleware/authorization"; import { sessions } from "../../../src/managers/sessions"; import { apiResponse } from "../../../src/modules/api-utils/apiResponse"; function createTestApp(permParams?: Parameters[0]) { const app = new Hono(); app.onError((err, c) => { const response = apiResponse.error(err); return c.json(response, response.status); }); app.use("*", authMiddleware(permParams)); app.get("/test", (c) => c.json({ ok: true })); return app; } describe("authMiddleware", () => { beforeEach(() => { // Reset mocks (sessions.fetch as any).mockReset?.(); }); // ------------------------------------------------------------------- // Missing authorization header // ------------------------------------------------------------------- test("rejects requests without authorization header", async () => { const app = createTestApp(); const res = await app.request("/test"); expect(res.status).toBe(401); const body: any = await res.json(); expect(body.error).toBe("AuthorizationError"); expect(body.message).toContain("authorization"); }); // ------------------------------------------------------------------- // Malformed authorization header // ------------------------------------------------------------------- test("rejects malformed authorization header", async () => { const app = createTestApp(); const res = await app.request("/test", { headers: { Authorization: "foobar" }, }); expect(res.status).toBe(401); const body: any = await res.json(); expect(body.error).toBe("AuthorizationError"); expect(body.message).toContain("malformed"); }); test("rejects authorization missing token value", async () => { const app = createTestApp(); const res = await app.request("/test", { headers: { Authorization: "Bearer " }, }); expect(res.status).toBeGreaterThanOrEqual(400); const body: any = await res.json(); expect(body.successful).toBe(false); }); // ------------------------------------------------------------------- // Forbidden auth types // ------------------------------------------------------------------- test("rejects forbidden auth types", async () => { const app = createTestApp({ forbiddenAuthTypes: ["Key"] }); const res = await app.request("/test", { headers: { Authorization: "Key aaa.bbb.ccc" }, }); expect(res.status).toBe(403); const body: any = await res.json(); expect(body.error).toBe("NonpermittedAuthType"); }); // ------------------------------------------------------------------- // Valid token flow // ------------------------------------------------------------------- test("calls sessions.fetch with access token", async () => { const mockUser = { hasPermission: mock(() => Promise.resolve(true)), }; const mockSession = { fetchUser: mock(() => Promise.resolve(mockUser)), }; (sessions.fetch as any).mockResolvedValue?.(mockSession) ?? ((sessions as any).fetch = mock(() => Promise.resolve(mockSession))); const app = createTestApp(); const res = await app.request("/test", { headers: { Authorization: "Bearer aaa.bbb.ccc" }, }); // If sessions.fetch resolves, the middleware should pass through expect(res.status).toBe(200); }); // ------------------------------------------------------------------- // Permission checking // ------------------------------------------------------------------- test("rejects when user lacks required permission", async () => { const mockUser = { hasPermission: mock(() => Promise.resolve(false)), }; const mockSession = { fetchUser: mock(() => Promise.resolve(mockUser)), }; (sessions as any).fetch = mock(() => Promise.resolve(mockSession)); const app = createTestApp({ permissions: ["admin.super"] }); const res = await app.request("/test", { headers: { Authorization: "Bearer aaa.bbb.ccc" }, }); expect(res.status).toBe(403); const body: any = await res.json(); expect(body.message).toContain("permission"); }); test("allows when user has all required permissions", async () => { const mockUser = { hasPermission: mock(() => Promise.resolve(true)), }; const mockSession = { fetchUser: mock(() => Promise.resolve(mockUser)), }; (sessions as any).fetch = mock(() => Promise.resolve(mockSession)); const app = createTestApp({ permissions: ["company.fetch", "company.list"], }); const res = await app.request("/test", { headers: { Authorization: "Bearer aaa.bbb.ccc" }, }); expect(res.status).toBe(200); }); test("passes through when no permissions required", async () => { const mockUser = { hasPermission: mock(() => Promise.resolve(true)) }; const mockSession = { fetchUser: mock(() => Promise.resolve(mockUser)) }; (sessions as any).fetch = mock(() => Promise.resolve(mockSession)); const app = createTestApp(); const res = await app.request("/test", { headers: { Authorization: "Bearer aaa.bbb.ccc" }, }); expect(res.status).toBe(200); }); });