6d70520e79
- 新增后端模块:Alert、APIAsset、Compliance、Lineage、Masking、Risk、SchemaChange、Unstructured、Watermark - 新增前端模块页面与API接口 - 新增Alembic迁移脚本(002-014)覆盖全量业务表 - 新增测试数据生成脚本与集成测试脚本 - 修复metadata模型JSON类型导入缺失导致启动失败的问题 - 修复前端Alert/APIAsset页面request模块路径错误 - 更新docker-compose与开发计划文档
93 lines
3.4 KiB
Python
93 lines
3.4 KiB
Python
from typing import List, Optional
|
|
from sqlalchemy.orm import Session
|
|
from datetime import datetime
|
|
|
|
from app.models.alert import AlertRule, AlertRecord, WorkOrder
|
|
from app.models.project import ClassificationProject, ClassificationResult
|
|
from app.models.risk import RiskAssessment
|
|
|
|
|
|
def init_builtin_alert_rules(db: Session):
|
|
if db.query(AlertRule).first():
|
|
return
|
|
rules = [
|
|
AlertRule(name="L5字段数量突增", trigger_condition="l5_count", threshold=5, severity="high"),
|
|
AlertRule(name="项目风险分过高", trigger_condition="risk_score", threshold=80, severity="critical"),
|
|
AlertRule(name="Schema新增敏感字段", trigger_condition="schema_change", threshold=1, severity="medium"),
|
|
]
|
|
for r in rules:
|
|
db.add(r)
|
|
db.commit()
|
|
|
|
|
|
def check_alerts(db: Session) -> List[AlertRecord]:
|
|
"""Run alert checks and create records."""
|
|
rules = db.query(AlertRule).filter(AlertRule.is_active == True).all()
|
|
records = []
|
|
for rule in rules:
|
|
if rule.trigger_condition == "l5_count":
|
|
projects = db.query(ClassificationProject).all()
|
|
for p in projects:
|
|
l5_count = db.query(ClassificationResult).filter(
|
|
ClassificationResult.project_id == p.id,
|
|
ClassificationResult.level_id.isnot(None),
|
|
).join(ClassificationResult.level).filter(
|
|
ClassificationResult.level.has(code="L5")
|
|
).count()
|
|
if l5_count >= rule.threshold:
|
|
rec = AlertRecord(
|
|
rule_id=rule.id,
|
|
title=f"项目 {p.name} L5字段数量达到 {l5_count}",
|
|
content=f"阈值: {rule.threshold}",
|
|
severity=rule.severity,
|
|
)
|
|
db.add(rec)
|
|
records.append(rec)
|
|
elif rule.trigger_condition == "risk_score":
|
|
risks = db.query(RiskAssessment).filter(
|
|
RiskAssessment.entity_type == "project",
|
|
RiskAssessment.risk_score >= rule.threshold,
|
|
).all()
|
|
for rsk in risks:
|
|
rec = AlertRecord(
|
|
rule_id=rule.id,
|
|
title=f"项目 {rsk.entity_name} 风险分 {rsk.risk_score}",
|
|
content=f"阈值: {rule.threshold}",
|
|
severity=rule.severity,
|
|
)
|
|
db.add(rec)
|
|
records.append(rec)
|
|
db.commit()
|
|
return records
|
|
|
|
|
|
def create_work_order(db: Session, alert_id: int, title: str, description: str, assignee_id: Optional[int] = None) -> WorkOrder:
|
|
wo = WorkOrder(
|
|
alert_id=alert_id,
|
|
title=title,
|
|
description=description,
|
|
assignee_id=assignee_id,
|
|
)
|
|
db.add(wo)
|
|
db.commit()
|
|
db.refresh(wo)
|
|
return wo
|
|
|
|
|
|
def update_work_order_status(db: Session, wo_id: int, status: str, resolution: str = None) -> WorkOrder:
|
|
wo = db.query(WorkOrder).filter(WorkOrder.id == wo_id).first()
|
|
if wo:
|
|
wo.status = status
|
|
if resolution:
|
|
wo.resolution = resolution
|
|
if status == "resolved":
|
|
wo.resolved_at = datetime.utcnow()
|
|
# Also resolve linked alert
|
|
if wo.alert_id:
|
|
alert = db.query(AlertRecord).filter(AlertRecord.id == wo.alert_id).first()
|
|
if alert:
|
|
alert.status = "resolved"
|
|
db.commit()
|
|
db.refresh(wo)
|
|
return wo
|