package webdav import ( "bytes" "io" "net/http" "strconv" "git.ma-al.com/goc_daniel/b2b/app/config" "git.ma-al.com/goc_daniel/b2b/app/service/storageService" "git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors" "github.com/gofiber/fiber/v3" ) type StorageHandler struct { storageService *storageService.StorageService config *config.Config } func NewStorageHandler() *StorageHandler { return &StorageHandler{ storageService: storageService.New(), config: config.Get(), } } func StorageHandlerRoutes(r fiber.Router) fiber.Router { handler := NewStorageHandler() // for webdav use only r.Get("/*", handler.Get) r.Head("/*", handler.Get) r.Put("/*", handler.Put) r.Delete("/*", handler.Delete) r.Add([]string{"MKCOL"}, "/*", handler.Mkcol) r.Add([]string{"PROPFIND"}, "/*", handler.Propfind) r.Add([]string{"PROPPATCH"}, "/*", handler.Proppatch) r.Add([]string{"MOVE"}, "/*", handler.Move) r.Add([]string{"COPY"}, "/*", handler.Copy) return r } func (h *StorageHandler) Get(c fiber.Ctx) error { // fmt.Println("GET") absPath, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Params("*")) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } info, err := h.storageService.EntryInfo(absPath) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } if info.IsDir() { xml, err := h.storageService.Propfind(h.config.Storage.RootFolder, absPath, "1") if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } c.Set("Content-Type", `application/xml; charset="utf-8"`) return c.Status(http.StatusMultiStatus).SendString(xml) } else { f, filename, filesize, err := h.storageService.DownloadFilePrep(absPath) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } c.Attachment(filename) c.Set("Content-Length", strconv.FormatInt(filesize, 10)) c.Set("Content-Type", "application/octet-stream") return c.SendStream(f, int(filesize)) } } func (h *StorageHandler) Put(c fiber.Ctx) error { // fmt.Println("PUT") absPath, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Params("*")) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } var src io.Reader if bodyStream := c.Request().BodyStream(); bodyStream != nil { defer c.Request().CloseBodyStream() src = bodyStream } else { src = bytes.NewReader(c.Body()) } err = h.storageService.Put(absPath, src) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } return c.SendStatus(http.StatusCreated) } func (h *StorageHandler) Delete(c fiber.Ctx) error { // fmt.Println("DELETE") absPath, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Params("*")) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } if absPath == h.config.Storage.RootFolder { return c.SendStatus(responseErrors.GetErrorStatus(responseErrors.ErrAccessDenied)) } err = h.storageService.Delete(absPath) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } return c.SendStatus(http.StatusNoContent) } func (h *StorageHandler) Mkcol(c fiber.Ctx) error { // fmt.Println("Mkcol") absPath, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Params("*")) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } err = h.storageService.Mkcol(absPath) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } return c.SendStatus(http.StatusCreated) } func (h *StorageHandler) Propfind(c fiber.Ctx) error { // fmt.Println("PROPFIND") absPath, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Params("*")) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } xml, err := h.storageService.Propfind(h.config.Storage.RootFolder, absPath, "1") if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } c.Set("Content-Type", `application/xml; charset="utf-8"`) return c.Status(http.StatusMultiStatus).SendString(xml) } func (h *StorageHandler) Proppatch(c fiber.Ctx) error { return c.SendStatus(http.StatusNotImplemented) // 501 } func (h *StorageHandler) Move(c fiber.Ctx) error { // fmt.Println("MOVE") srcAbsPath, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Params("*")) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } dest := c.Get("Destination") if dest == "" { return c.SendStatus(http.StatusBadRequest) } destAbsPath, err := h.storageService.ObtainDestPath(h.config.Storage.RootFolder, dest) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } err = h.storageService.Move(srcAbsPath, destAbsPath) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } return c.SendStatus(http.StatusCreated) } func (h *StorageHandler) Copy(c fiber.Ctx) error { // fmt.Println("COPY") srcAbsPath, err := h.storageService.AbsPath(h.config.Storage.RootFolder, c.Params("*")) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } dest := c.Get("Destination") if dest == "" { return c.SendStatus(http.StatusBadRequest) } destAbsPath, err := h.storageService.ObtainDestPath(h.config.Storage.RootFolder, dest) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } err = h.storageService.Copy(srcAbsPath, destAbsPath) if err != nil { return c.SendStatus(responseErrors.GetErrorStatus(err)) } return c.SendStatus(http.StatusCreated) }