fix(redis): Pool-Rollout vervollständigen + TOTP-Lockout fail-closed mit 503
Security Audit / Python Dependency Audit (push) Canceled after 0s
Security Audit / Node.js Dependency Audit (push) Canceled after 0s
Security Audit / Frontend Build (tsc + vite) (push) Canceled after 0s

Redis-Review deckte auf, dass der Pool-Fix vom letzten Commit nur
totp_login/kiosk_security erreichte. Login/Refresh (auth_service.py) und
PIN/NFC/QR-Kiosk-Login (kiosk_auth_service.py) öffneten weiterhin pro
Request eine neue aioredis-Verbindung. Zusätzlich nutzten
kiosk_session_service.py und public_stamp_session_service.py den
*sync* Redis-Client aus async-Code – blockierender Socket-Call im
Event-Loop bei jedem Kiosk-/Stempel-Request.

Alle auf get_async_redis() umgestellt. TOTP-Lockout wirft jetzt 503
statt eines ungefangenen 500 bei Redis-Ausfall (RedisError explizit
gefangen, eigene HTTPExceptions unberührt).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Ahyx6D3r7G1EuAc42nezn
This commit is contained in:
2026-09-03 00:09:35 +02:00
co-authored by Claude Sonnet 5
parent 5ba5a99e02
commit 56f6f16e27
5 changed files with 211 additions and 243 deletions
+7 -19
View File
@@ -23,21 +23,9 @@ SESSION_KEY_PREFIX = "kiosk_session:"
class KioskSessionService:
def _get_redis(self):
"""Redis-Client aus app.core.redis holen. Raises 503 wenn nicht verfügbar."""
try:
from app.core.redis import get_redis_client
client = get_redis_client()
if client is None:
raise HTTPException(
status_code=503,
detail="Session-Service nicht verfügbar (Redis nicht erreichbar)."
)
return client
except ImportError:
raise HTTPException(
status_code=503,
detail="Session-Service nicht konfiguriert."
)
"""Gepoolter async Redis-Client aus app.core.redis."""
from app.core.redis import get_async_redis
return get_async_redis()
async def create_session(
self,
@@ -58,7 +46,7 @@ class KioskSessionService:
"created_at": datetime.now(timezone.utc).isoformat(),
}
try:
redis.setex(key, SESSION_TTL_SECONDS, json.dumps(payload))
await redis.set(key, json.dumps(payload), ex=SESSION_TTL_SECONDS)
except Exception as exc:
raise HTTPException(
status_code=503,
@@ -71,7 +59,7 @@ class KioskSessionService:
redis = self._get_redis()
key = SESSION_KEY_PREFIX + session_token
try:
data = redis.get(key)
data = await redis.get(key)
except Exception as exc:
raise HTTPException(
status_code=503,
@@ -86,7 +74,7 @@ class KioskSessionService:
redis = self._get_redis()
key = SESSION_KEY_PREFIX + session_token
try:
redis.delete(key)
await redis.delete(key)
except Exception:
pass # Best-effort
@@ -95,7 +83,7 @@ class KioskSessionService:
redis = self._get_redis()
key = SESSION_KEY_PREFIX + session_token
try:
result = redis.expire(key, SESSION_TTL_SECONDS)
result = await redis.expire(key, SESSION_TTL_SECONDS)
return bool(result)
except Exception:
return False