From a58fb19340456291c5177c4608cf6c61c9976375 Mon Sep 17 00:00:00 2001 From: mptyl Date: Sat, 27 Jun 2026 21:13:26 +0200 Subject: [PATCH] feat(backend): pluggable auth (none/mock/oidc seam) - authPreHandler(mode) returns Fastify preHandler that sets req.user={id} - none: uses dev@local - mock: reads x-mock-user header - oidc: MVP stub returns 501 + throws - getUser(req) returns user object Co-Authored-By: Claude Opus 4.8 --- backend/src/auth/auth.ts | 20 ++++++++++++++++++++ backend/test/auth.test.ts | 24 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 backend/src/auth/auth.ts create mode 100644 backend/test/auth.test.ts diff --git a/backend/src/auth/auth.ts b/backend/src/auth/auth.ts new file mode 100644 index 00000000..00615667 --- /dev/null +++ b/backend/src/auth/auth.ts @@ -0,0 +1,20 @@ +import type { FastifyRequest, FastifyReply } from "fastify"; + +export function authPreHandler(mode: "none" | "mock" | "oidc") { + return async (req: FastifyRequest, reply: FastifyReply) => { + if (mode === "none") { + (req as any).user = { id: "dev@local" }; + } else if (mode === "mock") { + (req as any).user = { + id: (req.headers["x-mock-user"] as string) ?? "mock", + }; + } else { + reply.code(501); + throw new Error("OIDC non configurato (MVP: usa none/mock)"); + } + }; +} + +export function getUser(req: FastifyRequest): { id: string } { + return (req as any).user ?? { id: "dev@local" }; +} diff --git a/backend/test/auth.test.ts b/backend/test/auth.test.ts new file mode 100644 index 00000000..7a68ac3a --- /dev/null +++ b/backend/test/auth.test.ts @@ -0,0 +1,24 @@ +import { test, expect } from "vitest"; +import Fastify from "fastify"; +import { authPreHandler, getUser } from "../src/auth/auth.js"; + +test("mode none assegna dev@local", async () => { + const app = Fastify(); + app.addHook("preHandler", authPreHandler("none")); + app.get("/me", async (req) => getUser(req)); + expect((await app.inject({ method: "GET", url: "/me" })).json()).toEqual({ + id: "dev@local", + }); +}); + +test("mode mock legge l'header", async () => { + const app = Fastify(); + app.addHook("preHandler", authPreHandler("mock")); + app.get("/me", async (req) => getUser(req)); + const res = await app.inject({ + method: "GET", + url: "/me", + headers: { "x-mock-user": "alice" }, + }); + expect(res.json()).toEqual({ id: "alice" }); +});