import { and, desc, eq } from "drizzle-orm" import { FastifyInstance } from "fastify" import { documentImportItems, documentImportSources } from "../../db/schema" import { decrypt, encrypt } from "../utils/crypt" const decrypted = (value: unknown) => value ? decrypt(value as any) : null export default async function documentImportRoutes(server: FastifyInstance) { const tenantId = (req: any) => { if (!req.user?.tenant_id) throw new Error("Kein aktiver Mandant") return Number(req.user.tenant_id) } const response = (row: any) => ({ id: row.id, name: row.name, provider: row.provider, enabled: row.enabled, mailboxAddress: decrypted(row.mailboxAddressEncrypted), imapHost: decrypted(row.imapHostEncrypted), imapPort: row.imapPort, imapSecure: row.imapSecure, mailboxPath: row.mailboxPath, targetFolderId: row.targetFolderId, defaultFiletypeId: row.defaultFiletypeId, markAsSeen: row.markAsSeen, hasPassword: Boolean(row.passwordEncrypted), lastSyncedAt: row.lastSyncedAt, lastError: row.lastError, createdAt: row.createdAt, ...server.services.documentImports.getSyncStatus(row.id), }) server.get("/document-imports", async (req) => { const rows = await server.db.select().from(documentImportSources) .where(eq(documentImportSources.tenantId, tenantId(req))) .orderBy(documentImportSources.name) return rows.map(response) }) server.get("/document-imports/:id", async (req, reply) => { const { id } = req.params as { id: string } const [row] = await server.db.select().from(documentImportSources).where(and( eq(documentImportSources.id, id), eq(documentImportSources.tenantId, tenantId(req)), )).limit(1) if (!row) return reply.code(404).send({ error: "Importquelle wurde nicht gefunden" }) return response(row) }) server.post("/document-imports/:id?", async (req, reply) => { const currentTenantId = tenantId(req) const { id } = req.params as { id?: string } const body = (req.body || {}) as any if (!body.name?.trim()) return reply.code(400).send({ error: "Name fehlt" }) if ((body.provider || "imap") !== "imap") return reply.code(400).send({ error: "Aktuell wird nur IMAP unterstützt" }) if (!body.mailboxAddress || !body.imapHost) return reply.code(400).send({ error: "Postfachadresse und IMAP-Host sind erforderlich" }) const values: any = { name: body.name.trim(), provider: "imap", enabled: body.enabled !== false, mailboxAddressEncrypted: encrypt(body.mailboxAddress), imapHostEncrypted: encrypt(body.imapHost), imapPort: Number(body.imapPort || 993), imapSecure: body.imapSecure !== false, mailboxPath: body.mailboxPath?.trim() || "INBOX", targetFolderId: body.targetFolderId || null, defaultFiletypeId: body.defaultFiletypeId || null, markAsSeen: body.markAsSeen !== false, updatedAt: new Date(), } if (body.password) values.passwordEncrypted = encrypt(body.password) if (id) { const [existing] = await server.db.select({ id: documentImportSources.id }).from(documentImportSources).where(and( eq(documentImportSources.id, id), eq(documentImportSources.tenantId, currentTenantId), )).limit(1) if (!existing) return reply.code(404).send({ error: "Importquelle wurde nicht gefunden" }) await server.db.update(documentImportSources).set(values).where(eq(documentImportSources.id, id)) return { success: true, id } } if (!body.password) return reply.code(400).send({ error: "Passwort fehlt" }) const [created] = await server.db.insert(documentImportSources).values({ ...values, tenantId: currentTenantId, createdBy: req.user.user_id, }).returning({ id: documentImportSources.id }) return { success: true, id: created.id } }) server.post("/document-imports/:id/test", async (req, reply) => { try { return await server.services.documentImports.testConnection(tenantId(req), (req.params as { id: string }).id) } catch (error: any) { return reply.code(400).send({ error: error?.message || "Verbindung fehlgeschlagen" }) } }) server.post("/document-imports/:id/sync", async (req, reply) => { try { return reply.code(202).send(server.services.documentImports.startSync( tenantId(req), (req.params as { id: string }).id, )) } catch (error: any) { return reply.code(400).send({ error: error?.message || "Synchronisierung fehlgeschlagen" }) } }) server.get("/document-imports/:id/items", async (req) => { const currentTenantId = tenantId(req) const { id } = req.params as { id: string } return server.db.select().from(documentImportItems).where(and( eq(documentImportItems.tenantId, currentTenantId), eq(documentImportItems.sourceId, id), )).orderBy(desc(documentImportItems.createdAt)).limit(100) }) }