上传初始版,功能未经任何测试,仅为基本框架,目前为完全不可用状态
This commit is contained in:
@@ -0,0 +1,274 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"d:\项目\dobaochet\backend\config"
|
||||
"d:\项目\dobaochet\backend\db"
|
||||
"d:\项目\dobaochet\backend\models"
|
||||
"d:\项目\dobaochet\backend\utils"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UserAPI 用户API结构体
|
||||
type UserAPI struct {
|
||||
cfg *config.Config
|
||||
}
|
||||
|
||||
// NewUserAPI 创建用户API实例
|
||||
func NewUserAPI(cfg *config.Config) *UserAPI {
|
||||
return &UserAPI{cfg: cfg}
|
||||
}
|
||||
|
||||
// Register 注册用户
|
||||
func (api *UserAPI) Register(c *gin.Context) {
|
||||
var req models.RegisterRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户名是否已存在
|
||||
var existingUser models.User
|
||||
if result := db.GetDB().Where("username = ?", req.Username).First(&existingUser); result.Error == nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "用户名已存在"})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查邮箱是否已存在
|
||||
if result := db.GetDB().Where("email = ?", req.Email).First(&existingUser); result.Error == nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "邮箱已存在"})
|
||||
return
|
||||
}
|
||||
|
||||
// 密码加密
|
||||
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,
|
||||
IsActive: true,
|
||||
LastLoginAt: time.Now(),
|
||||
Quota: models.Quota{
|
||||
TotalTokens: api.cfg.Quota.DefaultTotalTokens,
|
||||
UsedTokens: 0,
|
||||
ResetAt: time.Now().Add(api.cfg.Quota.ResetInterval),
|
||||
TokenLimit: api.cfg.Quota.DefaultTokenLimit,
|
||||
},
|
||||
}
|
||||
|
||||
if result := db.GetDB().Create(&user); result.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建用户失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 返回用户信息(隐藏敏感信息)
|
||||
c.JSON(http.StatusCreated, gin.H{
|
||||
"id": user.ID,
|
||||
"username": user.Username,
|
||||
"email": user.Email,
|
||||
"is_admin": user.IsAdmin,
|
||||
"is_active": user.IsActive,
|
||||
"created_at": user.CreatedAt,
|
||||
})
|
||||
}
|
||||
|
||||
// Login 用户登录
|
||||
func (api *UserAPI) Login(c *gin.Context) {
|
||||
var req models.LoginRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 查找用户
|
||||
var user models.User
|
||||
if result := db.GetDB().Preload("Quota").Where("username = ?", req.Username).First(&user); result.Error != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证密码
|
||||
if err := utils.VerifyPassword(user.Password, req.Password); err != nil {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户名或密码错误"})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查用户是否激活
|
||||
if !user.IsActive {
|
||||
c.JSON(http.StatusForbidden, gin.H{"error": "用户已被禁用"})
|
||||
return
|
||||
}
|
||||
|
||||
// 更新登录时间
|
||||
user.LastLoginAt = time.Now()
|
||||
db.GetDB().Save(&user)
|
||||
|
||||
// 生成JWT令牌
|
||||
token, err := utils.GenerateToken(
|
||||
user.ID,
|
||||
user.Username,
|
||||
user.IsAdmin,
|
||||
api.cfg.JWT.SecretKey,
|
||||
api.cfg.JWT.AccessTokenExpire,
|
||||
)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "生成令牌失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 返回登录结果
|
||||
c.JSON(http.StatusOK, models.LoginResponse{
|
||||
Token: token,
|
||||
User: models.UserResponse{
|
||||
ID: user.ID,
|
||||
Username: user.Username,
|
||||
Email: user.Email,
|
||||
IsAdmin: user.IsAdmin,
|
||||
IsActive: user.IsActive,
|
||||
CreatedAt: user.CreatedAt,
|
||||
Quota: user.Quota,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GetUserInfo 获取当前用户信息
|
||||
func (api *UserAPI) GetUserInfo(c *gin.Context) {
|
||||
// 从上下文获取用户信息
|
||||
user, exists := c.Get("user")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
|
||||
return
|
||||
}
|
||||
|
||||
currentUser := user.(models.User)
|
||||
c.JSON(http.StatusOK, models.UserResponse{
|
||||
ID: currentUser.ID,
|
||||
Username: currentUser.Username,
|
||||
Email: currentUser.Email,
|
||||
IsAdmin: currentUser.IsAdmin,
|
||||
IsActive: currentUser.IsActive,
|
||||
CreatedAt: currentUser.CreatedAt,
|
||||
Quota: currentUser.Quota,
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUserInfo 更新用户信息
|
||||
func (api *UserAPI) UpdateUserInfo(c *gin.Context) {
|
||||
// 从上下文获取用户信息
|
||||
user, exists := c.Get("user")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
|
||||
return
|
||||
}
|
||||
|
||||
currentUser := user.(models.User)
|
||||
|
||||
// 解析请求
|
||||
var req struct {
|
||||
Email string `json:"email" binding:"omitempty,email"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 更新用户信息
|
||||
if req.Email != "" && req.Email != currentUser.Email {
|
||||
// 检查邮箱是否已被使用
|
||||
var existingUser models.User
|
||||
if result := db.GetDB().Where("email = ? AND id != ?", req.Email, currentUser.ID).First(&existingUser); result.Error == nil {
|
||||
c.JSON(http.StatusConflict, gin.H{"error": "邮箱已被使用"})
|
||||
return
|
||||
}
|
||||
currentUser.Email = req.Email
|
||||
}
|
||||
|
||||
if result := db.GetDB().Save(¤tUser); result.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "更新用户信息失败"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, models.UserResponse{
|
||||
ID: currentUser.ID,
|
||||
Username: currentUser.Username,
|
||||
Email: currentUser.Email,
|
||||
IsAdmin: currentUser.IsAdmin,
|
||||
IsActive: currentUser.IsActive,
|
||||
CreatedAt: currentUser.CreatedAt,
|
||||
Quota: currentUser.Quota,
|
||||
})
|
||||
}
|
||||
|
||||
// ChangePassword 修改密码
|
||||
func (api *UserAPI) ChangePassword(c *gin.Context) {
|
||||
// 从上下文获取用户信息
|
||||
user, exists := c.Get("user")
|
||||
if !exists {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
|
||||
return
|
||||
}
|
||||
|
||||
currentUser := user.(models.User)
|
||||
|
||||
// 解析请求
|
||||
var req struct {
|
||||
OldPassword string `json:"old_password" binding:"required"`
|
||||
NewPassword string `json:"new_password" binding:"required,min=6"`
|
||||
}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// 验证旧密码
|
||||
if err := utils.VerifyPassword(currentUser.Password, req.OldPassword); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "旧密码错误"})
|
||||
return
|
||||
}
|
||||
|
||||
// 加密新密码
|
||||
newHashedPassword, err := utils.HashPassword(req.NewPassword)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "密码加密失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 更新密码
|
||||
currentUser.Password = newHashedPassword
|
||||
if result := db.GetDB().Save(¤tUser); result.Error != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "修改密码失败"})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "密码修改成功"})
|
||||
}
|
||||
|
||||
// RegisterRoutes 注册用户路由
|
||||
func (api *UserAPI) RegisterRoutes(router *gin.RouterGroup) {
|
||||
userGroup := router.Group("/users")
|
||||
{
|
||||
// 公开路由
|
||||
userGroup.POST("/register", api.Register)
|
||||
userGroup.POST("/login", api.Login)
|
||||
|
||||
// 需要认证的路由
|
||||
authGroup := userGroup.Group("/")
|
||||
authGroup.Use(AuthMiddleware(api.cfg))
|
||||
{
|
||||
authGroup.GET("/me", api.GetUserInfo)
|
||||
authGroup.PUT("/me", api.UpdateUserInfo)
|
||||
authGroup.PUT("/me/password", api.ChangePassword)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user