Files
ci/internal/handler/project.go
2026-06-18 21:19:47 +08:00

130 lines
3.1 KiB
Go

package handler
import (
"net/http"
"strconv"
"ci/internal/model"
"ci/internal/service"
"github.com/gin-gonic/gin"
)
// ProjectHandler handles project CRUD endpoints.
type ProjectHandler struct {
Svc *service.ProjectService
}
func NewProjectHandler(svc *service.ProjectService) *ProjectHandler {
return &ProjectHandler{Svc: svc}
}
// ListProjects returns all projects.
func (h *ProjectHandler) ListProjects(c *gin.Context) {
projects, err := h.Svc.ListProjects()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
if projects == nil {
projects = []model.Project{}
}
c.JSON(http.StatusOK, projects)
}
// GetProject returns a single project by ID.
func (h *ProjectHandler) GetProject(c *gin.Context) {
id, err := parseID(c)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project id"})
return
}
project, err := h.Svc.GetProject(id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "project not found"})
return
}
c.JSON(http.StatusOK, project)
}
// CreateProject creates a new project.
func (h *ProjectHandler) CreateProject(c *gin.Context) {
var p model.Project
if err := c.ShouldBindJSON(&p); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if p.Name == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "name is required"})
return
}
if p.Mode != "git" && p.Mode != "upload" {
p.Mode = "git" // default
}
if err := h.Svc.CreateProject(&p); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, p)
}
// UpdateProject updates an existing project.
func (h *ProjectHandler) UpdateProject(c *gin.Context) {
id, err := parseID(c)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project id"})
return
}
existing, err := h.Svc.GetProject(id)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": "project not found"})
return
}
var updates model.Project
if err := c.ShouldBindJSON(&updates); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// Preserve fields that should not be updated from the request
updates.ID = existing.ID
updates.CreatedAt = existing.CreatedAt
updates.Status = existing.Status
updates.PID = existing.PID
// Preserve password if not sent
if updates.GitPassword == "" {
updates.GitPassword = existing.GitPassword
}
if err := h.Svc.UpdateProject(&updates); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, updates)
}
// DeleteProject deletes a project.
func (h *ProjectHandler) DeleteProject(c *gin.Context) {
id, err := parseID(c)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid project id"})
return
}
if err := h.Svc.DeleteProject(id); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "deleted"})
}
func parseID(c *gin.Context) (uint, error) {
idStr := c.Param("id")
id, err := strconv.ParseUint(idStr, 10, 64)
if err != nil {
return 0, err
}
return uint(id), nil
}