ws.py 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. from fastapi import APIRouter, HTTPException, Query, WebSocket, WebSocketDisconnect, status
  2. from sqlalchemy import select
  3. from backend.app.core.dependencies import get_current_user_by_token
  4. from backend.app.db.session import SessionLocal
  5. from backend.app.models import RolePermission
  6. from backend.app.services.center_sync import get_sync_status
  7. from backend.app.services.sync_ws import sync_broadcaster
  8. router = APIRouter()
  9. @router.websocket("/ws/sync")
  10. async def sync_status_socket(websocket: WebSocket, token: str | None = Query(default=None)):
  11. if not token:
  12. await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
  13. return
  14. async with SessionLocal() as db:
  15. try:
  16. user = await get_current_user_by_token(token, db)
  17. except HTTPException:
  18. await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
  19. return
  20. result = await db.execute(
  21. select(RolePermission.permission_code).where(RolePermission.role_id == user.role_id)
  22. )
  23. permissions = {row[0] for row in result.fetchall()}
  24. if "users.view" not in permissions:
  25. await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
  26. return
  27. await sync_broadcaster.connect(websocket)
  28. await sync_broadcaster.send_status(websocket, await get_sync_status(db))
  29. try:
  30. while True:
  31. await websocket.receive_text()
  32. except WebSocketDisconnect:
  33. pass
  34. finally:
  35. await sync_broadcaster.disconnect(websocket)