Fix 7 bugs: security, memory leak, stale state, error handling

- WebSocket: verify task ownership before allowing subscribe (security)
- POI routes: replace assert with HTTPException for production safety
- cancel_task: return HTTP 404 instead of 200 for missing tasks
- routing_config: add descriptive ValueError for invalid env vars
- POIManager: show error feedback instead of silently swallowing failures
- VisualizationCard: reset POI/travel mode state on metric switch
- Map: clean up heatmap layers/sources on unmount to prevent memory leak
- Update test to expect 404 from cancel_task ownership check
This commit is contained in:
Viktor Barzin 2026-02-13 19:36:43 +00:00
parent 25c87da1cf
commit 41b7d221e4
No known key found for this signature in database
GPG key ID: 0EB088298288D958
8 changed files with 45 additions and 9 deletions

View file

@ -415,7 +415,7 @@ async def cancel_task(
# Verify user owns this task
user_tasks = task_service.get_user_tasks(user.email)
if task_id not in user_tasks:
return {"success": False, "message": "Task not found or not owned by user"}
raise HTTPException(status_code=404, detail="Task not found or not owned by user")
try:
task_service.cancel_task(task_id, user_email=user.email)

View file

@ -60,7 +60,8 @@ def _get_user_id(user: User) -> int:
if db_user is None:
# Auto-create user on first POI interaction
db_user = user_repo.create_user(user.email)
assert db_user.id is not None
if db_user.id is None:
raise HTTPException(status_code=500, detail="Failed to create user")
return db_user.id

View file

@ -137,6 +137,10 @@ async def ws_task_progress(websocket: WebSocket) -> None:
if msg_type == "subscribe":
new_task_id = msg.get("task_id")
if new_task_id:
# Verify task belongs to the authenticated user
user_tasks = task_service.get_user_tasks(user.email)
if new_task_id not in user_tasks:
continue
channel = f"task_progress:{new_task_id}"
if channel not in subscribed_channels:
await pubsub.subscribe(channel)