umbau 1.0

This commit is contained in:
2026-09-02 20:30:44 +02:00
parent afe6719f51
commit 5c95b21be7
77 changed files with 10733 additions and 1914 deletions

View File

@ -272,6 +272,13 @@ async def logout(request: Request, response: Response, user: CurrentUser = Depen
conn, event_type="logout", user_id=user.id, client_ip=_client_ip(request), details={}
)
await conn.commit()
# Siehe change_password() unten fuer die ausfuehrliche Begruendung: die
# get_current_user()-Dependency hat bereits ein Refresh-Set-Cookie
# geschrieben, das hier entfernte werden muss, bevor delete_cookie()
# selbst noch ein Set-Cookie (mit Max-Age=0) anhaengt -- sonst zwei
# Set-Cookie-Kopfzeilen in einer Antwort.
if "set-cookie" in response.headers:
del response.headers["set-cookie"]
response.delete_cookie(SESSION_COOKIE_NAME, path="/")
return {"status": "ok"}
@ -289,6 +296,9 @@ async def logout_everywhere(
conn, event_type="logout_everywhere", user_id=user.id, client_ip=_client_ip(request), details={}
)
await conn.commit()
# Siehe change_password() unten fuer die ausfuehrliche Begruendung.
if "set-cookie" in response.headers:
del response.headers["set-cookie"]
response.delete_cookie(SESSION_COOKIE_NAME, path="/")
return {"status": "ok"}
@ -318,6 +328,27 @@ async def change_password(
)
await conn.commit()
# Bug-Fix (FORTSETZUNG_Teil_C.md Abschnitt 3 Punkt 6): get_current_user()
# (siehe app/auth/deps.py) hat als Dependency VOR dieser Routenfunktion
# bereits ein eigenes Set-Cookie in `response` geschrieben (gleitender
# Idle-Timeout-Refresh) -- MIT DER ALTEN session_version, weil die DB zu
# dem Zeitpunkt noch nicht aktualisiert war. Ohne diese Zeile wuerden
# ZWEI "Set-Cookie: jh_session=..."-Header in derselben Antwort stehen
# (die alte Refresh-Cookie UND die neue unten) -- welche davon ein Client
# am Ende tatsaechlich speichert, ist zwischen Browsern/HTTP-Bibliotheken
# nicht einheitlich definiert (in der Praxis eher "die letzte gewinnt",
# aber verlassen sollte man sich darauf nicht). Ein per-Request frischer
# Client akzeptiert die alte Sitzung danach zwar bereits korrekt nicht
# mehr (session_version-Pruefung in deps.py greift unabhaengig davon),
# aber die doppelte Kopfzeile bleibt unsauber und macht Tests, die den
# Cookie-Jar wiederverwenden, unnoetig fragil (siehe der dadurch lange
# falsch als "Sicherheitsluecke" vermutete Testfehlschlag). Die alte
# Set-Cookie-Kopfzeile wird deshalb hier explizit entfernt, bevor die
# neue, autoritative gesetzt wird -- `del response.headers["set-cookie"]`
# entfernt ALLE bisherigen Vorkommen dieses Headers (Starlette
# MutableHeaders.__delitem__), nicht nur das erste.
if "set-cookie" in response.headers:
del response.headers["set-cookie"]
token = create_session_token(user.id, new_version)
response.set_cookie(
SESSION_COOKIE_NAME, token, httponly=True, secure=True, samesite="strict", path="/"
@ -327,19 +358,8 @@ async def change_password(
@router.get("/me")
async def me(user: CurrentUser = Depends(get_current_user)):
tenant_admin_of = []
if user.tenant_admin_ids:
conn = get_db()
placeholders = ",".join("?" for _ in user.tenant_admin_ids)
cursor = await conn.execute(
f"SELECT id, name FROM tenants WHERE id IN ({placeholders}) ORDER BY name",
tuple(user.tenant_admin_ids),
)
tenant_admin_of = [{"id": r[0], "name": r[1]} for r in await cursor.fetchall()]
return {
"id": user.id,
"username": user.username,
"is_admin": user.is_admin,
"is_any_admin": user.is_any_admin,
"tenant_admin_of": tenant_admin_of,
}