test(phase-04): fill Nyquist validation gaps — FOLD-04, FOLD-05, SEC-08, SEC-09

Add 6 new tests covering document sort (name/size), FTS search cross-user
isolation, credentials_enc exclusion from all responses, and MinIO object
cleanup on user deletion.

Fix FTS try/except misplacement in api/documents.py — was wrapping the ORM
statement builder (never raises) instead of the execute call, causing HTTP 500
on SQLite test env. Now falls back to unfiltered results when @@ unsupported.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
curo1305
2026-05-31 15:21:02 +02:00
parent eab5f124f6
commit 62daf0d750
3 changed files with 370 additions and 35 deletions
+17 -18
View File
@@ -467,19 +467,6 @@ async def list_documents(
raise HTTPException(status_code=404, detail="Folder not found")
stmt = stmt.where(Document.folder_id == folder_uuid)
# Full-text search — plainto_tsquery on extracted_text (PostgreSQL only)
# Wrapped in try/except so unit tests on SQLite are not broken (FOLD-05)
fts_requested = q is not None and len(q) >= 2
if fts_requested:
try:
stmt = stmt.where(
func.to_tsvector("english", func.coalesce(Document.extracted_text, "")).op("@@")(
func.plainto_tsquery("english", q)
)
)
except Exception:
pass # FTS not available (e.g. SQLite) — return unfiltered results
# Sort
sort_col = Document.created_at # default: date
if sort == "name":
@@ -487,12 +474,24 @@ async def list_documents(
elif sort == "size":
sort_col = Document.size_bytes
if order == "asc":
stmt = stmt.order_by(sort_col.asc())
else:
stmt = stmt.order_by(sort_col.desc())
order_fn = sort_col.asc if order == "asc" else sort_col.desc
stmt = stmt.order_by(order_fn())
result = await session.execute(stmt)
# Full-text search — plainto_tsquery on extracted_text (PostgreSQL only)
# Falls back to unfiltered if the DB dialect doesn't support @@ (e.g. SQLite in test env)
fts_requested = q is not None and len(q) >= 2
if fts_requested:
fts_stmt = stmt.where(
func.to_tsvector("english", func.coalesce(Document.extracted_text, "")).op("@@")(
func.plainto_tsquery("english", q)
)
)
try:
result = await session.execute(fts_stmt)
except Exception:
result = await session.execute(stmt)
else:
result = await session.execute(stmt)
docs_orm = result.scalars().all()
# is_shared subquery