From 5141bfe673574e7be98424d5f3aaff5cd372ab70 Mon Sep 17 00:00:00 2001 From: Julian Mutter Date: Fri, 23 Jan 2026 21:55:21 +0100 Subject: [PATCH] Add composers --- src/database/connection.go | 2 +- src/go.mod | 2 +- src/handlers/composers.go | 96 ++++++++++++++++++++++++++++++++++++++ src/handlers/sheets.go | 9 ++-- src/models/composer.go | 17 +++++++ src/models/sheet.go | 2 +- src/routes/routes.go | 9 +++- 7 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 src/handlers/composers.go create mode 100644 src/models/composer.go diff --git a/src/database/connection.go b/src/database/connection.go index 961c0e4..6d773b8 100644 --- a/src/database/connection.go +++ b/src/database/connection.go @@ -18,7 +18,7 @@ func InitDatabase() { } // Auto migrate the schema - err = DB.AutoMigrate(&models.User{}, &models.Sheet{}) + err = DB.AutoMigrate(&models.User{}, &models.Sheet{}, &models.Composer{}) if err != nil { log.Fatal("Failed to migrate database:", err) } diff --git a/src/go.mod b/src/go.mod index 02eca8f..5e5ffef 100644 --- a/src/go.mod +++ b/src/go.mod @@ -5,6 +5,7 @@ go 1.21 require ( github.com/gin-gonic/gin v1.9.1 github.com/golang-jwt/jwt/v5 v5.0.0 + github.com/google/uuid v1.6.0 golang.org/x/crypto v0.9.0 gorm.io/driver/sqlite v1.5.4 gorm.io/gorm v1.25.5 @@ -19,7 +20,6 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/goccy/go-json v0.10.2 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect diff --git a/src/handlers/composers.go b/src/handlers/composers.go new file mode 100644 index 0000000..78877bd --- /dev/null +++ b/src/handlers/composers.go @@ -0,0 +1,96 @@ +package handlers + +import ( + "errors" + "net/http" + "sheetless-server/database" + "sheetless-server/models" + "time" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" +) + +func AddComposer(c *gin.Context) { + var req struct { + Name string `json:"name" binding:"required"` + Bio string `json:"bio"` + } + + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + uuid, err := GenerateNonexistentComposerUuid() + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Could not generate composer uuid"}) + return + } + + composer := models.Composer{ + Uuid: *uuid, + Name: req.Name, + Bio: req.Bio, + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + + if err := database.DB.Create(&composer).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create composer"}) + return + } + + c.JSON(http.StatusCreated, gin.H{ + "message": "Composer created successfully", + "composer": composer, + }) +} + +func ListComposers(c *gin.Context) { + var composers []models.Composer + + if err := database.DB.Find(&composers).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch composers"}) + return + } + + c.JSON(http.StatusOK, gin.H{"composers": composers}) +} + +func GetComposer(c *gin.Context) { + uuid, err := uuid.Parse(c.Param("uuid")) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid composer ID"}) + return + } + + var composer models.Composer + if err := database.DB.First(&composer, uuid).Error; err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "Composer not found"}) + return + } + c.JSON(http.StatusOK, composer) +} + +func GenerateNonexistentComposerUuid() (*uuid.UUID, error) { + for i := 0; i < 10; i++ { + uuid := uuid.New() + + var exists bool + err := database.DB.Model(&models.Composer{}). + Select("count(*) > 0"). + Where("uuid = ?", uuid). + Find(&exists). + Error + + if err != nil { + return nil, err + } + + if !exists { + return &uuid, nil + } + } + return nil, errors.New("Somehow unable to generate new uuid for sheet.") +} diff --git a/src/handlers/sheets.go b/src/handlers/sheets.go index 75a5b19..943cd5b 100644 --- a/src/handlers/sheets.go +++ b/src/handlers/sheets.go @@ -142,26 +142,23 @@ func ListSheets(c *gin.Context) { } func DownloadSheet(c *gin.Context) { - idStr := c.Param("id") - id, err := strconv.ParseUint(idStr, 10, 32) + uuid, err := uuid.Parse(c.Param("uuid")) if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid sheet ID"}) + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid sheet uuid"}) return } var sheet models.Sheet - if err := database.DB.First(&sheet, uint(id)).Error; err != nil { + if err := database.DB.First(&sheet, uuid).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Sheet not found"}) return } - // Check if file exists if _, err := os.Stat(sheet.FilePath); os.IsNotExist(err) { c.JSON(http.StatusNotFound, gin.H{"error": "File not found"}) return } - // Set headers for file download c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filepath.Base(sheet.FilePath))) c.Header("Content-Type", "application/pdf") c.File(sheet.FilePath) diff --git a/src/models/composer.go b/src/models/composer.go new file mode 100644 index 0000000..9d5978c --- /dev/null +++ b/src/models/composer.go @@ -0,0 +1,17 @@ +package models + +import ( + "time" + + "github.com/google/uuid" + "gorm.io/gorm" +) + +type Composer struct { + Uuid uuid.UUID `json:"uuid" gorm:"type:uuid;primaryKey"` + Name string `json:"name" gorm:"not null"` + Bio string `json:"bio"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` +} diff --git a/src/models/sheet.go b/src/models/sheet.go index 3aee692..55d907f 100644 --- a/src/models/sheet.go +++ b/src/models/sheet.go @@ -8,7 +8,7 @@ import ( ) type Sheet struct { - Uuid uuid.UUID `json:"uuid" gorm:"primaryKey"` + Uuid uuid.UUID `json:"uuid" gorm:"type:uuid;primaryKey"` Title string `json:"title" gorm:"not null"` Composer string `json:"composer"` Description string `json:"description"` diff --git a/src/routes/routes.go b/src/routes/routes.go index a448b1d..06a6c15 100644 --- a/src/routes/routes.go +++ b/src/routes/routes.go @@ -23,7 +23,14 @@ func SetupRoutes(r *gin.Engine) { { sheets.POST("/upload", handlers.UploadSheet) sheets.GET("/list", handlers.ListSheets) - sheets.GET("/get/:id", handlers.DownloadSheet) + sheets.GET("/get/:uuid", handlers.DownloadSheet) + } + + composers := api.Group("/composers") + { + composers.POST("/add", handlers.AddComposer) + composers.GET("/list", handlers.ListComposers) + composers.GET("/get/:uuid", handlers.GetComposer) } } }