diff --git a/model/notify_log.go b/model/notify_log.go index c80f926..5ae0fab 100644 --- a/model/notify_log.go +++ b/model/notify_log.go @@ -16,6 +16,7 @@ type NotifyLog struct { MessageType string `json:"message_type"` // 消息类型 MessageTitle string `json:"message_title"` // 消息标题 MessageContent string `json:"message_content"` // 消息内容 + Recipients string `json:"recipients"` // 收件人(仅邮件类型) Status int `json:"status"` // 发送状态:1成功,0失败 ErrorMsg string `json:"error_msg"` // 错误信息 SendTime string `json:"send_time"` // 发送时间 diff --git a/model/notify_subscription.go b/model/notify_subscription.go index 7ed5da2..01187fb 100644 --- a/model/notify_subscription.go +++ b/model/notify_subscription.go @@ -12,6 +12,7 @@ type NotifySubscription struct { baseorm.BaseOrm ChannelId string `json:"channel_id"` // 关联的渠道ID MessageType string `json:"message_type"` // 消息类型:user_login, attack_info, weekly_report等 + Recipients string `json:"recipients"` // 收件人列表(逗号分隔,主要用于邮件类型)留空则使用渠道默认收件人 Status int `json:"status"` // 状态:1启用,0禁用 FilterJSON string `json:"filter_json"` // 过滤条件(JSON格式) Remarks string `json:"remarks"` // 备注 diff --git a/model/request/waf_notify_subscription_req.go b/model/request/waf_notify_subscription_req.go index d84f320..f2306f4 100644 --- a/model/request/waf_notify_subscription_req.go +++ b/model/request/waf_notify_subscription_req.go @@ -4,6 +4,7 @@ package request type WafNotifySubscriptionAddReq struct { ChannelId string `json:"channel_id" binding:"required"` MessageType string `json:"message_type" binding:"required"` + Recipients string `json:"recipients"` Status int `json:"status"` FilterJSON string `json:"filter_json"` Remarks string `json:"remarks"` @@ -14,6 +15,7 @@ type WafNotifySubscriptionEditReq struct { Id string `json:"id" binding:"required"` ChannelId string `json:"channel_id" binding:"required"` MessageType string `json:"message_type" binding:"required"` + Recipients string `json:"recipients"` Status int `json:"status"` FilterJSON string `json:"filter_json"` Remarks string `json:"remarks"` diff --git a/service/waf_service/waf_notify_log.go b/service/waf_service/waf_notify_log.go index 4d6635c..abdb852 100644 --- a/service/waf_service/waf_notify_log.go +++ b/service/waf_service/waf_notify_log.go @@ -15,7 +15,7 @@ type WafNotifyLogService struct{} var WafNotifyLogServiceApp = new(WafNotifyLogService) // AddLog 添加通知日志 -func (receiver *WafNotifyLogService) AddLog(channelId, channelName, channelType, messageType, messageTitle, messageContent string, status int, errorMsg string) error { +func (receiver *WafNotifyLogService) AddLog(channelId, channelName, channelType, messageType, messageTitle, messageContent string, recipients string, status int, errorMsg string) error { var bean = &model.NotifyLog{ BaseOrm: baseorm.BaseOrm{ Id: uuid.GenUUID(), @@ -30,6 +30,7 @@ func (receiver *WafNotifyLogService) AddLog(channelId, channelName, channelType, MessageType: messageType, MessageTitle: messageTitle, MessageContent: messageContent, + Recipients: recipients, Status: status, ErrorMsg: errorMsg, SendTime: time.Now().Format("2006-01-02 15:04:05"), diff --git a/service/waf_service/waf_notify_sender.go b/service/waf_service/waf_notify_sender.go index 917d164..868ecce 100644 --- a/service/waf_service/waf_notify_sender.go +++ b/service/waf_service/waf_notify_sender.go @@ -10,6 +10,7 @@ import ( "SamWaf/wafnotify/feishu" "SamWaf/wafnotify/serverchan" "fmt" + "strings" ) type WafNotifySenderService struct{} @@ -35,8 +36,8 @@ func (receiver *WafNotifySenderService) SendNotification(messageType, title, con continue } - // 发送通知 - go receiver.sendToChannel(channel, messageType, title, content) + // 发送通知(传入subscription以支持订阅级收件人) + go receiver.sendToChannel(channel, subscription, messageType, title, content) } } @@ -46,10 +47,11 @@ func (receiver *WafNotifySenderService) getChannelById(channelId string, channel } // sendToChannel 发送到具体渠道 -func (receiver *WafNotifySenderService) sendToChannel(channel model.NotifyChannel, messageType, title, content string) { +func (receiver *WafNotifySenderService) sendToChannel(channel model.NotifyChannel, subscription model.NotifySubscription, messageType, title, content string) { var err error status := 1 errorMsg := "" + recipients := "" // 用于记录实际使用的收件人 switch channel.Type { case "dingtalk": @@ -63,6 +65,26 @@ func (receiver *WafNotifySenderService) sendToChannel(channel model.NotifyChanne if notifierErr != nil { err = notifierErr } else { + // 关键:支持订阅级别的收件人配置(向后兼容) + if subscription.Recipients != "" { + // 优先使用订阅中配置的收件人 + recipientList := strings.Split(subscription.Recipients, ",") + var trimmedRecipients []string + for _, r := range recipientList { + trimmed := strings.TrimSpace(r) + if trimmed != "" { + trimmedRecipients = append(trimmedRecipients, trimmed) + } + } + if len(trimmedRecipients) > 0 { + notifier.SetRecipients(trimmedRecipients) + recipients = strings.Join(trimmedRecipients, ", ") // 记录实际收件人 + } + } else { + // 使用渠道默认收件人(从notifier获取) + recipients = strings.Join(notifier.ToEmails, ", ") + } + // 如果订阅中没有配置收件人,则使用渠道配置中的收件人(向后兼容) err = notifier.SendMarkdown(title, content) } case "serverchan": @@ -90,6 +112,7 @@ func (receiver *WafNotifySenderService) sendToChannel(channel model.NotifyChanne messageType, title, content, + recipients, // 传递收件人信息 status, errorMsg, ) diff --git a/service/waf_service/waf_notify_subscription.go b/service/waf_service/waf_notify_subscription.go index 5abd6dc..b717ebf 100644 --- a/service/waf_service/waf_notify_subscription.go +++ b/service/waf_service/waf_notify_subscription.go @@ -26,6 +26,7 @@ func (receiver *WafNotifySubscriptionService) AddApi(req request.WafNotifySubscr }, ChannelId: req.ChannelId, MessageType: req.MessageType, + Recipients: req.Recipients, Status: req.Status, FilterJSON: req.FilterJSON, Remarks: req.Remarks, @@ -43,6 +44,7 @@ func (receiver *WafNotifySubscriptionService) ModifyApi(req request.WafNotifySub editMap := map[string]interface{}{ "ChannelId": req.ChannelId, "MessageType": req.MessageType, + "Recipients": req.Recipients, "Status": req.Status, "FilterJSON": req.FilterJSON, "Remarks": req.Remarks, @@ -90,7 +92,7 @@ func (receiver *WafNotifySubscriptionService) GetListApi(req request.WafNotifySu whereValues = append(whereValues, req.Status) } - global.GWAF_LOCAL_DB.Model(&model.NotifySubscription{}).Where(whereField, whereValues...).Limit(req.PageSize).Offset(req.PageSize * (req.PageIndex - 1)).Find(&list) + global.GWAF_LOCAL_DB.Model(&model.NotifySubscription{}).Where(whereField, whereValues...).Limit(req.PageSize).Order("create_time desc").Offset(req.PageSize * (req.PageIndex - 1)).Find(&list) global.GWAF_LOCAL_DB.Model(&model.NotifySubscription{}).Where(whereField, whereValues...).Count(&total) return list, total, nil diff --git a/wafdb/migrations_core.go b/wafdb/migrations_core.go index b4e68ee..c10ad0b 100644 --- a/wafdb/migrations_core.go +++ b/wafdb/migrations_core.go @@ -483,6 +483,34 @@ func RunCoreDBMigrations(db *gorm.DB) error { return nil }, }, + // 迁移13: 为 notify_subscription 表添加 recipients 字段(订阅级收件人) + { + ID: "202601300001_add_notify_subscription_recipients", + Migrate: func(tx *gorm.DB) error { + zlog.Info("迁移 202601300001: 为 notify_subscription 表添加 recipients 字段") + + // 检查字段是否已存在 + if tx.Migrator().HasColumn(&model.NotifySubscription{}, "recipients") { + zlog.Info("recipients 字段已存在,跳过添加") + return nil + } + + // 添加字段,默认值为空字符串(表示使用渠道默认收件人) + if err := tx.Migrator().AddColumn(&model.NotifySubscription{}, "recipients"); err != nil { + return fmt.Errorf("添加 recipients 字段失败: %w", err) + } + + zlog.Info("recipients 字段添加成功(空值时将使用渠道配置的默认收件人,保持向后兼容)") + return nil + }, + Rollback: func(tx *gorm.DB) error { + zlog.Info("回滚 202601300001: 删除 notify_subscription 表的 recipients 字段") + if tx.Migrator().HasColumn(&model.NotifySubscription{}, "recipients") { + return tx.Migrator().DropColumn(&model.NotifySubscription{}, "recipients") + } + return nil + }, + }, }) // 执行迁移 diff --git a/wafdb/migrations_log.go b/wafdb/migrations_log.go index d80ad2f..8068c5e 100644 --- a/wafdb/migrations_log.go +++ b/wafdb/migrations_log.go @@ -108,6 +108,34 @@ func RunLogDBMigrations(db *gorm.DB) error { ) }, }, + // 迁移4: 为 notify_log 表添加 recipients 字段(记录邮件收件人) + { + ID: "202601300002_add_notify_log_recipients", + Migrate: func(tx *gorm.DB) error { + zlog.Info("迁移 202601300002: 为 notify_log 表添加 recipients 字段") + + // 检查字段是否已存在 + if tx.Migrator().HasColumn(&model.NotifyLog{}, "recipients") { + zlog.Info("recipients 字段已存在,跳过添加") + return nil + } + + // 添加字段 + if err := tx.Migrator().AddColumn(&model.NotifyLog{}, "recipients"); err != nil { + return fmt.Errorf("添加 recipients 字段失败: %w", err) + } + + zlog.Info("recipients 字段添加成功(用于记录邮件通知的实际收件人)") + return nil + }, + Rollback: func(tx *gorm.DB) error { + zlog.Info("回滚 202601300002: 删除 notify_log 表的 recipients 字段") + if tx.Migrator().HasColumn(&model.NotifyLog{}, "recipients") { + return tx.Migrator().DropColumn(&model.NotifyLog{}, "recipients") + } + return nil + }, + }, }) // 执行迁移 diff --git a/wafnotify/email/email.go b/wafnotify/email/email.go index 6318965..d8be4ce 100644 --- a/wafnotify/email/email.go +++ b/wafnotify/email/email.go @@ -79,6 +79,13 @@ func NewEmailNotifier(configJSON string) (*EmailNotifier, error) { }, nil } +// SetRecipients 设置收件人(用于订阅级别的收件人配置) +func (e *EmailNotifier) SetRecipients(recipients []string) { + if len(recipients) > 0 { + e.ToEmails = recipients + } +} + // SendMarkdown 发送Markdown格式消息(转换为HTML) func (e *EmailNotifier) SendMarkdown(title, content string) error { // 将Markdown格式转换为简单的HTML