264 lines
6.9 KiB
Go
264 lines
6.9 KiB
Go
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,
|
||
},
|
||
})
|
||
}
|