Sprint 15: User-Profil (Bio, Wohnort, Erfahrung, Social, Avatar, Mitglied-seit)

This commit is contained in:
rene 2026-04-17 09:24:27 +02:00
parent 3642995409
commit 596c11d207
6 changed files with 189 additions and 1 deletions

37
backend/ratelimit.py Normal file
View file

@ -0,0 +1,37 @@
"""
BAN YARO Rate Limiter
Sliding-Window-Limiter, in-memory (kein Redis nötig für Single-Container).
"""
import threading
from collections import defaultdict, deque
from datetime import datetime, timedelta
from fastapi import HTTPException, Request
_buckets: dict[str, deque] = defaultdict(deque)
_lock = threading.Lock()
def check(request: Request, *, max_requests: int, window_seconds: int, key: str = ""):
"""
Wirft HTTP 429 wenn max_requests im Zeitfenster überschritten.
key: optionaler Präfix um verschiedene Limits zu trennen (z.B. 'register', 'login').
"""
ip = (request.client.host if request.client else "unknown")
bucket_key = f"{key}:{ip}"
now = datetime.utcnow()
cutoff = now - timedelta(seconds=window_seconds)
with _lock:
dq = _buckets[bucket_key]
# Alte Einträge raus
while dq and dq[0] < cutoff:
dq.popleft()
if len(dq) >= max_requests:
minutes = window_seconds // 60
raise HTTPException(
429,
f"Zu viele Versuche. Bitte warte {minutes} Minute(n) und versuche es erneut."
)
dq.append(now)