diff --git a/api.go b/api.go index bdc255c..b5ea14e 100644 --- a/api.go +++ b/api.go @@ -2,6 +2,7 @@ package main import ( "encoding/json" + "fmt" "net/http" "slices" "time" @@ -24,7 +25,7 @@ func ApiSnapshotAdd(c *gin.Context) { if err := app.RunStandaloneSchedule(schedule); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) } else { c.JSON(http.StatusOK, gin.H{ @@ -57,7 +58,7 @@ func ApiSnapshotList(c *gin.Context) { if snapshots, err := app.Snapshots(); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) } else { c.JSON(http.StatusOK, gin.H{ @@ -102,7 +103,7 @@ func ApiRunApp(c *gin.Context) { if err := app.RunStandaloneTime(time.Now()); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) } else { c.JSON(http.StatusOK, gin.H{ @@ -121,7 +122,7 @@ func ApiSave(c *gin.Context) { if err := cfg.Save(true); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) } else { c.JSON(http.StatusOK, gin.H{ @@ -134,7 +135,7 @@ func ApiConfig(c *gin.Context) { if b, err := cfg.Pretty(true); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) } else { c.Data(http.StatusOK, "application/json", b) @@ -154,7 +155,7 @@ func ApiConfigApp(c *gin.Context) { if b, err := app.Pretty(false); err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) } else { c.Data(http.StatusOK, "application/json", b) @@ -185,7 +186,7 @@ func ApiAppList(c *gin.Context) { if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) return } @@ -213,7 +214,7 @@ func ApiListSchedule(c *gin.Context) { if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) return } @@ -251,7 +252,7 @@ func ApiAppAdd(c *gin.Context) { if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) return } @@ -293,7 +294,7 @@ func ApiAppDel(c *gin.Context) { if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) return } @@ -323,7 +324,7 @@ func ApiAppActivate(c *gin.Context) { if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": "error", - "error": err, + "error": fmt.Sprint(err), }) return } @@ -331,6 +332,16 @@ func ApiAppActivate(c *gin.Context) { cfg.apps[app.Name] = a } } + + err := cfg.Save(false) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": fmt.Sprint(err), + }) + return + } + c.JSON(http.StatusOK, gin.H{ "message": "done", }) @@ -358,31 +369,203 @@ func ApiAppDeactivate(c *gin.Context) { } } + err := cfg.Save(false) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": fmt.Sprint(err), + }) + return + } + c.JSON(http.StatusOK, gin.H{ "message": "done", }) } -// FIXME func ApiAppSourceList(c *gin.Context) { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": "error", - "error": "not implemented", - }) + name := c.Param("app") + found := false + app := &AppConfig{} + + CfgLock() + defer CfgUnlock() + + for _, a := range cfg.Apps { + if a.Name == name { + found = true + app = a + } + } + + if !found { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": "app does not exist", + }) + return + } + + b, err := json.Marshal(app.Sources) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": fmt.Sprint(err), + }) + return + } + c.Data(http.StatusOK, "application/json", pretty.PrettyOptions(b, &pretty.Options{Indent: " "})) } -// FIXME func ApiAppSourceAdd(c *gin.Context) { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": "error", - "error": "not implemented", + name := c.Param("app") + found := false + app := &AppConfig{} + + CfgLock() + defer CfgUnlock() + + for _, a := range cfg.Apps { + if a.Name == name { + found = true + app = a + } + } + + if !found { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": "app does not exist", + }) + return + } + + src := Addr(c.Param("src")) + if src.Box() == "" { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": "source box incorrect", + }) + return + } + + if _, ok := cfg.box[src.Box()]; !ok { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": "source box doesn't exist", + }) + return + } + + if src.Path() == "" { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": "source path incorrect", + }) + return + } + + if slices.Contains(app.Sources, src.String()) { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": "source already exists", + }) + return + } + + app.Sources = append(app.Sources, src.String()) + + if app.Active { + a, err := cfg.NewApp(app.Name, app.Sources, app.Destinations, app.Schedule, app.Before, app.After) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": fmt.Sprint(err), + }) + return + } + + cfg.apps[a.name] = a + } + + err := cfg.Save(false) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": fmt.Sprint(err), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "done", }) + } // FIXME func ApiAppSourceDel(c *gin.Context) { - c.JSON(http.StatusInternalServerError, gin.H{ - "message": "error", - "error": "not implemented", + name := c.Param("app") + found := false + app := &AppConfig{} + + CfgLock() + defer CfgUnlock() + + for _, a := range cfg.Apps { + if a.Name == name { + found = true + app = a + } + } + + if !found { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": "app does not exist", + }) + return + } + + src := c.Param("src") + if !slices.Contains(app.Sources, src) { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": "source does not exist", + }) + return + } + + for id, s := range app.Sources { + if s == src { + app.Sources[id] = app.Sources[len(app.Sources)-1] + app.Sources = app.Sources[:len(app.Sources)-1] + } + } + + if app.Active { + a, err := cfg.NewApp(app.Name, app.Sources, app.Destinations, app.Schedule, app.Before, app.After) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": fmt.Sprint(err), + }) + return + } + + cfg.apps[a.name] = a + } + + err := cfg.Save(false) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "message": "error", + "error": fmt.Sprint(err), + }) + return + } + + c.JSON(http.StatusOK, gin.H{ + "message": "done", }) } diff --git a/app.go b/app.go index c119f1b..ecf62e8 100644 --- a/app.go +++ b/app.go @@ -2,7 +2,6 @@ package main import ( "errors" - "fmt" "regexp" "strings" "sync" @@ -25,19 +24,27 @@ func (c *Config) NewApp(name string, sources, destinations, schedule []string, b defer log.WithFields(log.Fields{"name": name}).Debugf("done") if _, ok := c.apps[name]; ok { - return nil, fmt.Errorf("app already exist") + err := errors.New("app already exist") + log.WithFields(log.Fields{"app": name, "error": err}).Errorf("") + return nil, err } if len(sources) == 0 { - return nil, fmt.Errorf("no sources") + err := errors.New("no sources") + log.WithFields(log.Fields{"app": name, "error": err}).Errorf("") + return nil, err } if len(destinations) == 0 { - return nil, fmt.Errorf("no destinations") + err := errors.New("no destinations") + log.WithFields(log.Fields{"app": name, "error": err}).Errorf("") + return nil, err } if len(schedule) == 0 { - return nil, fmt.Errorf("no schedule") + err := errors.New("no schedule") + log.WithFields(log.Fields{"app": name, "error": err}).Errorf("") + return nil, err } a := &App{ @@ -582,7 +589,9 @@ func (a *App) RunStandaloneTime(now time.Time) error { defer log.WithFields(log.Fields{"app": a.name}).Debugf("done") if cfgRun { - return fmt.Errorf("backup already running") + err := errors.New("backup already running") + log.WithFields(log.Fields{"app": a.name, "error": err}).Errorf("") + return err } CfgLock() @@ -615,7 +624,9 @@ func (a *App) RunStandaloneTime(now time.Time) error { return err } else { if sched == "" { - return fmt.Errorf("no backup needed") + err := errors.New("no backup needed") + log.WithFields(log.Fields{"app": a.name, "error": err}).Errorf("") + return err } } @@ -627,7 +638,9 @@ func (a *App) RunStandaloneSchedule(name string) error { defer log.WithFields(log.Fields{"app": a.name, "name": name}).Debugf("done") if cfgRun { - return fmt.Errorf("backup already running") + err := errors.New("backup already running") + log.WithFields(log.Fields{"app": a.name, "error": err}).Errorf("") + return err } CfgLock() diff --git a/config.go b/config.go index fe49b61..1fd5cc5 100644 --- a/config.go +++ b/config.go @@ -116,19 +116,19 @@ func LoadConfigByte(conf []byte) (*Config, error) { if c.Email != nil { if c.Email.Active { if len(c.Email.SmtpHost) == 0 { - err := fmt.Errorf("no smtp") + err := errors.New("no smtp") log.WithFields(log.Fields{"error": err}).Errorf("") return nil, err } if len(c.Email.FromEmail) == 0 { - err := fmt.Errorf("no email from") + err := errors.New("no email from") log.WithFields(log.Fields{"error": err}).Errorf("") return nil, err } if len(c.Email.ToEmail) == 0 { - err := fmt.Errorf("no email to") + err := errors.New("no email to") log.WithFields(log.Fields{"error": err}).Errorf("") return nil, err } diff --git a/version.go b/version.go index a6af4fa..e18ac06 100644 --- a/version.go +++ b/version.go @@ -1,7 +1,7 @@ // Code generated by version.sh (@generated) DO NOT EDIT. package main -var githash = "c871567" +var githash = "fd1c148" var branch = "master" -var buildstamp = "2025-12-28_18:26:51" -var commits = "124" -var version = "c871567-b124 - 2025-12-28_18:26:51" +var buildstamp = "2025-12-28_20:54:09" +var commits = "125" +var version = "fd1c148-b125 - 2025-12-28_20:54:09"