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个历史遗留)
This commit is contained in:
1 parent
ddf4856a85
commit
a9e214ef1a
11 files changed
+342
-62
No files matched your search
@@ -0,0 +1,79 @@
|
||||
"""审核规则自动同步到数据库。
|
||||
|
||||
启动时从 _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
|
||||
Reference in new issue
Block a user