klg-asutk-app/backend/app/api/routes/ws_notifications.py
Yuriy fabe4fa72f feat(backend): 6 модулей для main/роутов + ws_notifications
- api/helpers: audit, is_authority, get_org_name, paginate_query, require_roles
- services/ws_manager: connect(ws, user_id, org_id), send_to_user, send_to_org, broadcast, make_notification(event, entity_type, entity_id, **extra)
- services/risk_scheduler: setup_scheduler (заглушка/APScheduler)
- services/email_service: email_service.send (заглушка)
- middleware/request_logger: RequestLoggerMiddleware
- core/rate_limit: RateLimitMiddleware (in-memory, RATE_LIMIT_PER_MINUTE, /health в обход)
- api/routes/ws_notifications: WebSocket /ws/notifications?user_id=&org_id=

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-14 23:21:57 +03:00

34 lines
1013 B
Python

"""
WebSocket endpoint for realtime notifications.
Multi-user: each connection is scoped to user_id + org_id from JWT.
"""
from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Query
from app.services.ws_manager import ws_manager
router = APIRouter(tags=["websocket"])
@router.websocket("/ws/notifications")
async def ws_notifications(
ws: WebSocket,
user_id: str = Query(...),
org_id: str | None = Query(default=None),
):
"""
WebSocket endpoint for receiving realtime notifications.
Connect: ws://host/api/v1/ws/notifications?user_id=xxx&org_id=yyy
Messages are JSON: {type, entity_type, entity_id, timestamp, ...}
"""
await ws_manager.connect(ws, user_id, org_id)
try:
while True:
# Keep connection alive; client can send pings
data = await ws.receive_text()
if data == "ping":
await ws.send_text("pong")
except WebSocketDisconnect:
ws_manager.disconnect(ws, user_id, org_id)