Files
opsxsql/backend/app/services/audit_rule_sync.py
T
logan a9e214ef1a feat: 审核规则持久化到DB + 全面配置去硬编码化
- AuditRule模型: 新增code/config_json字段,支持规则编码和阈值参数持久化
- audit_engine_v2: _load_rules从DB读config_json覆盖默认config
- audit_rule_sync: 启动时自动从_RULE_REGISTRY同步规则到DB(239条)
- settings API: update后刷新query_service配置缓存
- query_service: MAX_ROWS/QUERY_TIMEOUT/MAX_QUERY_LENGTH/MAX_RESULT_MEMORY改为动态读取system_settings
- ticket_executor: SQL_TIMEOUT/REDIS_TIMEOUT/MONGO_TIMEOUT改为动态获取
- settings_seeds: 新增executor分组(sql/redis/mongo超时) + query_result_max_memory_mb
- audit_rule endpoint: 移除无效的AuditEngine缓存清理(每次audit是新实例)
- 测试: 1057 passed(修复所有新引入失败,17个历史遗留)
2026-05-25 02:29:52 +08:00

80 lines
3.3 KiB
Python
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.
"""审核规则自动同步到数据库。
启动时从 _RULE_REGISTRY 提取所有注册规则,同步到 audit_rules 表:
- 新增规则 → INSERT
- 已有规则 → UPDATE severity/config_json/is_enabled(保留用户自定义覆盖)
- 不再存在的规则 → 不删除(保留历史数据)
"""
import json
import logging
from typing import Any, Dict, List
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
logger = logging.getLogger(__name__)
async def sync_rules_to_db(db: AsyncSession) -> int:
"""将注册表中的规则同步到数据库。返回同步数量。"""
from app.services.audit_engine_v2 import _RULE_REGISTRY, RuleCategory, Severity
synced = 0
for code, (default_rule, _func) in _RULE_REGISTRY.items():
# 查找已有记录(按 code 或 name)
from app.models.audit_rule import AuditRule
stmt = select(AuditRule).where(AuditRule.code == code)
result = await db.execute(stmt)
existing = result.scalar_one_or_none()
if existing is None:
# 按 name 兼容查找
stmt2 = select(AuditRule).where(AuditRule.name == default_rule.name)
result2 = await db.execute(stmt2)
existing = result2.scalar_one_or_none()
config_json_str = json.dumps(default_rule.config, ensure_ascii=False) if default_rule.config else None
category = default_rule.category.value if isinstance(default_rule.category, RuleCategory) else str(default_rule.category)
severity = default_rule.severity.value if isinstance(default_rule.severity, Severity) else str(default_rule.severity)
if existing is None:
# 新增
new_rule = AuditRule(
code=code,
name=default_rule.name,
description=default_rule.description,
rule_type=category,
severity=severity,
db_type=default_rule.db_type,
pattern=default_rule.pattern,
value=None,
config_json=config_json_str,
is_enabled=default_rule.is_enabled,
message=default_rule.message_template,
)
db.add(new_rule)
synced += 1
else:
# 已有:更新 code 和 description(保留用户自定义的 severity/enabled/config)
needs_update = False
if existing.code is None:
existing.code = code
needs_update = True
if existing.description != default_rule.description and existing.description is None:
existing.description = default_rule.description
needs_update = True
if existing.message != default_rule.message_template and existing.message is None:
existing.message = default_rule.message_template
needs_update = True
# 仅在 config_json 为空时初始化(首次同步)
if existing.config_json is None and config_json_str:
existing.config_json = config_json_str
needs_update = True
if needs_update:
synced += 1
await db.commit()
if synced > 0:
logger.info(f"审核规则同步完成: {synced} 条更新")
return synced