fix(alerts): scope check-timeout batch upgrade by KPIAlert.entity_id

GET /api/cma/alerts/check-timeout picked candidates via the join on KPIDefinition.entity_id, so a session could batch-upgrade (red + processing) alert rows whose own entity_id belongs to another account. Switch the filter to the alert row's own entity_id, drop the now-unneeded join and the unused KPIDefinition import. Write path only; no data change, candidate ids on consistent rows are identical before/after.

Derived from dama-20260919-cma-alert-filter-and-cash-baseline-fix (C1/C2 residual in the write endpoint).
This commit is contained in:
Hermes CI Fix
2026-09-19 08:35:25 +08:00
parent 4225332aaf
commit d785a22efd
+9 -4
View File
@@ -5,7 +5,7 @@ from sqlalchemy.orm import Session
from app.database import get_db
from app.deps import get_entity_id, assert_entity_slug_scope, resolve_session_slug
from app.auth_middleware import require_auth, require_role
from app.models import KPIAlert, OperationLog, ActionPlan, KPIDefinition
from app.models import KPIAlert, OperationLog, ActionPlan
import logging
logger = logging.getLogger("cma.alerts")
@@ -94,11 +94,16 @@ def escalate_alert(alert_id: int, data: dict, db: Session = Depends(get_db), ent
@router.get("/check-timeout")
def check_alert_timeout(db: Session = Depends(get_db), entity_id: int = Depends(get_entity_id)):
"""超时预警检测 — 超过24小时未处理的pending预警自动升级为红色
(账套隔离: join kpi_definitions 按企业过滤, 2026-09-18 — 原为全账套批处理)"""
账套隔离(2026-09-19 写路径跨账套修复):按**预警行自身** KPIAlert.entity_id 过滤;
修复前 join kpi_definitions 按 KPI 归属企业过滤 → KPI 属他账套而预警行属本账套的行
会被本账套调用**批量改写**(升级 red + 置 processing),比只读泄漏更严重
(2026-08 之前为全账套批处理;2026-09-18 加的 join 口径见 dama-20260919 派生单)。
"""
from datetime import datetime, timedelta
cutoff = datetime.now() - timedelta(hours=24)
timeout_alerts = db.query(KPIAlert).join(KPIDefinition, KPIDefinition.id == KPIAlert.kpi_id).filter(
KPIDefinition.entity_id == entity_id,
timeout_alerts = db.query(KPIAlert).filter(
KPIAlert.entity_id == entity_id,
KPIAlert.status == "pending",
KPIAlert.created_at < cutoff,
KPIAlert.alert_level != "red",