fix: extract tenantId from session auth instead of request body/headers
AI routes now use requirePermission() + ctx.tenantId to get the tenant, ensuring getModelForTenant() is always called with the correct tenant ID so that stored API keys are used. Fixes norms/parse (was falling back to getModel()) and analyses/structured (was trusting x-tenant-id header). Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -4,19 +4,14 @@
|
||||
import { type NextRequest } from 'next/server';
|
||||
import { runStructuredAnalysis } from '@/lib/ai/structured-analysis';
|
||||
import { AnalyseMode } from '@/types';
|
||||
import { requirePermission } from '@/lib/auth/rbac';
|
||||
|
||||
const VALID_MODES = new Set(Object.values(AnalyseMode));
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
const tenantId = request.headers.get('x-tenant-id');
|
||||
const userId = request.headers.get('x-user-id');
|
||||
|
||||
if (!tenantId || !userId) {
|
||||
return Response.json(
|
||||
{ error: 'Missing x-tenant-id or x-user-id header' },
|
||||
{ status: 401 },
|
||||
);
|
||||
}
|
||||
const auth = await requirePermission('analyses:create');
|
||||
if ('response' in auth) return auth.response;
|
||||
const { ctx } = auth;
|
||||
|
||||
const body = await request.json();
|
||||
const {
|
||||
@@ -46,8 +41,8 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
try {
|
||||
const result = await runStructuredAnalysis({
|
||||
tenantId,
|
||||
userId,
|
||||
tenantId: ctx.tenantId,
|
||||
userId: ctx.userId,
|
||||
caseId,
|
||||
mode,
|
||||
title,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// POST /api/norms/parse
|
||||
// Accepts raw law text (Fließtext) or a PDF file and uses AI to parse it into structured provisions.
|
||||
//
|
||||
// JSON body: { text: string, tenantId?: string }
|
||||
// OR multipart/form-data: file (PDF/TXT), tenantId (optional)
|
||||
// JSON body: { text: string }
|
||||
// OR multipart/form-data: file (PDF/TXT)
|
||||
//
|
||||
// Returns: {
|
||||
// provisions: Array<{
|
||||
@@ -13,7 +13,8 @@
|
||||
// }
|
||||
|
||||
import { generateText } from 'ai';
|
||||
import { getModelForTenant, getModel } from '@/lib/ai/providers';
|
||||
import { getModelForTenant } from '@/lib/ai/providers';
|
||||
import { requirePermission } from '@/lib/auth/rbac';
|
||||
|
||||
const PARSE_SYSTEM_PROMPT = `Du bist ein Experte fuer deutsches Recht und Gesetzestexte. Deine Aufgabe ist es, einen Fliesstext eines Gesetzes, Tarifvertrags oder einer anderen Rechtsquelle in einzelne Paragraphen zu zerlegen.
|
||||
|
||||
@@ -45,15 +46,17 @@ async function extractTextFromPdf(buffer: Buffer): Promise<string> {
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
const auth = await requirePermission('norms:write');
|
||||
if ('response' in auth) return auth.response;
|
||||
const { ctx } = auth;
|
||||
|
||||
let text: string;
|
||||
let tenantId: string | undefined;
|
||||
|
||||
const contentType = request.headers.get('content-type') ?? '';
|
||||
|
||||
if (contentType.includes('multipart/form-data')) {
|
||||
const formData = await request.formData();
|
||||
const file = formData.get('file');
|
||||
tenantId = (formData.get('tenantId') as string) || undefined;
|
||||
|
||||
if (!file || !(file instanceof File)) {
|
||||
return Response.json({ error: 'file field is required.' }, { status: 400 });
|
||||
@@ -76,7 +79,7 @@ export async function POST(request: Request) {
|
||||
text = new TextDecoder('utf-8').decode(buffer);
|
||||
}
|
||||
} else {
|
||||
let body: { text?: string; tenantId?: string };
|
||||
let body: { text?: string };
|
||||
try {
|
||||
body = await request.json();
|
||||
} catch {
|
||||
@@ -84,7 +87,6 @@ export async function POST(request: Request) {
|
||||
}
|
||||
|
||||
text = body.text ?? '';
|
||||
tenantId = body.tenantId;
|
||||
}
|
||||
|
||||
if (!text || typeof text !== 'string' || text.trim().length === 0) {
|
||||
@@ -102,13 +104,7 @@ export async function POST(request: Request) {
|
||||
}
|
||||
|
||||
try {
|
||||
let model;
|
||||
if (tenantId) {
|
||||
const result = await getModelForTenant(tenantId);
|
||||
model = result.model;
|
||||
} else {
|
||||
model = getModel();
|
||||
}
|
||||
const { model } = await getModelForTenant(ctx.tenantId);
|
||||
|
||||
const result = await generateText({
|
||||
model,
|
||||
|
||||
Reference in New Issue
Block a user