Files
lijiaoqiao/supply-api/internal/audit/model/alert.go
Your Name d5b5a8ece0 fix: 系统性修复安全问题、性能问题和错误处理
安全问题修复:
- X-Forwarded-For越界检查(auth.go)
- checkTokenStatus Context参数传递(auth.go)
- Type Assertion安全检查(auth.go)

性能问题修复:
- TokenCache过期清理机制
- BruteForceProtection过期清理
- InMemoryIdempotencyStore过期清理

错误处理修复:
- AuditStore.Emit返回error
- domain层emitAudit辅助方法
- List方法返回空slice而非nil
- 金额/价格负数验证

架构一致性:
- 统一使用model.RoleHierarchyLevels

新增功能:
- Alert API完整实现(CRUD+Resolve)
- pkg/error错误码集中管理
2026-04-07 07:41:25 +08:00

196 lines
5.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package model
import (
"time"
"github.com/google/uuid"
)
// 告警级别常量
const (
AlertLevelInfo = "info"
AlertLevelWarning = "warning"
AlertLevelError = "error"
AlertLevelCritical = "critical"
)
// 告警状态常量
const (
AlertStatusActive = "active"
AlertStatusResolved = "resolved"
AlertStatusAcknowledged = "acknowledged"
AlertStatusSuppressed = "suppressed"
)
// 告警类型常量
const (
AlertTypeSecurity = "security"
AlertTypeInvariant = "invariant"
AlertTypeCredential = "credential"
AlertTypeAuthentication = "authentication"
AlertTypeAuthorization = "authorization"
AlertTypeQuota = "quota"
)
// Alert 告警
type Alert struct {
// 基础标识
AlertID string `json:"alert_id"` // 告警唯一ID
AlertName string `json:"alert_name"` // 告警名称
AlertType string `json:"alert_type"` // 告警类型 (security/invariant/credential/etc.)
AlertLevel string `json:"alert_level"` // 告警级别 (info/warning/error/critical)
TenantID int64 `json:"tenant_id"` // 租户ID
SupplierID int64 `json:"supplier_id,omitempty"` // 供应商ID可选
// 告警内容
Title string `json:"title"` // 告警标题
Message string `json:"message"` // 告警消息
Description string `json:"description,omitempty"` // 详细描述
// 关联事件
EventID string `json:"event_id,omitempty"` // 关联的事件ID
EventIDs []string `json:"event_ids,omitempty"` // 关联的事件ID列表多个
// 触发条件
TriggerCondition string `json:"trigger_condition,omitempty"` // 触发条件
Threshold float64 `json:"threshold,omitempty"` // 阈值
CurrentValue float64 `json:"current_value,omitempty"` // 当前值
// 状态
Status string `json:"status"` // 状态 (active/resolved/acknowledged/suppressed)
ResolvedAt *time.Time `json:"resolved_at,omitempty"` // 解决时间
ResolvedBy string `json:"resolved_by,omitempty"` // 解决人
ResolveNote string `json:"resolve_note,omitempty"` // 解决备注
// 通知
NotifyEnabled bool `json:"notify_enabled"` // 是否启用通知
NotifyChannels []string `json:"notify_channels,omitempty"` // 通知渠道 (email/sms/webhook/etc.)
// 时间戳
CreatedAt time.Time `json:"created_at"` // 创建时间
UpdatedAt time.Time `json:"updated_at"` // 更新时间
FirstSeenAt time.Time `json:"first_seen_at"` // 首次出现时间
LastSeenAt time.Time `json:"last_seen_at"` // 最后出现时间
// 元数据
Metadata map[string]any `json:"metadata,omitempty"` // 扩展元数据
Tags []string `json:"tags,omitempty"` // 标签
}
// NewAlert 创建新告警
func NewAlert(alertName, alertType, alertLevel, tenantID string, title, message string) *Alert {
now := time.Now()
return &Alert{
AlertID: generateAlertID(),
AlertName: alertName,
AlertType: alertType,
AlertLevel: alertLevel,
TenantID: parseTenantID(tenantID),
Title: title,
Message: message,
Status: AlertStatusActive,
NotifyEnabled: true,
CreatedAt: now,
UpdatedAt: now,
FirstSeenAt: now,
LastSeenAt: now,
Metadata: make(map[string]any),
Tags: []string{},
}
}
// generateAlertID 生成告警ID
func generateAlertID() string {
return "ALT-" + uuid.New().String()[:8]
}
// parseTenantID 解析租户ID
func parseTenantID(tenantID string) int64 {
var id int64
for _, c := range tenantID {
if c >= '0' && c <= '9' {
id = id*10 + int64(c-'0')
}
}
return id
}
// IsActive 检查告警是否处于活跃状态
func (a *Alert) IsActive() bool {
return a.Status == AlertStatusActive
}
// IsResolved 检查告警是否已解决
func (a *Alert) IsResolved() bool {
return a.Status == AlertStatusResolved
}
// Resolve 解决告警
func (a *Alert) Resolve(resolvedBy, note string) {
now := time.Now()
a.Status = AlertStatusResolved
a.ResolvedAt = &now
a.ResolvedBy = resolvedBy
a.ResolveNote = note
a.UpdatedAt = now
}
// Acknowledge 确认告警
func (a *Alert) Acknowledge() {
a.Status = AlertStatusAcknowledged
a.UpdatedAt = time.Now()
}
// Suppress 抑制告警
func (a *Alert) Suppress() {
a.Status = AlertStatusSuppressed
a.UpdatedAt = time.Now()
}
// UpdateLastSeen 更新最后出现时间
func (a *Alert) UpdateLastSeen() {
a.LastSeenAt = time.Now()
a.UpdatedAt = time.Now()
}
// AddEventID 添加关联事件ID
func (a *Alert) AddEventID(eventID string) {
a.EventIDs = append(a.EventIDs, eventID)
if a.EventID == "" {
a.EventID = eventID
}
a.UpdateLastSeen()
}
// SetMetadata 设置元数据
func (a *Alert) SetMetadata(key string, value any) {
if a.Metadata == nil {
a.Metadata = make(map[string]any)
}
a.Metadata[key] = value
}
// AddTag 添加标签
func (a *Alert) AddTag(tag string) {
for _, t := range a.Tags {
if t == tag {
return
}
}
a.Tags = append(a.Tags, tag)
}
// AlertFilter 告警查询过滤器
type AlertFilter struct {
TenantID int64
SupplierID int64
AlertType string
AlertLevel string
Status string
StartTime time.Time
EndTime time.Time
Keywords string // 关键字搜索(标题/消息)
Limit int
Offset int
}