Protect private API routes and scope agent data
This commit is contained in:
@@ -8,15 +8,17 @@ import unittest
|
||||
from io import BytesIO
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
from uuid import uuid4
|
||||
|
||||
from PIL import Image, ImageDraw
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
_TEST_DATA_DIR = tempfile.TemporaryDirectory(prefix="sovereignai-knowledge-tests-")
|
||||
os.environ["SOVEREIGNAI_DATA_DIR"] = _TEST_DATA_DIR.name
|
||||
|
||||
from app import knowledge
|
||||
from fastapi.testclient import TestClient
|
||||
from app import auth, database, knowledge
|
||||
from app.main import app
|
||||
from tests.api_client import authenticated_client
|
||||
|
||||
|
||||
class KnowledgeIndexTests(unittest.TestCase):
|
||||
@@ -135,7 +137,7 @@ class KnowledgeIndexTests(unittest.TestCase):
|
||||
def test_api_indexes_selected_file_and_returns_matching_source(self) -> None:
|
||||
file = self.workspace / "guide.md"
|
||||
file.write_text("The project stores conversations in SQLite.", encoding="utf-8")
|
||||
client = TestClient(app)
|
||||
client = authenticated_client(app)
|
||||
|
||||
indexed = client.post(
|
||||
"/v1/agent/knowledge/index",
|
||||
@@ -162,6 +164,57 @@ class KnowledgeIndexTests(unittest.TestCase):
|
||||
self.assertEqual(deleted.status_code, 200, deleted.text)
|
||||
self.assertTrue(deleted.json()["deleted"][0]["deleted"])
|
||||
|
||||
def test_api_knowledge_index_isolated_between_account_sessions(self) -> None:
|
||||
marker = "OwnerScopedKnowledgeMarker"
|
||||
(self.workspace / "private.md").write_text(marker, encoding="utf-8")
|
||||
owner_id = auth.create_account(
|
||||
f"{uuid4().hex}@example.test", "account one secure passphrase"
|
||||
)
|
||||
other_id = auth.create_account(
|
||||
f"{uuid4().hex}@example.test", "account two secure passphrase"
|
||||
)
|
||||
self.addCleanup(self._delete_test_users, owner_id, other_id)
|
||||
owner_token, _ = auth.issue_session(owner_id)
|
||||
other_token, _ = auth.issue_session(other_id)
|
||||
owner_client = TestClient(
|
||||
app, headers={"Authorization": f"Bearer {owner_token}"}
|
||||
)
|
||||
other_client = TestClient(
|
||||
app, headers={"Authorization": f"Bearer {other_token}"}
|
||||
)
|
||||
payload = {
|
||||
"workspace_path": str(self.workspace),
|
||||
"files": ["private.md"],
|
||||
}
|
||||
|
||||
indexed = owner_client.post("/v1/agent/knowledge/index", json=payload)
|
||||
owner_results = owner_client.post(
|
||||
"/v1/agent/knowledge/search",
|
||||
json={"workspace_path": str(self.workspace), "task": marker},
|
||||
)
|
||||
other_results = other_client.post(
|
||||
"/v1/agent/knowledge/search",
|
||||
json={"workspace_path": str(self.workspace), "task": marker},
|
||||
)
|
||||
|
||||
self.assertEqual(indexed.status_code, 200, indexed.text)
|
||||
self.assertEqual(owner_results.status_code, 200, owner_results.text)
|
||||
self.assertEqual(other_results.status_code, 200, other_results.text)
|
||||
self.assertEqual(owner_results.json()["results"][0]["path"], "private.md")
|
||||
self.assertEqual(other_results.json()["results"], [])
|
||||
knowledge.delete_document(
|
||||
user_id=owner_id,
|
||||
workspace_path=self.workspace,
|
||||
relative_path="private.md",
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _delete_test_users(*user_ids: str) -> None:
|
||||
with database._connect() as connection:
|
||||
connection.executemany(
|
||||
"DELETE FROM users WHERE id=?", [(user_id,) for user_id in user_ids]
|
||||
)
|
||||
|
||||
def test_api_ocr_indexes_a_scanned_pdf_and_retrieves_its_text(self) -> None:
|
||||
pdf_path = self.workspace / "notice.pdf"
|
||||
image = Image.new("RGB", (900, 1165), "white")
|
||||
@@ -169,7 +222,7 @@ class KnowledgeIndexTests(unittest.TestCase):
|
||||
output = BytesIO()
|
||||
image.save(output, format="PDF", resolution=144)
|
||||
pdf_path.write_bytes(output.getvalue())
|
||||
client = TestClient(app)
|
||||
client = authenticated_client(app)
|
||||
ocr = {
|
||||
"engine": "easyocr-local-ar-en",
|
||||
"text": "Community Reading Meetup Place Amman",
|
||||
@@ -198,7 +251,7 @@ class KnowledgeIndexTests(unittest.TestCase):
|
||||
def test_api_indexes_digital_and_scanned_pages_from_mixed_pdf(self) -> None:
|
||||
pdf_path = self.workspace / "mixed.pdf"
|
||||
pdf_path.write_bytes(b"%PDF-mixed-test")
|
||||
client = TestClient(app)
|
||||
client = authenticated_client(app)
|
||||
rendered = {
|
||||
"pages": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user