Files
phylum/server/internal/api/webdav/handler.go
2025-05-14 11:04:36 +05:30

86 lines
2.5 KiB
Go

package webdav
import (
"errors"
"net/http"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
webdav "github.com/shroff/phylum/server/internal/api/webdav/impl"
"github.com/shroff/phylum/server/internal/core/fs"
"github.com/shroff/phylum/server/internal/core/user"
"github.com/sirupsen/logrus"
)
type handler struct {
prefix string
lockSystem webdav.LockSystem
}
func SetupHandler(r *gin.RouterGroup) {
logrus.Debug("Setting up WebDAV access at " + r.BasePath())
handler := &handler{
prefix: r.BasePath(),
lockSystem: webdav.NewMemLS(),
}
r.Handle("OPTIONS", "/:root/*path", handler.HandleRequest)
r.Handle("GET", "/:root/*path", handler.HandleRequest)
r.Handle("PUT", "/:root/*path", handler.HandleRequest)
r.Handle("HEAD", "/:root/*path", handler.HandleRequest)
r.Handle("POST", "/:root/*path", handler.HandleRequest)
r.Handle("DELETE", "/:root/*path", handler.HandleRequest)
r.Handle("MOVE", "/:root/*path", handler.HandleRequest)
r.Handle("COPY", "/:root/*path", handler.HandleRequest)
r.Handle("MKCOL", "/:root/*path", handler.HandleRequest)
r.Handle("PROPFIND", "/:root/*path", handler.HandleRequest)
r.Handle("PROPPATCH", "/:root/*path", handler.HandleRequest)
r.Handle("LOCK", "/:root/*path", handler.HandleRequest)
r.Handle("UNLOCK", "/:root/*path", handler.HandleRequest)
}
func (h *handler) HandleRequest(c *gin.Context) {
authSuccess := false
var f fs.FileSystem
if email, pass, ok := c.Request.BasicAuth(); ok {
ctx := c.Request.Context()
userManager := user.ManagerFromContext(ctx)
if u, err := userManager.VerifyUserPassword(email, pass); err == nil {
authSuccess = true
root := c.Param("root")
f = u.OpenFileSystem(ctx)
if root[0] == '~' {
id, err := userManager.UserHome(root[1:])
if err != nil {
if errors.Is(err, user.ErrNotFound) {
c.AbortWithStatus(http.StatusNotFound)
return
} else {
panic(err)
}
}
f = f.WithPathRoot(id)
} else if id, err := uuid.Parse(root); err != nil {
f = f.WithPathRoot(pgtype.UUID{Bytes: id, Valid: false})
} else {
c.AbortWithStatus(http.StatusNotFound)
return
}
} else if !errors.Is(err, user.ErrCredentialsInvalid) {
panic(err)
}
}
if !authSuccess {
c.Header("WWW-Authenticate", "Basic realm=\"Phylum WebDAV\"")
c.AbortWithStatus(http.StatusUnauthorized)
return
}
webdavHandler := webdav.Handler{
Prefix: h.prefix + "/" + c.Param("root"),
FileSystem: f,
LockSystem: h.lockSystem,
}
webdavHandler.ServeHTTP(c.Writer, c.Request)
}