Files
pipely/internal/artefact/handler.go
T

138 lines
3.0 KiB
Go
Raw Normal View History

2026-07-07 10:29:28 +08:00
package artefact
import (
"crypto/sha256"
"errors"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strconv"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"onixbyte.com/pipely/internal/database"
"onixbyte.com/pipely/internal/model"
2026-07-07 10:29:28 +08:00
)
type Handler struct {
db *gorm.DB
artefactDir string
}
func NewHandler(db *gorm.DB, artefactDir string) *Handler {
return &Handler{db: db, artefactDir: artefactDir}
}
func (h *Handler) Upload(c *gin.Context) {
version := c.PostForm("version")
if version == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "version is required"})
return
}
deltaRef := c.PostForm("deltaRef")
metadata := c.PostForm("metadata")
if metadata == "" {
metadata = "{}"
}
file, header, err := c.Request.FormFile("file")
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "file is required: " + err.Error()})
return
}
defer file.Close()
destDir := filepath.Join(h.artefactDir, version)
if err := os.MkdirAll(destDir, 0755); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create directory"})
return
}
destPath := filepath.Join(destDir, header.Filename)
out, err := os.Create(destPath)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to create file"})
return
}
defer out.Close()
hasher := sha256.New()
writer := io.MultiWriter(out, hasher)
size, err := io.Copy(writer, file)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to write file"})
return
}
sha256Hash := fmt.Sprintf("%x", hasher.Sum(nil))
artefact := &model.Artefact{
Version: version,
FileName: header.Filename,
FilePath: destPath,
FileSize: size,
SHA256Hash: sha256Hash,
DeltaRef: deltaRef,
IsDelta: deltaRef != "",
Metadata: metadata,
}
if err := database.CreateArtefact(h.db, artefact); err != nil {
os.Remove(destPath)
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save artefact: " + err.Error()})
return
}
c.JSON(http.StatusCreated, artefact)
}
func (h *Handler) List(c *gin.Context) {
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20"))
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 20
}
artefacts, total, err := database.ListArtefacts(h.db, page, pageSize)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, model.PaginatedResponse{
Data: artefacts,
Total: total,
Page: page,
PageSize: pageSize,
})
}
func (h *Handler) Get(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"})
return
}
artefact, err := database.GetArtefactByID(h.db, id)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "Artefact not found"})
return
}
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, artefact)
}