feat(PROJ-70): Self-Service IMAP-Rückholung (Backend)

Neuer Opt-in-Endpunkt, mit dem User archivierte Mails per IMAP APPEND
zurück in ihr eigenes externes Postfach (INBOX) kopieren können. Das
Archiv selbst bleibt read-only (nur storage.Load(), kein Schreibzugriff
auf internal/imapserver).

- PATCH /api/auth/imap-restore: Opt-in-Flag umschalten, Aktivierung
  erfordert Passwort-Reverifikation.
- POST /api/mails/{id}/restore: lädt Mail lesend, prüft Mail- und
  Account-Ownership in restoreAccessAllowed() (PROJ-61-Muster), APPEND
  via neuer internal/imap/append.go, kein Admin-Override.
- Audit-Log-Eintrag (EventRestore) pro Versuch, erfolgreich und
  fehlgeschlagen.
- imap_restore_enabled-Spalte (default false) via idempotenter
  initSchema-Migration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-07-07 00:36:44 +02:00
co-authored by Claude Sonnet 5
parent 7aa63e30ca
commit da79a56b3e
7 changed files with 379 additions and 5 deletions
+9 -4
View File
@@ -108,11 +108,16 @@ func (s *Server) handleMe(w http.ResponseWriter, r *http.Request) {
return
}
// PROJ-70: expose the restore opt-in flag so the frontend can show/hide the
// "Zurück ins Postfach"-Button. Best effort — a lookup error defaults to false.
restoreEnabled, _ := s.users.GetRestoreEnabled(r.Context(), user.ID)
writeJSON(w, http.StatusOK, map[string]interface{}{
"username": user.Username,
"email": user.Email,
"role": user.Role,
"list_page_size": user.ListPageSize,
"username": user.Username,
"email": user.Email,
"role": user.Role,
"list_page_size": user.ListPageSize,
"imap_restore_enabled": restoreEnabled,
})
}