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:
attacker committed 2026-06-25 20:16:30 +08:00
1 parent e57718998a
commit 77c234b060
314 files changed
+10050 -4065

No files matched your search

+146
View File
@@ -0,0 +1,146 @@
#!/usr/bin/env python3
"""
AIOps Integration Tests
python3 tests/integration_test.py [--host HOST] [--port PORT]
"""
import urllib.request, urllib.error, json, sys, time, argparse
parser = argparse.ArgumentParser()
parser.add_argument("--host", default="localhost")
parser.add_argument("--port", default="80")
args = parser.parse_args()
BASE = "http://{}:{}".format(args.host, args.port)
TOKEN = ""
PASSED = 0
FAILED = 0
def api(method, path, body=None, auth=True):
url = BASE + path
data = json.dumps(body).encode() if body else None
req = urllib.request.Request(url, data=data, method=method)
req.add_header("Content-Type", "application/json")
if auth and TOKEN:
req.add_header("Authorization", "Bearer " + TOKEN)
try:
resp = urllib.request.urlopen(req, timeout=10)
return resp.status, json.loads(resp.read())
except urllib.error.HTTPError as e:
try:
return e.code, json.loads(e.read().decode())
except:
return e.code, {}
except Exception as e:
return 0, {"error": str(e)[:100]}
def check(name, status, detail=""):
global PASSED, FAILED
ok = 200 <= status < 300
mark = "PASS" if ok else "FAIL"
if ok: PASSED += 1
else: FAILED += 1
d = str(detail)[:80] if detail else ""
print(" [{}] {}: HTTP {} {}".format(mark, name, status, d))
return ok
print("\n" + "=" * 60)
print("AIOps Integration Tests — " + BASE)
print("=" * 60)
# [1] Health
print("\n[1] Basic checks")
s, d = api("GET", "/health", auth=False)
check("Health check", s)
s, d = api("GET", "/version", auth=False)
check("Version API ", s)
# [2] Login
print("\n[2] Authentication")
s, d = api("POST", "/api/v1/auth/login",
body={"username": "admin", "password": "123456"}, auth=False)
if check("Login ", s):
TOKEN = d.get("data", {}).get("token", "")
if TOKEN:
print(" [INFO] Token: " + TOKEN[:40] + "...")
else:
print(" [WARN] No token in response")
FAILED += 1
if not TOKEN:
print("[SKIP] No auth token, skipping authenticated tests\n")
print("=" * 60)
print("Result: {} passed, {} failed".format(PASSED, FAILED))
print("=" * 60)
sys.exit(1)
# [3] User
print("\n[3] Users")
s, d = api("GET", "/api/v1/admin/users")
check("Profile ", s)
s, d = api("GET", "/api/v1/admin/users")
check("Admin users ", s)
# [4] Dashboard
print("\n[4] Dashboard")
s, d = api("GET", "/api/v1/dashboard/stats")
check("Stats ", s)
s, d = api("GET", "/api/v1/dashboard/recent-alerts")
check("Recent alert", s)
# [5] Servers
print("\n[5] Servers")
s, d = api("GET", "/api/v1/servers")
check("List ", s)
s, d = api("GET", "/api/v1/servers/stats")
check("Stats ", s)
# Create + Delete
name = "test-" + str(int(time.time()))
s, d = api("POST", "/api/v1/servers", body={
"name": name, "hostname": "test.local",
"ip": "10.0.0.99", "port": 22,
"os_type": "Ubuntu", "status": "offline"
})
if check("Create ", s):
sid = d.get("data", {}).get("id", 0)
if sid:
s, d = api("GET", "/api/v1/servers/" + str(sid))
check("Get by ID ", s)
s, d = api("DELETE", "/api/v1/servers/" + str(sid))
check("Delete ", s)
# [6] Navigation
print("\n[6] Navigation")
s, d = api("GET", "/api/v1/navigations/groups")
check("Tree ", s)
# [7] Credentials
print("\n[7] Credentials")
s, d = api("GET", "/api/v1/credentials")
check("List ", s)
# [8] Pipelines
print("\n[8] Pipelines")
s, d = api("GET", "/api/v1/pipelines")
check("List ", s)
# [9] Environments
print("\n[9] Deploy Environments")
s, d = api("GET", "/api/v1/deploy/environments")
check("List ", s)
# [10] Roles
print("\n[10] Roles")
s, d = api("GET", "/api/v1/admin/roles")
check("Roles ", s)
# Summary
total = PASSED + FAILED
print("\n" + "=" * 60)
print("Result: {}/{} passed, {} failed".format(PASSED, total, FAILED))
if FAILED == 0:
print("ALL TESTS PASSED!")
else:
print("WARNING: {} failures".format(FAILED))
print("=" * 60 + "\n")
sys.exit(0 if FAILED == 0 else 1)