import { FastifyInstance } from "fastify" import { authUsers, authTenantUsers, tenants, authProfiles, authUserRoles, authRoles, authRolePermissions, } from "../../../db/schema" import { eq, and, or, isNull } from "drizzle-orm" import { enrichProfilesWithBranches } from "../../utils/profileBranches" export default async function meRoutes(server: FastifyInstance) { server.get("/me", async (req, reply) => { try { const authUser = req.user if (!authUser) { return reply.code(401).send({ error: "Unauthorized" }) } const userId = authUser.user_id const activeTenantId = authUser.tenant_id // ---------------------------------------------------- // 1) USER LADEN // ---------------------------------------------------- const userResult = await server.db .select({ id: authUsers.id, email: authUsers.email, created_at: authUsers.created_at, must_change_password: authUsers.must_change_password, is_admin: authUsers.is_admin, }) .from(authUsers) .where(eq(authUsers.id, userId)) .limit(1) const user = userResult[0] if (!user) { return reply.code(401).send({ error: "User not found" }) } // ---------------------------------------------------- // 2) TENANTS LADEN // ---------------------------------------------------- const tenantRows = await server.db .select({ id: tenants.id, name: tenants.name, short: tenants.short, locked: tenants.locked, features: tenants.features, extraModules: tenants.extraModules, businessInfo: tenants.businessInfo, numberRanges: tenants.numberRanges, accountChart: tenants.accountChart, taxEvaluationPeriod: tenants.taxEvaluationPeriod, dokuboxkey: tenants.dokuboxkey, standardEmailForInvoices: tenants.standardEmailForInvoices, standardPaymentDays: tenants.standardPaymentDays, }) .from(authTenantUsers) .innerJoin(tenants, eq(authTenantUsers.tenant_id, tenants.id)) .where(eq(authTenantUsers.user_id, userId)) const tenantList = tenantRows ?? [] // ---------------------------------------------------- // 3) ACTIVE TENANT // ---------------------------------------------------- const activeTenant = activeTenantId // ---------------------------------------------------- // 4) PROFIL LADEN // ---------------------------------------------------- let profile = null if (activeTenantId) { const profileResult = await server.db .select() .from(authProfiles) .where( and( eq(authProfiles.user_id, userId), eq(authProfiles.tenant_id, activeTenantId) ) ) .limit(1) const enrichedProfiles = await enrichProfilesWithBranches(server, profileResult) profile = enrichedProfiles?.[0] ?? null } // ---------------------------------------------------- // 5) PERMISSIONS — RPC ERSETZT // ---------------------------------------------------- const permissionRows = (await server.db .select({ permission: authRolePermissions.permission, }) .from(authUserRoles) .innerJoin( authRoles, and( eq(authRoles.id, authUserRoles.role_id), or( isNull(authRoles.tenant_id), // globale Rolle eq(authRoles.tenant_id, activeTenantId) // tenant-spezifische Rolle ) ) ) .innerJoin( authRolePermissions, eq(authRolePermissions.role_id, authRoles.id) ) .where( and( eq(authUserRoles.user_id, userId), eq(authUserRoles.tenant_id, activeTenantId) ) )) ?? [] const permissions = Array.from( new Set(permissionRows.map((p) => p.permission)) ) // ---------------------------------------------------- // RESPONSE // ---------------------------------------------------- return { user, tenants: tenantList, activeTenant, profile, permissions, } } catch (err: any) { console.error("ERROR in /me route:", err) return reply.code(500).send({ error: "Internal server error" }) } }) }