"""审核规则自动同步到数据库。 启动时从 _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