先说结论
很多人以为 Odoo 的客户项目共享就是:
- 发给客户一个 portal 链接
- 客户进去看看任务
但从 project 模块源码看,实际是几层东西叠在一起:
- 经典 portal 文档访问:
/my/projects/... - 基于
access_token的公开文档校验 - 项目共享(project sharing)专用页面:
/project_sharing project.collaborator记录谁是共享协作者limited_access决定是不是受限协作者- portal 用户对任务字段有专门的可读 / 可写白名单
一句话说:
Odoo 的项目共享不是“一个链接打开全部”,而是“文档访问、协作身份、可编辑能力”三层叠加出来的结果。
第一层:portal 看项目,和 project sharing 视图,不是同一件事
在 controllers/portal.py 里,普通入口是:
/my/projects/my/projects/<project_id>/my/projects/<project_id>/task/<task_id>
这是典型 portal 文档浏览逻辑。
但如果项目有协作者,而且当前用户通过 _check_project_sharing_access() 满足共享条件,控制器会把他重定向到:
/my/projects/<project_id>/project_sharing
这说明 Odoo 区分得非常明确:
- portal page:以文档页思路呈现
- project sharing view:更像受控的轻量后端界面
所以 project sharing 不是 portal 的皮肤,而是另一种交互模式。
第二层:access token 解决“能不能打开”,collaborator 解决“你是什么身份”
很多人容易把 token 和共享权限混成一件事。
其实它们职责不同。
access_token
它主要用于文档访问校验,解决的是:
- 这个链接是否能打开这份项目 / 任务
project.collaborator
它记录的是:
- 哪个 partner 是这个共享项目的协作者
- 是否
limited_access
也就是说:
token 更像“入口钥匙”,collaborator 更像“进入后你是什么角色”。
这两个概念不分开,实施时很容易讲错。
第三层:为什么 project.collaborator 是单独模型
Odoo 专门建了:
project.collaborator
而不是把共享名单直接塞到项目上的普通 many2many。
这很有意思,因为它说明系统不只是想记住“谁能看”,还想记住:
- 这是哪一个项目的共享身份
- 这个协作者是不是 limited access
- 整个 project sharing 规则是否应该启用
源码里在第一次创建 collaborator 时,还会激活 portal 侧相关 access / rule;如果一个 collaborator 都没有了,又会把这套规则关掉。
这说明 project sharing 在 Odoo 里不是常开默认,而是按是否真的使用来启用。
第四层:limited access 为什么重要
从源码看,display_follow_button 会结合项目协作者的 limited_access 来决定一些交互按钮是否显示。
这代表 Odoo 对 portal 协作者并不是只有“可编辑 / 不可编辑”两挡,而是会再细分:
- 是共享协作者
- 但是否拥有完整交互能力
这非常符合真实客户协作场景。
因为很多客户需要:
- 看进度
- 评论
- 关注某些任务
但不一定应该拥有所有项目内操作入口。
第五层:portal 用户为什么看不到完整 assignees,却还能看到名字
这是 project sharing 里一个很妙的边界。
源码里:
- portal 用户可读字段有白名单
- 可写字段也有白名单
user_ids这种字段会受 record rule 和字段访问限制
但同时,Odoo 又在 project.task 里做了:
portal_user_names
并且测试里明确验证:portal 用户可能看不到真实 user_ids,却能通过 portal_user_names 看到 assignee 名称列表。
这说明 Odoo 的思路是:
不给你完整内部用户记录,不等于不给你协作所需的可读信息。
这是一种很典型的“信息可见 ≠ 记录完全可访问”的权限设计。
第六层:为什么 portal 用户能改 stage,却不等于能像内部用户那样改一切
PROJECT_TASK_WRITABLE_FIELDS 里,portal 用户能写的是一小组字段,比如:
- 名称
- 描述
- deadline
- 标签
- stage
- 优先级
- parent / child 等少量结构字段
但像 user_ids 这样的内部协作字段并不在 portal 白名单里。
所以 project sharing 的真正语义是:
- 可以参与任务推进
- 但不等于获得内部项目管理权
这也是为什么 portal 协作者能在某些场景改阶段、触发评级邮件逻辑,但仍然不具备完整后台权限。
新手最容易误解的 4 件事
1. 以为项目共享就是 portal 页面
不对。project sharing 有自己单独的页面与 session 信息。
2. 以为 access token 就等于协作者权限
不对。token 解决打开入口,collaborator 解决共享身份。
3. 以为 portal 用户看到的 assignee 列表就代表能访问所有内部用户记录
不对。portal_user_names 专门就是为这个边界存在的。
4. 以为客户能改 stage,就说明权限接近内部用户
不对。portal 可写字段是白名单式设计。
实战上最该注意什么
1. 跟业务方讲权限时,一定把“可打开 / 可查看 / 可编辑”分开讲
不然他们会把 token、portal、协作者身份混成一个词:共享。
2. 不要随便扩大 portal 可写字段
因为这会直接改变 project sharing 的边界,很容易把本来安全的受控协作,改成半个后台入口。
3. 如果客户说“我为什么看不到负责人详情”,先区分是权限设计还是 bug
很多时候这不是 bug,而是 Odoo 故意只暴露名字,不暴露完整用户记录。
一句话记忆法
Odoo 项目共享不是“发个链接给客户”,而是“token 管入口、collaborator 管身份、字段白名单管可操作范围”的三层权限设计。
DISCUSSION
评论区