spb/chat-spboucher-ai
Public
1import { z } from "zod";2import { guarded, json, body } from "@/lib/api";3import { sql, setSetting } from "@/lib/db";4import { hashPassword, verifyPassword, revokeAllSessions } from "@/lib/auth";5import { TOOLS } from "@/lib/tools";6import { env } from "@/lib/env";78export const GET = guarded(async () => {9 const rows = await sql<{ key: string; value: unknown }[]>`SELECT key, value FROM settings`;10 const settings = Object.fromEntries(rows.map(r => [r.key, r.value]));11 const owner = await sql<{ username: string; created_at: Date; totp_secret: string | null }[]>`SELECT username, created_at, totp_secret FROM owner WHERE id = 1`;12 return json({ settings, owner: owner[0] ? { username: owner[0].username, createdAt: owner[0].created_at, totp: !!owner[0].totp_secret } : null,13 tools: TOOLS.map(t => ({ name: t.name, description: t.description, permission: t.permission, category: t.category })),14 integrations: { openai: !!env.OPENAI_API_KEY, anthropic: !!env.ANTHROPIC_API_KEY, tavily: !!env.TAVILY_API_KEY } });15});1617export const PATCH = guarded(async (req, { session }) => {18 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() }));19 if (b.password) {20 const o = await sql<{ password_hash: string }[]>`SELECT password_hash FROM owner WHERE id = 1`;21 if (!o[0] || !(await verifyPassword(o[0].password_hash, b.password.current))) return json({ error: "Mot de passe actuel invalide" }, { status: 403 });22 await sql`UPDATE owner SET password_hash = ${await hashPassword(b.password.next)}, updated_at = now() WHERE id = 1`;23 await revokeAllSessions(session.id);24 return json({ ok: true, note: "Mot de passe changé ; autres sessions révoquées." });25 }26 if (b.key && b.value !== undefined) { await setSetting(b.key, b.value); return json({ ok: true }); }27 return json({ error: "Rien à modifier" }, { status: 400 });28});29