fix: Kontolöschung schlug mit 500 fehl (bytes-vs-str, psycopg-Eigenart)
Live bei der Verifikation gefunden: konto_loeschen() lud das Zielkonto über get_by_email(ziel['email']) nach - der email-Wert kam aus fetch_benutzer_fuer_organisation()'s sync-Verbindungspfad, wo psycopg TEXT-Spalten teils als bytes statt str liefert (dasselbe bereits bekannte, nicht deterministische Verhalten wie in _row_to_user(), siehe dortiger Kommentar) - die async get_by_email()-Abfrage bekam dadurch einen bytes-Parameter und scheiterte mit 'operator does not exist: text = bytea'. Zwei Fixes: konto_loeschen() nutzt jetzt user_manager.get(id) statt des E-Mail-Umwegs (nur async-Pfad, umgeht das Problem strukturell). fetch_benutzer_fuer_organisation() bekommt zusätzlich denselben defensiven bytes-Decode wie _row_to_user(), damit das nicht an anderer Stelle erneut zuschlägt. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
ec11de1ee9
commit
9265d47916
19
auth.py
19
auth.py
@ -211,16 +211,25 @@ def fetch_benutzer_fuer_organisation(organization_id: str) -> list[dict]:
|
||||
""",
|
||||
(organization_id,),
|
||||
)
|
||||
return [
|
||||
{
|
||||
ergebnis = []
|
||||
for benutzer_id, email, is_superuser, ist_organisationsadmin, created_at in cur.fetchall():
|
||||
# psycopg liefert TEXT-Spalten hier teils als bytes zurück,
|
||||
# nicht deterministisch (dasselbe bekannte Verhalten wie in
|
||||
# _row_to_user()) - live gefunden, als ein daraus
|
||||
# weitergereichter bytes-Wert eine spätere SQL-Abfrage mit
|
||||
# "operator does not exist: text = bytea" zum Absturz brachte.
|
||||
if isinstance(email, bytes):
|
||||
email = email.decode("utf-8")
|
||||
|
||||
ergebnis.append({
|
||||
"id": str(benutzer_id),
|
||||
"email": email,
|
||||
"is_superuser": is_superuser,
|
||||
"ist_organisationsadmin": ist_organisationsadmin,
|
||||
"created_at": created_at,
|
||||
}
|
||||
for benutzer_id, email, is_superuser, ist_organisationsadmin, created_at in cur.fetchall()
|
||||
]
|
||||
})
|
||||
|
||||
return ergebnis
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@ -101,7 +101,14 @@ async def konto_loeschen(
|
||||
if ziel is None:
|
||||
raise HTTPException(status_code=404, detail="Konto wurde nicht gefunden.")
|
||||
|
||||
ziel_user = await user_manager.get_by_email(ziel["email"])
|
||||
# Über die ID statt per E-Mail nachladen: get_by_email() lief über den
|
||||
# sync-Verbindungspfad von fetch_benutzer_fuer_organisation() zurück in
|
||||
# eine async-Abfrage - psycopg liefert TEXT-Spalten dort teils als bytes
|
||||
# zurück (dasselbe bekannte Verhalten wie bei _row_to_user()), was hier
|
||||
# zu "operator does not exist: text = bytea" führte (live gefunden bei
|
||||
# der Verifikation). user_manager.get(id) nutzt ausschließlich den
|
||||
# async-Pfad (UserDatabase.get(), mit korrektem Decode in _row_to_user()).
|
||||
ziel_user = await user_manager.get(user_manager.parse_id(konto_id))
|
||||
await user_manager.delete(ziel_user)
|
||||
|
||||
return RedirectResponse("/organisation", status_code=303)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user