package handlers import ( "net/http" "strconv" "simple_portal/models" "simple_portal/session" "github.com/gin-gonic/gin" "golang.org/x/crypto/bcrypt" ) // LoginLogsGet 渲染登录日志页面。 func LoginLogsGet(c *gin.Context) { username, _ := c.Get("username") page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) if page < 1 { page = 1 } pageSize := 20 logs, total, err := models.GetLoginLogs(page, pageSize) if err != nil { logs = []models.LoginLog{} total = 0 } // 获取活跃的封禁列表 bans, _ := models.GetAllActiveBans() if bans == nil { bans = []models.IPBan{} } totalPages := (total + pageSize - 1) / pageSize if totalPages < 1 { totalPages = 1 } c.HTML(http.StatusOK, "admin/logs.html", gin.H{ "Title": "登录日志", "Username": username, "Logs": logs, "Bans": bans, "Page": page, "TotalPages": totalPages, "Total": total, }) } // UnbanIP 处理手动解封IP的请求。 func UnbanIP(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { c.Redirect(http.StatusFound, "/admin/logs") return } _ = models.DeleteIPBan(id) c.Redirect(http.StatusFound, "/admin/logs") } // ChangePasswordGet 渲染修改密码页面。 func ChangePasswordGet(c *gin.Context) { username, _ := c.Get("username") c.HTML(http.StatusOK, "admin/password.html", gin.H{ "Title": "修改密码", "Username": username, "Error": "", "Message": "", }) } // ChangePasswordPost 处理修改密码表单提交。 func ChangePasswordPost(c *gin.Context) { username, _ := c.Get("username") adminID, _ := c.Get("adminID") oldPassword := c.PostForm("old_password") newPassword := c.PostForm("new_password") confirmPassword := c.PostForm("confirm_password") // 验证输入 if oldPassword == "" || newPassword == "" || confirmPassword == "" { c.HTML(http.StatusOK, "admin/password.html", gin.H{ "Title": "修改密码", "Username": username, "Error": "请填写所有字段", "Message": "", }) return } if len(newPassword) < 6 { c.HTML(http.StatusOK, "admin/password.html", gin.H{ "Title": "修改密码", "Username": username, "Error": "新密码长度不能少于6位", "Message": "", }) return } if newPassword != confirmPassword { c.HTML(http.StatusOK, "admin/password.html", gin.H{ "Title": "修改密码", "Username": username, "Error": "两次输入的新密码不一致", "Message": "", }) return } // 验证旧密码 admin, err := models.GetAdminByUsername(username.(string)) if err != nil || admin == nil { c.HTML(http.StatusOK, "admin/password.html", gin.H{ "Title": "修改密码", "Username": username, "Error": "用户不存在", "Message": "", }) return } if err := bcrypt.CompareHashAndPassword([]byte(admin.Password), []byte(oldPassword)); err != nil { c.HTML(http.StatusOK, "admin/password.html", gin.H{ "Title": "修改密码", "Username": username, "Error": "旧密码不正确", "Message": "", }) return } // 生成新密码hash hashedPassword, err := bcrypt.GenerateFromPassword([]byte(newPassword), bcrypt.DefaultCost) if err != nil { c.HTML(http.StatusOK, "admin/password.html", gin.H{ "Title": "修改密码", "Username": username, "Error": "密码加密失败", "Message": "", }) return } // 更新密码 if err := models.ChangePassword(adminID.(int), string(hashedPassword)); err != nil { c.HTML(http.StatusOK, "admin/password.html", gin.H{ "Title": "修改密码", "Username": username, "Error": "密码修改失败: " + err.Error(), "Message": "", }) return } // 记录登录日志 ip := c.ClientIP() userAgent := c.Request.UserAgent() adminIDInt := adminID.(int) _ = models.CreateLoginLog(&adminIDInt, username.(string), ip, userAgent, true) // 清除当前session,强制重新登录 sessionID, _ := c.Cookie("session_id") if sessionID != "" { store := c.MustGet("sessionStore").(*session.SessionStore) store.Delete(sessionID) } c.SetCookie("session_id", "", -1, "/", "", false, true) c.Redirect(http.StatusFound, "/admin/login") } // IPWhitelistGet 渲染IP白名单管理页面。 func IPWhitelistGet(c *gin.Context) { username, _ := c.Get("username") list, err := models.GetAllWhitelist() if err != nil { list = []models.IPWhitelist{} } hasWhitelist := len(list) > 0 c.HTML(http.StatusOK, "admin/ip_whitelist.html", gin.H{ "Title": "IP白名单", "Username": username, "Whitelist": list, "HasWhitelist": hasWhitelist, "Error": "", "Message": "", }) } // IPWhitelistAdd 处理添加IP白名单的请求。 // 当白名单从空变为非空时,自动将当前操作者的IP也加入白名单,防止锁定自己。 func IPWhitelistAdd(c *gin.Context) { username, _ := c.Get("username") ip := c.PostForm("ip") comment := c.PostForm("comment") if ip == "" { list, _ := models.GetAllWhitelist() c.HTML(http.StatusOK, "admin/ip_whitelist.html", gin.H{ "Title": "IP白名单", "Username": username, "Whitelist": list, "HasWhitelist": len(list) > 0, "Error": "IP地址不能为空", "Message": "", }) return } // 检查白名单是否之前为空(首次启用白名单时需自动加入当前操作者IP) wasEmpty, _ := models.HasWhitelist() if err := models.AddWhitelist(ip, comment); err != nil { list, _ := models.GetAllWhitelist() c.HTML(http.StatusOK, "admin/ip_whitelist.html", gin.H{ "Title": "IP白名单", "Username": username, "Whitelist": list, "HasWhitelist": len(list) > 0, "Error": "添加失败: " + err.Error(), "Message": "", }) return } // 首次启用白名单:自动把当前操作者IP也加入,防止锁定 if !wasEmpty { c.Redirect(http.StatusFound, "/admin/ip-whitelist") return } currentIP := c.ClientIP() // 检查当前IP是否和刚添加的一样 isAlreadyAdded, _ := models.IsIPWhitelisted(currentIP) if !isAlreadyAdded { _ = models.AddWhitelist(currentIP, "自动添加(当前操作者)") } c.Redirect(http.StatusFound, "/admin/ip-whitelist") } // IPWhitelistDelete 处理删除IP白名单的请求。 func IPWhitelistDelete(c *gin.Context) { id, err := strconv.Atoi(c.Param("id")) if err != nil { c.Redirect(http.StatusFound, "/admin/ip-whitelist") return } _ = models.DeleteWhitelist(id) c.Redirect(http.StatusFound, "/admin/ip-whitelist") }