Files
GitM/internal/handler/auth.go
2026-03-31 16:17:30 +08:00

110 lines
3.2 KiB
Go

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"})
}