import type { CreateExpressContextOptions } from "@trpc/server/adapters/express"; import type { User } from "../../drizzle/schema"; import { sdk } from "./sdk"; import { parse as parseCookieHeader } from "cookie"; import { verifyLocalToken, getLocalUserById, LOCAL_AUTH_COOKIE } from "../localAuth"; export type TrpcContext = { req: CreateExpressContextOptions["req"]; res: CreateExpressContextOptions["res"]; user: User | null; }; export async function createContext( opts: CreateExpressContextOptions ): Promise { let user: User | null = null; // 1. Essayer l'authentification Manus OAuth try { user = await sdk.authenticateRequest(opts.req); } catch { user = null; } // 2. Si pas d'utilisateur OAuth, essayer le cookie d'auth locale if (!user) { try { const cookieHeader = opts.req.headers.cookie; if (cookieHeader) { const cookies = parseCookieHeader(cookieHeader); const localToken = cookies[LOCAL_AUTH_COOKIE]; if (localToken) { const payload = await verifyLocalToken(localToken); if (payload) { const localUser = await getLocalUserById(payload.userId); if (localUser && localUser.isActive) { // Construire un objet User compatible avec le type attendu par tRPC // On utilise un openId synthétique basé sur l'id local user = { id: localUser.id, openId: `local:${localUser.id}`, name: localUser.name, email: localUser.email ?? null, loginMethod: "local", role: localUser.role === "admin" ? "admin" : "user", createdAt: localUser.createdAt, updatedAt: localUser.updatedAt, lastSignedIn: localUser.lastSignedIn ?? new Date(), } as User; } } } } } catch (error) { // Auth locale optionnelle — on ignore les erreurs user = null; } } return { req: opts.req, res: opts.res, user, }; }