权限门禁

Odoo 的 ACL 和记录规则为什么要分两层:权限门禁的真实顺序

很多人把 ACL 和记录规则混成“同一种权限”。其实 Odoo 先用 ir.model.access 判断你能不能碰这个模型,再用 ir.rule 缩小你能看见或操作的记录集合。

框架
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 3 阅读

先说结论

Odoo 的权限判断不是一把锁,而是两道门:

  1. ACL(ir.model.access) 先判断你有没有“碰这个模型”的资格
  2. 记录规则(ir.rule) 再判断你能碰到哪些具体记录

这两层不是重复,而是分工。 如果你把它们当成同一个概念,很多 AccessError、sudo 误判、以及“为什么搜索得到但写不了”的问题都会看起来很乱。


第一层:ACL 先管“模型级别能不能做事”

IrModelAccess.check() 做的是最基础的模型访问判断。 它会先看当前用户是否已经在允许模型集合里。

源码里的关键点是:

  • env.su 直接放行
  • 否则读取 _get_allowed_models(mode)
  • 如果模型不在允许集合里,就直接抛 AccessError

这意味着 ACL 解决的是最粗的一层问题:

你有没有资格去读、写、建、删这个模型。

它不关心你要访问哪条记录,只管“这个门你能不能进”。


第二层:记录规则再管“你能看见哪些记录”

如果 ACL 通过了,Odoo 还会继续算 ir.rule

IrRule._compute_domain() 会把规则转成一个 domain,然后和模型本身的访问一起合并。

这一步很重要,因为记录规则会同时考虑:

  • 当前用户是谁
  • 当前公司有哪些
  • 当前上下文里有什么 key
  • 哪些规则是 global,哪些是 group-based

换句话说,ACL 是“能不能进大门”,记录规则是“进门以后哪些房间能进”。


为什么要分开,而不是只保留一种权限

如果只有 ACL,系统只能做“模型级放行”,没法表达:

  • 只能看自己负责的销售单
  • 只能看当前公司的单据
  • 只能看符合某个业务 domain 的记录

如果只有记录规则,很多基本能力又会变得太慢、太复杂,甚至无法明确阻断“完全没资格访问这个模型”的情况。

所以 Odoo 把两层拆开,是为了同时做到:

  • 粗粒度快拦截
  • 细粒度按业务场景过滤

这是一种非常典型的平台设计。


缓存为什么会让排查变得更像魔术

IrRule._compute_domain() 有缓存,而且缓存键不只是用户 ID。 它还会把一些上下文值放进 key,尤其是 allowed_company_ids

这背后的原因很简单:

  • 同一个用户在不同公司切换时,domain 可能不同
  • 同一个模型在不同上下文里,规则结果也可能不同

所以你在调试时,如果只盯着“这个用户明明有权限”,但没看公司上下文,常常会走偏。


sudo() 为什么经常让人误判

sudo() 很容易让人以为“权限没问题”。 但在 Odoo 里,它只是让当前环境跳过很多访问判断。

这会导致两个常见错觉:

  1. 你在 sudo 环境里查到记录,不代表普通用户也查得到
  2. 你在 sudo 环境里看不到报错,不代表规则没问题

所以调试权限问题时,最忌讳只用 sudo 看结果。 你需要回到真实用户、真实公司上下文再验证。


AccessError 是怎么拼出来的

IrRule._make_access_error()IrModelAccess._make_access_error() 都不是只抛一个冷冰冰的错误。 它们会尽量告诉你:

  • 是 ACL 拦了,还是记录规则拦了
  • 拦的是哪个模型
  • 如果是记录规则,还会给出一些更有帮助的线索

这也是 Odoo 排障体验里的一个细节: 系统不是只拒绝你,还尽量告诉你“为什么拒绝”。


新手最容易混淆的 4 件事

1. “有菜单,就一定有模型权限”

不对。菜单只是导航入口,不等于模型 ACL 已经放行。

2. “查得到记录,就一定写得了”

也不对。读和写会分别走自己的权限和规则判断。

3. “sudo 查到了,所以普通用户也行”

不对。sudo 只是特权视角,不是普通视角。

4. “记录规则就是更复杂的 ACL”

不是。它们的职责根本不同。


实战排查顺序

如果你遇到权限问题,我建议这样看:

  1. 先确认模型 ACL 是否允许当前操作
  2. 再确认记录规则是否把目标记录过滤掉
  3. 再检查公司上下文和 allowed_company_ids
  4. 最后再看是不是 sudo 让你误读了现场

按这个顺序,通常比直接翻规则配置快很多。


最后一句话

Odoo 的 ACL 和记录规则不是两份重复清单,而是两道不同层级的门禁:

  • ACL 决定你能不能进模型
  • 记录规则决定你能碰到哪些记录

把这两层分开理解,权限问题就会清楚很多。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。