package file import ( "bytes" "fmt" "io" "os" "strings" "github.com/labstack/echo/v4" "gitnet.fr/deblan/budget/backend/controller/crud" "gitnet.fr/deblan/budget/backend/message" "gitnet.fr/deblan/budget/config" "gitnet.fr/deblan/budget/database/model" f "gitnet.fr/deblan/budget/file" ) type Controller struct { } func New(e *echo.Echo) *Controller { c := Controller{} e.GET("/api/filemanager/files", c.List) e.POST("/api/filemanager/file", c.CreateFile) e.POST("/api/filemanager/directory", c.CreateDirectory) e.GET("/api/filemanager/file/:id/:name", c.Download) e.DELETE("/api/filemanager/file/:id", c.Delete) return &c } func (ctrl *Controller) List(c echo.Context) error { if nil == model.LoadApiUser(c) { return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } tree := f.GetTree("", config.Get().File.Path) return c.JSON(200, tree) } func (ctrl *Controller) CreateFile(c echo.Context) error { if nil == model.LoadApiUser(c) { return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } file, err := c.FormFile("file") if err != nil { return c.JSON(400, crud.Error{ Code: 400, Message: err.Error(), }) } src, err := file.Open() if err != nil { return c.JSON(400, crud.Error{ Code: 400, Message: err.Error(), }) } defer src.Close() var buf bytes.Buffer io.Copy(&buf, src) output := searchDirectory(c.FormValue("path"), f.GetTree("", config.Get().File.Path)) if output != nil { os.WriteFile(output.Path+"/"+file.Filename, buf.Bytes(), 0644) return c.JSON(200, true) } return c.JSON(400, false) } func (ctrl *Controller) CreateDirectory(c echo.Context) error { if nil == model.LoadApiUser(c) { return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } type body struct { Directory string `json:"directory" validate:"required"` Path string `json:"path" validate:"required"` } value := new(body) if err := c.Bind(value); err != nil { return c.JSON(400, crud.Error{ Code: 400, Message: "Bad request", }) } fmt.Printf("%+v\n", value) value.Directory = strings.ReplaceAll(value.Directory, "..", "") value.Directory = strings.ReplaceAll(value.Directory, "/", "") value.Directory = strings.ReplaceAll(value.Directory, "\\", "") value.Directory = strings.TrimSpace(value.Directory) fmt.Printf("%+v\n", value) if err := c.Validate(value); err != nil { return c.JSON(400, crud.Error{ Code: 400, Message: err.Error(), }) } output := searchDirectory(value.Path, f.GetTree("", config.Get().File.Path)) if output != nil { dir := strings.ReplaceAll(output.Path+"/"+value.Directory, "//", "/") os.MkdirAll(dir, 0750) return c.JSON(200, true) } return c.JSON(400, crud.Error{ Code: 400, Message: "Bad request", }) } func (ctrl *Controller) Download(c echo.Context) error { if nil == model.LoadUser(c) { return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } var file string var contentType string files := []f.File{} f.GetFiles(&files, config.Get().File.Path) for _, f := range files { if f.Id == c.Param("id") { file = f.Path contentType = f.Type } } if file == "" { return c.JSON(404, message.FileNotFound) } content, _ := os.ReadFile(file) return c.Blob(200, contentType, content) } func (ctrl *Controller) Delete(c echo.Context) error { if nil == model.LoadApiUser(c) { return c.JSON(403, crud.Error{Code: 403, Message: message.LoginRequired}) } var file string files := []f.File{} directories := []f.Directory{} f.GetFiles(&files, config.Get().File.Path) f.GetDirectories(&directories, config.Get().File.Path) for _, f := range files { if f.Id == c.Param("id") { file = f.Path } } for _, f := range directories { if f.Id == c.Param("id") { file = f.Path } } if file == "" { return c.JSON(404, message.FileNotFound) } os.RemoveAll(file) return c.JSON(200, nil) } func searchDirectory(id string, tree f.Tree) *f.Tree { if tree.Id == id { return &tree } for _, tree = range tree.Directories { tr := searchDirectory(id, tree) if tr != nil { return tr } } return nil }