更新底层架构

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

@@ -1,55 +1,52 @@
package admin
import (
"context"
"NetworkAuth/config"
"NetworkAuth/models"
"NetworkAuth/services"
"NetworkAuth/utils"
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"net/http"
"networkDev/controllers"
"networkDev/models"
"networkDev/services"
"networkDev/utils"
)
// ============================================================================
// 全局变量
// ============================================================================
// 创建基础控制器实例
var settingsBaseController = controllers.NewBaseController()
// ============================================================================
// 页面处理器
// ============================================================================
// SettingsFragmentHandler 设置片段渲染
// - 渲染设置表单通过前端JS调用API加载/保存)
func SettingsFragmentHandler(c *gin.Context) {
c.HTML(http.StatusOK, "settings.html", gin.H{})
c.HTML(http.StatusOK, "settings.html", map[string]interface{}{})
}
// ============================================================================
// API处理器
// ============================================================================
// SubAccountSimpleListHandler 子账号简单列表API处理器 (Mock)
func SubAccountSimpleListHandler(c *gin.Context) {
// Mock implementation for NetworkAuth which has no subaccounts
c.JSON(http.StatusOK, gin.H{
"code": 0,
"msg": "success",
"data": []interface{}{},
})
}
// SettingsQueryHandler 设置查询API
// - 返回所有设置项的 name:value 映射
func SettingsQueryHandler(c *gin.Context) {
db, ok := settingsBaseController.GetDB(c)
db, ok := authBaseController.GetDB(c)
if !ok {
return
}
var list []models.Settings
if err := db.Find(&list).Error; err != nil {
settingsBaseController.HandleInternalError(c, "查询失败", err)
authBaseController.HandleInternalError(c, "查询失败", err)
return
}
res := map[string]string{}
for _, s := range list {
res[s.Name] = s.Value
}
settingsBaseController.HandleSuccess(c, "ok", res)
authBaseController.HandleSuccess(c, "ok", res)
}
// SettingsUpdateHandler 更新系统设置处理器
@@ -65,7 +62,8 @@ func SettingsQueryHandler(c *gin.Context) {
func SettingsUpdateHandler(c *gin.Context) {
// 先尝试解析为直接字段格式
var directBody map[string]interface{}
if !settingsBaseController.BindJSON(c, &directBody) {
if err := c.ShouldBindJSON(&directBody); err != nil {
authBaseController.HandleValidationError(c, "请求体错误")
return
}
@@ -82,7 +80,7 @@ func SettingsUpdateHandler(c *gin.Context) {
}
}
} else {
settingsBaseController.HandleValidationError(c, "settings字段格式错误")
authBaseController.HandleValidationError(c, "settings字段格式错误")
return
}
} else {
@@ -99,11 +97,19 @@ func SettingsUpdateHandler(c *gin.Context) {
}
if len(settingsData) == 0 {
settingsBaseController.HandleValidationError(c, "无设置项")
authBaseController.HandleValidationError(c, "无设置项")
return
}
db, ok := settingsBaseController.GetDB(c)
// 验证设置项值
for k, v := range settingsData {
if err := validateSettingValue(k, v); err != nil {
authBaseController.HandleValidationError(c, err.Error())
return
}
}
db, ok := authBaseController.GetDB(c)
if !ok {
return
}
@@ -113,13 +119,66 @@ func SettingsUpdateHandler(c *gin.Context) {
// 批量处理设置项
for k, v := range settingsData {
// 特殊处理 admin_password
if k == "admin_password" {
// 如果密码为空,跳过更新(保留原密码)
if v == "" {
continue
}
// 记录操作日志
// 由于 NetworkAuth 中没有 SystemAdminUser 全局变量,这里暂时使用 "admin"
// operator := "admin"
// 尝试从上下文获取用户名(如果中间件设置了的话)
// if user, exists := c.Get("username"); exists {
// operator = user.(string)
// }
// 生成随机盐值
salt, err := utils.GenerateRandomSalt()
if err != nil {
authBaseController.HandleInternalError(c, "生成盐值失败", err)
return
}
// 使用盐值哈希密码
hash, err := utils.HashPasswordWithSalt(v, salt)
if err != nil {
authBaseController.HandleInternalError(c, "密码哈希失败", err)
return
}
// 更新 salt 设置项(如果不存在则创建)
var saltSetting models.Settings
if err := db.Where("name = ?", "admin_password_salt").First(&saltSetting).Error; err != nil {
saltSetting = models.Settings{Name: "admin_password_salt", Value: salt}
if err := db.Create(&saltSetting).Error; err != nil {
logrus.WithError(err).Error("创建admin_password_salt失败")
authBaseController.HandleInternalError(c, "保存盐值失败", err)
return
}
} else {
if err := db.Model(&saltSetting).Update("value", salt).Error; err != nil {
logrus.WithError(err).Error("更新admin_password_salt失败")
authBaseController.HandleInternalError(c, "更新盐值失败", err)
return
}
}
// 将盐值相关的缓存键加入清理列表
keysToDel = append(keysToDel, "setting:admin_password_salt")
// 将当前处理的值替换为哈希后的密码
v = hash
}
var s models.Settings
if err := db.Where("name = ?", k).First(&s).Error; err != nil {
// 不存在则创建
s = models.Settings{Name: k, Value: v}
if err := db.Create(&s).Error; err != nil {
logrus.WithError(err).WithField("setting_name", k).Error("创建设置失败")
settingsBaseController.HandleInternalError(c, fmt.Sprintf("保存设置 %s 失败", k), err)
authBaseController.HandleInternalError(c, fmt.Sprintf("保存设置 %s 失败", k), err)
return
}
@@ -127,7 +186,7 @@ func SettingsUpdateHandler(c *gin.Context) {
// 存在则更新
if err := db.Model(&models.Settings{}).Where("id = ?", s.ID).Update("value", v).Error; err != nil {
logrus.WithError(err).WithField("setting_name", k).Error("更新设置失败")
settingsBaseController.HandleInternalError(c, fmt.Sprintf("更新设置 %s 失败", k), err)
authBaseController.HandleInternalError(c, fmt.Sprintf("更新设置 %s 失败", k), err)
return
}
@@ -137,10 +196,60 @@ func SettingsUpdateHandler(c *gin.Context) {
}
// 删除Redis缓存键如果Redis不可用则静默跳过
_ = utils.RedisDel(context.Background(), keysToDel...)
_ = utils.RedisDel(c.Request.Context(), keysToDel...)
// 刷新内存中的设置缓存,保证后续读取一致
services.GetSettingsService().RefreshCache()
settingsBaseController.HandleSuccess(c, "保存成功", nil)
authBaseController.HandleSuccess(c, "保存成功", nil)
}
// validateSettingValue 验证设置项值的合法性
func validateSettingValue(key, value string) error {
switch key {
case "jwt_refresh":
// 验证JWT刷新时间至少1小时
hours, err := strconv.Atoi(value)
if err != nil {
return fmt.Errorf("JWT刷新阈值必须是整数")
}
if hours < 1 {
return fmt.Errorf("JWT刷新阈值必须至少为1小时")
}
case "jwt_expire":
// 验证JWT有效期至少1小时
hours, err := strconv.Atoi(value)
if err != nil {
return fmt.Errorf("JWT有效期必须是整数")
}
if hours < 1 {
return fmt.Errorf("JWT有效期必须至少为1小时")
}
}
return nil
}
// SettingsGenerateKeyHandler 生成安全密钥API
// - type: "jwt" 或 "encryption"
func SettingsGenerateKeyHandler(c *gin.Context) {
keyType := c.Query("type")
var key string
var err error
switch keyType {
case "jwt":
key, err = config.GenerateSecureJWTSecret()
case "encryption":
key, err = config.GenerateSecureEncryptionKey()
default:
authBaseController.HandleValidationError(c, "无效的密钥类型")
return
}
if err != nil {
authBaseController.HandleInternalError(c, "生成密钥失败: "+err.Error(), err)
return
}
authBaseController.HandleSuccess(c, "生成成功", map[string]string{"key": key})
}