فهرست منبع

feat(admin): 添加 WAF 日志查询功能

- 新增 WafLogHandler 处理 WAF 日志查询请求
- 实现 GetWafLog 和 GetWafLogList 方法
- 添加 WafLogRepository 接口和实现类- 创建 WafLogService 接口和实现类
- 在 HTTP 服务器中注册 WAF 日志查询路由
fusu 1 هفته پیش
والد
کامیت
660fe6fda7

+ 17 - 0
api/v1/admin/wafLog.go

@@ -0,0 +1,17 @@
+package admin
+
+type SearchWafLogParams struct {
+	RequestIp string `form:"requestIp" json:"requestIp"`
+	Uid       int64  `form:"uid" json:"uid"`
+	Api       string `form:"api" json:"api"`
+	Message   string `form:"message" json:"message"`
+	ExtraData string `form:"extraData" json:"extraData"`
+	Current  int	`form:"current" json:"current" default:"1"`
+	PageSize int	`form:"pageSize" json:"pageSize" default:"10"`
+	Column   string `form:"column" json:"column" default:"id"`
+	Order    string `form:"order" json:"order" default:"desc"`
+}
+
+type LogId struct {
+	Id int64 `json:"id" form:"id" validate:"required,min=1" `
+}

+ 3 - 0
cmd/server/wire/wire.go

@@ -60,6 +60,7 @@ var repositorySet = wire.NewSet(
 	wafRep.NewGatewayipRepository,
 	adminRep.NewGatewayIpAdminRepository,
 	flexCdnRep.NewCcIpListRepository,
+	adminRep.NewWafLogRepository,
 
 )
 
