feat(backend): add backup and restore functionality

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
sagit
2026-02-13 03:06:23 +00:00
parent 69f62188cf
commit b11283d488
2 changed files with 1128 additions and 0 deletions
@@ -166,6 +166,9 @@ func (h *Handler) Register(mux *http.ServeMux) {
mux.HandleFunc("/api/v1/federation/runtime/diagnose", h.authPeer(h.federationRuntimeDiagnose))
mux.HandleFunc("/api/v1/federation/node/import", h.nodeImport)
mux.HandleFunc("/api/v1/backup/export", h.backupExport)
mux.HandleFunc("/api/v1/backup/import", h.backupImport)
mux.HandleFunc("/flow/test", h.flowTest)
mux.HandleFunc("/flow/config", h.flowConfig)
mux.HandleFunc("/flow/upload", h.flowUpload)
@@ -1108,3 +1111,77 @@ func (h *Handler) verifyCloudflareTurnstile(token, secretKey string) bool {
}
return body.Success
}
type backupExportRequest struct {
Types []string `json:"types"`
}
func (h *Handler) backupExport(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
response.WriteJSON(w, response.ErrDefault("请求失败"))
return
}
var req backupExportRequest
if err := decodeJSON(r.Body, &req); err != nil {
response.WriteJSON(w, response.Err(500, "请求参数错误"))
return
}
var backup interface{}
var err error
if len(req.Types) == 0 {
backup, err = h.repo.ExportAll()
} else {
backup, err = h.repo.ExportPartial(req.Types)
}
if err != nil {
response.WriteJSON(w, response.Err(-2, err.Error()))
return
}
w.Header().Set("Content-Disposition", "attachment; filename=backup.json")
w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(backup); err != nil {
response.WriteJSON(w, response.Err(-2, err.Error()))
return
}
}
type backupImportRequest struct {
Types []string `json:"types"`
}
func (h *Handler) backupImport(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
response.WriteJSON(w, response.ErrDefault("请求失败"))
return
}
var req backupImportRequest
if err := decodeJSON(r.Body, &req); err != nil {
response.WriteJSON(w, response.Err(500, "请求参数错误"))
return
}
if len(req.Types) == 0 {
response.WriteJSON(w, response.Err(500, "请选择要导入的数据类型"))
return
}
var backup sqlite.BackupData
if err := decodeJSON(r.Body, &backup); err != nil {
response.WriteJSON(w, response.Err(500, "备份数据格式错误"))
return
}
result, err := h.repo.Import(&backup, req.Types)
if err != nil {
response.WriteJSON(w, response.Err(-2, err.Error()))
return
}
response.WriteJSON(w, response.OK(result))
}
File diff suppressed because it is too large Load Diff