From 9ef77609678ddd80686d14f7ae6a876958be9b83 Mon Sep 17 00:00:00 2001 From: grngxd <36968271+grngxd@users.noreply.github.com> Date: Tue, 10 Jun 2025 00:10:03 +0100 Subject: [PATCH] split single file id "" into 2 properties --- internal/api/routes/files.go | 143 +++++++++++++++++++++++------------ internal/types/types.go | 2 +- 2 files changed, 96 insertions(+), 49 deletions(-) diff --git a/internal/api/routes/files.go b/internal/api/routes/files.go index a345fdf..3123de0 100644 --- a/internal/api/routes/files.go +++ b/internal/api/routes/files.go @@ -47,7 +47,7 @@ func RegisterFileRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { } fileMeta := types.File{ - ID: uid + "_" + file.Filename, + Name: file.Filename, Owner: uid, CreatedAt: time.Now(), Size: file.Size, @@ -58,66 +58,113 @@ func RegisterFileRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { return } - c.JSON(200, gin.H{"message": "file uploaded successfully", "file_id": fileMeta.ID}) + c.JSON(200, gin.H{"message": "file uploaded successfully", "name": fileMeta.Name}) }) - api.DELETE("/delete", auth.JwtMiddleware(cfg.JWTSecret), func(c *gin.Context) { + // api.DELETE("/delete", auth.JwtMiddleware(cfg.JWTSecret), func(c *gin.Context) { + // claims := c.MustGet("claims").(jwt.MapClaims) + // user := claims["user"].(auth.User) + + // uid := user.ID + // if uid == "" { + // c.JSON(401, gin.H{"error": "unauthorized"}) + // return + // } + + // var response struct { + // Name string `json:"name" binding:"required"` + // ID string `json:"id" binding:"required"` + // } + + // if err := c.ShouldBindJSON(&response); err != nil { + // c.JSON(400, gin.H{"error": "name is required"}) + // return + // } + + // name := response.Name + // if name == "" { + // c.JSON(400, gin.H{"error": "name cannot be empty"}) + // return + // } + + // resID := response.ID + // if resID == "" { + // c.JSON(400, gin.H{"error": "id cannot be empty"}) + // return + // } + + // if resID != uid { + // c.JSON(403, gin.H{"error": "you can only delete your own files"}) + // return + // } + + // filePath := filepath.Join(cfg.ImagePath, uid, name) + // if err := os.Remove(filePath); err != nil { + // c.JSON(500, gin.H{"error": "failed to delete file"}) + // return + // } + + // if err := cfg.Database.Where("name = ?", name).Where("owner = ?", uid).Delete(&types.File{}).Error; err != nil { + // c.JSON(500, gin.H{"error": "failed to delete file metadata"}) + // return + // } + + // c.JSON(200, gin.H{"message": "file deleted successfully"}) + // }) + + api.DELETE("/:uid/:name", auth.JwtMiddleware(cfg.JWTSecret), func(c *gin.Context) { claims := c.MustGet("claims").(jwt.MapClaims) user := claims["user"].(auth.User) - uid := user.ID + uid := c.Param("uid") + uid = strings.TrimSpace(uid) if uid == "" { - c.JSON(401, gin.H{"error": "unauthorized"}) + c.JSON(400, gin.H{"error": "uid is required"}) return } - var response struct { - FileID string `json:"file_id" binding:"required"` - } - - if err := c.ShouldBindJSON(&response); err != nil { - c.JSON(400, gin.H{"error": "file_id is required"}) - return - } - - resfID := response.FileID - if resfID == "" { - c.JSON(400, gin.H{"error": "file_id cannot be empty"}) - return - } - - parts := strings.SplitN(resfID, "_", 2) - if len(parts) != 2 { - c.JSON(400, gin.H{"error": "invalid file_id format"}) - return - } - - fileID, filename := parts[0], parts[1] - if fileID != uid { + if uid != user.ID { c.JSON(403, gin.H{"error": "you can only delete your own files"}) return } - filePath := filepath.Join(cfg.ImagePath, uid, filename) - if err := os.Remove(filePath); err != nil { + filename := c.Param("name") + filename = strings.TrimSpace(filename) + if filename == "" { + c.JSON(400, gin.H{"error": "filename is required"}) + return + } + + path := filepath.Join(cfg.ImagePath, uid, filename) + if _, err := os.Stat(path); os.IsNotExist(err) { + c.JSON(404, gin.H{"error": "file not found"}) + return + } + + if err := os.Remove(path); err != nil { c.JSON(500, gin.H{"error": "failed to delete file"}) return } - - if err := cfg.Database.Where("id = ?", resfID).Delete(&types.File{}).Error; err != nil { + if err := cfg.Database.Where("owner = ? AND name = ?", uid, filename).Delete(&types.File{}).Error; err != nil { c.JSON(500, gin.H{"error": "failed to delete file metadata"}) return } - c.JSON(200, gin.H{"message": "file deleted successfully"}) }) - api.GET("/:name", func(c *gin.Context) { - name := c.Param("name") - name = strings.TrimSpace(name) + api.GET("/:uid/:name", func(c *gin.Context) { + uid := c.Param("uid") + uid = strings.TrimSpace(uid) + if uid == "" { + c.JSON(400, gin.H{"error": "uid is required"}) + return + } + + filename := c.Param("name") + filename = strings.TrimSpace(filename) safe := "" - for _, r := range name { + for _, r := range filename { if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9') || r == '_' || r == '.' || r == '-' { safe += string(r) @@ -125,19 +172,19 @@ func RegisterFileRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { safe += "_" } } - name = safe + filename = safe - parts := strings.SplitN(name, "_", 2) - if len(parts) != 2 { - c.JSON(400, gin.H{"error": "invalid file name"}) - return - } + // parts := strings.SplitN(name, "_", 2) + // if len(parts) != 2 { + // c.JSON(400, gin.H{"error": "invalid file name"}) + // return + // } - uid, filename := parts[0], parts[1] - if uid == "" || filename == "" { - c.JSON(400, gin.H{"error": "invalid file name"}) - return - } + // uid, filename := parts[0], parts[1] + // if uid == "" || filename == "" { + // c.JSON(400, gin.H{"error": "invalid file name"}) + // return + // } path := filepath.Join(cfg.ImagePath, uid, filename) if _, err := os.Stat(path); err != nil { diff --git a/internal/types/types.go b/internal/types/types.go index abae4ee..9dd0178 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -25,7 +25,7 @@ type StereoConfig struct { } type File struct { - ID string `gorm:"primaryKey"` + Name string `gorm:"primaryKey"` Owner string `gorm:"not null;index"` Size int64 `gorm:"not null;type:bigint"` CreatedAt time.Time `gorm:"autoCreateTime"`