""" Einfacher In-Memory Rate-Limiter fuer den Login-Endpunkt (pro Quell-IP). Fuer einen Single-Process-ASGI-Deployment (siehe Konzept: kleine/mittlere Umgebung) ausreichend. Bei horizontaler Skalierung auf mehrere Prozesse/Hosts muss dies durch einen geteilten Store (z.B. Redis) ersetzt werden -- als Erweiterungspunkt bewusst hinter einer kleinen Klasse gekapselt. """ from __future__ import annotations import time from collections import defaultdict, deque class SlidingWindowRateLimiter: def __init__(self, max_events: int, window_seconds: int) -> None: self.max_events = max_events self.window_seconds = window_seconds self._events: dict[str, deque[float]] = defaultdict(deque) def allow(self, key: str) -> bool: now = time.time() window = self._events[key] while window and now - window[0] > self.window_seconds: window.popleft() if len(window) >= self.max_events: return False window.append(now) return True # Max. 10 Login-Versuche pro Minute und Quell-IP; ergaenzt den # Account-basierten Lockout in app/auth/routes.py. login_rate_limiter = SlidingWindowRateLimiter(max_events=10, window_seconds=60)