2024-11-14 14:55:43 +00:00
|
|
|
package api
|
|
|
|
|
|
|
|
import (
|
|
|
|
"licserver/internal/service"
|
|
|
|
|
|
|
|
"net/http"
|
|
|
|
"strconv"
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
)
|
|
|
|
|
|
|
|
type UserHandler struct {
|
|
|
|
userService *service.UserService
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewUserHandler(userService *service.UserService) *UserHandler {
|
|
|
|
|
|
|
|
return &UserHandler{userService: userService}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *UserHandler) Login(c *gin.Context) {
|
|
|
|
|
2024-11-16 15:59:15 +00:00
|
|
|
var input service.LoginInput
|
2024-11-14 14:55:43 +00:00
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 验证验证码
|
2024-11-16 15:59:15 +00:00
|
|
|
if !h.userService.VerifyCaptcha(input.CaptchaId, input.Captcha) {
|
2024-11-14 14:55:43 +00:00
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "验证码错误"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-11-16 15:59:15 +00:00
|
|
|
// 验证用户名密码
|
|
|
|
user, err := h.userService.ValidateUser(input.Username, input.Password)
|
2024-11-14 14:55:43 +00:00
|
|
|
if err != nil {
|
2024-11-16 15:59:15 +00:00
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
2024-11-14 14:55:43 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-11-16 15:59:15 +00:00
|
|
|
// 生成 JWT token
|
|
|
|
token, err := h.userService.GenerateToken(user)
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "生成token失败"})
|
|
|
|
return
|
|
|
|
}
|
2024-11-14 14:55:43 +00:00
|
|
|
|
2024-11-16 15:59:15 +00:00
|
|
|
// 返回token和用户信息
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
"code": 0,
|
|
|
|
"data": gin.H{
|
|
|
|
"token": token,
|
|
|
|
"user": gin.H{
|
|
|
|
"id": user.ID,
|
|
|
|
"username": user.Username,
|
|
|
|
"email": user.Email,
|
|
|
|
"role": user.Role,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
2024-11-14 14:55:43 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *UserHandler) Register(c *gin.Context) {
|
|
|
|
|
|
|
|
var input struct {
|
|
|
|
Username string `json:"username" binding:"required"`
|
|
|
|
|
|
|
|
Password string `json:"password" binding:"required,min=6"`
|
|
|
|
|
|
|
|
Email string `json:"email" binding:"required,email"`
|
|
|
|
|
|
|
|
Captcha string `json:"captcha" binding:"required,len=6"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.userService.Register(input.Username, input.Password, input.Email, input.Captcha); err != nil {
|
|
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "注册成功"})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *UserHandler) ResetPasswordWithToken(c *gin.Context) {
|
|
|
|
|
|
|
|
var input struct {
|
|
|
|
Token string `json:"token" binding:"required"`
|
|
|
|
|
|
|
|
NewPassword string `json:"new_password" binding:"required,min=6"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.userService.ResetPasswordWithToken(input.Token, input.NewPassword); err != nil {
|
|
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "密码重置成功"})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *UserHandler) ResetPassword(c *gin.Context) {
|
|
|
|
|
|
|
|
var input struct {
|
|
|
|
Email string `json:"email" binding:"required,email"`
|
|
|
|
|
|
|
|
Captcha string `json:"captcha" binding:"required,len=6"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.userService.ResetPassword(input.Email, input.Captcha); err != nil {
|
|
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-11-16 15:59:15 +00:00
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "重置密邮件已发送"})
|
2024-11-14 14:55:43 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *UserHandler) SendRegisterCaptcha(c *gin.Context) {
|
|
|
|
|
|
|
|
var input struct {
|
|
|
|
Email string `json:"email" binding:"required,email"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.userService.SendRegisterCaptcha(input.Email); err != nil {
|
|
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "验证码已发送"})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *UserHandler) SendResetPasswordCaptcha(c *gin.Context) {
|
|
|
|
|
|
|
|
var input struct {
|
|
|
|
Email string `json:"email" binding:"required,email"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.userService.SendResetPasswordCaptcha(input.Email); err != nil {
|
|
|
|
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "验证码已发送"})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// 在 UserHandler 中添加以下方法
|
|
|
|
|
|
|
|
// 获取图片验证码
|
|
|
|
func (h *UserHandler) GetCaptcha(c *gin.Context) {
|
|
|
|
id, b64s, err := h.userService.GetCaptchaService().GenerateImageCaptcha()
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{
|
|
|
|
"error": "生成验证码失败: " + err.Error(),
|
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
"captchaId": id,
|
|
|
|
"imageBase64": b64s,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 验证图片验证码
|
|
|
|
func (h *UserHandler) VerifyCaptcha(c *gin.Context) {
|
|
|
|
var input struct {
|
|
|
|
CaptchaId string `json:"captcha_id" binding:"required"`
|
|
|
|
Code string `json:"code" binding:"required"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if !h.userService.GetCaptchaService().VerifyImageCaptcha(input.CaptchaId, input.Code) {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "验证码错误"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "验证成功"})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取用户列表
|
|
|
|
func (h *UserHandler) GetUsers(c *gin.Context) {
|
|
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
|
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
|
|
|
|
username := c.Query("username")
|
|
|
|
role := c.Query("role")
|
|
|
|
|
|
|
|
users, total, err := h.userService.GetUsers(username, role, page, pageSize)
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{
|
|
|
|
"code": 0,
|
|
|
|
"msg": "获取用户列表成功",
|
|
|
|
"count": total,
|
|
|
|
"data": users,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 创建用户
|
|
|
|
func (h *UserHandler) CreateUser(c *gin.Context) {
|
|
|
|
var input struct {
|
|
|
|
Username string `json:"username" binding:"required"`
|
|
|
|
Password string `json:"password" binding:"required"`
|
|
|
|
Email string `json:"email" binding:"required,email"`
|
|
|
|
Role string `json:"role" binding:"required,oneof=admin user"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 检查权限
|
|
|
|
if c.GetString("role") != "admin" {
|
|
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "需要管理员权限"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
err := h.userService.CreateUser(input.Username, input.Password, input.Email, input.Role)
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "用户创建成功"})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 更新用户
|
|
|
|
func (h *UserHandler) UpdateUser(c *gin.Context) {
|
|
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的用户ID"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var input struct {
|
|
|
|
Email string `json:"email" binding:"required,email"`
|
|
|
|
Role string `json:"role" binding:"required,oneof=admin user"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 检查权限
|
|
|
|
if c.GetString("role") != "admin" {
|
|
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "需要管理员权限"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
err = h.userService.UpdateUser(uint(id), input.Email, input.Role)
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "用户更新成功"})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 删除用户
|
|
|
|
func (h *UserHandler) DeleteUser(c *gin.Context) {
|
|
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的用户ID"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 检查权限
|
|
|
|
if c.GetString("role") != "admin" {
|
|
|
|
c.JSON(http.StatusForbidden, gin.H{"error": "需要管理员权限"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 不能删除自己
|
|
|
|
if uint(id) == c.GetUint("userID") {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "不能删除自己"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
err = h.userService.DeleteUser(uint(id))
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "用户删除成功"})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取用户信息
|
|
|
|
func (h *UserHandler) GetUserInfo(c *gin.Context) {
|
|
|
|
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的用户ID"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
user, err := h.userService.GetUserByID(uint(id))
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, user)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取当前用户信息
|
|
|
|
func (h *UserHandler) GetProfile(c *gin.Context) {
|
|
|
|
userID := c.GetUint("userID")
|
|
|
|
user, err := h.userService.GetUserByID(userID)
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "用户不存在"})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, user)
|
|
|
|
}
|
|
|
|
|
|
|
|
// 修改密码
|
|
|
|
func (h *UserHandler) ChangePassword(c *gin.Context) {
|
|
|
|
var input struct {
|
|
|
|
OldPassword string `json:"old_password" binding:"required"`
|
|
|
|
NewPassword string `json:"new_password" binding:"required,min=6"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
userID := c.GetUint("userID")
|
|
|
|
err := h.userService.ChangePassword(userID, input.OldPassword, input.NewPassword)
|
|
|
|
if err != nil {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "密码修改成功"})
|
|
|
|
}
|
|
|
|
|
|
|
|
// 在 UserHandler 结构体中添加 UpdateProfile 方法
|
|
|
|
func (h *UserHandler) UpdateProfile(c *gin.Context) {
|
|
|
|
var input struct {
|
|
|
|
Email string `json:"email" binding:"required,email"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
userID := c.GetUint("userID")
|
|
|
|
if err := h.userService.UpdateProfile(userID, input.Email); err != nil {
|
|
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "个人信息更新成功"})
|
|
|
|
}
|