import { FastifyInstance } from "fastify" import { eq, and, isNull } from "drizzle-orm" import { authUsers, authProfiles, } from "../../../db/schema" export default async function userRoutes(server: FastifyInstance) { // ------------------------------------------------------------- // GET /user/:id // ------------------------------------------------------------- server.get("/user/:id", async (req, reply) => { try { const authUser = req.user const { id } = req.params as { id: string } if (!authUser) { return reply.code(401).send({ error: "Unauthorized" }) } // 1️⃣ User laden const [user] = await server.db .select({ id: authUsers.id, email: authUsers.email, created_at: authUsers.created_at, must_change_password: authUsers.must_change_password, }) .from(authUsers) .where(eq(authUsers.id, id)) if (!user) { return reply.code(404).send({ error: "User not found" }) } // 2️⃣ Profil im Tenant let profile = null if (authUser.tenant_id) { const [profileRow] = await server.db .select() .from(authProfiles) .where( and( eq(authProfiles.user_id, id), eq(authProfiles.tenant_id, authUser.tenant_id) ) ) profile = profileRow || null } return { user, profile } } catch (err: any) { console.error("/user/:id ERROR", err) return reply.code(500).send({ error: err.message || "Internal error" }) } }) // ------------------------------------------------------------- // PUT /user/:id/profile // ------------------------------------------------------------- server.put("/user/:id/profile", async (req, reply) => { try { const { id } = req.params as { id: string } const { data } = req.body as { data?: Record } if (!req.user?.tenant_id) { return reply.code(401).send({ error: "Unauthorized" }) } if (!data || typeof data !== "object") { return reply.code(400).send({ error: "data object required" }) } // 1️⃣ Profil für diesen Tenant laden (damit wir die ID kennen) const [profile] = await server.db .select() .from(authProfiles) .where( and( eq(authProfiles.user_id, id), eq(authProfiles.tenant_id, req.user.tenant_id), isNull(authProfiles.archived_at) ) ) if (!profile) { return reply.code(404).send({ error: "Profile not found in tenant" }) } // 2️⃣ Timestamp-Felder normalisieren (falls welche drin sind) const normalizeDate = (val: any) => { if (!val) return null const d = new Date(val) return isNaN(d.getTime()) ? null : d } const updateData: any = { ...data } for (const key of ["archived_at", "user_id", "tenant_id", "id"]) delete updateData[key] // bekannte Date-Felder prüfen if (data.entry_date !== undefined) updateData.entry_date = normalizeDate(data.entry_date) if (data.birthday !== undefined) updateData.birthday = normalizeDate(data.birthday) if (data.created_at !== undefined) updateData.created_at = normalizeDate(data.created_at) updateData.updated_at = new Date() // 3️⃣ Update durchführen const [updatedProfile] = await server.db .update(authProfiles) .set(updateData) .where(and(eq(authProfiles.id, profile.id), isNull(authProfiles.archived_at))) .returning() if (!updatedProfile) return reply.code(404).send({ error: "Profile not found in tenant" }) return { profile: updatedProfile } } catch (err: any) { console.error("PUT /user/:id/profile ERROR", err) return reply.code(500).send({ error: err.message || "Internal server error" }) } }) }