Add composers

This commit is contained in:
2026-01-23 21:55:21 +01:00
parent 4540c0d880
commit 5141bfe673
7 changed files with 127 additions and 10 deletions

View File

@@ -18,7 +18,7 @@ func InitDatabase() {
} }
// Auto migrate the schema // Auto migrate the schema
err = DB.AutoMigrate(&models.User{}, &models.Sheet{}) err = DB.AutoMigrate(&models.User{}, &models.Sheet{}, &models.Composer{})
if err != nil { if err != nil {
log.Fatal("Failed to migrate database:", err) log.Fatal("Failed to migrate database:", err)
} }

View File

@@ -5,6 +5,7 @@ go 1.21
require ( require (
github.com/gin-gonic/gin v1.9.1 github.com/gin-gonic/gin v1.9.1
github.com/golang-jwt/jwt/v5 v5.0.0 github.com/golang-jwt/jwt/v5 v5.0.0
github.com/google/uuid v1.6.0
golang.org/x/crypto v0.9.0 golang.org/x/crypto v0.9.0
gorm.io/driver/sqlite v1.5.4 gorm.io/driver/sqlite v1.5.4
gorm.io/gorm v1.25.5 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/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/goccy/go-json v0.10.2 // 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/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect

96
src/handlers/composers.go Normal file
View File

@@ -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.")
}

View File

@@ -142,26 +142,23 @@ func ListSheets(c *gin.Context) {
} }
func DownloadSheet(c *gin.Context) { func DownloadSheet(c *gin.Context) {
idStr := c.Param("id") uuid, err := uuid.Parse(c.Param("uuid"))
id, err := strconv.ParseUint(idStr, 10, 32)
if err != nil { if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid sheet ID"}) c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid sheet uuid"})
return return
} }
var sheet models.Sheet 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"}) c.JSON(http.StatusNotFound, gin.H{"error": "Sheet not found"})
return return
} }
// Check if file exists
if _, err := os.Stat(sheet.FilePath); os.IsNotExist(err) { if _, err := os.Stat(sheet.FilePath); os.IsNotExist(err) {
c.JSON(http.StatusNotFound, gin.H{"error": "File not found"}) c.JSON(http.StatusNotFound, gin.H{"error": "File not found"})
return return
} }
// Set headers for file download
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filepath.Base(sheet.FilePath))) c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", filepath.Base(sheet.FilePath)))
c.Header("Content-Type", "application/pdf") c.Header("Content-Type", "application/pdf")
c.File(sheet.FilePath) c.File(sheet.FilePath)

17
src/models/composer.go Normal file
View File

@@ -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"`
}

View File

@@ -8,7 +8,7 @@ import (
) )
type Sheet struct { 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"` Title string `json:"title" gorm:"not null"`
Composer string `json:"composer"` Composer string `json:"composer"`
Description string `json:"description"` Description string `json:"description"`

View File

@@ -23,7 +23,14 @@ func SetupRoutes(r *gin.Engine) {
{ {
sheets.POST("/upload", handlers.UploadSheet) sheets.POST("/upload", handlers.UploadSheet)
sheets.GET("/list", handlers.ListSheets) 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)
} }
} }
} }