package handler import ( "fmt" "net/http" "github.com/gin-gonic/gin" "golang.org/x/crypto/bcrypt" "gitm/internal/database" "gitm/internal/middleware" ) type LoginRequest struct { Password string `json:"password" binding:"required"` } type LoginResponse struct { Token string `json:"token"` } func HandleLogin(c *gin.Context) { var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Password required"}) return } hashedPassword, err := database.GetSetting("admin_password") if err != nil || hashedPassword == "" { c.JSON(http.StatusInternalServerError, gin.H{"error": "Server not initialized"}) return } if err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(req.Password)); err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid password"}) return } token, err := middleware.GenerateToken("admin") if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate token"}) return } c.JSON(http.StatusOK, LoginResponse{Token: token}) } func HandleInit(c *gin.Context) { var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Password required"}) return } hashedPassword, _ := database.GetSetting("admin_password") if hashedPassword != "" { c.JSON(http.StatusBadRequest, gin.H{"error": "Already initialized"}) return } hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to hash password"}) return } database.SetSetting("admin_password", string(hash)) database.SetSetting("listen_addr", ":9000") database.SetSetting("max_concurrent", "3") c.JSON(http.StatusOK, gin.H{"message": "Initialized successfully"}) } func HandleGetSettings(c *gin.Context) { listenAddr, _ := database.GetSetting("listen_addr") if listenAddr == "" { listenAddr = ":9000" } reposDir, _ := database.GetSetting("repos_dir") maxConcurrent, _ := database.GetSetting("max_concurrent") maxCon := 3 if maxConcurrent != "" { fmt.Sscanf(maxConcurrent, "%d", &maxCon) } c.JSON(http.StatusOK, gin.H{ "admin_password": "********", "listen_addr": listenAddr, "repos_dir": reposDir, "max_concurrent": maxCon, }) } func HandleUpdateSettings(c *gin.Context) { var req map[string]interface{} if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if pwd, ok := req["admin_password"].(string); ok && pwd != "" && pwd != "********" { hash, err := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to hash password"}) return } database.SetSetting("admin_password", string(hash)) } if addr, ok := req["listen_addr"].(string); ok && addr != "" { database.SetSetting("listen_addr", addr) } if dir, ok := req["repos_dir"].(string); ok && dir != "" { database.SetSetting("repos_dir", dir) } if max, ok := req["max_concurrent"].(float64); ok { database.SetSetting("max_concurrent", fmt.Sprintf("%d", int(max))) } c.JSON(http.StatusOK, gin.H{"message": "Settings updated"}) }