From 70a9bcd904ff421c697fd7f572a9f0133618efdc Mon Sep 17 00:00:00 2001 From: juls0730 <62722391+juls0730@users.noreply.github.com> Date: Mon, 9 Sep 2024 01:35:33 -0500 Subject: [PATCH] bug fixes file deletions and more --- main.go | 7 +- models/user.go | 1 + routes/auth.go | 8 ++ routes/files.go | 94 ++++++++++++++++-- ui/components/Breadcrumbs.vue | 6 +- ui/components/Checkbox.vue | 23 +++++ ui/components/FileNav.vue | 5 - ui/components/Nav.vue | 2 +- ui/components/Popup.vue | 43 ++++++++ ui/pages/home/[...name].vue | 179 +++++++++++++++++++++++++++++----- ui/pages/login.vue | 1 - ui/pages/signup.vue | 1 - ui/types/file.ts | 3 +- ui/types/user.ts | 3 +- 14 files changed, 325 insertions(+), 51 deletions(-) create mode 100644 ui/components/Checkbox.vue create mode 100644 ui/components/Popup.vue diff --git a/main.go b/main.go index 8340b10..5bb1a98 100644 --- a/main.go +++ b/main.go @@ -74,10 +74,11 @@ func main() { // everything past this needs auth api.Use(middleware.SessionMiddleware(db)) api.GET("/user", routes.GetUser) - api.GET("/user/usage", routes.GetUsage) - api.POST("/upload*", routes.UploadFile) - api.GET("/files*", routes.GetFiles) + api.POST("/files/upload*", routes.UploadFile) + api.GET("/files/get/*", routes.GetFiles) + api.GET("/files/download/*", routes.GetFile) + api.POST("/files/delete*", routes.DeleteFiles) } // redirects to the proper pages if you are trying to access one that expects you have/dont have an api key diff --git a/models/user.go b/models/user.go index a6e04a5..cd4dd10 100644 --- a/models/user.go +++ b/models/user.go @@ -24,6 +24,7 @@ type User struct { PasswordHash string `bun:"passwordHash,notnull" json:"-"` PlanID int64 `bun:"plan_id,notnull" json:"-"` Plan Plan `bun:"rel:belongs-to,join:plan_id=id" json:"plan"` + Usage int64 `bun:"-" json:"usage"` } type Session struct { diff --git a/routes/auth.go b/routes/auth.go index ed76e98..678c4b6 100644 --- a/routes/auth.go +++ b/routes/auth.go @@ -136,5 +136,13 @@ func GetUser(c echo.Context) error { return c.JSON(http.StatusNotFound, map[string]string{"message": "User not found"}) } + basePath := fmt.Sprintf("%s/%s/", os.Getenv("STORAGE_PATH"), user.(*models.User).ID) + storageUsage, err := calculateStorageUsage(basePath) + if err != nil { + return err + } + + user.(*models.User).Usage = storageUsage + return c.JSON(http.StatusOK, user.(*models.User)) } diff --git a/routes/files.go b/routes/files.go index 8c1272f..7961e50 100644 --- a/routes/files.go +++ b/routes/files.go @@ -23,14 +23,51 @@ func UploadFile(c echo.Context) error { fullPath := strings.Trim(c.Param("*"), "/") basePath := fmt.Sprintf("%s/%s/%s/", os.Getenv("STORAGE_PATH"), user.ID, fullPath) - currentUsage, err := calculateStorageUsage(basePath) + currentUsage, err := calculateStorageUsage(fmt.Sprintf("%s/%s", os.Getenv("STORAGE_PATH"), user.ID)) if err != nil { fmt.Println(err) return err } + _, err = os.Stat(basePath) + directoryExists := err == nil + + // Create the directories if they don't exist + if !directoryExists { + err = os.MkdirAll(basePath, os.ModePerm) + if err != nil { + fmt.Println(err) + return err + } + } + reader, err := c.Request().MultipartReader() if err != nil { + if err == http.ErrNotMultipart { + if directoryExists { + // Directories exist, but no file was uploaded + return c.JSON(http.StatusBadRequest, map[string]string{"message": "A folder with that name already exists"}) + } + // Directories were just created, and no file was provided + entry, err := os.Stat(basePath) + + if err != nil { + fmt.Println(err) + return err + } + + uploadFile := &UploadResponse{ + Usage: currentUsage + entry.Size(), + File: File{ + Name: entry.Name(), + IsDir: entry.IsDir(), + Size: entry.Size(), + LastModified: entry.ModTime().Format("1/2/2006"), + }, + } + + return c.JSON(http.StatusOK, uploadFile) + } fmt.Println(err) return err } @@ -41,6 +78,11 @@ func UploadFile(c echo.Context) error { return err } + if err != nil { + fmt.Println(err) + return err + } + filepath := filepath.Join(basePath, part.FileName()) if _, err = os.Stat(filepath); err == nil { @@ -173,22 +215,58 @@ func GetFiles(c echo.Context) error { Name: f.Name(), IsDir: f.IsDir(), Size: f.Size(), - LastModified: f.ModTime().Format("1/2/2006"), + LastModified: f.ModTime().Format("2 Jan 06"), }) } return c.JSON(http.StatusOK, jsonFiles) } -func GetUsage(c echo.Context) error { +func GetFile(c echo.Context) error { user := c.Get("user").(*models.User) fullPath := strings.Trim(c.Param("*"), "/") - basePath := fmt.Sprintf("%s/%s/%s/", os.Getenv("STORAGE_PATH"), user.ID, fullPath) - storageUsage, err := calculateStorageUsage(basePath) - if err != nil { - return err + basePath := fmt.Sprintf("%s/%s/%s", os.Getenv("STORAGE_PATH"), user.ID, fullPath) + + return c.File(basePath) +} + +type DeleteRequest struct { + Files []File `json:"files"` +} + +func DeleteFiles(c echo.Context) error { + var deleteData DeleteRequest + + if err := c.Bind(&deleteData); err != nil { + fmt.Println(err) + return c.JSON(http.StatusInternalServerError, map[string]string{"message": "An unknown error occoured!"}) } - return c.JSON(http.StatusOK, map[string]int64{"usage": storageUsage}) + if len(deleteData.Files) == 0 { + return c.JSON(http.StatusBadRequest, map[string]string{"message": "Files are required!"}) + } + + user := c.Get("user").(*models.User) + + fullPath := strings.Trim(c.Param("*"), "/") + basePath := fmt.Sprintf("%s/%s/%s", os.Getenv("STORAGE_PATH"), user.ID, fullPath) + + for _, file := range deleteData.Files { + path := filepath.Join(basePath, file.Name) + err := os.RemoveAll(path) + if err != nil { + fmt.Println(err) + return c.JSON(http.StatusInternalServerError, map[string]string{"message": "An unknown error occoured!"}) + } + } + + word := "file" + fileLen := len(deleteData.Files) + + if fileLen != 1 { + word = word + "s" + } + + return c.JSON(http.StatusOK, map[string]string{"message": fmt.Sprintf("Successfully deleted %d %s", fileLen, word)}) } diff --git a/ui/components/Breadcrumbs.vue b/ui/components/Breadcrumbs.vue index e7892eb..af54883 100644 --- a/ui/components/Breadcrumbs.vue +++ b/ui/components/Breadcrumbs.vue @@ -25,9 +25,9 @@ const crumbs = computed(() => { - {{ - crumb.name }} + {{ + crumb.name }} \ No newline at end of file diff --git a/ui/components/Checkbox.vue b/ui/components/Checkbox.vue new file mode 100644 index 0000000..9df3f03 --- /dev/null +++ b/ui/components/Checkbox.vue @@ -0,0 +1,23 @@ + + + \ No newline at end of file diff --git a/ui/components/FileNav.vue b/ui/components/FileNav.vue index d4e3747..0cda88f 100644 --- a/ui/components/FileNav.vue +++ b/ui/components/FileNav.vue @@ -19,7 +19,6 @@ const percentage = computed(() => { return (props.usageBytes / capacityBytes.value); }); -console.log(percentage.value, props.usageBytes, capacityBytes.value) const offset = computed(() => { return circumference - percentage.value * circumference; }); @@ -30,10 +29,6 @@ const capacity = computed(() => { return formatBytes(capacityBytes.value) }); -if (props.usageBytes > capacityBytes.value) { - console.log("SCAN SCAN SCAM SCAM") -} - const isAllFilesActive = computed(() => route.path === '/home'); const isInFolder = computed(() => route.path.startsWith('/home/') && route.path !== '/home'); diff --git a/ui/components/Nav.vue b/ui/components/Nav.vue index aff9e0f..56c800e 100644 --- a/ui/components/Nav.vue +++ b/ui/components/Nav.vue @@ -18,7 +18,7 @@ const changeTheme = () => {