fix(cma): isolate KPI alignment tree by entity (project-20260918-alignment-entity-leak)
GET /api/cma/alignment/tree queried all active KPIs without entity_id filter, so switching the three alignment modes showed other tenants' KPIs. Add get_entity_id dependency and filter KPIDefinition by entity_id. Three mode builders (_build_vertical_tree/_build_horizontal_tree/_build_bsc_chain) unchanged. Auth semantics unchanged; cross-entity explicit entity_id still returns 403. Test: tests/test_alignment_entity_isolation_20260918.py (3 modes x both directions, 403, 401).
This commit is contained in:
@@ -10,6 +10,7 @@ import json
|
||||
|
||||
from app.database import get_db
|
||||
from app.auth_middleware import require_auth, require_role, require_auth_401
|
||||
from app.deps import get_entity_id
|
||||
from app.models import KPIDefinition, OperationLog, RolePermission
|
||||
|
||||
router = APIRouter(prefix="/api/cma/alignment", tags=["KPI目标对齐"],
|
||||
@@ -90,14 +91,20 @@ def set_alignment_config(
|
||||
@router.get("/tree")
|
||||
def get_alignment_tree(
|
||||
kpi_id: Optional[int] = Query(None),
|
||||
entity_id: int = Depends(get_entity_id),
|
||||
db: Session = Depends(get_db),
|
||||
user = Depends(require_auth),
|
||||
):
|
||||
"""获取KPI对齐关系树
|
||||
"""获取KPI对齐关系树(按当前账套隔离)
|
||||
|
||||
根据当前系统配置的对齐模式,返回KPI的父子层级关系。
|
||||
如果指定kpi_id,返回该KPI及其下级树;
|
||||
如果不指定,返回整个对齐树。
|
||||
|
||||
账套隔离(2026-09-18 project-20260918-alignment-entity-leak):
|
||||
只取 entity_id 归属本账套的 KPI(entity_id 来自会话 token 绑定,写法对齐
|
||||
growth-quality / predict.accuracy)。三种模式共用本列表 → 三模式同时隔离。
|
||||
跨实体显式传参(?entity_id=<他人账套>)由 get_entity_id 返回 403。
|
||||
"""
|
||||
# 获取当前模式
|
||||
config_perm = db.query(RolePermission).filter(RolePermission.key == "alignment_config").first()
|
||||
@@ -105,8 +112,11 @@ def get_alignment_tree(
|
||||
if not mode:
|
||||
raise HTTPException(400, "系统未配置对齐模式,请先在系统设置中初始化")
|
||||
|
||||
# 获取所有KPI
|
||||
kpis = db.query(KPIDefinition).filter(KPIDefinition.status == "active").order_by(KPIDefinition.kpi_code).all()
|
||||
# 获取本账套所有KPI(账套隔离:仅当前 entity_id,不再返回全实体 KPI)
|
||||
kpis = (db.query(KPIDefinition)
|
||||
.filter(KPIDefinition.entity_id == entity_id, KPIDefinition.status == "active")
|
||||
.order_by(KPIDefinition.kpi_code)
|
||||
.all())
|
||||
kpi_map = {k.id: k for k in kpis}
|
||||
|
||||
# 构建父子关系
|
||||
|
||||
Reference in New Issue
Block a user