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