Security: Passwort-Minimum, Rate Limits, Headers, Passwort-vergessen, email_verified

- Passwort-Minimum 8 Zeichen bei Register + Reset
- Rate Limit auf /resend-verification (3/h) und /forgot-password (3/h)
- Security-Headers: X-Frame-Options, X-Content-Type-Options, Referrer-Policy etc.
- email_verified in get_current_user SELECT ergänzt
- Forum: create_thread + create_post erfordern email_verified
- POST /auth/forgot-password + /auth/reset-password (2h-Token, via support@)
- DB-Migration: password_reset_token + password_reset_expires
- Frontend: Passwort-vergessen-Modal im Login, Reset-Formular mit Passphrase-Generator
- SW by-v576, APP_VER 553
This commit is contained in:
rene 2026-04-30 20:23:43 +02:00
parent 82d6417d09
commit 526ff42215
8 changed files with 232 additions and 4 deletions

View file

@ -166,6 +166,8 @@ async def list_threads(
# ------------------------------------------------------------------
@router.post("/threads", status_code=201)
async def create_thread(data: ThreadCreate, user=Depends(get_current_user)):
if not user.get("email_verified"):
raise HTTPException(403, "Bitte bestätige zuerst deine E-Mail-Adresse um im Forum zu schreiben.")
if not data.titel.strip():
raise HTTPException(400, "Titel darf nicht leer sein.")
if not data.text.strip():
@ -304,6 +306,8 @@ async def patch_thread(thread_id: int, data: ThreadPatch, user=Depends(get_curre
# ------------------------------------------------------------------
@router.post("/threads/{thread_id}/posts", status_code=201)
async def create_post(thread_id: int, data: PostCreate, user=Depends(get_current_user)):
if not user.get("email_verified"):
raise HTTPException(403, "Bitte bestätige zuerst deine E-Mail-Adresse um im Forum zu schreiben.")
if not data.text.strip():
raise HTTPException(400, "Text darf nicht leer sein.")
with db() as conn: