62 lines
2.4 KiB
JavaScript
62 lines
2.4 KiB
JavaScript
import { jest } from "@jest/globals";
|
|
import express from "express";
|
|
import request from "supertest";
|
|
|
|
// Manual mocks: the API-key verifier and the DB pool. No real database, no scrypt
|
|
// — apiMiddleware's branching is what we exercise here.
|
|
const verifyKey = jest.fn();
|
|
const query = jest.fn();
|
|
const release = jest.fn(async () => {});
|
|
jest.unstable_mockModule("../modules/core/apiKey.js", () => ({ verifyKey }));
|
|
jest.unstable_mockModule("../db/index.js", () => ({ getPool: async () => ({ query, release }) }));
|
|
|
|
const { apiMiddleware } = await import("./auth.js");
|
|
|
|
function makeApp() {
|
|
const app = express();
|
|
app.use((req, _res, next) => { req.session = {}; next(); });
|
|
app.get("/probe", apiMiddleware, (req, res) => res.json({ userId: req.session.user_id }));
|
|
return app;
|
|
}
|
|
|
|
beforeEach(() => {
|
|
verifyKey.mockReset();
|
|
query.mockReset();
|
|
release.mockClear();
|
|
});
|
|
|
|
describe("apiMiddleware", () => {
|
|
it("authenticates a valid hashed key and sets req.session.user_id (no legacy lookup)", async () => {
|
|
verifyKey.mockResolvedValue({ user_id: 42, app_id: 1 });
|
|
const res = await request(makeApp()).get("/probe").set("Authorization", "Bearer good-key");
|
|
expect(res.status).toBe(200);
|
|
expect(res.body.userId).toBe(42);
|
|
expect(verifyKey).toHaveBeenCalledWith("good-key");
|
|
expect(query).not.toHaveBeenCalled(); // hashed path short-circuits the legacy fallback
|
|
});
|
|
|
|
it("falls back to the legacy plaintext auth key when the hashed store misses", async () => {
|
|
verifyKey.mockResolvedValue(null);
|
|
query.mockResolvedValue({ rowCount: 1, rows: [{ user_id: 7 }] });
|
|
const res = await request(makeApp()).get("/probe").set("Authorization", "Bearer legacy-key");
|
|
expect(res.status).toBe(200);
|
|
expect(res.body.userId).toBe(7);
|
|
expect(query.mock.calls[0][1]).toEqual(["legacy-key"]);
|
|
expect(release).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it("rejects an unknown key with 401", async () => {
|
|
verifyKey.mockResolvedValue(null);
|
|
query.mockResolvedValue({ rowCount: 0, rows: [] });
|
|
const res = await request(makeApp()).get("/probe").set("Authorization", "Bearer bogus");
|
|
expect(res.status).toBe(401);
|
|
});
|
|
|
|
it("rejects a request with no Authorization header with 401 (no lookups)", async () => {
|
|
const res = await request(makeApp()).get("/probe");
|
|
expect(res.status).toBe(401);
|
|
expect(verifyKey).not.toHaveBeenCalled();
|
|
expect(query).not.toHaveBeenCalled();
|
|
});
|
|
});
|