fix: allow case-less ("general") chat without ownership check

requireAuth treated every chat caseId as a real cases row and rejected
"general" (the no-file chat sentinel) with 403. general chat now skips
the ownership check and is answered without touching chat_messages,
since that table's case_id is a NOT NULL FK to cases.
This commit is contained in:
mstfyldz
2026-08-09 01:52:53 +03:00
parent afbfb413ce
commit b030bdaa60
2 changed files with 37 additions and 1 deletions
+34
View File
@@ -12,6 +12,40 @@ export const chatMessage = async (req: AuthenticatedRequest, res: Response) => {
return res.status(400).json({ error: 'Missing caseId or content' });
}
// "general" = dosyasız/genel sohbet. Şemada chat_messages.case_id NOT NULL bir
// cases FK'si olduğundan bu moddaki mesajları veritabanına yazmıyoruz — sadece
// AI'ye iletip yanıtı doğrudan döndürüyoruz.
if (caseId === 'general') {
const generalSystemPrompt = 'Sen bir hukuk asistanısın. Belirli bir dava dosyasına bağlı olmayan genel hukuki soruları cevaplıyorsun. Emin olmadığın noktalarda bunu açıkça belirt, uydurma bilgi verme.';
const aiModel = process.env.AI_MODEL || 'mizan-fixed';
const runpodUrl = process.env.RUNPOD_API_BASE_URL || 'https://q190env94stwis-11434.proxy.runpod.net';
const response = await fetch(`${runpodUrl}/api/chat`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: aiModel,
messages: [
{ role: 'system', content: generalSystemPrompt },
{ role: 'user', content },
],
think: false,
stream: false,
}),
});
if (!response.ok) {
throw new Error(`AI Model request failed: ${response.statusText}`);
}
const data = await response.json();
const aiContent = data.message?.content || 'Yanıt alınamadı.';
return res.json({
message: { id: `general-${Date.now()}`, case_id: 'general', role: 'assistant', content: aiContent },
});
}
const { data: userMessage, error: userMsgError } = await supabase
.from('chat_messages')
.insert([{ case_id: caseId, user_id: userId, role: 'user', content }])
+3 -1
View File
@@ -33,8 +33,10 @@ export const requireAuth = async (req: AuthenticatedRequest, res: Response, next
req.user = user;
// P0-3: Kaynak Sahipliği Doğrulama (Eğer istekte caseId veya case_id varsa)
// "general", dosyasız/genel sohbet için ayrılmış bir sentinel değer — gerçek bir
// case kaydı değil, bu yüzden sahiplik kontrolüne tabi tutulmaz.
const caseId = req.params.caseId || req.body?.case_id;
if (caseId) {
if (caseId && caseId !== 'general') {
const { data: caseRecord, error: caseError } = await supabase
.from('cases')
.select('id')