权限上下文

Odoo sudo、with_user、with_company 到底差在哪:权限、身份、公司上下文别再混了

很多 Odoo 定制问题,看起来像“权限怪怪的”,其实是 sudo、with_user、with_company 混用导致边界不清。本文把这三个常见 API 讲透。

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

先说结论

很多 Odoo 开发里最危险的误区之一,就是把 sudo()with_user()with_company() 都当成“切个环境继续跑”。

它们确实都会改变执行上下文,但改的层面根本不是一回事:

  • sudo():改变安全边界
  • with_user():改变当前用户身份视角
  • with_company():改变公司上下文

这三个如果混着用却不分清,会非常容易出现:

  • 权限绕过
  • 多公司取值异常
  • 看起来偶发、其实边界错位的 bug

为什么这三个特别容易被混

因为它们都长得像“我想换个环境执行一下”。

于是很多人脑子里只剩一句模糊的话:

  • 换一下上下文就好了

但真正问题在于,它们各自改变的是完全不同的维度。

如果你不区分“权限是谁的”“身份是谁的”“公司是哪家的”,后面排查会非常痛苦。


sudo() 真正改变了什么

sudo() 最核心的意义不是“换用户”,而是:

绕开普通权限边界,让操作以更高权限执行。

这通常意味着:

  • access rights 检查可能被绕过
  • record rules 边界可能不同
  • 某些普通用户做不到的底层动作可以继续推进

所以 sudo() 的危险点就在于,它很容易让你在不知不觉中扩大可操作范围。


with_user() 真正改变了什么

with_user() 更接近:

让这段逻辑以“某个具体用户的身份视角”运行。

也就是说,它强调的是“像这个用户一样看和做”。

这和 sudo() 不是一回事。

如果你想模拟某个用户真实能看到什么、能操作什么,with_user() 才更贴近语义。

而不是一上来就 sudo()


with_company() 又在改变什么

with_company() 关心的不是权限,也不是身份本身,而是:

当前逻辑应当以哪个公司上下文来解释字段、规则与业务环境。

这在多公司场景里非常关键。

因为很多东西会受公司上下文影响:

  • 公司相关默认值
  • company_dependent 字段
  • 某些规则与取值
  • 业务配置解释方式

所以它处理的是“在哪家公司语境里运行”,不是“谁有权限”。


为什么 sudo().with_company(...) 经常一起出现

因为它们处理的是不同维度,所以确实可能同时需要。

比如某些系统流程要:

  • 以系统权限推进底层动作
  • 但又必须在正确公司上下文里创建对象

这时就可能会看到类似组合。

但“常一起出现”不等于“总是一起用”。

真正该不该组合,还是取决于:

  • 你要切的是权限、身份、还是公司语境

一个特别实用的判断方法

遇到这类 API 选择题时,先问自己:

1. 我是想提权,还是只是想模拟某个用户?

提权更接近 sudo();模拟用户更接近 with_user()

2. 问题是权限边界,还是公司语境?

如果是公司维度解释不同,更接近 with_company()

3. 用户可见结果是否也应该被提权后的范围影响?

这一步很关键,很多越权泄露就出在这里。


实战里最容易踩的 5 个坑

1. 本来只是想模拟用户,却直接 sudo()

结果把权限问题藏起来了。

2. 明明是多公司上下文问题,却一直查 group 和 access

方向就查偏了。

3. 提权执行后,把不该暴露的结果返回给前端

这是非常危险的边界错误。

4. 以为 with_company() 会自动解决权限问题

它不会。

5. 三者混着链式调用,却没想清每一步在改什么

这类代码后期最难维护。


一句话记忆法

把它们记成一句话:

sudo() 是提权,with_user() 是换身份视角,with_company() 是换公司语境;它们都能改上下文,但改的根本不是同一层。

理解这一句,很多 Odoo 权限和多公司问题就没那么容易看混。

DISCUSSION

评论区

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