diff --git a/backend/00-router.go b/backend/00-router.go index 5bac384..56ce059 100644 --- a/backend/00-router.go +++ b/backend/00-router.go @@ -7,6 +7,8 @@ import ( "html" "net/http" "net/url" + "os" + "path/filepath" "strconv" "strings" ) @@ -20,8 +22,10 @@ func RegisterRoutes(mux *http.ServeMux) { mux.HandleFunc("/accounts/save", accountSaveHandler) // TODO Codex mux.HandleFunc("/accounts/delete", accountDeleteHandler) // TODO Codex mux.HandleFunc("/accounts/test", accountTestHandler) // TODO Codex: Quelle+Ziel-Login pruefen - mux.HandleFunc("/migrate/run", migrateRunHandler) // TODO Codex: RunMigration im Hintergrund - mux.HandleFunc("/migrate/status", migrateStatusHandler) // TODO Codex: jobs-Fortschritt (HTMX-Poll) + mux.HandleFunc("/archives/create", archiveCreateHandler) + mux.HandleFunc("/archives/delete", archiveDeleteHandler) + mux.HandleFunc("/migrate/run", migrateRunHandler) // TODO Codex: RunMigration im Hintergrund + mux.HandleFunc("/migrate/status", migrateStatusHandler) // TODO Codex: jobs-Fortschritt (HTMX-Poll) // Viewer (lokale mbox betrachten + weiterleiten) mux.HandleFunc("/view", viewerHandler) @@ -164,6 +168,58 @@ func accountTestHandler(w http.ResponseWriter, r *http.Request) { redirectAccounts(w, r, name, "Quelle und Ziel erfolgreich getestet.") } +func archiveCreateHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + name, err := safeArchiveName(r.FormValue("archive_name")) + if err != nil { + redirectAccounts(w, r, "", err.Error()) + return + } + if err := os.MkdirAll(filepath.Join(Cfg.MboxRoot, name), 0o700); err != nil { + redirectAccounts(w, r, "", err.Error()) + return + } + redirectAccounts(w, r, "", "Archiv-Mailbox angelegt.") +} + +func archiveDeleteHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + name, err := safeArchiveName(r.FormValue("archive_name")) + if err != nil { + redirectAccounts(w, r, "", err.Error()) + return + } + if archiveInUse(name) { + redirectAccounts(w, r, "", "Archiv-Mailbox ist noch einem Postfach zugeordnet.") + return + } + path := filepath.Join(Cfg.MboxRoot, name) + entries, err := os.ReadDir(path) + if os.IsNotExist(err) { + redirectAccounts(w, r, "", "Archiv-Mailbox existiert nicht.") + return + } + if err != nil { + redirectAccounts(w, r, "", err.Error()) + return + } + if len(entries) > 0 { + redirectAccounts(w, r, "", "Archiv-Mailbox ist nicht leer und wurde nicht entfernt.") + return + } + if err := os.Remove(path); err != nil { + redirectAccounts(w, r, "", err.Error()) + return + } + redirectAccounts(w, r, "", "Leere Archiv-Mailbox entfernt.") +} + func migrateRunHandler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) @@ -214,13 +270,14 @@ func renderAccountsPage(w http.ResponseWriter, accounts []Account, edit Account, if edit.Name == "" { edit = Account{SrcPort: 993, SrcSecurity: "tls", SrcProto: "imap", DstPort: 993, DstSecurity: "tls", Active: true} } + archives := archiveMailboxes(accounts) w.Header().Set("Content-Type", "text/html; charset=utf-8") fmt.Fprintf(w, ` Postfach-Verwaltung - Mail-Graveyard - + - +