package handlers import ( "net/http" "github.com/gin-gonic/gin" "golang.org/x/crypto/bcrypt" "airwallex-admin/config" "airwallex-admin/middleware" "airwallex-admin/models" ) type loginRequest struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } func Login(c *gin.Context) { var req loginRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Invalid request body"}) return } if req.Username != config.Cfg.AdminUsername { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Invalid username or password"}) return } passwordHash := models.GetSetting(models.DB, "admin_password_hash") if passwordHash == "" { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Invalid username or password"}) return } if err := bcrypt.CompareHashAndPassword([]byte(passwordHash), []byte(req.Password)); err != nil { c.JSON(http.StatusUnauthorized, gin.H{"detail": "Invalid username or password"}) return } token, err := middleware.GenerateToken(req.Username) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"detail": "Failed to generate token"}) return } // Create audit log models.DB.Create(&models.AuditLog{ Action: "login", ResourceType: "auth", Operator: req.Username, IPAddress: c.ClientIP(), }) c.JSON(http.StatusOK, gin.H{ "access_token": token, "token_type": "bearer", }) } func GetMe(c *gin.Context) { username, _ := c.Get("username") c.JSON(http.StatusOK, gin.H{ "username": username, }) }