package handler import ( "net/http" "time" "lmvpn/internal/db" "lmvpn/internal/middleware" "lmvpn/internal/model" "github.com/gin-gonic/gin" "github.com/google/uuid" "golang.org/x/crypto/bcrypt" ) type loginRequest struct { Username string `json:"username" binding:"required"` Password string `json:"password" binding:"required"` } type loginResponse struct { Token string `json:"token"` User userInfo `json:"user"` } type userInfo struct { ID uint `json:"id"` Username string `json:"username"` Role string `json:"role"` } func Login(c *gin.Context) { var req loginRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "请输入用户名和密码"}) return } var user model.User if err := db.DB.Where("username = ?", req.Username).First(&user).Error; err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"}) return } if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.Password)); err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"}) return } if user.Status != 1 { c.JSON(http.StatusForbidden, gin.H{"error": "账号已被禁用"}) return } sessionID := uuid.New().String() token, err := middleware.GenerateToken(sessionID, user.ID, user.Username, user.Role) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "生成令牌失败"}) return } session := model.Session{ SessionID: sessionID, UserID: user.ID, IP: c.ClientIP(), UserAgent: c.GetHeader("User-Agent"), ExpiresAt: time.Now().Add(24 * time.Hour), } if err := db.DB.Create(&session).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "创建会话失败"}) return } c.JSON(http.StatusOK, loginResponse{ Token: token, User: userInfo{ ID: user.ID, Username: user.Username, Role: user.Role, }, }) } type changePasswordRequest struct { OldPassword string `json:"old_password" binding:"required"` NewPassword string `json:"new_password" binding:"required"` } func ChangePassword(c *gin.Context) { var req changePasswordRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "请输入原密码和新密码"}) return } if len(req.NewPassword) < 6 { c.JSON(http.StatusBadRequest, gin.H{"error": "新密码长度不能少于6位"}) return } userID, _ := c.Get("user_id") var user model.User if err := db.DB.First(&user, userID).Error; err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"}) return } if err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(req.OldPassword)); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "原密码错误"}) return } hash, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "密码加密失败"}) return } now := time.Now() if err := db.DB.Model(&user).Updates(map[string]interface{}{ "password": string(hash), "token_invalid_before": now, }).Error; err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "密码修改失败"}) return } sessionID, _ := c.Get("session_id") db.DB.Model(&model.Session{}).Where("user_id = ? AND session_id != ?", userID, sessionID).Update("invalid", true) c.JSON(http.StatusOK, gin.H{"message": "密码修改成功"}) } func Me(c *gin.Context) { userID, _ := c.Get("user_id") username, _ := c.Get("username") role, _ := c.Get("role") c.JSON(http.StatusOK, userInfo{ ID: userID.(uint), Username: username.(string), Role: role.(string), }) }