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:
@@ -12,6 +12,40 @@ export const chatMessage = async (req: AuthenticatedRequest, res: Response) => {
|
|||||||
return res.status(400).json({ error: 'Missing caseId or content' });
|
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
|
const { data: userMessage, error: userMsgError } = await supabase
|
||||||
.from('chat_messages')
|
.from('chat_messages')
|
||||||
.insert([{ case_id: caseId, user_id: userId, role: 'user', content }])
|
.insert([{ case_id: caseId, user_id: userId, role: 'user', content }])
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ export const requireAuth = async (req: AuthenticatedRequest, res: Response, next
|
|||||||
req.user = user;
|
req.user = user;
|
||||||
|
|
||||||
// P0-3: Kaynak Sahipliği Doğrulama (Eğer istekte caseId veya case_id varsa)
|
// 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;
|
const caseId = req.params.caseId || req.body?.case_id;
|
||||||
if (caseId) {
|
if (caseId && caseId !== 'general') {
|
||||||
const { data: caseRecord, error: caseError } = await supabase
|
const { data: caseRecord, error: caseError } = await supabase
|
||||||
.from('cases')
|
.from('cases')
|
||||||
.select('id')
|
.select('id')
|
||||||
|
|||||||
Reference in New Issue
Block a user