feat(audit): F1+F2 告警静默规则标记完成 + 审计日志CSV导出实现
F1 告警静默规则 [done]: - 后端 alert_silence.go: CRUD + Toggle (onetime/daily/weekly 三模式) - 告警引擎 isSilenced 集成 (alert_engine.go) - 前端 SilenceRuleTab + SilenceDialog - 路由 /alerts/silences 已注册 F2 审计日志导出 [done]: - 重写 ExportAuditLogs: 真正的 CSV 导出 (encoding/csv + UTF-8 BOM) - 支持 module/action/username/startTime/endTime 筛选 - 导出限制 10000 条防溢出,自动记录审计日志 - JSON 格式向后兼容 (format=json) - 前端 exportLogs 传递查询参数 同时包含累积的前期工作: - 目录重构 internal/ -> controller/model/router (v0.55-v0.57) - 后端分层架构 dto/repository/service/utils - 审计模块全功能 (终端审计/操作审计/登录日志) - asciicast v2 录制格式 - SFTP 文件浏览器 - StatStrip 紧凑统计条 - 在线会话自动刷新 - LiveMonitor WebSocket 诊断修复 验证: go build ✅ | npm run build ✅ | Docker 部署 ✅ | 10 回归端点 ✅ | CSV 导出 ✅ | 静默 CRUD ✅
This commit is contained in:
1 parent
e57718998a
commit
77c234b060
314 files changed
+10050
-4065
No files matched your search
@@ -0,0 +1,239 @@
|
||||
// Package repository 提供数据访问层 — 所有 DB 操作集中在此
|
||||
// Handler / Service 不直接操作 *gorm.DB
|
||||
package repository
|
||||
|
||||
import (
|
||||
"ezops/model"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// ━━━ Server Repository ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
type ServerRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewServerRepository(db *gorm.DB) *ServerRepository {
|
||||
return &ServerRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *ServerRepository) DB() *gorm.DB {
|
||||
return r.db
|
||||
}
|
||||
|
||||
// List 分页查询服务器列表
|
||||
func (r *ServerRepository) List(keyword, status, regionID string, page, pageSize int) ([]model.Server, int64, error) {
|
||||
q := r.db.Model(&model.Server{})
|
||||
if keyword != "" {
|
||||
q = q.Where("hostname LIKE ? OR ip LIKE ? OR public_ip LIKE ?",
|
||||
"%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%")
|
||||
}
|
||||
if status != "" {
|
||||
q = q.Where("status = ?", status)
|
||||
}
|
||||
if regionID != "" {
|
||||
q = q.Where("region_id = ?", regionID)
|
||||
}
|
||||
|
||||
var total int64
|
||||
q.Count(&total)
|
||||
|
||||
var list []model.Server
|
||||
err := q.Preload("Region").Preload("Cloud").
|
||||
Offset((page - 1) * pageSize).Limit(pageSize).
|
||||
Order("created_at DESC").Find(&list).Error
|
||||
|
||||
return list, total, err
|
||||
}
|
||||
|
||||
// GetByID 根据 ID 获取服务器
|
||||
func (r *ServerRepository) GetByID(id uint) (*model.Server, error) {
|
||||
var s model.Server
|
||||
err := r.db.Preload("Region").Preload("Cloud").First(&s, id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
// Create 创建服务器
|
||||
func (r *ServerRepository) Create(s *model.Server) error {
|
||||
return r.db.Create(s).Error
|
||||
}
|
||||
|
||||
// Update 更新服务器 (全量)
|
||||
func (r *ServerRepository) Update(s *model.Server) error {
|
||||
return r.db.Save(s).Error
|
||||
}
|
||||
|
||||
// UpdateFields 部分更新
|
||||
func (r *ServerRepository) UpdateFields(id uint, updates map[string]interface{}) error {
|
||||
return r.db.Model(&model.Server{}).Where("id = ?", id).Updates(updates).Error
|
||||
}
|
||||
|
||||
// Delete 删除服务器
|
||||
func (r *ServerRepository) Delete(id uint) error {
|
||||
return r.db.Delete(&model.Server{}, id).Error
|
||||
}
|
||||
|
||||
// CountByStatus 按状态统计
|
||||
func (r *ServerRepository) CountByStatus(status string) int64 {
|
||||
var c int64
|
||||
r.db.Model(&model.Server{}).Where("status = ?", status).Count(&c)
|
||||
return c
|
||||
}
|
||||
|
||||
// AvgMetric 获取平均指标
|
||||
func (r *ServerRepository) AvgMetric(field string) float64 {
|
||||
var v float64
|
||||
r.db.Model(&model.Server{}).Select("AVG(" + field + ")").Scan(&v)
|
||||
return v
|
||||
}
|
||||
|
||||
// ━━━ Credential Repository ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
type CredentialRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewCredentialRepository(db *gorm.DB) *CredentialRepository {
|
||||
return &CredentialRepository{db: db}
|
||||
}
|
||||
|
||||
// List 分页查询凭据
|
||||
func (r *CredentialRepository) List(keyword, secretType string, page, pageSize int) ([]model.Credential, int64, error) {
|
||||
q := r.db.Model(&model.Credential{})
|
||||
if keyword != "" {
|
||||
q = q.Where("name LIKE ?", "%"+keyword+"%")
|
||||
}
|
||||
if secretType != "" {
|
||||
q = q.Where("secret_type = ?", secretType)
|
||||
}
|
||||
|
||||
var total int64
|
||||
q.Count(&total)
|
||||
|
||||
var list []model.Credential
|
||||
err := q.Offset((page - 1) * pageSize).Limit(pageSize).
|
||||
Order("created_at DESC").Find(&list).Error
|
||||
|
||||
return list, total, err
|
||||
}
|
||||
|
||||
// GetByID 根据 ID 获取凭据
|
||||
func (r *CredentialRepository) GetByID(id uint) (*model.Credential, error) {
|
||||
var c model.Credential
|
||||
err := r.db.First(&c, id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
// Create 创建凭据
|
||||
func (r *CredentialRepository) Create(c *model.Credential) error {
|
||||
return r.db.Create(c).Error
|
||||
}
|
||||
|
||||
// Update 全量更新凭据
|
||||
func (r *CredentialRepository) Update(c *model.Credential) error {
|
||||
return r.db.Save(c).Error
|
||||
}
|
||||
|
||||
// UpdateFields 部分更新
|
||||
func (r *CredentialRepository) UpdateFields(id uint, updates map[string]interface{}) error {
|
||||
return r.db.Model(&model.Credential{}).Where("id = ?", id).Updates(updates).Error
|
||||
}
|
||||
|
||||
// Delete 删除凭据
|
||||
func (r *CredentialRepository) Delete(id uint) error {
|
||||
return r.db.Delete(&model.Credential{}, id).Error
|
||||
}
|
||||
|
||||
// ━━━ Alert Contact Repository ━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
type AlertContactRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewAlertContactRepository(db *gorm.DB) *AlertContactRepository {
|
||||
return &AlertContactRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *AlertContactRepository) List(keyword string, page, pageSize int) ([]model.AlertContact, int64, error) {
|
||||
q := r.db.Model(&model.AlertContact{})
|
||||
if keyword != "" {
|
||||
q = q.Where("name LIKE ?", "%"+keyword+"%")
|
||||
}
|
||||
var total int64
|
||||
q.Count(&total)
|
||||
var list []model.AlertContact
|
||||
err := q.Offset((page - 1) * pageSize).Limit(pageSize).
|
||||
Order("created_at DESC").Find(&list).Error
|
||||
return list, total, err
|
||||
}
|
||||
|
||||
func (r *AlertContactRepository) GetByID(id uint) (*model.AlertContact, error) {
|
||||
var c model.AlertContact
|
||||
err := r.db.First(&c, id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &c, nil
|
||||
}
|
||||
|
||||
func (r *AlertContactRepository) Create(c *model.AlertContact) error {
|
||||
return r.db.Create(c).Error
|
||||
}
|
||||
|
||||
func (r *AlertContactRepository) Update(c *model.AlertContact) error {
|
||||
return r.db.Save(c).Error
|
||||
}
|
||||
|
||||
func (r *AlertContactRepository) Delete(id uint) error {
|
||||
return r.db.Delete(&model.AlertContact{}, id).Error
|
||||
}
|
||||
|
||||
// AlertContactGroup Repository
|
||||
type AlertContactGroupRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewAlertContactGroupRepository(db *gorm.DB) *AlertContactGroupRepository {
|
||||
return &AlertContactGroupRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *AlertContactGroupRepository) List(keyword string, page, pageSize int) ([]model.AlertContactGroup, int64, error) {
|
||||
q := r.db.Model(&model.AlertContactGroup{})
|
||||
if keyword != "" {
|
||||
q = q.Where("group_name LIKE ?", "%"+keyword+"%")
|
||||
}
|
||||
var total int64
|
||||
q.Count(&total)
|
||||
var list []model.AlertContactGroup
|
||||
err := q.Offset((page - 1) * pageSize).Limit(pageSize).
|
||||
Order("created_at DESC").Find(&list).Error
|
||||
return list, total, err
|
||||
}
|
||||
|
||||
func (r *AlertContactGroupRepository) GetByID(id uint) (*model.AlertContactGroup, error) {
|
||||
var g model.AlertContactGroup
|
||||
err := r.db.First(&g, id).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &g, nil
|
||||
}
|
||||
|
||||
func (r *AlertContactGroupRepository) Create(g *model.AlertContactGroup) error {
|
||||
return r.db.Create(g).Error
|
||||
}
|
||||
|
||||
func (r *AlertContactGroupRepository) UpdateFields(id uint, updates map[string]interface{}) error {
|
||||
return r.db.Model(&model.AlertContactGroup{}).Where("id = ?", id).Updates(updates).Error
|
||||
}
|
||||
|
||||
func (r *AlertContactGroupRepository) Delete(id uint) error {
|
||||
return r.db.Delete(&model.AlertContactGroup{}, id).Error
|
||||
}
|
||||
Reference in new issue
Block a user