安全问题修复: - 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错误码集中管理
196 lines
5.3 KiB
Go
196 lines
5.3 KiB
Go
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
|
||
}
|