diff --git a/server/internal/api/routes/fs/cat.go b/server/internal/api/routes/fs/cat.go new file mode 100644 index 00000000..3c3bfc7f --- /dev/null +++ b/server/internal/api/routes/fs/cat.go @@ -0,0 +1,22 @@ +package fs + +import ( + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/shroff/phylum/server/internal/api/auth" + "github.com/shroff/phylum/server/internal/net/serve" +) + +func handleCatRequest(c *gin.Context) { + resourceID, err := uuid.Parse(c.Param("id")) + if err != nil { + panic(errResourceIDInvalid) + } + + fs := auth.GetFileSystem(c) + r, err := fs.ResourceByID(resourceID) + if err != nil { + panic(err) + } + serve.ServeResource(c.Writer, c.Request, fs, r) +} diff --git a/server/internal/api/routes/fs/du.go b/server/internal/api/routes/fs/du.go new file mode 100644 index 00000000..ea0f0fdd --- /dev/null +++ b/server/internal/api/routes/fs/du.go @@ -0,0 +1,36 @@ +package fs + +import ( + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/shroff/phylum/server/internal/api/auth" +) + +type DiskUsageResponse struct { + TotalSize int64 `json:"size"` + Files int64 `json:"files"` + Dirs int64 `json:"dirs"` +} + +func handleDuRequest(c *gin.Context) { + resourceId, err := uuid.Parse(c.Param("id")) + if err != nil { + panic(errResourceIDInvalid) + } + + fs := auth.GetFileSystem(c) + resource, err := fs.ResourceByID(resourceId) + if err != nil { + panic(err) + } + + info, err := fs.DiskUsage(resource) + if err != nil { + panic(err) + } + c.JSON(200, DiskUsageResponse{ + TotalSize: info.TotalSize, + Files: info.Files, + Dirs: info.Dirs, + }) +} diff --git a/server/internal/api/routes/fs/ls.go b/server/internal/api/routes/fs/ls.go index 2a5be476..b1b83086 100644 --- a/server/internal/api/routes/fs/ls.go +++ b/server/internal/api/routes/fs/ls.go @@ -13,7 +13,7 @@ type ResourceLsResponse struct { InheritedPermissions string `json:"inherited,omitempty"` } -func handleResourceLsRoute(c *gin.Context) { +func handleLsRequest(c *gin.Context) { resourceID, err := uuid.Parse(c.Param("id")) if err != nil { panic(errResourceIDInvalid) diff --git a/server/internal/api/routes/fs/mkdir.go b/server/internal/api/routes/fs/mkdir.go new file mode 100644 index 00000000..646e5ab1 --- /dev/null +++ b/server/internal/api/routes/fs/mkdir.go @@ -0,0 +1,38 @@ +package fs + +import ( + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/shroff/phylum/server/internal/api/auth" +) + +type mkdirParams struct { + Name string `json:"name" binding:"required"` + ParentID uuid.UUID `json:"parent_id" binding:"required"` +} + +func handleMkdirRequest(c *gin.Context) { + var params mkdirParams + err := c.ShouldBindJSON(¶ms) + if err != nil || params.Name == "" { + panic(errInvalidParams) + } + + resourceID, err := uuid.Parse(c.Param("id")) + if err != nil { + panic(errResourceIDInvalid) + } + + fs := auth.GetFileSystem(c) + parent, err := fs.ResourceByID(params.ParentID) + if err != nil { + panic(err) + } + + r, err := fs.CreateMemberResource(parent, resourceID, params.Name, true) + if err != nil { + panic(err) + } + + c.JSON(200, r) +} diff --git a/server/internal/api/routes/fs/mv.go b/server/internal/api/routes/fs/mv.go new file mode 100644 index 00000000..bdb10680 --- /dev/null +++ b/server/internal/api/routes/fs/mv.go @@ -0,0 +1,38 @@ +package fs + +import ( + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/shroff/phylum/server/internal/api/auth" +) + +type mvParams struct { + ParentID uuid.UUID `json:"parent_id"` + Name string `json:"name"` + Overwrite bool `json:"overwrite"` +} + +func handleMvRequest(c *gin.Context) { + var params mvParams + err := c.ShouldBindJSON(¶ms) + if err != nil || (params.ParentID == uuid.Nil && params.Name == "") { + panic(errInvalidParams) + } + + resourceID, err := uuid.Parse(c.Param("id")) + if err != nil { + panic(errResourceIDInvalid) + } + + fs := auth.GetFileSystem(c) + r, err := fs.ResourceByID(resourceID) + if err != nil { + panic(err) + } + + if r, err := fs.Move(r, params.ParentID, params.Name, params.Overwrite); err != nil { + panic(err) + } else { + c.JSON(200, r) + } +} diff --git a/server/internal/api/routes/fs/responses.go b/server/internal/api/routes/fs/responses.go deleted file mode 100644 index 6c0cbc7d..00000000 --- a/server/internal/api/routes/fs/responses.go +++ /dev/null @@ -1,7 +0,0 @@ -package fs - -type DiskUsageResponse struct { - TotalSize int64 `json:"size"` - Files int64 `json:"files"` - Dirs int64 `json:"dirs"` -} diff --git a/server/internal/api/routes/fs/rm.go b/server/internal/api/routes/fs/rm.go new file mode 100644 index 00000000..b4cf788e --- /dev/null +++ b/server/internal/api/routes/fs/rm.go @@ -0,0 +1,26 @@ +package fs + +import ( + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/shroff/phylum/server/internal/api/auth" +) + +func handleRmRequest(c *gin.Context) { + id, err := uuid.Parse(c.Param("id")) + if err != nil { + panic(errResourceIDInvalid) + } + + fs := auth.GetFileSystem(c) + r, err := fs.ResourceByID(id) + if err != nil { + panic(err) + } + ids, err := fs.DeleteRecursive(r, false) + if err != nil { + panic(err) + } + + c.JSON(200, gin.H{"ids": ids}) +} diff --git a/server/internal/api/routes/fs/routes.go b/server/internal/api/routes/fs/routes.go index 8901fd67..272888c6 100644 --- a/server/internal/api/routes/fs/routes.go +++ b/server/internal/api/routes/fs/routes.go @@ -1,15 +1,10 @@ package fs import ( - "io" "net/http" "github.com/gin-gonic/gin" - "github.com/google/uuid" - "github.com/shroff/phylum/server/internal/api/auth" "github.com/shroff/phylum/server/internal/api/errors" - "github.com/shroff/phylum/server/internal/core" - "github.com/shroff/phylum/server/internal/net/serve" ) var ( @@ -17,192 +12,13 @@ var ( errInvalidParams = errors.New(http.StatusBadRequest, "invalid_parameters", "Invalid Request Parameters") ) -type resourceMkdirParams struct { - Name string `json:"name" binding:"required"` - ParentID uuid.UUID `json:"parent_id" binding:"required"` -} - -type resourceMoveParams struct { - ParentID uuid.UUID `json:"parent_id"` - Name string `json:"name"` - Overwrite bool `json:"overwrite"` -} - func SetupRoutes(r *gin.RouterGroup) { - group := r.Group("/resources") - group.GET("/du/:id", handleResourceDiskUsageRoute) - group.GET("/ls/:id", handleResourceLsRoute) - group.GET("/contents/:id", handleResourceContentsRoute) - group.POST("/mkdir/:id", handleResourceMkdirRoute) - group.POST("/move/:id", handleResourceMoveRoute) - group.PUT("/upload/:id", handleResourceUploadRoute) - group.DELETE("/delete/:id", handleResourceDeleteRoute) -} - -func handleResourceDiskUsageRoute(c *gin.Context) { - resourceId, err := uuid.Parse(c.Param("id")) - if err != nil { - panic(errResourceIDInvalid) - } - - fs := auth.GetFileSystem(c) - resource, err := fs.ResourceByID(resourceId) - if err != nil { - panic(err) - } - - info, err := fs.DiskUsage(resource) - if err != nil { - panic(err) - } - c.JSON(200, DiskUsageResponse{ - TotalSize: info.TotalSize, - Files: info.Files, - Dirs: info.Dirs, - }) -} - -func handleResourceContentsRoute(c *gin.Context) { - resourceID, err := uuid.Parse(c.Param("id")) - if err != nil { - panic(errResourceIDInvalid) - } - - fs := auth.GetFileSystem(c) - r, err := fs.ResourceByID(resourceID) - if err != nil { - panic(err) - } - serve.ServeResource(c.Writer, c.Request, fs, r) -} - -func handleResourceMkdirRoute(c *gin.Context) { - var params resourceMkdirParams - err := c.ShouldBindJSON(¶ms) - if err != nil || params.Name == "" { - panic(errInvalidParams) - } - - resourceID, err := uuid.Parse(c.Param("id")) - if err != nil { - panic(errResourceIDInvalid) - } - - fs := auth.GetFileSystem(c) - parent, err := fs.ResourceByID(params.ParentID) - if err != nil { - panic(err) - } - - r, err := fs.CreateMemberResource(parent, resourceID, params.Name, true) - if err != nil { - panic(err) - } - - c.JSON(200, r) -} - -func handleResourceMoveRoute(c *gin.Context) { - var params resourceMoveParams - err := c.ShouldBindJSON(¶ms) - if err != nil || (params.ParentID == uuid.Nil && params.Name == "") { - panic(errInvalidParams) - } - - resourceID, err := uuid.Parse(c.Param("id")) - if err != nil { - panic(errResourceIDInvalid) - } - - fs := auth.GetFileSystem(c) - r, err := fs.ResourceByID(resourceID) - if err != nil { - panic(err) - } - - if r, err := fs.Move(r, params.ParentID, params.Name, params.Overwrite); err != nil { - panic(err) - } else { - c.JSON(200, r) - } -} - -func handleResourceUploadRoute(c *gin.Context) { - resourceID, err := uuid.Parse(c.Param("id")) - if err != nil { - panic(errResourceIDInvalid) - } - - name := c.Request.FormValue("name") - parentID, err := uuid.Parse(c.Request.FormValue("parent_id")) - if err != nil || name == "" { - panic(errInvalidParams) - } - // TODO: Calculate and verify sha sum - // c.Request.FormValue("sha256sum") - - f := auth.GetFileSystem(c) - err = f.RunInTx(func(fs core.FileSystem) error { - parent, err := fs.ResourceByID(parentID) - if err != nil { - return err - } - - res, err := fs.CreateMemberResource(parent, resourceID, name, false) - if err != nil { - return err - } - - file, err := c.FormFile("contents") - if err != nil { - if err == http.ErrMissingFile { - return errInvalidParams - } - return err - } - - src, err := file.Open() - if err != nil { - return err - } - defer src.Close() - - out, err := fs.OpenWrite(res) - if err != nil { - return err - } - defer out.Close() - - _, err = io.Copy(out, src) - return err - }) - if err != nil { - panic(err) - } - - // TODO: Avoid reading from db again if we can update size and etag - r, err := f.ResourceByID(resourceID) - if err != nil { - panic(err) - } - c.JSON(200, r) -} - -func handleResourceDeleteRoute(c *gin.Context) { - id, err := uuid.Parse(c.Param("id")) - if err != nil { - panic(errResourceIDInvalid) - } - - fs := auth.GetFileSystem(c) - r, err := fs.ResourceByID(id) - if err != nil { - panic(err) - } - ids, err := fs.DeleteRecursive(r, false) - if err != nil { - panic(err) - } - - c.JSON(200, gin.H{"ids": ids}) + group := r.Group("/fs") + group.GET("/du/:id", handleDuRequest) + group.GET("/ls/:id", handleLsRequest) + group.POST("/mkdir/:id", handleMkdirRequest) + group.POST("/mv/:id", handleMvRequest) + group.DELETE("/rm/:id", handleRmRequest) + group.PUT("/upload/:id", handleUploadRequest) + group.GET("/cat/:id", handleCatRequest) } diff --git a/server/internal/api/routes/fs/upload.go b/server/internal/api/routes/fs/upload.go new file mode 100644 index 00000000..38676271 --- /dev/null +++ b/server/internal/api/routes/fs/upload.go @@ -0,0 +1,72 @@ +package fs + +import ( + "io" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/shroff/phylum/server/internal/api/auth" + "github.com/shroff/phylum/server/internal/core" +) + +func handleUploadRequest(c *gin.Context) { + resourceID, err := uuid.Parse(c.Param("id")) + if err != nil { + panic(errResourceIDInvalid) + } + + name := c.Request.FormValue("name") + parentID, err := uuid.Parse(c.Request.FormValue("parent_id")) + if err != nil || name == "" { + panic(errInvalidParams) + } + // TODO: Calculate and verify sha sum + // c.Request.FormValue("sha256sum") + + f := auth.GetFileSystem(c) + err = f.RunInTx(func(fs core.FileSystem) error { + parent, err := fs.ResourceByID(parentID) + if err != nil { + return err + } + + res, err := fs.CreateMemberResource(parent, resourceID, name, false) + if err != nil { + return err + } + + file, err := c.FormFile("contents") + if err != nil { + if err == http.ErrMissingFile { + return errInvalidParams + } + return err + } + + src, err := file.Open() + if err != nil { + return err + } + defer src.Close() + + out, err := fs.OpenWrite(res) + if err != nil { + return err + } + defer out.Close() + + _, err = io.Copy(out, src) + return err + }) + if err != nil { + panic(err) + } + + // TODO: Avoid reading from db again if we can update size and etag + r, err := f.ResourceByID(resourceID) + if err != nil { + panic(err) + } + c.JSON(200, r) +}