fixtureqa 0.1.2__tar.gz → 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {fixtureqa-0.1.2/fixtureqa.egg-info → fixtureqa-0.1.3}/PKG-INFO +1 -1
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/ws.py +14 -2
- {fixtureqa-0.1.2 → fixtureqa-0.1.3/fixtureqa.egg-info}/PKG-INFO +1 -1
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/pyproject.toml +1 -1
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/LICENSE +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/README.md +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/__init__.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/__main__.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/__init__.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/app.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/connection_manager.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/deps.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/__init__.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/admin.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/auth.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/branding.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/fix_spec.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/messages.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/scenarios.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/sessions.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/setup.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/routers/templates.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/api/schemas.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/config/__init__.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/__init__.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/auth.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/config_store.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/events.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/fix_application.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/fix_parser.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/fix_spec_parser.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/fix_tags.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/housekeeping.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/message_log.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/message_store.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/models.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/scenario_runner.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/scenario_store.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/session.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/session_manager.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/template_store.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/user_store.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/core/venue_responses.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/fix_specs/FIX42.xml +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/fix_specs/FIX44.xml +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/server.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/static/assets/ag-grid-_QKprVdm.js +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/static/assets/index-B31-1dt-.css +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/static/assets/index-CTsKxGdI.js +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/static/assets/react-vendor-2eF0YfZT.js +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/static/favicon.svg +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/static/index.html +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixture/ui/__init__.py +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixtureqa.egg-info/SOURCES.txt +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixtureqa.egg-info/dependency_links.txt +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixtureqa.egg-info/entry_points.txt +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixtureqa.egg-info/requires.txt +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/fixtureqa.egg-info/top_level.txt +0 -0
- {fixtureqa-0.1.2 → fixtureqa-0.1.3}/setup.cfg +0 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import logging
|
|
2
3
|
from typing import Annotated, Optional
|
|
3
4
|
|
|
4
5
|
from fastapi import APIRouter, Depends, Query, WebSocket, WebSocketDisconnect
|
|
@@ -10,6 +11,8 @@ from ..deps import get_session_manager, get_conn_manager
|
|
|
10
11
|
from ...core.auth import decode_token
|
|
11
12
|
from ...core.user_store import UserStore
|
|
12
13
|
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
13
16
|
router = APIRouter(tags=["websocket"])
|
|
14
17
|
|
|
15
18
|
SM = Annotated[SessionManager, Depends(get_session_manager)]
|
|
@@ -62,6 +65,7 @@ async def ws_all_sessions(
|
|
|
62
65
|
"""Subscribe to events from all sessions."""
|
|
63
66
|
uid, is_admin = _authenticate_ws(websocket, token)
|
|
64
67
|
if not uid:
|
|
68
|
+
logger.warning("WS /ws: auth failed (no token or invalid JWT)")
|
|
65
69
|
await websocket.close(code=4003, reason="Unauthorized")
|
|
66
70
|
return
|
|
67
71
|
|
|
@@ -69,14 +73,16 @@ async def ws_all_sessions(
|
|
|
69
73
|
store: UserStore = websocket.app.state.user_store
|
|
70
74
|
user = store.get_by_uid(uid)
|
|
71
75
|
if user is None or not user.is_active:
|
|
76
|
+
logger.warning("WS /ws: auth failed — user not found or inactive: uid=%s", uid)
|
|
72
77
|
await websocket.close(code=4003, reason="Unauthorized")
|
|
73
78
|
return
|
|
74
79
|
|
|
80
|
+
logger.info("WS /ws: client connected uid=%s is_admin=%s", uid, is_admin)
|
|
75
81
|
await conn_mgr.connect(websocket, session_id="*", uid=uid, is_admin=is_admin)
|
|
76
82
|
try:
|
|
77
83
|
await _send_snapshot(websocket, sm, uid, is_admin)
|
|
78
84
|
while True:
|
|
79
|
-
await asyncio.sleep(
|
|
85
|
+
await asyncio.sleep(5)
|
|
80
86
|
try:
|
|
81
87
|
await websocket.send_json({"type": "ping"})
|
|
82
88
|
except Exception:
|
|
@@ -84,6 +90,7 @@ async def ws_all_sessions(
|
|
|
84
90
|
except WebSocketDisconnect:
|
|
85
91
|
pass
|
|
86
92
|
finally:
|
|
93
|
+
logger.info("WS /ws: client disconnected uid=%s", uid)
|
|
87
94
|
conn_mgr.disconnect(websocket, session_id="*")
|
|
88
95
|
|
|
89
96
|
|
|
@@ -98,12 +105,14 @@ async def ws_single_session(
|
|
|
98
105
|
"""Subscribe to events from a single session."""
|
|
99
106
|
uid, is_admin = _authenticate_ws(websocket, token)
|
|
100
107
|
if not uid:
|
|
108
|
+
logger.warning("WS /ws/%s: auth failed (no token or invalid JWT)", session_id)
|
|
101
109
|
await websocket.close(code=4003, reason="Unauthorized")
|
|
102
110
|
return
|
|
103
111
|
|
|
104
112
|
store: UserStore = websocket.app.state.user_store
|
|
105
113
|
user = store.get_by_uid(uid)
|
|
106
114
|
if user is None or not user.is_active:
|
|
115
|
+
logger.warning("WS /ws/%s: auth failed — user not found or inactive: uid=%s", session_id, uid)
|
|
107
116
|
await websocket.close(code=4003, reason="Unauthorized")
|
|
108
117
|
return
|
|
109
118
|
|
|
@@ -111,14 +120,16 @@ async def ws_single_session(
|
|
|
111
120
|
configs = sm.list_sessions()
|
|
112
121
|
cfg = next((c for c in configs if c.session_id == session_id), None)
|
|
113
122
|
if cfg is None or (not is_admin and cfg.owner_uid != uid):
|
|
123
|
+
logger.warning("WS /ws/%s: access denied for uid=%s", session_id, uid)
|
|
114
124
|
await websocket.close(code=4003, reason="Access denied")
|
|
115
125
|
return
|
|
116
126
|
|
|
127
|
+
logger.info("WS /ws/%s: client connected uid=%s is_admin=%s", session_id, uid, is_admin)
|
|
117
128
|
await conn_mgr.connect(websocket, session_id=session_id, uid=uid, is_admin=is_admin)
|
|
118
129
|
try:
|
|
119
130
|
await _send_snapshot(websocket, sm, uid, is_admin, session_id=session_id)
|
|
120
131
|
while True:
|
|
121
|
-
await asyncio.sleep(
|
|
132
|
+
await asyncio.sleep(5)
|
|
122
133
|
try:
|
|
123
134
|
await websocket.send_json({"type": "ping"})
|
|
124
135
|
except Exception:
|
|
@@ -126,4 +137,5 @@ async def ws_single_session(
|
|
|
126
137
|
except WebSocketDisconnect:
|
|
127
138
|
pass
|
|
128
139
|
finally:
|
|
140
|
+
logger.info("WS /ws/%s: client disconnected uid=%s", session_id, uid)
|
|
129
141
|
conn_mgr.disconnect(websocket, session_id=session_id)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|