Files
SamWaf/api/waf_plugin.go
T
2025-12-26 23:48:28 +08:00

315 lines
7.9 KiB
Go

package api
import (
"SamWaf/common/zlog"
"SamWaf/global"
"SamWaf/globalobj"
"SamWaf/model"
"SamWaf/model/common/response"
pluginconfig "SamWaf/plugin/config"
"encoding/json"
"github.com/gin-gonic/gin"
)
type WafPluginApi struct {
}
// GetListApi 获取插件列表
func (w *WafPluginApi) GetListApi(c *gin.Context) {
var plugins []model.WafPluginConfig
err := global.GWAF_LOCAL_DB.Find(&plugins).Error
if err != nil {
response.FailWithMessage("查询失败", c)
return
}
response.OkWithDetailed(plugins, "获取成功", c)
}
// GetDetailApi 获取插件详情
func (w *WafPluginApi) GetDetailApi(c *gin.Context) {
pluginID := c.Query("plugin_id")
if pluginID == "" {
response.FailWithMessage("插件ID不能为空", c)
return
}
var plugin model.WafPluginConfig
err := global.GWAF_LOCAL_DB.Where("plugin_id = ?", pluginID).First(&plugin).Error
if err != nil {
response.FailWithMessage("插件不存在", c)
return
}
response.OkWithDetailed(plugin, "获取成功", c)
}
// AddApi 添加插件
func (w *WafPluginApi) AddApi(c *gin.Context) {
var plugin model.WafPluginConfig
err := c.ShouldBindJSON(&plugin)
if err != nil {
response.FailWithMessage("参数解析失败", c)
return
}
// 检查插件ID是否已存在
var count int64
global.GWAF_LOCAL_DB.Model(&model.WafPluginConfig{}).Where("plugin_id = ?", plugin.PluginID).Count(&count)
if count > 0 {
response.FailWithMessage("插件ID已存在", c)
return
}
// 保存到数据库
err = global.GWAF_LOCAL_DB.Create(&plugin).Error
if err != nil {
response.FailWithMessage("添加失败", c)
return
}
// 如果插件已启用,尝试加载
if plugin.Enabled == 1 && globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER != nil {
config := w.convertToPluginConfig(&plugin)
if err := globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER.LoadPlugin(config); err != nil {
zlog.Error("加载插件失败", "plugin_id", plugin.PluginID, "error", err)
response.FailWithMessage("添加成功但加载失败: "+err.Error(), c)
return
}
}
response.OkWithMessage("添加成功", c)
}
// ModifyApi 修改插件
func (w *WafPluginApi) ModifyApi(c *gin.Context) {
var plugin model.WafPluginConfig
err := c.ShouldBindJSON(&plugin)
if err != nil {
response.FailWithMessage("参数解析失败", c)
return
}
// 更新数据库
err = global.GWAF_LOCAL_DB.Where("plugin_id = ?", plugin.PluginID).Updates(&plugin).Error
if err != nil {
response.FailWithMessage("更新失败", c)
return
}
// 重新加载插件
if globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER != nil {
// 先卸载旧插件
globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER.UnloadPlugin(plugin.PluginID)
// 如果启用,重新加载
if plugin.Enabled == 1 {
config := w.convertToPluginConfig(&plugin)
if err := globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER.LoadPlugin(config); err != nil {
zlog.Error("重新加载插件失败", "plugin_id", plugin.PluginID, "error", err)
}
}
}
response.OkWithMessage("更新成功", c)
}
// DeleteApi 删除插件
func (w *WafPluginApi) DeleteApi(c *gin.Context) {
pluginID := c.Query("plugin_id")
if pluginID == "" {
response.FailWithMessage("插件ID不能为空", c)
return
}
// 从数据库删除
err := global.GWAF_LOCAL_DB.Where("plugin_id = ?", pluginID).Delete(&model.WafPluginConfig{}).Error
if err != nil {
response.FailWithMessage("删除失败", c)
return
}
// 卸载插件
if globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER != nil {
globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER.UnloadPlugin(pluginID)
}
response.OkWithMessage("删除成功", c)
}
// ToggleApi 启用/禁用插件
func (w *WafPluginApi) ToggleApi(c *gin.Context) {
pluginID := c.Query("plugin_id")
if pluginID == "" {
response.FailWithMessage("插件ID不能为空", c)
return
}
// 查询插件
var plugin model.WafPluginConfig
err := global.GWAF_LOCAL_DB.Where("plugin_id = ?", pluginID).First(&plugin).Error
if err != nil {
response.FailWithMessage("插件不存在", c)
return
}
// 切换状态
newStatus := 0
if plugin.Enabled == 0 {
newStatus = 1
}
// 更新数据库
err = global.GWAF_LOCAL_DB.Model(&plugin).Update("enabled", newStatus).Error
if err != nil {
response.FailWithMessage("更新失败", c)
return
}
// 加载或卸载插件
if globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER != nil {
if newStatus == 1 {
// 启用:加载插件
plugin.Enabled = 1
config := w.convertToPluginConfig(&plugin)
if err := globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER.LoadPlugin(config); err != nil {
zlog.Error("加载插件失败", "plugin_id", pluginID, "error", err)
response.FailWithMessage("启用失败: "+err.Error(), c)
return
}
} else {
// 禁用:卸载插件
globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER.UnloadPlugin(pluginID)
}
}
response.OkWithMessage("操作成功", c)
}
// GetSystemConfigApi 获取插件系统配置
func (w *WafPluginApi) GetSystemConfigApi(c *gin.Context) {
var configs []model.WafPluginSystemConfig
err := global.GWAF_LOCAL_DB.Find(&configs).Error
if err != nil {
response.FailWithMessage("查询失败", c)
return
}
// 转换为map格式
configMap := make(map[string]string)
for _, config := range configs {
configMap[config.Key] = config.Value
}
response.OkWithDetailed(configMap, "获取成功", c)
}
// UpdateSystemConfigApi 更新插件系统配置
func (w *WafPluginApi) UpdateSystemConfigApi(c *gin.Context) {
var req map[string]string
err := c.ShouldBindJSON(&req)
if err != nil {
response.FailWithMessage("参数解析失败", c)
return
}
// 更新配置
for key, value := range req {
var config model.WafPluginSystemConfig
err := global.GWAF_LOCAL_DB.Where("key = ?", key).First(&config).Error
if err == nil {
// 更新
global.GWAF_LOCAL_DB.Model(&config).Update("value", value)
} else {
// 创建
config = model.WafPluginSystemConfig{
Key: key,
Value: value,
}
global.GWAF_LOCAL_DB.Create(&config)
}
}
// 如果修改了enabled,更新插件管理器状态
if enabled, ok := req["enabled"]; ok && globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER != nil {
globalobj.GWAF_RUNTIME_OBJ_PLUGIN_MANAGER.SetEnabled(enabled == "1" || enabled == "true")
}
response.OkWithMessage("更新成功", c)
}
// GetPluginLogsApi 获取插件日志
func (w *WafPluginApi) GetPluginLogsApi(c *gin.Context) {
pluginID := c.Query("plugin_id")
page := c.DefaultQuery("page", "1")
pageSize := c.DefaultQuery("page_size", "20")
var logs []model.WafPluginLog
query := global.GWAF_LOCAL_DB.Model(&model.WafPluginLog{})
if pluginID != "" {
query = query.Where("plugin_id = ?", pluginID)
}
// 分页
var total int64
query.Count(&total)
var pageInt, pageSizeInt int
json.Unmarshal([]byte(page), &pageInt)
json.Unmarshal([]byte(pageSize), &pageSizeInt)
offset := (pageInt - 1) * pageSizeInt
err := query.Order("created_at desc").Offset(offset).Limit(pageSizeInt).Find(&logs).Error
if err != nil {
response.FailWithMessage("查询失败", c)
return
}
result := map[string]interface{}{
"list": logs,
"total": total,
"page": pageInt,
"page_size": pageSizeInt,
}
response.OkWithDetailed(result, "获取成功", c)
}
// convertToPluginConfig 转换数据库模型为插件配置
func (w *WafPluginApi) convertToPluginConfig(plugin *model.WafPluginConfig) *pluginconfig.PluginConfig {
config := &pluginconfig.PluginConfig{
ID: plugin.PluginID,
Name: plugin.Name,
Description: plugin.Description,
Type: plugin.Type,
Version: plugin.Version,
Enabled: plugin.Enabled == 1,
BinaryPath: plugin.BinaryPath,
Priority: plugin.Priority,
}
// 解析JSON字段
if plugin.Groups != "" {
json.Unmarshal([]byte(plugin.Groups), &config.Groups)
}
if plugin.Params != "" {
json.Unmarshal([]byte(plugin.Params), &config.Params)
}
if plugin.InputSchema != "" {
json.Unmarshal([]byte(plugin.InputSchema), &config.InputSchema)
}
if plugin.OutputSchema != "" {
json.Unmarshal([]byte(plugin.OutputSchema), &config.OutputSchema)
}
return config
}