package handlers import ( "fmt" "net/http" "software-download-center/database" "software-download-center/models" "software-download-center/utils" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // RegisterRequest 注册请求 type RegisterRequest struct { Username string `json:"username" binding:"required,min=3,max=50"` Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required,min=8"` } // LoginRequest 登录请求 type LoginRequest struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } // Register 用户注册 func Register(c *gin.Context) { var req RegisterRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "请求参数错误: " + err.Error(), }) return } // 验证密码强度 if err := utils.ValidatePasswordStrength(req.Password); err != nil { AddLog("WARN", fmt.Sprintf("注册失败(密码强度不足): 用户名=%s, IP=%s", req.Username, c.ClientIP())) c.JSON(http.StatusBadRequest, gin.H{ "error": err.Error(), }) return } // 检查用户名是否已存在 var existingUser models.User if err := database.DB.Where("username = ?", req.Username).First(&existingUser).Error; err == nil { AddLog("WARN", fmt.Sprintf("注册失败(用户名已存在): 用户名=%s, IP=%s", req.Username, c.ClientIP())) c.JSON(http.StatusConflict, gin.H{ "error": "用户名已存在", }) return } // 检查邮箱是否已存在 if err := database.DB.Where("email = ?", req.Email).First(&existingUser).Error; err == nil { AddLog("WARN", fmt.Sprintf("注册失败(邮箱已被注册): 邮箱=%s, IP=%s", req.Email, c.ClientIP())) c.JSON(http.StatusConflict, gin.H{ "error": "邮箱已被注册", }) return } // 检查是否是第一个用户(自动成为管理员) var userCount int64 database.DB.Model(&models.User{}).Count(&userCount) isAdmin := userCount == 0 // 加密密码 hashedPassword, err := utils.HashPassword(req.Password) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "密码加密失败", }) return } // 创建用户 user := models.User{ Username: req.Username, Email: req.Email, Password: hashedPassword, IsAdmin: isAdmin, IsActive: true, } if err := database.DB.Create(&user).Error; err != nil { AddLog("ERROR", fmt.Sprintf("创建用户数据库错误: 用户名=%s - %s, IP=%s", req.Username, err.Error(), c.ClientIP())) c.JSON(http.StatusInternalServerError, gin.H{ "error": "创建用户失败", }) return } AddLog("INFO", fmt.Sprintf("用户注册成功: 用户名=%s, 邮箱=%s, 管理员=%v, IP=%s", user.Username, user.Email, user.IsAdmin, c.ClientIP())) // 生成 token token, err := utils.GenerateToken(user.ID, user.Username, user.IsAdmin) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "生成 token 失败", }) return } // 设置 cookie c.SetCookie("token", token, 24*3600, "/", "", false, true) c.JSON(http.StatusOK, gin.H{ "message": "注册成功", "token": token, "user": gin.H{ "id": user.ID, "username": user.Username, "email": user.Email, "is_admin": user.IsAdmin, }, }) } // Login 用户登录 func Login(c *gin.Context) { var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{ "error": "请求参数错误", }) return } // 检查数据库是否已初始化 if !database.IsDBInitialized() { // 使用默认管理员账号 if req.Username == "admin" && req.Password == "admin123456" { // 生成临时 token(用于安装页面) token, err := utils.GenerateToken(0, "admin", true) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "生成 token 失败", }) return } AddLog("INFO", fmt.Sprintf("默认管理员登录成功: 用户名=%s, IP=%s", req.Username, c.ClientIP())) c.SetCookie("token", token, 24*3600, "/", "", false, true) c.JSON(http.StatusOK, gin.H{ "message": "登录成功,请配置数据库", "token": token, "user": gin.H{ "id": 0, "username": "admin", "is_admin": true, "is_setup": false, // 标记需要安装 }, }) return } c.JSON(http.StatusUnauthorized, gin.H{ "error": "数据库未初始化,请使用默认管理员账号登录(admin/admin123456)", }) return } // 查找用户 var user models.User if err := database.DB.Where("username = ?", req.Username).First(&user).Error; err != nil { if err == gorm.ErrRecordNotFound { AddLog("WARN", fmt.Sprintf("登录失败(用户不存在): 用户名=%s, IP=%s", req.Username, c.ClientIP())) c.JSON(http.StatusUnauthorized, gin.H{ "error": "用户名或密码错误", }) return } AddLog("ERROR", fmt.Sprintf("查询用户失败: 用户名=%s - %s, IP=%s", req.Username, err.Error(), c.ClientIP())) c.JSON(http.StatusInternalServerError, gin.H{ "error": "查询用户失败", }) return } // 检查用户是否激活 if !user.IsActive { AddLog("WARN", fmt.Sprintf("登录失败(账户已禁用): 用户名=%s, IP=%s", req.Username, c.ClientIP())) c.JSON(http.StatusForbidden, gin.H{ "error": "账户已被禁用", }) return } // 验证密码 if !utils.CheckPassword(req.Password, user.Password) { AddLog("WARN", fmt.Sprintf("登录失败(密码错误): 用户名=%s, IP=%s", req.Username, c.ClientIP())) c.JSON(http.StatusUnauthorized, gin.H{ "error": "用户名或密码错误", }) return } AddLog("INFO", fmt.Sprintf("用户登录成功: 用户名=%s, 管理员=%v, IP=%s", user.Username, user.IsAdmin, c.ClientIP())) // 生成 token token, err := utils.GenerateToken(user.ID, user.Username, user.IsAdmin) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "error": "生成 token 失败", }) return } // 设置 cookie c.SetCookie("token", token, 24*3600, "/", "", false, true) c.JSON(http.StatusOK, gin.H{ "message": "登录成功", "token": token, "user": gin.H{ "id": user.ID, "username": user.Username, "email": user.Email, "is_admin": user.IsAdmin, }, }) } // Logout 用户登出 func Logout(c *gin.Context) { c.SetCookie("token", "", -1, "/", "", false, true) c.JSON(http.StatusOK, gin.H{ "message": "登出成功", }) } // GetCurrentUser 获取当前用户信息 func GetCurrentUser(c *gin.Context) { userID, exists := c.Get("user_id") if !exists { c.JSON(http.StatusUnauthorized, gin.H{ "error": "未授权", }) return } var user models.User if err := database.DB.First(&user, userID).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{ "error": "用户不存在", }) return } c.JSON(http.StatusOK, gin.H{ "user": gin.H{ "id": user.ID, "username": user.Username, "email": user.Email, "is_admin": user.IsAdmin, "is_active": user.IsActive, }, }) }