From c99c202bc859b4be1b03b6075d4fcbe259becdf9 Mon Sep 17 00:00:00 2001 From: hex Date: Sat, 14 Jun 2025 23:39:20 +0200 Subject: [PATCH] new error system (+ some quick fixes) --- internal/api/routes/files.go | 62 ++++++++++++++------------------- internal/types/errors.go | 66 ++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 36 deletions(-) create mode 100644 internal/types/errors.go diff --git a/internal/api/routes/files.go b/internal/api/routes/files.go index e827e17..74a0fd3 100644 --- a/internal/api/routes/files.go +++ b/internal/api/routes/files.go @@ -3,7 +3,6 @@ package routes import ( "bytes" "io" - "log" "strings" "time" @@ -27,40 +26,42 @@ func RegisterFileRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { uid := user.ID if uid == "" { - c.JSON(401, gin.H{"error": "unauthorized"}) + types.ErrorInvalidParams.Throw(c, nil) return } file, err := c.FormFile("file") if err != nil { - c.JSON(400, gin.H{"error": "file is required"}) + types.ErrorInvalidParams.Throw(c, err) return } if file.Size <= 0 { - c.JSON(400, gin.H{"error": "file size must be greater than zero"}) + types.ErrorInvalidParams.Throw(c, nil) return } fileReader, err := file.Open() if err != nil { - c.JSON(500, gin.H{"error": "couldn't open file"}) - log.Println(err) + types.ErrorReaderOpen.Throw(c, err) return } buf, err := io.ReadAll(fileReader) if err != nil { - c.JSON(500, gin.H{"error": "couldn't open file"}) - log.Println(err) + types.ErrorReaderOpen.Throw(c, err) + return + } + + if !filetype.IsImage(buf) { + types.ErrorInvalidFile.Throw(c, nil) return } fileType, err := filetype.Match(buf) if err != nil { - c.JSON(500, gin.H{"error": "couldn't open file"}) - log.Println(err) + types.ErrorReaderOpen.Throw(c, err) return } @@ -73,15 +74,14 @@ func RegisterFileRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { } if err := cfg.Database.Create(&fileMeta).Error; err != nil { - c.JSON(500, gin.H{"error": "failed to save file metadata"}) + types.ErrorDatabase.Throw(c, err) return } _, err = cfg.MinioClient.PutObject(cfg.Context, cfg.Bucket, fileMeta.ID.String(), intoReader(buf), fileMeta.Size, minio.PutObjectOptions{ContentType: fileMeta.Mime}) if err != nil { - c.JSON(500, gin.H{"error": "failed to upload file"}) - log.Println(err) + types.ErrorS3.Throw(c, err) return } @@ -92,21 +92,9 @@ func RegisterFileRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { claims := c.MustGet("claims").(jwt.MapClaims) user := claims["user"].(auth.User) - uid := c.Param("uid") - uid = strings.TrimSpace(uid) - if uid == "" { - c.JSON(400, gin.H{"error": "uid is required"}) - return - } - - if uid != user.ID { - c.JSON(403, gin.H{"error": "you can only delete your own files"}) - return - } - fileID, err := uuid.FromString(strings.TrimSpace(c.Param("id"))) if err != nil { - c.JSON(404, gin.H{"error": "file not found"}) + types.ErrorInvalidFile.Throw(c, err) return } @@ -115,17 +103,22 @@ func RegisterFileRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { cfg.Database.First(&file, fileID) if file == nil { - c.JSON(404, gin.H{"error": "file not found"}) + types.ErrorFileNotFound.Throw(c, nil) + return + } + + if file.Owner != user.ID { + types.ErrorUnauthorized.Throw(c, nil) return } if err := cfg.MinioClient.RemoveObject(cfg.Context, cfg.Bucket, fileID.String(), minio.RemoveObjectOptions{}); err != nil { - c.JSON(500, gin.H{"error": "failed to delete file"}) + types.ErrorS3.Throw(c, err) return } if err := cfg.Database.Delete(&file).Error; err != nil { - c.JSON(500, gin.H{"error": "failed to delete file metadata"}) + types.ErrorDatabase.Throw(c, err) return } @@ -140,23 +133,20 @@ func RegisterFileRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { id, err := uuid.FromString(fileID) if err != nil { - c.JSON(500, gin.H{"error": "invalid file id"}) - log.Println(err) + types.ErrorInvalidFile.Throw(c, err) return } cfg.Database.First(&file, id) if file == nil { - c.JSON(500, gin.H{"error": "file does not exist"}) - log.Println(err) + types.ErrorFileNotFound.Throw(c, nil) return } object, err := cfg.MinioClient.GetObject(cfg.Context, cfg.Bucket, fileID, minio.GetObjectOptions{}) if err != nil { - c.JSON(500, gin.H{"error": "failed to retrieve file"}) - log.Println(err) + types.ErrorS3.Throw(c, err) return } @@ -169,7 +159,7 @@ func RegisterFileRoutes(cfg *types.StereoConfig, api *gin.RouterGroup) { var files []types.File if err := cfg.Database.Where("owner = ?", user.ID).Find(&files).Error; err != nil { - c.JSON(500, gin.H{"error": "failed to retrieve files"}) + types.ErrorDatabase.Throw(c, err) return } diff --git a/internal/types/errors.go b/internal/types/errors.go new file mode 100644 index 0000000..3ed414e --- /dev/null +++ b/internal/types/errors.go @@ -0,0 +1,66 @@ +package types + +import ( + "errors" + "fmt" + + "github.com/gin-gonic/gin" +) + +type StereoError struct { + Code int + StatusCode int +} + +func (e *StereoError) Throw(c *gin.Context, err error) { + c.JSON(e.StatusCode, gin.H{ + "code": e.Code, + "success": false, + }) + + if err != nil { + c.Error(err) + } else { + c.Error(errors.New(fmt.Sprintf("Got an error with code: %v", e.Code))) + } +} + +var ErrorFileNotFound = StereoError{ + Code: 0, + StatusCode: 404, +} + +var ErrorReaderOpen = StereoError{ + Code: 1, + StatusCode: 500, +} + +var ErrorUnauthorized = StereoError{ + Code: 2, + StatusCode: 401, +} + +var ErrorInvalidParams = StereoError{ + Code: 3, + StatusCode: 400, +} + +var ErrorEmptyFile = StereoError{ + Code: 4, + StatusCode: 400, +} + +var ErrorInvalidFile = StereoError{ + Code: 5, + StatusCode: 400, +} + +var ErrorDatabase = StereoError{ + Code: 6, + StatusCode: 500, +} + +var ErrorS3 = StereoError{ + Code: 7, + StatusCode: 500, +}