import "server-only"; import { NextResponse } from "next/server"; import { withUser } from "@/lib/db"; import { currentUserId } from "./session"; // Route Handlers under /api/export/* are outside the App Router layout tree, // so app/(app)/layout.tsx's HR gate never runs for them — each one has to // re-establish that the caller is an active HR user itself. RLS is still the // real boundary (an unauthorized session simply reads nothing); this exists // so those routes answer 401/403 instead of handing back an empty workbook. export type HrGate = { denied: NextResponse } | { userId: string }; export async function requireHrUser(): Promise { const userId = await currentUserId(); if (!userId) return { denied: NextResponse.json({ error: "Nicht angemeldet." }, { status: 401 }) }; const profile = await withUser(userId, (tx) => tx.selectFrom("profiles").select(["role", "is_active"]).where("id", "=", userId).executeTakeFirst() ); if (profile?.role !== "hr" || profile.is_active !== true) { return { denied: NextResponse.json({ error: "Nicht berechtigt." }, { status: 403 }) }; } return { userId }; }