From 978e95711447ceacc0042fef72803cf22e61924c Mon Sep 17 00:00:00 2001 From: BroodjeAap Date: Mon, 30 Jan 2023 20:52:11 +0000 Subject: [PATCH] added backup download functionality --- main.go | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/main.go b/main.go index 5a028d5..de4d5af 100644 --- a/main.go +++ b/main.go @@ -200,6 +200,7 @@ func (web *Web) initRouter() { web.router.POST("/backup/test", web.backupTest) web.router.POST("/backup/restore", web.backupRestore) web.router.POST("/backup/delete", web.backupDelete) + web.router.GET("/backup/download/:id", web.backupDownload) web.router.SetTrustedProxies(nil) } @@ -1212,6 +1213,72 @@ func (web *Web) backupDelete(c *gin.Context) { c.Redirect(http.StatusSeeOther, "/backup/view") } +// backupDownload (/backup/download) serves the backup file in index 'id' +func (web *Web) backupDownload(c *gin.Context) { + importID, err := strconv.Atoi(c.Param("id")) + if err != nil { + c.AbortWithError(http.StatusBadRequest, err) + return + } + if importID < 0 { + c.Redirect(http.StatusSeeOther, "/backup/view") + return + } + + if !viper.IsSet("database.backup") { + c.HTML(http.StatusOK, "backupView", gin.H{"Error": "database.backup not set"}) + return + } + if !viper.IsSet("database.backup.schedule") { + c.HTML(http.StatusOK, "backupView", gin.H{"Error": "database.backup.schedule not set"}) + return + } + if !viper.IsSet("database.backup.path") { + c.HTML(http.StatusOK, "backupView", gin.H{"Error": "database.backup.path not set"}) + return + } + + backupPath := viper.GetString("database.backup.path") + + backupDir, err := filepath.Abs(filepath.Dir(backupPath)) + if err != nil { + c.HTML(http.StatusOK, "backupView", gin.H{"Error": err}) + return + } + + filesInBackupDir, err := ioutil.ReadDir(backupDir) + if err != nil { + c.HTML(http.StatusOK, "backupView", gin.H{"Error": err}) + return + } + if importID >= len(filesInBackupDir) { + c.HTML(http.StatusOK, "backupView", gin.H{"Error": err}) + return + } + + backupFileName := filesInBackupDir[importID] + backupFullPath := filepath.Join(backupDir, backupFileName.Name()) + + backupFile, err := os.Open(backupFullPath) + if err != nil { + c.HTML(http.StatusOK, "backupView", gin.H{"Error": err}) + return + } + defer backupFile.Close() + + rawBytes, err := io.ReadAll(backupFile) + if err != nil { + c.HTML(http.StatusOK, "backupView", gin.H{"Error": err}) + return + } + + c.Header("Content-Disposition", "attachment; filename=\""+backupFileName.Name()+"\"") + c.Stream(func(w io.Writer) bool { + w.Write(rawBytes) + return false + }) +} + // exportWatch (/watch/export/:id) creates a json export of the current watch func (web *Web) exportWatch(c *gin.Context) { watchID := c.Param("id")