- 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个历史遗留)
80 lines
3.3 KiB
Python
80 lines
3.3 KiB
Python
"""审核规则自动同步到数据库。
|
||
|
||
启动时从 _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
|