/* @Time : 2020/6/28 21:40 @Author : xuyiqing @File : users.py */ package controllers import ( "fmt" "go_blog/models" "go_blog/pkg/util" "go_blog/serializers" "go_blog/themes" "html/template" "net/http" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" ) // 登录 func UsersLoginHandler(ctx *gin.Context) { var loginUser serializers.Login if err := ctx.ShouldBind(&loginUser); err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "请求参数错误: " + err.Error(), }) return } // 验证用户逻辑不变 user := &models.Account{Username: loginUser.Username} if err := models.DB.Where("username = ?", user.Username).First(user).Error; err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "用户不存在", }) return } if !user.IsPasswordEqual(loginUser.Password) { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "密码错误", }) return } // 改为设置Session(替代JWT) session := sessions.Default(ctx) session.Set("user_id", user.ID) // 存储用户ID到Session session.Save() // 表单提交场景:直接跳转(无需设置JWT Cookie) if ctx.ContentType() == "application/x-www-form-urlencoded" { ctx.Redirect(http.StatusFound, "/admin/index") return } // API请求场景:返回登录成功(无需返回token) data, _ := util.PrecisionLost(user) ctx.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "msg": "登录成功", "data": data}) } // 注册 func UsersRegisterHandler(ctx *gin.Context) { var registerUser serializers.Login if err := ctx.ShouldBind(®isterUser); err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "请求参数错误: " + err.Error(), }) // 替换 panic 为错误响应 return } user := registerUser.GetUser() status := user.CheckDuplicateUsername() if status == false { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "用户名已存在", }) return } if err := user.SetPassword(user.Password); err != nil { panic(err) } user.IsActive = true models.DB.Create(&user) ctx.JSON(http.StatusOK, gin.H{"code": http.StatusOK, "msg": "注册成功"}) } // 修改用户信息 func UsersSetInfoHandler(ctx *gin.Context) { jsonData, err := util.GetBodyData(ctx) if err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "参数解析失败", }) return } fmt.Println(jsonData) if jsonData == nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "获取不到参数", }) return } // 从上下文中获取用户(假设 JWT 中间件已将用户存入 "user" 键) user, exists := ctx.Get("user") if !exists { ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "code": http.StatusUnauthorized, "msg": "未登录", }) return } currentUser, ok := user.(*models.Account) // 明确类型为 models.Account if !ok { ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "用户类型错误", }) return } models.DB.Model(currentUser).Updates(jsonData) ctx.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "更新成功", }) } // 修改密码 func UsersSetPwdHandler(ctx *gin.Context) { // 从上下文中获取用户(替换原 jwt.AssertUser 调用) ctxuser, exists := ctx.Get("user") if !exists { ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "code": http.StatusUnauthorized, "msg": "未验证登录", }) return } currentUser, ok := ctxuser.(*models.Account) if !ok { ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "用户类型错误", }) return } if currentUser == nil { ctx.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{ "code": http.StatusUnauthorized, "msg": "未验证登录", }) return } var user serializers.Account if err := ctx.ShouldBindJSON(&user); err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "参数解析失败", }) return } if user.Username != currentUser.Username { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "当前登录用户用户名与输入用户名不符", }) return } if user.OldPwd == user.NewPwd { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "两次输入的密码相同", }) return } if isPwd := currentUser.IsPasswordEqual(user.OldPwd); !isPwd { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": "原密码错误", }) return } if err := currentUser.SetPassword(user.NewPwd); err != nil { ctx.AbortWithStatusJSON(http.StatusBadRequest, gin.H{ "code": http.StatusBadRequest, "msg": err.Error(), }) return } models.DB.Save(¤tUser) ctx.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, "msg": "密码修改成功", }) } func UsersListHandler(ctx *gin.Context) { var pager serializers.Pager pager.InitPager(ctx) var users []models.Account // 先查询总记录数 var totalCount int64 models.DB.Model(&models.Account{}).Count(&totalCount) pager.Total = int(totalCount) // 正确设置总数 // 分页查询 // 由于 pager.OffSet 是 int 类型,直接使用该变量,无需调用函数 models.DB.Offset(pager.OffSet).Limit(pager.PageSize).Find(&users) pager.GetPager() ctx.JSON(http.StatusOK, gin.H{ "Code": http.StatusOK, "Msg": "返回成功", "Data": users, "Pager": pager, }) } // ShowLoginPage 渲染登录页面 func ShowLoginPage(c *gin.Context) { // 直接加载 web/admin 目录下的 login.tmpl 模板(需确保文件存在) tpl, err := template.ParseFiles("web/admin/login.tmpl") if err != nil { c.String(http.StatusInternalServerError, "加载模板失败: "+err.Error()) return } c.Status(http.StatusOK) c.Header("Content-Type", "text/html; charset=utf-8") err = tpl.Execute(c.Writer, gin.H{ "Title": "用户登录", }) if err != nil { c.String(http.StatusInternalServerError, "渲染模板错误: "+err.Error()) } } // ShowRegisterPage 渲染注册页面 func ShowRegisterPage(c *gin.Context) { tm, exists := c.Get("ThemeManager") if !exists { c.String(http.StatusInternalServerError, "Theme manager not found") return } themeManager, ok := tm.(*themes.ThemeManager) if !ok { c.String(http.StatusInternalServerError, "Invalid theme manager type") return } // 假设主题中存在 register.tmpl 模板(或使用后台固定模板) tpl := themeManager.GetTemplate("register") if tpl == nil { c.String(http.StatusInternalServerError, "Template 'register' not found in current theme. Make sure 'register.html' or 'register.tmpl' exists.") return } c.Status(http.StatusOK) c.Header("Content-Type", "text/html; charset=utf-8") err := tpl.Execute(c.Writer, gin.H{ "Title": "用户注册", }) if err != nil { c.String(http.StatusInternalServerError, "Error rendering template: "+err.Error()) } } // 退出登录 func UsersLogoutHandler(ctx *gin.Context) { session := sessions.Default(ctx) // 获取当前请求的Session // 清除Session中的用户ID session.Delete("user_id") // 保存Session修改(必须调用) if err := session.Save(); err != nil { ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{ "code": http.StatusInternalServerError, "msg": "退出失败: " + err.Error(), }) return } // 重定向到登录页 ctx.Redirect(http.StatusFound, "/admin/login") }