@@ -100,6 +101,7 @@ var serviceSet = wire.NewSet(
 	waf.NewCdnLogService,
 	waf.NewBuildAudunService,
 	waf.NewZzybgpService,
+	admin.NewWafLogService,
 )
 
 var handlerSet = wire.NewSet(
@@ -124,6 +126,7 @@ var handlerSet = wire.NewSet(
 	wafHandler.NewGatewayipHandler,
 	wafHandler.NewCcIpListHandler,
 	wafHandler.NewCdnLogHandler,
+	adminHandler.NewWafLogHandler,
 )
 
 

+ 7 - 4
cmd/server/wire/wire_gen.go

@@ -113,7 +113,10 @@ func NewWire(viperViper *viper.Viper, logger *log.Logger) (*app.App, func(), err
 	ccIpListHandler := waf3.NewCcIpListHandler(handlerHandler, ccIpListService)
 	cdnLogService := waf2.NewCdnLogService(serviceService, tcpforwardingRepository, udpForWardingRepository, webForwardingRepository, cdnService, ccIpListService)
 	cdnLogHandler := waf3.NewCdnLogHandler(handlerHandler, cdnLogService)
-	httpServer := server.NewHTTPServer(logger, viperViper, jwtJWT, syncedEnforcer, limiterLimiter, handlerFunc, userHandler, gameShieldHandler, gameShieldBackendHandler, webForwardingHandler, tcpforwardingHandler, udpForWardingHandler, globalLimitHandler, adminHandler, gatewayIpAdminHandler, allowAndDenyIpHandler, ccHandler, logService, ccIpListHandler, cdnLogHandler)
+	wafLogRepository := admin.NewWafLogRepository(repositoryRepository)
+	wafLogService := admin2.NewWafLogService(serviceService, wafLogRepository)
+	wafLogHandler := admin3.NewWafLogHandler(handlerHandler, wafLogService)
+	httpServer := server.NewHTTPServer(logger, viperViper, jwtJWT, syncedEnforcer, limiterLimiter, handlerFunc, userHandler, gameShieldHandler, gameShieldBackendHandler, webForwardingHandler, tcpforwardingHandler, udpForWardingHandler, globalLimitHandler, adminHandler, gatewayIpAdminHandler, allowAndDenyIpHandler, ccHandler, logService, ccIpListHandler, cdnLogHandler, wafLogHandler)
 	appApp := newApp(httpServer)
 	return appApp, func() {
 		cleanup()
@@ -122,11 +125,11 @@ func NewWire(viperViper *viper.Viper, logger *log.Logger) (*app.App, func(), err
 
 // wire.go:
 
-var repositorySet = wire.NewSet(repository.NewDB, repository.NewRedis, repository.NewCasbinEnforcer, repository.NewMongoClient, repository.NewMongoDB, repository.NewRabbitMQ, repository.NewRepository, repository.NewTransaction, admin.NewAdminRepository, admin.NewUserRepository, repository.NewGameShieldRepository, repository.NewGameShieldPublicIpRepository, waf.NewWebForwardingRepository, waf.NewTcpforwardingRepository, waf.NewUdpForWardingRepository, repository.NewGameShieldUserIpRepository, repository.NewGameShieldBackendRepository, repository.NewGameShieldSdkIpRepository, repository.NewHostRepository, waf.NewGlobalLimitRepository, repository.NewGatewayGroupRepository, repository.NewGateWayGroupIpRepository, flexCdn.NewCdnRepository, waf.NewAllowAndDenyIpRepository, flexCdn.NewProxyRepository, flexCdn.NewCcRepository, repository.NewExpiredRepository, repository.NewLogRepository, waf.NewGatewayipRepository, admin.NewGatewayIpAdminRepository, flexCdn.NewCcIpListRepository)
+var repositorySet = wire.NewSet(repository.NewDB, repository.NewRedis, repository.NewCasbinEnforcer, repository.NewMongoClient, repository.NewMongoDB, repository.NewRabbitMQ, repository.NewRepository, repository.NewTransaction, admin.NewAdminRepository, admin.NewUserRepository, repository.NewGameShieldRepository, repository.NewGameShieldPublicIpRepository, waf.NewWebForwardingRepository, waf.NewTcpforwardingRepository, waf.NewUdpForWardingRepository, repository.NewGameShieldUserIpRepository, repository.NewGameShieldBackendRepository, repository.NewGameShieldSdkIpRepository, repository.NewHostRepository, waf.NewGlobalLimitRepository, repository.NewGatewayGroupRepository, repository.NewGateWayGroupIpRepository, flexCdn.NewCdnRepository, waf.NewAllowAndDenyIpRepository, flexCdn.NewProxyRepository, flexCdn.NewCcRepository, repository.NewExpiredRepository, repository.NewLogRepository, waf.NewGatewayipRepository, admin.NewGatewayIpAdminRepository, flexCdn.NewCcIpListRepository, admin.NewWafLogRepository)
 
-var serviceSet = wire.NewSet(service.NewService, admin2.NewUserService, admin2.NewGatewayIpAdminService, admin2.NewAdminService, gameShield.NewGameShieldService, service.NewAoDunService, service.NewGameShieldPublicIpService, service.NewDuedateService, service.NewFormatterService, service.NewParserService, service.NewRequiredService, service.NewCrawlerService, waf2.NewWebForwardingService, waf2.NewTcpforwardingService, waf2.NewUdpForWardingService, service.NewGameShieldUserIpService, gameShield.NewGameShieldBackendService, service.NewGameShieldSdkIpService, service.NewHostService, waf2.NewGlobalLimitService, service.NewGatewayGroupService, waf2.NewWafFormatterService, service.NewGateWayGroupIpService, service.NewRequestService, flexCdn2.NewCdnService, waf2.NewAllowAndDenyIpService, flexCdn2.NewProxyService, flexCdn2.NewSslCertService, flexCdn2.NewWebsocketService, waf2.NewCcService, service.NewLogService, waf2.NewGatewayipService, waf2.NewCcIpListService, waf2.NewCdnLogService, waf2.NewBuildAudunService, waf2.NewZzybgpService)
+var serviceSet = wire.NewSet(service.NewService, admin2.NewUserService, admin2.NewGatewayIpAdminService, admin2.NewAdminService, gameShield.NewGameShieldService, service.NewAoDunService, service.NewGameShieldPublicIpService, service.NewDuedateService, service.NewFormatterService, service.NewParserService, service.NewRequiredService, service.NewCrawlerService, waf2.NewWebForwardingService, waf2.NewTcpforwardingService, waf2.NewUdpForWardingService, service.NewGameShieldUserIpService, gameShield.NewGameShieldBackendService, service.NewGameShieldSdkIpService, service.NewHostService, waf2.NewGlobalLimitService, service.NewGatewayGroupService, waf2.NewWafFormatterService, service.NewGateWayGroupIpService, service.NewRequestService, flexCdn2.NewCdnService, waf2.NewAllowAndDenyIpService, flexCdn2.NewProxyService, flexCdn2.NewSslCertService, flexCdn2.NewWebsocketService, waf2.NewCcService, service.NewLogService, waf2.NewGatewayipService, waf2.NewCcIpListService, waf2.NewCdnLogService, waf2.NewBuildAudunService, waf2.NewZzybgpService, admin2.NewWafLogService)
 
-var handlerSet = wire.NewSet(handler.NewHandler, admin3.NewUserHandler, admin3.NewAdminHandler, admin3.NewGatewayIpAdminHandler, handler.NewGameShieldHandler, handler.NewGameShieldPublicIpHandler, waf3.NewWebForwardingHandler, waf3.NewTcpforwardingHandler, waf3.NewUdpForWardingHandler, handler.NewGameShieldUserIpHandler, handler.NewGameShieldBackendHandler, handler.NewGameShieldSdkIpHandler, handler.NewHostHandler, waf3.NewGlobalLimitHandler, handler.NewGatewayGroupHandler, handler.NewGateWayGroupIpHandler, waf3.NewAllowAndDenyIpHandler, waf3.NewCcHandler, waf3.NewGatewayipHandler, waf3.NewCcIpListHandler, waf3.NewCdnLogHandler)
+var handlerSet = wire.NewSet(handler.NewHandler, admin3.NewUserHandler, admin3.NewAdminHandler, admin3.NewGatewayIpAdminHandler, handler.NewGameShieldHandler, handler.NewGameShieldPublicIpHandler, waf3.NewWebForwardingHandler, waf3.NewTcpforwardingHandler, waf3.NewUdpForWardingHandler, handler.NewGameShieldUserIpHandler, handler.NewGameShieldBackendHandler, handler.NewGameShieldSdkIpHandler, handler.NewHostHandler, waf3.NewGlobalLimitHandler, handler.NewGatewayGroupHandler, handler.NewGateWayGroupIpHandler, waf3.NewAllowAndDenyIpHandler, waf3.NewCcHandler, waf3.NewGatewayipHandler, waf3.NewCcIpListHandler, waf3.NewCdnLogHandler, admin3.NewWafLogHandler)
 
 // 限流器依赖集
 var limiterSet = wire.NewSet(limiter.NewLimiter, middleware.NewRateLimitMiddleware)

+ 56 - 0
internal/handler/admin/waflog.go

@@ -0,0 +1,56 @@
+package admin
+
+import (
+	"github.com/gin-gonic/gin"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	"github.com/go-nunu/nunu-layout-advanced/api/v1/admin"
+	"github.com/go-nunu/nunu-layout-advanced/internal/handler"
+	adminService "github.com/go-nunu/nunu-layout-advanced/internal/service/admin"
+	"github.com/mcuadros/go-defaults"
+	"net/http"
+)
+
+type WafLogHandler struct {
+	*handler.Handler
+	wafLogService adminService.WafLogService
+}
+
+func NewWafLogHandler(
+    handler *handler.Handler,
+    wafLogService adminService.WafLogService,
+) *WafLogHandler {
+	return &WafLogHandler{
+		Handler:      handler,
+		wafLogService: wafLogService,
+	}
+}
+
+func (h *WafLogHandler) GetWafLog(ctx *gin.Context) {
+	var req admin.LogId
+	if err := ctx.ShouldBind(req); err != nil {
+		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, err.Error())
+		return
+	}
+	defaults.SetDefaults(&req)
+	res, err := h.wafLogService.GetWafLog(ctx, req.Id)
+	if err != nil {
+		v1.HandleError(ctx, http.StatusInternalServerError, err, err.Error())
+		return
+	}
+	v1.HandleSuccess(ctx, res)
+}
+
+func (h *WafLogHandler) GetWafLogList(ctx *gin.Context) {
+	var req admin.SearchWafLogParams
+	if err := ctx.ShouldBind(&req); err != nil {
+		v1.HandleError(ctx, http.StatusBadRequest, v1.ErrBadRequest, err.Error())
+		return
+	}
+	defaults.SetDefaults(&req)
+	res, err := h.wafLogService.GetWafLogList(ctx, req)
+	if err != nil {
+		v1.HandleError(ctx, http.StatusInternalServerError, err, err.Error())
+		return
+	}
+	v1.HandleSuccess(ctx, res)
+}

+ 114 - 0
internal/repository/admin/waflog.go

@@ -0,0 +1,114 @@
+package admin
+
+import (
+    "context"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	admin "github.com/go-nunu/nunu-layout-advanced/api/v1/admin"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+	"github.com/go-nunu/nunu-layout-advanced/internal/repository"
+	"math"
+	"strings"
+)
+
+type WafLogRepository interface {
+	GetWafLog(ctx context.Context, id int64) (*model.Log, error)
+	GetWafLogList(ctx context.Context, req admin.SearchWafLogParams) (*v1.PaginatedResponse[model.Log], error)
+}
+
+func NewWafLogRepository(
+	repository *repository.Repository,
+) WafLogRepository {
+	return &wafLogRepository{
+		Repository: repository,
+	}
+}
+
+type wafLogRepository struct {
+	*repository.Repository
+}
+
+func (r *wafLogRepository) GetWafLog(ctx context.Context, id int64) (*model.Log, error) {
+	var res model.Log
+	return &res, r.DB(ctx).Where("id = ?", id).First(&res).Error
+}
+
+func (r *wafLogRepository) GetWafLogList(ctx context.Context, req admin.SearchWafLogParams) (*v1.PaginatedResponse[model.Log], error) {
+	var res []model.Log
+	var total int64
+
+	query := r.Db.WithContext(ctx).Model(&model.Gatewayip{})
+	if  req.RequestIp != "" {
+		trimmedName := strings.TrimSpace(req.RequestIp)
+		// 使用 LIKE 进行模糊匹配
+		query = query.Where("request_ip LIKE CONCAT('%', ?, '%')", trimmedName)
+	}
+
+
+	if req.Uid != 0 {
+		query = query.Where("uid = ?", req.Uid)
+	}
+
+	if req.Api != "" {
+		trimmedName := strings.TrimSpace(req.Api)
+		// 使用 LIKE 进行模糊匹配
+		query = query.Where("api LIKE CONCAT('%', ?, '%')", trimmedName)
+	}
+
+	if req.Message != "" {
+		trimmedName := strings.TrimSpace(req.Message)
+		// 使用 LIKE 进行模糊匹配
+		query = query.Where("message LIKE CONCAT('%', ?, '%')", trimmedName)
+	}
+
+
+	if req.ExtraData != "" {
+		trimmedName := strings.TrimSpace(req.ExtraData)
+		// 使用 LIKE 进行模糊匹配
+		query = query.Where("extra_data LIKE CONCAT('%', ?, '%')", trimmedName)
+	}
+
+	if req.Column != "" {
+		if req.Column == "createTime" {
+			query = query.Order("created_at" + " " + req.Order)
+		}
+	}
+
+	if err := query.Count(&total).Error; err != nil {
+		// 如果连计数都失败了,直接返回错误
+		return nil, err
+	}
+
+
+	page := req.Current
+	pageSize := req.PageSize
+
+	if page <= 0 {
+		page = 1
+	}
+
+	if pageSize <= 0 {
+		pageSize = 10 // 默认每页 10 条
+	} else if pageSize > 100 {
+		pageSize = 100 // 每页最多 100 条
+	}
+
+	// 计算 offset (偏移量)
+	// 例如,第 1 页,offset = (1-1)*10 = 0 (从第0条开始)
+	// 第 2 页,offset = (2-1)*10 = 10 (从第10条开始)
+	offset := (page - 1) * pageSize
+	// 3. 执行最终的查询
+	// 在所有条件都添加完毕后,再执行 .Find()
+	result := query.Offset(offset).Limit(pageSize).Find(&res)
+	if result.Error != nil {
+		// 这里的错误可能是数据库连接问题等,而不是“未找到记录”
+		return nil, result.Error
+	}
+	return &v1.PaginatedResponse[model.Log]{
+		Records: res,
+		Page: page,
+		PageSize: pageSize,
+		Total: total,
+		TotalPages: int(math.Ceil(float64(total) / float64(pageSize))),
+
+	}, nil
+}

+ 5 - 0
internal/server/http.go

@@ -40,6 +40,7 @@ func NewHTTPServer(
 	logService service.LogService,
 	ccIpListHandler *waf.CcIpListHandler,
 	cdnLogHandler *waf.CdnLogHandler,
+	wafLogHandler *admin.WafLogHandler,
 ) *http.Server {
 	gin.SetMode(gin.DebugMode)
 	s := http.NewServer(
@@ -186,6 +187,10 @@ func NewHTTPServer(
 			strictAuthRouter.DELETE("/gatewayIp/del", gatewayIpAdminHandler.DeleteGatewayIpAdmin)
 			strictAuthRouter.DELETE("/gatewayIp/delList", gatewayIpAdminHandler.DeleteGatewayIpsAdmin)
 
+
+			strictAuthRouter.GET("/wafLog/get", wafLogHandler.GetWafLog)
+			strictAuthRouter.GET("/wafLog/getList", wafLogHandler.GetWafLogList)
+
 		}
 	}
 

+ 37 - 0
internal/service/admin/waflog.go

@@ -0,0 +1,37 @@
+package admin
+
+import (
+	"context"
+	v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
+	admin "github.com/go-nunu/nunu-layout-advanced/api/v1/admin"
+	"github.com/go-nunu/nunu-layout-advanced/internal/model"
+	adminRep "github.com/go-nunu/nunu-layout-advanced/internal/repository/admin"
+	"github.com/go-nunu/nunu-layout-advanced/internal/service"
+)
+
+type WafLogService interface {
+	GetWafLog(ctx context.Context, id int64) (*model.Log, error)
+	GetWafLogList(ctx context.Context, req admin.SearchWafLogParams) (*v1.PaginatedResponse[model.Log], error)
+}
+func NewWafLogService(
+    service *service.Service,
+    wafLogRepository adminRep.WafLogRepository,
+) WafLogService {
+	return &wafLogService{
+		Service:        service,
+		wafLogRepository: wafLogRepository,
+	}
+}
+
+type wafLogService struct {
+	*service.Service
+	wafLogRepository adminRep.WafLogRepository
+}
+
+func (s *wafLogService) GetWafLog(ctx context.Context, id int64) (*model.Log, error) {
+	return s.wafLogRepository.GetWafLog(ctx, id)
+}
+
+func (s *wafLogService) GetWafLogList(ctx context.Context, req admin.SearchWafLogParams) (*v1.PaginatedResponse[model.Log], error) {
+	return s.wafLogRepository.GetWafLogList(ctx, req)
+}