Files
AetherTable/python/tests/test_auth.py
T
John SmithandClaude ce03c0fae0 feat(wave10): real multiplayer backbone — WebSocket CRDT relay, live presence & server-backed auth
- vtt-server: activate the dormant CrdtRelayHub with a live PeerRegistry and
  actix-ws endpoint /ws/sessions/{id}/sync (root + /api/v1 alias). Token moves
  pass LWW vector-clock arbitration before fan-out; stale transforms are
  suppressed. GET /rooms/{id}/presence reports connected peers.
- client: VttCrdtSyncClient gains remote-update listeners, exponential
  backoff reconnect, solo-safe no-ops; App.tsx instantiates it, broadcasts
  token drags, applies peer updates; LobbyView polls live relay presence
- orchestrator: /api/v1/auth/{signup,login,session} — PBKDF2-salted password
  hashes, HMAC-signed 12h tokens (AUTH_SECRET env), default GM seed account;
  AuthModal uses the server with demo-account fallback offline
- tests: +5 auth suite; all suites green (46 pytest engine-up, cargo clean,
  client ~1s build, MCR 100% / HCI 1.0)

Co-Authored-By: Claude <[email protected]>
2026-08-23 01:23:15 -04:00

77 lines
2.3 KiB
Python

"""Tests for orchestrator-backed identity & sessions (/api/v1/auth/*)."""
import pytest
from fastapi.testclient import TestClient
from vtt_orchestrator.server import app
client = TestClient(app)
@pytest.fixture()
def fresh_account(request):
email = f"player_{abs(hash(request.node.name)) % 10**8}@aethertable.io"
password = "secret-dice"
resp = client.post(
"/api/v1/auth/signup",
json={
"email": email,
"display_name": "Test Hero",
"password": password,
"role": "player",
},
)
assert resp.status_code == 200, resp.text
return {"email": email, "password": password}
def test_signup_login_and_session_roundtrip(fresh_account):
login = client.post(
"/api/v1/auth/login",
json={"email": fresh_account["email"], "password": fresh_account["password"]},
)
assert login.status_code == 200
body = login.json()
assert body["user"]["role"] == "player"
assert body["expires_in"] > 0
session = client.get("/api/v1/auth/session", params={"token": body["token"]})
assert session.status_code == 200
assert session.json()["valid"] is True
assert session.json()["user"]["email"] == fresh_account["email"]
def test_wrong_password_rejected():
resp = client.post(
"/api/v1/auth/login",
json={"email": "[email protected]", "password": "wrong-password"},
)
assert resp.status_code == 401
def test_default_gm_account_seeds_on_first_login():
resp = client.post(
"/api/v1/auth/login", json={"email": "[email protected]", "password": "dragonlance"}
)
assert resp.status_code == 200
assert resp.json()["user"]["role"] == "gm"
def test_tampered_token_rejected():
login = client.post(
"/api/v1/auth/login",
json={"email": "[email protected]", "password": "dragonlance"},
)
token = login.json()["token"]
tampered = token[:-4] + ("0000" if not token.endswith("0000") else "1111")
resp = client.get("/api/v1/auth/session", params={"token": tampered})
assert resp.status_code == 401
def test_duplicate_signup_conflict(fresh_account):
resp = client.post(
"/api/v1/auth/signup",
json={"email": fresh_account["email"], "password": fresh_account["password"]},
)
assert resp.status_code == 409