更新底层架构

This commit is contained in:
2026-03-18 21:51:17 +08:00
parent b69c6ccbca
commit 68bea98b81
71 changed files with 5220 additions and 7619 deletions

View File

@@ -0,0 +1,262 @@
package admin
import (
"NetworkAuth/database"
"NetworkAuth/models"
"NetworkAuth/services"
"NetworkAuth/utils"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
)
// ProfileFragmentHandler 个人资料片段渲染
// - 渲染个人资料与修改密码表单
func ProfileFragmentHandler(c *gin.Context) {
c.HTML(http.StatusOK, "profile.html", map[string]interface{}{})
}
// ProfileInfoHandler 查询当前登录管理员的基本信息
// - 返回 username 字段
func ProfileInfoHandler(c *gin.Context) {
_, _, err := GetCurrentAdminUserWithRefresh(c)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{
"code": 1,
"msg": "未登录或会话已过期",
"data": nil,
})
return
}
// 获取最新设置
settingsService := services.GetSettingsService()
username := settingsService.GetString("admin_username", "admin")
authBaseController.HandleSuccess(c, "ok", map[string]interface{}{
"username": username,
})
}
// ProfilePasswordUpdateHandler 修改当前登录管理员的密码
// - 接收 JSON: {old_password, new_password, confirm_password}
// - 校验旧密码正确性、新密码与确认一致性
// - 成功后更新密码哈希
func ProfilePasswordUpdateHandler(c *gin.Context) {
_, _, err := GetCurrentAdminUserWithRefresh(c)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{
"code": 1,
"msg": "未登录或会话已过期",
"data": nil,
})
return
}
var body struct {
OldPassword string `json:"old_password"`
NewPassword string `json:"new_password"`
ConfirmPassword string `json:"confirm_password"`
}
if !authBaseController.BindJSON(c, &body) {
return
}
// 基础校验
if body.OldPassword == "" || body.NewPassword == "" || body.ConfirmPassword == "" {
authBaseController.HandleValidationError(c, "旧密码/新密码/确认密码均不能为空")
return
}
if len(body.NewPassword) < 6 {
authBaseController.HandleValidationError(c, "新密码长度不能少于6位")
return
}
if body.NewPassword != body.ConfirmPassword {
authBaseController.HandleValidationError(c, "两次输入的新密码不一致")
return
}
if body.NewPassword == body.OldPassword {
authBaseController.HandleValidationError(c, "新密码不能与旧密码相同")
return
}
// 获取当前密码设置
settingsService := services.GetSettingsService()
currentHash := settingsService.GetString("admin_password", "")
currentSalt := settingsService.GetString("admin_password_salt", "")
// 校验旧密码
if !utils.VerifyPasswordWithSalt(body.OldPassword, currentSalt, currentHash) {
authBaseController.HandleValidationError(c, "旧密码不正确")
return
}
// 生成新盐值和哈希
newSalt, err := utils.GenerateRandomSalt()
if err != nil {
authBaseController.HandleInternalError(c, "生成盐值失败", err)
return
}
newHash, err := utils.HashPasswordWithSalt(body.NewPassword, newSalt)
if err != nil {
authBaseController.HandleInternalError(c, "生成密码哈希失败", err)
return
}
// 更新数据库
db, ok := authBaseController.GetDB(c)
if !ok {
return
}
// 更新 admin_password
if err := updateSetting(db, "admin_password", newHash); err != nil {
authBaseController.HandleInternalError(c, "更新密码失败", err)
return
}
// 更新 admin_password_salt
if err := updateSetting(db, "admin_password_salt", newSalt); err != nil {
authBaseController.HandleInternalError(c, "更新盐值失败", err)
return
}
// 刷新缓存
settingsService.RefreshCache()
// 清除相关缓存键
_ = utils.RedisDel(c.Request.Context(), "setting:admin_password", "setting:admin_password_salt")
// 获取当前用户名
currentUsername := settingsService.GetString("admin_username", "admin")
// 重新签发JWT并写入Cookie
token, err := generateJWTTokenForAdmin(currentUsername, newHash)
if err != nil {
authBaseController.HandleInternalError(c, "生成新令牌失败", err)
return
}
secure, sameSite, domain, maxAge := settingsService.GetCookieConfig()
cookie := utils.CreateSecureCookie("admin_session", token, maxAge, domain, secure, sameSite)
c.SetCookie(cookie.Name, cookie.Value, cookie.MaxAge, cookie.Path, cookie.Domain, cookie.Secure, cookie.HttpOnly)
authBaseController.HandleSuccess(c, "密码修改成功", nil)
}
// ProfileUpdateHandler 修改当前登录管理员的用户名
// - 接收 JSON: {username}
// - 校验用户名非空、长度
// - 更新数据库后重新签发JWT并写入 Cookie保持前端展示的一致性
func ProfileUpdateHandler(c *gin.Context) {
_, _, err := GetCurrentAdminUserWithRefresh(c)
if err != nil {
c.JSON(http.StatusUnauthorized, gin.H{
"code": 1,
"msg": "未登录或会话已过期",
"data": nil,
})
return
}
var body struct {
Username string `json:"username"`
OldPassword string `json:"old_password"`
}
if !authBaseController.BindJSON(c, &body) {
return
}
username := strings.TrimSpace(body.Username)
if username == "" {
authBaseController.HandleValidationError(c, "用户名不能为空")
return
}
if len(username) > 64 {
authBaseController.HandleValidationError(c, "用户名长度不能超过64字符")
return
}
settingsService := services.GetSettingsService()
currentUsername := settingsService.GetString("admin_username", "admin")
// 如果未变化则直接返回成功
if strings.EqualFold(username, currentUsername) {
authBaseController.HandleSuccess(c, "保存成功", map[string]interface{}{
"username": username,
})
return
}
// 修改用户名需要进行当前密码校验
if strings.TrimSpace(body.OldPassword) == "" {
authBaseController.HandleValidationError(c, "修改用户名需要提供当前密码")
return
}
currentHash := settingsService.GetString("admin_password", "")
currentSalt := settingsService.GetString("admin_password_salt", "")
// 校验旧密码
if !utils.VerifyPasswordWithSalt(body.OldPassword, currentSalt, currentHash) {
authBaseController.HandleValidationError(c, "当前密码不正确")
return
}
// 更新数据库
db, ok := authBaseController.GetDB(c)
if !ok {
return
}
if err := updateSetting(db, "admin_username", username); err != nil {
authBaseController.HandleInternalError(c, "更新用户名失败", err)
return
}
// 重新签发JWT并写入Cookie
token, err := generateJWTTokenForAdmin(username, currentHash)
if err != nil {
authBaseController.HandleInternalError(c, "生成新令牌失败", err)
return
}
secure, sameSite, domain, maxAge := settingsService.GetCookieConfig()
cookie := utils.CreateSecureCookie("admin_session", token, maxAge, domain, secure, sameSite)
c.SetCookie(cookie.Name, cookie.Value, cookie.MaxAge, cookie.Path, cookie.Domain, cookie.Secure, cookie.HttpOnly)
// 刷新缓存
settingsService.RefreshCache()
_ = utils.RedisDel(c.Request.Context(), "setting:admin_username")
authBaseController.HandleSuccess(c, "用户名修改成功", map[string]interface{}{
"username": username,
})
}
// 辅助函数:更新设置项
func updateSetting(db interface{}, name, value string) error {
// 类型断言
gormDB, ok := db.(*gorm.DB)
if !ok {
// 如果断言失败,尝试重新获取连接
var err error
gormDB, err = database.GetDB()
if err != nil {
return err
}
}
var setting models.Settings
if err := gormDB.Where("name = ?", name).First(&setting).Error; err != nil {
// 如果不存在则创建
setting = models.Settings{Name: name, Value: value}
return gormDB.Create(&setting).Error
}
// 存在则更新
return gormDB.Model(&setting).Update("value", value).Error
}