fix: OpenCode审查16条修复 — 战略地图隔离/安全/逻辑漏洞

安全:
- ⑦ update_map 字段白名单(禁entity_id篡改, status限值域)
- ⑧ objectives 全端点补entity校验(原括号错位导致隔离失效) + update白名单
- ⑨ strategic_map_versions 加entity_id列+回填, list/snapshot/rollback过滤
- ⑩ get_map_review KPI查询加entity(同编码跨企业混入)
- ⑪ _sync_map_objectives 强制继承地图entity

逻辑:
- ③ MapCanvas 自动保存 currentMap.value 解包(30s自动保存修复)
- ④ 乐观锁字段 version_num→version 对齐
- ⑤ 红黄绿灯: 越低越好型反向 + 负值修正 + 月目标优先
- ⑥ review 补 action_plan_summary 字段

验证: 跨企业写目标404✓ entity_id注入被拒✓ pytest 531 passed✓
This commit is contained in:
Hermes CI Fix
2026-08-26 23:25:44 +08:00
parent 95b73c9b90
commit 9b61c48051
5 changed files with 54 additions and 18 deletions
+15 -5
View File
@@ -23,7 +23,7 @@ def list_objectives(map_id: int, db: Session = Depends(get_db), entity_id: int =
@router.post("/{map_id}/objectives")
def create_objective(map_id: int, data: dict, db: Session = Depends(get_db), entity_id: int = Depends(get_entity_id)):
"""新增目标"""
m = db.query(StrategicMap).filter(StrategicMap.id == map_id), StrategicMap.entity_id == entity_id.first()
m = db.query(StrategicMap).filter(StrategicMap.id == map_id, StrategicMap.entity_id == entity_id).first()
if not m:
raise HTTPException(404, "战略地图不存在")
obj = MapObjective(
@@ -42,14 +42,18 @@ def create_objective(map_id: int, data: dict, db: Session = Depends(get_db), ent
@router.put("/{map_id}/objectives/{obj_id}")
def update_objective(map_id: int, obj_id: int, data: dict, db: Session = Depends(get_db), entity_id: int = Depends(get_entity_id)):
"""修改目标"""
"""修改目标(账套隔离 + 字段白名单, OpenCode审查#8"""
m = db.query(StrategicMap).filter(StrategicMap.id == map_id, StrategicMap.entity_id == entity_id).first()
if not m:
raise HTTPException(404, "战略地图不存在")
obj = db.query(MapObjective).filter(
MapObjective.id == obj_id, MapObjective.map_id == map_id
).first()
if not obj:
raise HTTPException(404, "目标不存在")
ALLOWED_OBJ_FIELDS = {"name", "description", "icon", "sort_order", "kpis", "dimension_key"}
for k, v in data.items():
if hasattr(obj, k) and v is not None:
if k in ALLOWED_OBJ_FIELDS and hasattr(obj, k) and v is not None:
setattr(obj, k, v)
db.commit()
return _obj_to_dict(obj)
@@ -57,7 +61,10 @@ def update_objective(map_id: int, obj_id: int, data: dict, db: Session = Depends
@router.delete("/{map_id}/objectives/{obj_id}")
def delete_objective(map_id: int, obj_id: int, db: Session = Depends(get_db), entity_id: int = Depends(get_entity_id)):
"""删除目标"""
"""删除目标(账套隔离)"""
m = db.query(StrategicMap).filter(StrategicMap.id == map_id, StrategicMap.entity_id == entity_id).first()
if not m:
raise HTTPException(404, "战略地图不存在")
obj = db.query(MapObjective).filter(
MapObjective.id == obj_id, MapObjective.map_id == map_id
).first()
@@ -70,7 +77,10 @@ def delete_objective(map_id: int, obj_id: int, db: Session = Depends(get_db), en
@router.put("/{map_id}/objectives/sort")
def sort_objectives(map_id: int, data: dict, db: Session = Depends(get_db), entity_id: int = Depends(get_entity_id)):
"""批量排序: {"ids": [3, 1, 2]}"""
"""批量排序: {"ids": [3, 1, 2]}(账套隔离)"""
m = db.query(StrategicMap).filter(StrategicMap.id == map_id, StrategicMap.entity_id == entity_id).first()
if not m:
raise HTTPException(404, "战略地图不存在")
ids = data.get("ids", [])
for idx, obj_id in enumerate(ids):
db.query(MapObjective).filter(