66 lines
2.0 KiB
TypeScript
66 lines
2.0 KiB
TypeScript
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<TrpcContext> {
|
|
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,
|
|
};
|
|
}
|