import { Router } from "express"; import { db, geminiAccountsTable } from "@workspace/db"; import { eq, desc } from "drizzle-orm"; import { requireAdmin } from "./admin"; import { requireJwtAuth } from "./auth"; const router = Router(); router.use(requireJwtAuth); router.get("/", requireAdmin, async (_req, res) => { const rows = await db .select() .from(geminiAccountsTable) .orderBy(desc(geminiAccountsTable.createdAt)); res.json( rows.map((r) => ({ id: r.id, label: r.label, tokenPreview: r.bearerToken ? r.bearerToken.substring(0, 12) + "..." : null, hasRefreshToken: !!r.refreshToken, isActive: r.isActive, lastUsedAt: r.lastUsedAt?.toISOString() ?? null, createdAt: r.createdAt.toISOString(), })) ); }); router.post("/", requireAdmin, async (req, res) => { const { label, bearerToken, refreshToken } = req.body as { label?: string; bearerToken?: string; refreshToken?: string; }; if (!bearerToken?.trim()) { return res.status(400).json({ error: "bearerToken is required" }); } const [inserted] = await db .insert(geminiAccountsTable) .values({ label: (label || "帳戶").trim(), bearerToken: bearerToken.trim(), refreshToken: refreshToken?.trim() || null, isActive: true, }) .returning(); res.json({ id: inserted.id, label: inserted.label, tokenPreview: inserted.bearerToken.substring(0, 12) + "...", isActive: inserted.isActive, createdAt: inserted.createdAt.toISOString(), }); }); router.patch("/:id/label", requireAdmin, async (req, res) => { const id = Number(req.params.id); const { label } = req.body as { label?: string }; if (!label?.trim()) return res.status(400).json({ error: "label is required" }); await db.update(geminiAccountsTable).set({ label: label.trim() }).where(eq(geminiAccountsTable.id, id)); res.json({ success: true }); }); router.patch("/:id/toggle", requireAdmin, async (req, res) => { const id = Number(req.params.id); const rows = await db.select().from(geminiAccountsTable).where(eq(geminiAccountsTable.id, id)).limit(1); if (!rows.length) return res.status(404).json({ error: "Account not found" }); const newActive = !rows[0].isActive; await db.update(geminiAccountsTable).set({ isActive: newActive }).where(eq(geminiAccountsTable.id, id)); res.json({ success: true, isActive: newActive }); }); router.delete("/:id", requireAdmin, async (req, res) => { const id = Number(req.params.id); await db.delete(geminiAccountsTable).where(eq(geminiAccountsTable.id, id)); res.json({ success: true }); }); export default router;