Dashboard authenticates: token prompt + bearer on REST/WS/recordings
The UI never sent the bearer token, so with API_TOKEN set every data call 401'd and /ws/events was rejected pre-accept (the 403s in the uvicorn log). The API client now keeps the token in localStorage, attaches Authorization to every request, prompts once on a 401 and retries, and appends ?token= to the WebSocket connect — the page's reconnect loop picks the token up after the first prompt. require_token also accepts a ?token= query parameter (same convention as the WebSocket) because <audio> elements fetching recordings can't set headers; recordingUrl() rides the token there. The dashboard header's status call moved to a new authenticated GET /api/v1/status — its old source was the JSON root endpoint that the dashboard itself replaced at /. Two new auth tests (query-param accepted / wrong query-param 401); dashboard rebuilt. Verified live: WS rejected without token and connected with ?token=, status 200, ?token=wrong 401. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,15 @@ class TestBearerToken:
|
||||
resp = await client.get("/api/v1/calls/active")
|
||||
assert resp.status_code == 503
|
||||
|
||||
async def test_query_param_token_accepted(self, token_enabled, client):
|
||||
"""<audio>/<a> elements can't set headers — ?token= must work."""
|
||||
resp = await client.get(f"/api/v1/calls/active?token={TOKEN}")
|
||||
assert resp.status_code == 503 # auth accepted, handler 503s (no lifespan)
|
||||
|
||||
async def test_wrong_query_param_token_rejected(self, token_enabled, client):
|
||||
resp = await client.get("/api/v1/calls/active?token=wrong")
|
||||
assert resp.status_code == 401
|
||||
|
||||
async def test_all_api_routers_protected(self, token_enabled, client):
|
||||
for path in ("/api/v1/calls/active", "/api/v1/call-flows/", "/api/v1/devices/",
|
||||
"/api/v1/routing/rules", "/api/v1/calls/history"):
|
||||
|
||||
Reference in New Issue
Block a user