审批系统最危险的不是流程复杂,而是大家以为“反正能看到,就顺手改一下”。Approvals 在 approval.request 和 approval.approver 两层上,把 owner、officer、approver 的权力拆得很细。
参考入口:
enterprise/approvals/models/approval_request.pyenterprise/approvals/models/approval_approver.pyenterprise/approvals/tests/test_approvals.py
一、申请人不是永远都能编辑自己的单
approval.request.write() 明确限制了 owner 的行为:
- 草稿时可以改业务字段;
- 进入
pending / approved / refused后,owner 不能继续随意改内容; - 对已处理单,owner 允许的主动作是先取消,再回草稿;
- owner 也不能通过写
request_status=approved/refused给自己放行。
这和很多人直觉相反:提交后 owner 并不是“还有编辑权,只是别乱动”,而是模型层就开始收口。
二、审批专员能改 approver 行,普通人不行
测试 test_approval_approvers_access 很清楚:只有 approval officer 才能给请求新增 approver、修改 approver 的 required 标记、删除 approver 行。普通用户哪怕是请求 owner,也不能越过这层边界。
原因很简单:approver roster 一旦人人能改,minimum、required、sequence 都失去可信度。
三、普通 approver 的核心权力只有“对属于自己的那一行表态”
approval.approver.action_approve() / action_refuse() 最终回到 request 上执行,但前提是这条 approver 行属于当前用户。测试里也验证了:用户 1 不能替用户 2 的 approver 行点批准。
也就是说,普通 approver 的权限不是“能碰审批单”,而是“能处理自己的审批责任”。
四、移动 approver 到别的 request 也不是普通写操作
approval.approver.write() 对 request_id 特别加了访问检查:
- 先看目标 request 是否有写权限;
- 如果 approver 已经挂在某张单上,还禁止把它改挂到另一张 request。
这堵住了一个很隐蔽的洞:有人试图通过编辑 approver 行,把自己的审批责任转移到另一张单上。
五、实战建议
- 给业务 owner 的不是“全程编辑权”,而是“发起 + 撤回 + 重提”的能力。
- approver 管理集中交给审批专员或管理员,不要开放给流程参与者。
- 出现“我能看到但不能改”时,优先从角色设计解释,而不是当成 bug。
六、结论
Approvals 的权限设计不是谁高谁低那么简单,而是按责任粒度切:owner 管业务归属,approver 管自己的表态,officer 管审批链结构。三者混掉,审批就会失真。
DISCUSSION
评论区