Files
GitM/internal/handler/server.go
2026-03-31 16:24:20 +08:00

239 lines
6.3 KiB
Go

package handler
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"gitm/internal/database"
"gitm/internal/gitea"
"gitm/internal/models"
"gitm/internal/sync"
)
func HandleListServers(c *gin.Context) {
servers, err := database.GetServers()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, servers)
}
func HandleCreateServer(c *gin.Context) {
var req struct {
Name string `json:"name" binding:"required"`
URL string `json:"url" binding:"required"`
Token string `json:"token" binding:"required"`
SyncInterval int `json:"sync_interval"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
server := &models.GiteaServer{
Name: req.Name,
URL: req.URL,
Token: req.Token,
SyncInterval: req.SyncInterval,
Status: "active",
}
if err := database.CreateServer(server); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusCreated, server)
}
func HandleUpdateServer(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"})
return
}
server, err := database.GetServer(id)
if err != nil || server == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Server not found"})
return
}
var req struct {
Name *string `json:"name"`
URL *string `json:"url"`
Token *string `json:"token"`
SyncInterval *int `json:"sync_interval"`
Status *string `json:"status"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
if req.Name != nil {
server.Name = *req.Name
}
if req.URL != nil {
server.URL = *req.URL
}
if req.Token != nil {
server.Token = *req.Token
}
if req.SyncInterval != nil {
server.SyncInterval = *req.SyncInterval
}
if req.Status != nil {
server.Status = *req.Status
}
if err := database.UpdateServer(server); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, server)
}
func HandleDeleteServer(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"})
return
}
if err := database.DeleteServer(id); err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Server deleted"})
}
func HandleTestConnection(c *gin.Context) {
var req struct {
URL string `json:"url" binding:"required"`
Token string `json:"token" binding:"required"`
}
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
client, err := gitea.NewClient(req.URL, req.Token)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
user, err := client.ValidateToken()
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication failed"})
return
}
c.JSON(http.StatusOK, gin.H{"message": "Connection successful", "user": user.Login})
}
func HandleListRepos(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"})
return
}
repos, err := database.GetReposByServer(id)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, repos)
}
func HandleDiscoverRepos(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"})
return
}
server, err := database.GetServer(id)
if err != nil || server == nil {
c.JSON(http.StatusNotFound, gin.H{"error": "Server not found"})
return
}
client, err := gitea.NewClient(server.URL, server.Token)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
giteaRepos, err := client.GetAllRepos()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
reposDir, _ := database.GetSetting("repos_dir")
if reposDir == "" {
reposDir = "./data/repos"
}
serverDir := reposDir + "/" + strconv.FormatInt(id, 10) + "_" + server.Name
discovered := 0
for _, gr := range giteaRepos {
existing, _ := database.GetRepoByFullName(id, gr.FullName)
if existing == nil {
repo := &models.Repo{
ServerID: id,
Name: gr.Name,
FullName: gr.FullName,
CloneURL: gr.CloneURL,
LocalPath: serverDir + "/" + gr.FullName + ".git",
SyncStatus: "pending",
}
database.CreateRepo(repo)
discovered++
}
}
c.JSON(http.StatusOK, gin.H{
"message": fmt.Sprintf("Discovered %d new repositories", discovered),
"total_repos": len(giteaRepos),
"new_repos": discovered,
})
}
func HandleSyncServer(engine *sync.Engine) gin.HandlerFunc {
return func(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"})
return
}
if engine.IsSyncing(id) {
c.JSON(http.StatusConflict, gin.H{"error": "Sync already in progress"})
return
}
go engine.SyncServer(id)
c.JSON(http.StatusAccepted, gin.H{"message": "Sync started", "server_id": id})
}
}
func HandleSyncAll(engine *sync.Engine) gin.HandlerFunc {
return func(c *gin.Context) {
servers, err := database.GetServers()
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
started := 0
for _, server := range servers {
if server.Status == "active" && !engine.IsSyncing(server.ID) {
go engine.SyncServer(server.ID)
started++
}
}
c.JSON(http.StatusAccepted, gin.H{"message": fmt.Sprintf("Started sync for %d servers", started)})
}
}
func HandleGetSyncStatus(engine *sync.Engine) gin.HandlerFunc {
return func(c *gin.Context) {
id, err := strconv.ParseInt(c.Param("id"), 10, 64)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"})
return
}
status := "idle"
if engine.IsSyncing(id) {
status = "syncing"
}
c.JSON(http.StatusOK, gin.H{"server_id": id, "status": status})
}
}