权限排错

Odoo 为什么列表能看见,点进去却报权限错误:ACL 与记录规则域合并顺序

用户能在列表里看到记录,点进详情却报权限错,常见原因不是单纯“没给权限”,而是 ACL、全局规则、组规则和关联模型读取顺序叠在了一起。

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

先给答案

Odoo 权限不是“ACL 和记录规则二选一”,而是 先过 ACL,再过记录规则

odoo/orm/models.py_check_access() 里,顺序很明确:

  1. 先调用 ir.model.access 检查模型级权限
  2. ACL 通过后,再去算 ir.rule 的 domain
  3. 如果当前记录不落在允许 domain 里,就仍然报权限错误

所以:

ACL 决定你有没有资格碰这个模型,记录规则决定你能碰这个模型里的哪些记录。

少任何一层,结论都会错。


第一层:ACL 先决定“你配不配进门”

源码里先做的是:

Access = self.env['ir.model.access']
if not Access.check(self._name, operation, raise_exception=False):
    ...

这一步只回答一个问题:

  • 你对这个模型有没有 read / write / unlink 这样的基本操作资格

它不关心你要读哪一条记录。

所以如果 ACL 没给:

  • 你连这个模型的大门都进不去
  • 后面的记录规则根本没机会救你

这是许多排错时的第一个误区: 有人看到写了规则,就以为规则会“放行”。 不会。 ACL 先卡死,规则根本不参与。


第二层:记录规则决定“进门后你能看到哪些记录”

ACL 通过后,源码会继续:

  • ir.rule
  • 计算当前模型、当前操作下的 domain
  • self.sudo().with_context(active_test=False).filtered_domain(domain) 过滤允许记录
  • 其余记录判定为 forbidden

这里最值得注意的一点是:

Odoo 在做记录规则判断时,核心不是“逐条 if else 写死”,而是:

先把规则合并成 domain,再拿 domain 去筛记录。

这解释了为什么很多权限问题本质上是 domain 问题,而不是“系统神秘抽风”。


最容易被忽略的一点:全局规则和组规则不是同一种叠加法

ir_rule.py_compute_domain() 里,逻辑非常关键:

  • 全局规则进入 global_domains
  • 有组的规则进入 group_domains
  • 最终结果是:
  • 全局规则们 AND 在一起
  • 分组规则们先 OR 在一起
  • 再和全局规则整体 AND

把它翻成人话就是:

全局规则

像“所有人都必须满足的门禁”。

多个全局规则越加越严,因为是 AND。

组规则

像“你属于这些角色中的任一放行通道”。

多个组规则之间是 OR,不是 AND。

最终效果

你必须:

  • 同时满足所有全局门禁
  • 并且在自己所属组规则里至少命中一条放行通道

这正是很多人配置完权限后觉得“明明给了组规则,怎么还是被挡住”的原因。

因为真正挡住你的,可能是全局规则。


为什么会出现“列表里能看见,点进去却报权限错误”

这类问题很常见,但不一定是主记录本身的规则矛盾。

常见原因有三类:

1. 你能读主记录,但读不到关联记录

列表页只取少数字段,表单页会加载更多字段、关联模型、聊天记录、附件、统计信息。

于是:

  • 主模型 ACL/规则没问题
  • 但关联模型没有权限
  • 结果打开详情时报错

2. 搜索场景和详情场景触发的上下文不同

规则 domain 可能和公司、上下文 key、活动记录过滤等有关。

3. 你看的不是同一层问题

有人以为“能搜到 = 一定可编辑”。 但 readwriteunlink 是不同操作,规则可以分别限制。

所以排这类问题时,别只盯一张截图。 要明确:

  • 哪个模型
  • 哪个操作
  • 哪条记录
  • 哪个关联字段在报错

过时接口名字为什么还会误导你

源码里 check_access_rights()check_access_rule() 已经标成 deprecated,最终都汇到更统一的 check_access() / _check_access() 逻辑。

这件事提醒我们:

  • 概念上还是 ACL + 规则两层
  • 但排查时最好回到新主入口 _check_access() 看真实顺序

否则你可能盯着老方法名理解,结果和现在的调用链对不上。


排权限问题,我一般按这个顺序

  1. 先确认模型 ACL 有没有给到对应操作
  2. 再确认当前用户属于哪些组
  3. 看有没有全局规则在收紧范围
  4. 再看组规则有没有放行路径
  5. 如果是“列表能看、详情报错”,继续检查关联模型权限
  6. 最后才去怀疑是不是缓存或界面问题

大多数权限 bug,到第 4 步其实就已经定位了。


最后一句话

Odoo 权限的核心不是“有没有写规则”,而是你要同时想清楚三件事:

  • 模型级操作资格在不在
  • 记录级 domain 怎么算
  • 全局规则和组规则到底是 AND 还是 OR

把这三层理顺后,权限问题会从“玄学报错”变回一套很工整的布尔逻辑。

DISCUSSION

评论区

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