import { z } from "zod"; import { guarded, json, body } from "@/lib/api"; import { sql, setSetting } from "@/lib/db"; import { hashPassword, verifyPassword, revokeAllSessions } from "@/lib/auth"; import { TOOLS } from "@/lib/tools"; import { env } from "@/lib/env"; export const GET = guarded(async () => { const rows = await sql<{ key: string; value: unknown }[]>`SELECT key, value FROM settings`; const settings = Object.fromEntries(rows.map(r => [r.key, r.value])); const owner = await sql<{ username: string; created_at: Date; totp_secret: string | null }[]>`SELECT username, created_at, totp_secret FROM owner WHERE id = 1`; return json({ settings, owner: owner[0] ? { username: owner[0].username, createdAt: owner[0].created_at, totp: !!owner[0].totp_secret } : null, tools: TOOLS.map(t => ({ name: t.name, description: t.description, permission: t.permission, category: t.category })), integrations: { openai: !!env.OPENAI_API_KEY, anthropic: !!env.ANTHROPIC_API_KEY, tavily: !!env.TAVILY_API_KEY } }); }); export const PATCH = guarded(async (req, { session }) => { const b = await body(req, z.object({ key: z.string().max(40).optional(), value: z.unknown().optional(), password: z.object({ current: z.string(), next: z.string().min(12).max(1000) }).optional() })); if (b.password) { const o = await sql<{ password_hash: string }[]>`SELECT password_hash FROM owner WHERE id = 1`; if (!o[0] || !(await verifyPassword(o[0].password_hash, b.password.current))) return json({ error: "Mot de passe actuel invalide" }, { status: 403 }); await sql`UPDATE owner SET password_hash = ${await hashPassword(b.password.next)}, updated_at = now() WHERE id = 1`; await revokeAllSessions(session.id); return json({ ok: true, note: "Mot de passe changé ; autres sessions révoquées." }); } if (b.key && b.value !== undefined) { await setSetting(b.key, b.value); return json({ ok: true }); } return json({ error: "Rien à modifier" }, { status: 400 }); });