feat: implement server management handlers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
238
internal/handler/server.go
Normal file
238
internal/handler/server.go
Normal file
@@ -0,0 +1,238 @@
|
||||
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})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user