147 lines
3.5 KiB
Go
147 lines
3.5 KiB
Go
|
|
package handlers
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"net/http"
|
||
|
|
"os"
|
||
|
|
"os/exec"
|
||
|
|
"path/filepath"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
func (h *Handler) BackupList(w http.ResponseWriter, r *http.Request) {
|
||
|
|
backups, err := h.DB.ListBackups()
|
||
|
|
if err != nil {
|
||
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if acceptsJSON(r) {
|
||
|
|
writeJSON(w, http.StatusOK, backups)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
h.render(w, "backups.html", backups)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Handler) BackupSite(w http.ResponseWriter, r *http.Request) {
|
||
|
|
id, err := paramInt(r, "id")
|
||
|
|
if err != nil {
|
||
|
|
writeError(w, http.StatusBadRequest, "invalid id")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
site, err := h.DB.GetSite(id)
|
||
|
|
if err != nil || site == nil {
|
||
|
|
writeError(w, http.StatusNotFound, "site not found")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create backup directory
|
||
|
|
backupDir := h.Config.Backups.Dir
|
||
|
|
os.MkdirAll(backupDir, 0755)
|
||
|
|
|
||
|
|
timestamp := time.Now().Format("20060102-150405")
|
||
|
|
filename := fmt.Sprintf("site-%s-%s.tar.gz", site.Domain, timestamp)
|
||
|
|
backupPath := filepath.Join(backupDir, filename)
|
||
|
|
|
||
|
|
// Create tar.gz
|
||
|
|
cmd := exec.Command("tar", "-czf", backupPath, "-C", filepath.Dir(site.AppRoot), filepath.Base(site.AppRoot))
|
||
|
|
out, err := cmd.CombinedOutput()
|
||
|
|
if err != nil {
|
||
|
|
writeError(w, http.StatusInternalServerError, fmt.Sprintf("backup failed: %s", string(out)))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get file size
|
||
|
|
info, _ := os.Stat(backupPath)
|
||
|
|
size := int64(0)
|
||
|
|
if info != nil {
|
||
|
|
size = info.Size()
|
||
|
|
}
|
||
|
|
|
||
|
|
bID, _ := h.DB.CreateBackup(&id, "site", backupPath, size)
|
||
|
|
writeJSON(w, http.StatusCreated, map[string]interface{}{
|
||
|
|
"id": bID,
|
||
|
|
"path": backupPath,
|
||
|
|
"size": size,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Handler) BackupFull(w http.ResponseWriter, r *http.Request) {
|
||
|
|
backupDir := h.Config.Backups.Dir
|
||
|
|
os.MkdirAll(backupDir, 0755)
|
||
|
|
|
||
|
|
timestamp := time.Now().Format("20060102-150405")
|
||
|
|
filename := fmt.Sprintf("full-system-%s.tar.gz", timestamp)
|
||
|
|
backupPath := filepath.Join(backupDir, filename)
|
||
|
|
|
||
|
|
// Backup key directories
|
||
|
|
dirs := []string{
|
||
|
|
h.Config.Nginx.Webroot,
|
||
|
|
"/etc/nginx",
|
||
|
|
"/opt/setec-manager/data",
|
||
|
|
}
|
||
|
|
|
||
|
|
args := []string{"-czf", backupPath}
|
||
|
|
for _, d := range dirs {
|
||
|
|
if _, err := os.Stat(d); err == nil {
|
||
|
|
args = append(args, d)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
cmd := exec.Command("tar", args...)
|
||
|
|
out, err := cmd.CombinedOutput()
|
||
|
|
if err != nil {
|
||
|
|
writeError(w, http.StatusInternalServerError, fmt.Sprintf("backup failed: %s", string(out)))
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
info, _ := os.Stat(backupPath)
|
||
|
|
size := int64(0)
|
||
|
|
if info != nil {
|
||
|
|
size = info.Size()
|
||
|
|
}
|
||
|
|
|
||
|
|
bID, _ := h.DB.CreateBackup(nil, "full", backupPath, size)
|
||
|
|
writeJSON(w, http.StatusCreated, map[string]interface{}{
|
||
|
|
"id": bID,
|
||
|
|
"path": backupPath,
|
||
|
|
"size": size,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Handler) BackupDelete(w http.ResponseWriter, r *http.Request) {
|
||
|
|
id, err := paramInt(r, "id")
|
||
|
|
if err != nil {
|
||
|
|
writeError(w, http.StatusBadRequest, "invalid id")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get backup info to delete file
|
||
|
|
var filePath string
|
||
|
|
h.DB.Conn().QueryRow(`SELECT file_path FROM backups WHERE id=?`, id).Scan(&filePath)
|
||
|
|
if filePath != "" {
|
||
|
|
os.Remove(filePath)
|
||
|
|
}
|
||
|
|
|
||
|
|
h.DB.DeleteBackup(id)
|
||
|
|
writeJSON(w, http.StatusOK, map[string]string{"status": "deleted"})
|
||
|
|
}
|
||
|
|
|
||
|
|
func (h *Handler) BackupDownload(w http.ResponseWriter, r *http.Request) {
|
||
|
|
id, err := paramInt(r, "id")
|
||
|
|
if err != nil {
|
||
|
|
writeError(w, http.StatusBadRequest, "invalid id")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
var filePath string
|
||
|
|
h.DB.Conn().QueryRow(`SELECT file_path FROM backups WHERE id=?`, id).Scan(&filePath)
|
||
|
|
if filePath == "" {
|
||
|
|
writeError(w, http.StatusNotFound, "backup not found")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filepath.Base(filePath)))
|
||
|
|
http.ServeFile(w, r, filePath)
|
||
|
|
}
|