false, 'error' => 'Not authenticated.']); exit; } // SSO uid for SSO users; session id as stable key for client sessions $ssoUid = (string)($_SESSION['dbn_tools_sso_uid'] ?? ''); $userKey = $ssoUid !== '' ? $ssoUid : 'sess_' . session_id(); header('Content-Type: application/json; charset=utf-8'); // ── Connect to the shared dobetternorge DB (dbn_user_docs lives here) ───────── function dbnSharedDb(): ?PDO { static $pdo = null; if ($pdo !== null) return $pdo; $host = dbnToolsEnv('DBN_DB_HOST', dbnToolsEnv('DBNM_DB_HOST', 'localhost')); $name = dbnToolsEnv('DBN_DB_NAME', dbnToolsEnv('DBNM_DB_NAME', 'dobetternorge')); $user = dbnToolsEnv('DBN_DB_USER', dbnToolsEnv('DBNM_DB_USER', 'root')); $pass = dbnToolsEnv('DBN_DB_PASS', dbnToolsEnv('DBNM_DB_PASS', '')); try { $pdo = new PDO("mysql:host={$host};dbname={$name};charset=utf8mb4", $user, $pass, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_TIMEOUT => 5, ]); return $pdo; } catch (Throwable) { return null; } } $method = $_SERVER['REQUEST_METHOD']; // ── POST — upload a document ────────────────────────────────────────────────── if ($method === 'POST') { if (empty($_FILES['file']) || !is_array($_FILES['file'])) { http_response_code(422); echo json_encode(['ok' => false, 'error' => 'No file uploaded.']); exit; } try { $extracted = dbnToolsExtractUploadedFile($_FILES['file']); } catch (Throwable $e) { http_response_code(422); echo json_encode(['ok' => false, 'error' => $e->getMessage()]); exit; } $docId = uniqid('wbd_', true); $filename = basename((string)($_FILES['file']['name'] ?? 'document')); $fileType = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); $chunks = isset($extracted['text']) ? max(1, (int)ceil(mb_strlen($extracted['text']) / 1000)) : 0; $now = gmdate('Y-m-d H:i:s'); $db = dbnSharedDb(); if ($db) { $db->prepare( 'INSERT INTO dbn_user_docs (id, user_id, filename, file_type, chunk_count, source, status, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)' )->execute([$docId, $userKey, $filename, $fileType, $chunks, 'workbench', 'ready', $now]); } echo json_encode([ 'ok' => true, 'doc' => [ 'doc_id' => $docId, 'filename' => $filename, 'file_type' => $fileType, 'chunk_count' => $chunks, 'source' => 'workbench', 'created_at' => $now, ], ]); exit; } // ── DELETE ──────────────────────────────────────────────────────────────────── if ($method === 'DELETE') { $docId = trim($_GET['id'] ?? ''); if ($docId === '') { http_response_code(400); echo json_encode(['ok' => false, 'error' => 'Missing id parameter.']); exit; } $db = dbnSharedDb(); if ($db) { $stmt = $db->prepare('SELECT id FROM dbn_user_docs WHERE id = ? AND user_id = ?'); $stmt->execute([$docId, $userKey]); if ($stmt->fetch()) { $db->prepare('DELETE FROM dbn_user_docs WHERE id = ? AND user_id = ?') ->execute([$docId, $userKey]); // Delete Qdrant points for this doc $qdrantUrl = 'http://10.0.2.10:6333'; $body = [ 'filter' => [ 'must' => [ ['key' => 'doc_id', 'match' => ['value' => $docId]], ['key' => 'user_id', 'match' => ['value' => $userKey]], ], ], ]; $ch = curl_init("$qdrantUrl/collections/dbn_user_docs/points/delete"); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode($body), ]); curl_exec($ch); curl_close($ch); } } echo json_encode(['ok' => true]); exit; } // ── GET ─────────────────────────────────────────────────────────────────────── $db = dbnSharedDb(); if (!$db) { echo json_encode(['ok' => true, 'docs' => []]); exit; } $stmt = $db->prepare( 'SELECT id, filename, file_type, chunk_count, source, created_at FROM dbn_user_docs WHERE user_id = ? AND status = ? ORDER BY created_at DESC LIMIT 50' ); $stmt->execute([$userKey, 'ready']); $rows = $stmt->fetchAll(); $docs = array_map(static fn($r) => [ 'doc_id' => $r['id'], 'filename' => $r['filename'], 'file_type' => $r['file_type'], 'chunk_count' => (int)$r['chunk_count'], 'source' => $r['source'], 'created_at' => $r['created_at'], ], $rows); echo json_encode(['ok' => true, 'docs' => $docs]);