123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- package admin
- import (
- "context"
- "fmt"
- v1 "github.com/go-nunu/nunu-layout-advanced/api/v1"
- adminApi "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"
- "time"
- )
- type WafLogRepository interface {
- GetWafLog(ctx context.Context, id int64) (*model.WafLog, error)
- GetWafLogList(ctx context.Context, req adminApi.SearchWafLogParams) (*v1.PaginatedResponse[model.WafLog], error)
- AddWafLog(ctx context.Context, log *model.WafLog) error
- BatchAddWafLog(ctx context.Context, logs []*model.WafLog) error
- // 导出日志
- ExportWafLog(ctx context.Context, req adminApi.ExportWafLog) ([]model.WafLog, error)
- // 支持分页的导出方法
- ExportWafLogWithPagination(ctx context.Context, req adminApi.ExportWafLog, page, pageSize int) ([]model.WafLog, error)
- // 获取导出数据总数
- GetWafLogExportCount(ctx context.Context, req adminApi.ExportWafLog) (int, error)
- // 获取网关组记录
- GetWafLogGateWayIp(ctx context.Context, hostId int64, Uid int64,createdAt time.Time) (model.WafLog, error)
- // 批量获取网关组记录
- BatchGetWafLogGateWayIps(ctx context.Context, hostIds []int64, uids []int64, maxCreatedAt time.Time) (map[string]model.WafLog, 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.WafLog, error) {
- var res model.WafLog
- return &res, r.DBWithName(ctx,"admin").Where("id = ?", id).First(&res).Error
- }
- func (r *wafLogRepository) GetWafLogList(ctx context.Context, req adminApi.SearchWafLogParams) (*v1.PaginatedResponse[model.WafLog], error) {
- var res []model.WafLog
- var total int64
- query := r.DBWithName(ctx,"admin").Model(&model.WafLog{})
- 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.Name != "" {
- trimmedName := strings.TrimSpace(req.Name)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("name LIKE CONCAT('%', ?, '%')", trimmedName)
- }
- if req.RuleId != 0 {
- query = query.Where("rule_id = ?", req.RuleId)
- }
- if req.HostId != 0 {
- query = query.Where("host_id = ?", req.HostId)
- }
- if req.Api != "" {
- trimmedName := strings.TrimSpace(req.Api)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("api LIKE CONCAT('%', ?, '%')", trimmedName)
- }
- if req.UserAgent != "" {
- trimmedName := strings.TrimSpace(req.UserAgent)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("user_agent LIKE CONCAT('%', ?, '%')", trimmedName)
- }
- if req.ApiName != "" {
- trimmedName := strings.TrimSpace(req.ApiName)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("api_name LIKE CONCAT('%', ?, '%')", trimmedName)
- }
- if req.ApiType != "" {
- query = query.Where("api_type = ?", req.ApiType)
- }
- if req.Column != "" {
- query = query.Order(req.Column + " " + 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.WafLog]{
- Records: res,
- Page: page,
- PageSize: pageSize,
- Total: total,
- TotalPages: int(math.Ceil(float64(total) / float64(pageSize))),
- }, nil
- }
- func (r *wafLogRepository) AddWafLog(ctx context.Context, log *model.WafLog) error {
- return r.DBWithName(ctx,"admin").Create(log).Error
- }
- func (r *wafLogRepository) BatchAddWafLog(ctx context.Context, logs []*model.WafLog) error {
- if len(logs) == 0 {
- return nil
- }
- return r.DBWithName(ctx, "admin").CreateInBatches(logs, len(logs)).Error
- }
- func (r *wafLogRepository) ExportWafLog(ctx context.Context, req adminApi.ExportWafLog) ([]model.WafLog, error) {
- return r.ExportWafLogWithPagination(ctx, req, 0, 0)
- }
- // ExportWafLogWithPagination 支持分页的导出方法
- func (r *wafLogRepository) ExportWafLogWithPagination(ctx context.Context, req adminApi.ExportWafLog, page, pageSize int) ([]model.WafLog, error) {
- var res []model.WafLog
- query := r.DBWithName(ctx,"admin").Model(&model.WafLog{})
- if req.RequestIp != "" {
- trimmedName := strings.TrimSpace(req.RequestIp)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("request_ip = ?", trimmedName)
- }
- if req.Uid != 0 {
- query = query.Where("uid = ?", req.Uid)
- }
- if req.Api != "" {
- trimmedName := strings.TrimSpace(req.Api)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("api = ?", trimmedName)
- }
- if req.Name != "" {
- trimmedName := strings.TrimSpace(req.Name)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("name = ?", trimmedName)
- }
- if req.RuleId != 0 {
- query = query.Where("rule_id = ?", req.RuleId)
- }
- if len(req.HostIds) > 0 {
- query = query.Where("host_id IN ?", req.HostIds)
- }
- if req.Api != "" {
- trimmedName := strings.TrimSpace(req.Api)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("api = ?", trimmedName)
- }
- if req.UserAgent != "" {
- trimmedName := strings.TrimSpace(req.UserAgent)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("user_agent = ?", trimmedName)
- }
- if len(req.ApiNames) > 0 {
- trimmedNames := make([]string, len(req.ApiNames))
- for _, apiName := range req.ApiNames {
- trimmedNames = append(trimmedNames, strings.TrimSpace(apiName))
- }
- // 使用 LIKE 进行模糊匹配
- query = query.Where("api_name IN ?", trimmedNames)
- }
- if len(req.ApiTypes) > 0 {
- query = query.Where("api_type IN ?", req.ApiTypes)
- }
- if req.StartTime != "" {
- trimmedName := strings.TrimSpace(req.StartTime)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("created_at > ?", trimmedName)
- }
- if req.EndTime != "" {
- trimmedName := strings.TrimSpace(req.EndTime)
- // 使用 LIKE 进行模糊匹配
- query = query.Where("created_at < ?", trimmedName)
- }
- // 添加分页逻辑
- if page > 0 && pageSize > 0 {
- offset := (page - 1) * pageSize
- query = query.Offset(offset).Limit(pageSize)
- }
- result := query.Find(&res)
- if result.Error != nil {
- return nil, result.Error
- }
- return res, nil
- }
- // GetWafLogExportCount 获取导出数据总数
- func (r *wafLogRepository) GetWafLogExportCount(ctx context.Context, req adminApi.ExportWafLog) (int, error) {
- var count int64
- query := r.DBWithName(ctx,"admin").Model(&model.WafLog{})
-
- // 复用ExportWafLog的查询条件
- if req.RequestIp != "" {
- trimmedName := strings.TrimSpace(req.RequestIp)
- query = query.Where("request_ip = ?", trimmedName)
- }
- if req.Uid != 0 {
- query = query.Where("uid = ?", req.Uid)
- }
- if req.Api != "" {
- trimmedName := strings.TrimSpace(req.Api)
- query = query.Where("api = ?", trimmedName)
- }
- if req.Name != "" {
- trimmedName := strings.TrimSpace(req.Name)
- query = query.Where("name = ?", trimmedName)
- }
- if req.RuleId != 0 {
- query = query.Where("rule_id = ?", req.RuleId)
- }
- if len(req.HostIds) > 0 {
- query = query.Where("host_id IN ?", req.HostIds)
- }
- if req.UserAgent != "" {
- trimmedName := strings.TrimSpace(req.UserAgent)
- query = query.Where("user_agent = ?", trimmedName)
- }
- if len(req.ApiNames) > 0 {
- trimmedNames := make([]string, len(req.ApiNames))
- for _, apiName := range req.ApiNames {
- trimmedNames = append(trimmedNames, strings.TrimSpace(apiName))
- }
- query = query.Where("api_name IN ?", trimmedNames)
- }
- if len(req.ApiTypes) > 0 {
- query = query.Where("api_type IN ?", req.ApiTypes)
- }
- if req.StartTime != "" {
- trimmedName := strings.TrimSpace(req.StartTime)
- query = query.Where("created_at > ?", trimmedName)
- }
- if req.EndTime != "" {
- trimmedName := strings.TrimSpace(req.EndTime)
- query = query.Where("created_at < ?", trimmedName)
- }
- result := query.Count(&count)
- if result.Error != nil {
- return 0, result.Error
- }
- return int(count), nil
- }
- func (r *wafLogRepository) GetWafLogGateWayIp(ctx context.Context, hostId int64, Uid int64,createdAt time.Time) (model.WafLog, error) {
- var res model.WafLog
- return res, r.DBWithName(ctx,"admin").Where("host_id = ? and uid = ? and api_name = ? and created_at < ? ", hostId, Uid, "分配网关组", createdAt).First(&res).Error
- }
- // BatchGetWafLogGateWayIps 批量获取网关组记录,避免N+1查询问题
- func (r *wafLogRepository) BatchGetWafLogGateWayIps(ctx context.Context, hostIds []int64, uids []int64, maxCreatedAt time.Time) (map[string]model.WafLog, error) {
- if len(hostIds) == 0 || len(uids) == 0 {
- return make(map[string]model.WafLog), nil
- }
- var gateWayLogs []model.WafLog
-
- // 构建查询条件,获取所有相关的网关组记录
- query := r.DBWithName(ctx, "admin").
- Where("api_name = ?", "分配网关组").
- Where("created_at < ?", maxCreatedAt)
-
- // 如果hostIds和uids数量较少,使用IN查询
- if len(hostIds) <= 1000 && len(uids) <= 1000 {
- query = query.Where("host_id IN ? AND uid IN ?", hostIds, uids)
- }
-
- // 按创建时间倒序,确保获取最新的网关组配置
- err := query.Order("created_at DESC").Find(&gateWayLogs).Error
- if err != nil {
- return nil, err
- }
- // 构建映射表,key为"hostId_uid",value为最新的网关组记录
- result := make(map[string]model.WafLog)
- for _, log := range gateWayLogs {
- key := fmt.Sprintf("%d_%d", log.HostId, log.Uid)
- // 由于已经按创建时间倒序排列,第一次遇到的就是最新的记录
- if _, exists := result[key]; !exists {
- result[key] = log
- }
- }
- return result, nil
- }
|