Files
mailgoserver/internal/webui/domain_backup.go
T

79 lines
2.5 KiB
Go

package webui
import (
"fmt"
"net/http"
"time"
"mailgoserver/internal/backup"
)
// exportDomain streams a passphrase-encrypted archive of every mailbox in a domain —
// see internal/backup.WriteDomain for exactly what's included.
func (a *App) exportDomain(w http.ResponseWriter, r *http.Request) {
dom, err := a.DB.GetDomainByID(pathID(r))
if err != nil || dom == nil {
http.NotFound(w, r)
return
}
if !requireDomainAccess(w, r, dom.ID) {
return
}
passphrase := r.FormValue("passphrase")
if passphrase == "" {
setFlash(w, "error", "A passphrase is required to export a domain")
http.Redirect(w, r, fmt.Sprintf("%s/domains/%d/edit", Prefix, dom.ID), http.StatusFound)
return
}
filename := fmt.Sprintf("%s-export-%s.tar.gz", dom.DomainName, time.Now().UTC().Format("2006-01-02-150405"))
w.Header().Set("Content-Disposition", `attachment; filename="`+filename+`"`)
w.Header().Set("Content-Type", "application/gzip")
if err := backup.WriteDomain(w, a.DB, a.Mailstore, dom.ID, passphrase); err != nil {
a.Logger.Error("domain export %s: %v", dom.DomainName, err)
}
}
// importDomain restores an archive produced by exportDomain into an existing domain.
// A mailbox whose email already exists anywhere on this server is skipped, not
// overwritten — see internal/backup.RestoreDomain.
func (a *App) importDomain(w http.ResponseWriter, r *http.Request) {
dom, err := a.DB.GetDomainByID(pathID(r))
if err != nil || dom == nil {
http.NotFound(w, r)
return
}
if !requireDomainAccess(w, r, dom.ID) {
return
}
redirect := fmt.Sprintf("%s/domains/%d/edit", Prefix, dom.ID)
if err := r.ParseMultipartForm(10 << 20); err != nil {
setFlash(w, "error", "Invalid upload")
http.Redirect(w, r, redirect, http.StatusFound)
return
}
passphrase := r.FormValue("passphrase")
file, _, err := r.FormFile("archive")
if err != nil {
setFlash(w, "error", "No archive file provided")
http.Redirect(w, r, redirect, http.StatusFound)
return
}
defer file.Close()
skipped, err := backup.RestoreDomain(file, a.DB, a.Mailstore, dom.ID, passphrase)
if err != nil {
a.Logger.Error("domain import into %s: %v", dom.DomainName, err)
setFlash(w, "error", "Import failed: "+err.Error())
http.Redirect(w, r, redirect, http.StatusFound)
return
}
if len(skipped) > 0 {
setFlash(w, "success", fmt.Sprintf("Import complete. Skipped %d mailbox(es) whose address already existed: %v", len(skipped), skipped))
} else {
setFlash(w, "success", "Import complete")
}
http.Redirect(w, r, redirect, http.StatusFound)
}