fix(backend): 权限漏洞修复 + 业务逻辑审查修复
1. 宏观状态越权修复 (products.py + product_service.py): - update_overall_status 增加权限校验:仅 SUPER_ADMIN 或当前操作该产品主线任务的人可修改,否则 403 2. 任务撤回越权修复 (task_service.py + tasks.py): - recall_task 增加校验:操作人必须等于上游任务负责人(谁发出的谁撤回),否则 403 - 管理员 (SUPER_ADMIN/SUPERVISOR) 直接放行 3. 驳回上游溯源修复 (task_service.py - reject_task): - 将 TaskLog (action_type=create) 提升为优先溯源方式,解决协助分支转交后驳回找不到正确发起人的 Bug - 保留 parent_task.assignee_id + task.assignee_id 两级兜底 4. complete_task 父节点继承修复: - 修复 task_type == 'MAIN' 永不匹配的 Bug(模型无此值) - 改为 not parent_task_id or task_type in (TRANSFER, RECOVERY)
This commit is contained in:
@ -275,8 +275,17 @@ async def update_product(db: AsyncSession, product_id: uuid.UUID, data: ProductU
|
||||
VALID_OVERALL_STATUS = {"备货", "生产", "测试", "维修", "在库"}
|
||||
|
||||
|
||||
async def update_overall_status(db: AsyncSession, serial_number: str, status_value: str) -> ProductScanResponse:
|
||||
"""更新产品宏观状态"""
|
||||
async def update_overall_status(
|
||||
db: AsyncSession, serial_number: str, status_value: str,
|
||||
current_user: dict | None = None,
|
||||
) -> ProductScanResponse:
|
||||
"""更新产品宏观状态
|
||||
|
||||
权限校验:
|
||||
- SUPER_ADMIN 角色:直接放行
|
||||
- 当前操作该产品主线任务(WIP/PENDING 状态主干任务)的人:放行
|
||||
- 其他:403
|
||||
"""
|
||||
if status_value not in VALID_OVERALL_STATUS:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
@ -292,6 +301,38 @@ async def update_overall_status(db: AsyncSession, serial_number: str, status_val
|
||||
if not product:
|
||||
raise HTTPException(status_code=404, detail=f"未找到序列号 {serial_number} 的产品")
|
||||
|
||||
# ── 权限校验 ──
|
||||
if current_user:
|
||||
user_role = current_user.get("role", "")
|
||||
user_username = current_user.get("username", "")
|
||||
|
||||
# SUPER_ADMIN 直接放行
|
||||
if user_role == "SUPER_ADMIN":
|
||||
pass
|
||||
else:
|
||||
# 检查当前用户是否是该产品主线任务的负责人
|
||||
from sqlalchemy import or_
|
||||
main_task_result = await db.execute(
|
||||
select(Task).where(
|
||||
Task.product_id == product.id,
|
||||
Task.status.in_(["WIP", "PENDING"]),
|
||||
or_(
|
||||
Task.parent_task_id.is_(None),
|
||||
Task.task_type.in_(["TRANSFER", "RECOVERY"]),
|
||||
),
|
||||
).order_by(Task.created_at.desc()).limit(1)
|
||||
)
|
||||
main_task = main_task_result.scalar_one_or_none()
|
||||
has_permission = (
|
||||
main_task
|
||||
and main_task.assignee_id == user_username
|
||||
)
|
||||
if not has_permission:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail="只有 SUPER_ADMIN 或当前操作该产品主线任务的人才能修改宏观状态",
|
||||
)
|
||||
|
||||
product.overall_status = status_value
|
||||
await db.commit()
|
||||
await db.refresh(product)
|
||||
|
||||
Reference in New Issue
Block a user