feat(admin): DELETE /api/admin/users/{id} — Nutzer und alle Daten löschen
- Store.delete_user() löscht User + Sessions + Nachrichten + Erinnerungen + Nutzung
(atomic, anonymer Nutzer geschützt)
- DELETE /api/admin/users/{user_id} (Admin-Key erforderlich)
→ 200 {"deleted":"..."} | 404 | 400 (anonymous)
- BEDIENUNGSANLEITUNG: $URL-Erklärung am Anfang, § 7.2 vollständig mit
Anlegen/Anzeigen/Löschen-Beispielen inkl. realer Beispiel-Antworten
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5b9b9bbdcf
commit
4970bdc85a
3 changed files with 127 additions and 11 deletions
23
app/store.py
23
app/store.py
|
|
@ -118,6 +118,12 @@ class Store(ABC):
|
|||
def add_usage(self, user_id: str, units: int = 0, day: str | None = None) -> int:
|
||||
"""Zaehlt eine Anfrage (+units) und liefert die neue Tages-Anfragezahl."""
|
||||
|
||||
@abstractmethod
|
||||
def delete_user(self, user_id: str) -> bool:
|
||||
"""Loescht einen Nutzer und alle seine Daten (Sessions, Nachrichten, Erinnerungen,
|
||||
Nutzungsdaten). Anonymer Nutzer kann nicht geloescht werden.
|
||||
Liefert True, wenn der Nutzer existierte und geloescht wurde."""
|
||||
|
||||
@abstractmethod
|
||||
def log_emergency(self, user_id: str, category: str, snippet: str) -> None:
|
||||
"""Protokolliert ein erkanntes Notfall-Signal (sensibel!)."""
|
||||
|
|
@ -422,6 +428,23 @@ class SQLiteStore(Store):
|
|||
).fetchone()
|
||||
return int(row["requests"])
|
||||
|
||||
def delete_user(self, user_id: str) -> bool:
|
||||
if user_id == ANONYMOUS_USER_ID:
|
||||
raise ValueError("Der anonyme Nutzer kann nicht geloescht werden.")
|
||||
with self._connect() as conn:
|
||||
if not conn.execute("SELECT 1 FROM users WHERE id = ?", (user_id,)).fetchone():
|
||||
return False
|
||||
conn.execute(
|
||||
"DELETE FROM messages WHERE session_id IN"
|
||||
" (SELECT id FROM sessions WHERE user_id = ?)",
|
||||
(user_id,),
|
||||
)
|
||||
conn.execute("DELETE FROM sessions WHERE user_id = ?", (user_id,))
|
||||
conn.execute("DELETE FROM memories WHERE user_id = ?", (user_id,))
|
||||
conn.execute("DELETE FROM usage WHERE user_id = ?", (user_id,))
|
||||
conn.execute("DELETE FROM users WHERE id = ?", (user_id,))
|
||||
return True
|
||||
|
||||
# ----- Notfall-Protokoll ------------------------------------------------
|
||||
def log_emergency(self, user_id: str, category: str, snippet: str) -> None:
|
||||
with self._connect() as conn:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue