fix: IMAP-Konto bearbeiten + Löschen auch bei sync_running

- Store: UpdateCredentials() — Zugangsdaten + Passwort neu verschlüsseln,
  setzt status='idle', error_msg='', sync_running=false zurück
- Handler: PATCH /api/imap/{id} unterstützt nun Credential-Update
  (name/host/username vorhanden = Credential-Update, sonst sync_interval)
- Frontend: "Bearbeiten"-Button öffnet Edit-Dialog mit allen Feldern;
  Passwort-Feld leer = unverändertes Passwort
- Frontend: Löschen-Button nicht mehr durch sync_running blockiert
  (nur noch bei status=running gesperrt)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sysops
2026-03-20 00:49:37 +01:00
parent 4a4136e4a6
commit c59cad92be
4 changed files with 184 additions and 3 deletions
+39 -2
View File
@@ -273,7 +273,9 @@ func (s *Server) handleSyncNow(w http.ResponseWriter, r *http.Request) {
writeJSON(w, http.StatusOK, acc)
}
// handleUpdateImapInterval updates the automatic sync interval for an IMAP account.
// handleUpdateImapInterval updates the automatic sync interval or full credentials
// of an IMAP account. When name/host/username are present the credentials are updated;
// otherwise only sync_interval_min is changed.
func (s *Server) handleUpdateImapInterval(w http.ResponseWriter, r *http.Request) {
if s.imapStore == nil {
writeError(w, http.StatusServiceUnavailable, "IMAP not configured")
@@ -299,13 +301,48 @@ func (s *Server) handleUpdateImapInterval(w http.ResponseWriter, r *http.Request
}
var req struct {
SyncIntervalMin int `json:"sync_interval_min"`
SyncIntervalMin int `json:"sync_interval_min"`
Name string `json:"name"`
Host string `json:"host"`
Port int `json:"port"`
TLS string `json:"tls"`
Username string `json:"username"`
Password string `json:"password"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeError(w, http.StatusBadRequest, "invalid request body")
return
}
// Credential update when name/host/username are provided.
if req.Name != "" || req.Host != "" || req.Username != "" {
if req.Name == "" || req.Host == "" || req.Username == "" {
writeError(w, http.StatusBadRequest, "name, host and username are required for credential update")
return
}
port := req.Port
if port == 0 {
port = acc.Port
}
tls := req.TLS
if tls == "" {
tls = acc.TLS
}
updated := imapstore.Account{Name: req.Name, Host: req.Host, Port: port, TLS: tls, Username: req.Username}
if err := s.imapStore.UpdateCredentials(r.Context(), id, updated, req.Password); err != nil {
writeError(w, http.StatusInternalServerError, "failed to update credentials")
return
}
acc, err = s.imapStore.Get(r.Context(), id)
if err != nil {
writeError(w, http.StatusInternalServerError, "failed to reload account")
return
}
writeJSON(w, http.StatusOK, acc)
return
}
// Sync interval update.
// 0 = disabled; otherwise must be between 5 and 1440 minutes.
if req.SyncIntervalMin != 0 && (req.SyncIntervalMin < 5 || req.SyncIntervalMin > 1440) {
writeError(w, http.StatusBadRequest, "sync_interval_min must be 0 (disabled) or between 5 and 1440")