fix: resolve CI test failures — schema, OPC mocking, download auth, router reloads

Fix 20 pre-existing test failures:
- Update mock conversation DB schema with missing columns
- Add in-memory OPC database mock to avoid PostgreSQL dependency in CI
- Fix file download endpoint to check auth before revealing file existence
- Reload routers.system and routers.security in test_app for fresh config
- Reset cached Docker client in security router between tests
- Fix websocket auth test to properly check for connection rejection

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Gan, Jimmy
2026-05-03 21:57:00 +08:00
parent e8534728ef
commit 56a8ff28ad
3 changed files with 225 additions and 14 deletions
+18 -3
View File
@@ -8,12 +8,15 @@ from pathlib import Path
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, Query
from fastapi.responses import StreamingResponse
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
import auth_service as auth
from config import VOLUME_ROOT
from rbac import require_admin
router = APIRouter()
public_router = APIRouter() # For endpoints that don't require auth
_bearer = HTTPBearer(auto_error=False)
logger = logging.getLogger(__name__)
BASE = Path(VOLUME_ROOT)
@@ -119,7 +122,7 @@ def create_download_token(path: str):
@public_router.get("/download")
def download(path: str = None, token: str = Query(None)):
def download(path: str = None, token: str = Query(None), credentials: HTTPAuthorizationCredentials | None = Depends(_bearer)):
"""Download a file. Supports both authenticated access (path param) and token-based access (token param)."""
try:
if token:
@@ -136,10 +139,22 @@ def download(path: str = None, token: str = Query(None)):
del _download_tokens[token]
target = Path(file_path)
else:
# Authenticated download
# Authenticated download — check auth before revealing file existence
if not path:
raise HTTPException(status_code=400, detail="Path or token required")
target = _safe_path(path)
if not credentials:
raise HTTPException(status_code=401, detail="Not authenticated")
try:
auth.user_from_access_token(credentials.credentials)
except HTTPException:
raise HTTPException(status_code=401, detail="Not authenticated")
try:
target = _safe_path(path)
except ValueError:
raise HTTPException(status_code=403, detail="Access denied")
if not target.exists():
raise HTTPException(status_code=404, detail="File not found")