先说结论
Odoo 的项目共享从来不是“生成一个公开地址”这么简单。
从 project.share.wizard、project.collaborator 和 project.project 的实现看,系统同时维护三层状态:
- 共享入口:wizard 里给人的访问模式是
read、edit、edit_limited - 长期授权:真正能编辑的对象会落成
project.collaborator - 协作订阅:无论读还是改,都还要通过 project / task 的 follower 体系让消息、入口和门户可见性成立
所以最短结论是:
项目共享不是“发链接”,而是“访问模式 + collaborator 权限 + follower 订阅”三件事同时生效。
为什么 wizard 里的 access mode 不能直接等于最终权限
project.share.wizard.default_get() 会把现有协作者和 follower 重新映射回界面:
- collaborator 且
limited_access=False→edit - collaborator 且
limited_access=True→edit_limited - 只是 follower、不是 collaborator →
read
这已经说明一件事:
界面上的 access mode,是对底层状态的“翻译结果”,不是唯一真相。
真正的真相要看两张表:
- 在不在
project.collaborator - 在不在
message_partner_ids
只盯着分享弹窗,往往会低估 follower 的作用。
read 为什么本质上更像“门户可见 + 订阅”
源码里如果某人是 read 模式,wizard 并不会给他创建 project.collaborator,而是让他停留在 follower 体系里。
这意味着只读共享更像:
- 让门户用户能进入项目或任务
- 让系统知道他是这个协作上下文里的参与者
- 但不授予 project sharing 的编辑能力
很多实施把只读当成“编辑权限关掉”来理解,其实不完整。
更准确地说,它是:
先让人进入协作上下文,再限制其只能读。
这也是为什么删 follower 往往比改一个按钮更有杀伤力——入口本身可能就没了。
edit 与 edit_limited 的区别到底在哪里
当 wizard 看到 edit 或 edit_limited,会把人写入 project.collaborator。
区别只在 limited_access 这一个布尔值,但后续影响不小:
edit:是完整协作者edit_limited:是受限协作者
源码里 _compute_display_follow_button() 甚至会根据 limited_access 决定门户用户是否显示 follow 按钮。这说明 limited 模式不是装饰性字段,而是会继续影响前端交互与后续订阅动作。
对业务来说,可以把它理解成:
edit适合外部协作方要持续参与项目推进edit_limited适合给对方一个可操作入口,但又不想让他把协作范围继续外扩
为什么新增编辑协作者时还会顺手订阅任务
project.share.wizard.create() 在新增可编辑协作者时,不只是创建 collaborator,还会:
- 让项目增加 follower
- 对任务做
message_subscribe()
这一步特别关键。
因为 Odoo 的协同不是“你有 ACL 就结束”,而是“你得真的进入消息上下文”。
如果只给 collaborator、不补 follower,常见后果是:
- 人能进项目,但收不到后续协作变化
- 门户里看得到项目,具体任务却像断层
- Chatter 线程参与关系不完整
所以 Odoo 的设计很现实:共享权限和消息订阅必须一起补。
为什么移除协作者时还要顺手清 follower
同一个 create() 里,wizard 也会找出:
- 该删的
project.collaborator - 该移除的门户 follower
这说明 Odoo 不允许“授权删了,但订阅还吊着”这种半残状态长期存在。
否则就会出现典型脏数据:
- 对方明面上不再是协作者
- 但还在项目消息链里
- 某些 portal 页面还能继续被命中
对协同系统来说,这种“历史订阅残留”比显式报错更难排查。
public link 为什么只是只读入口,不是共享策略本身
share_link 的帮助文案写得很清楚:Anyone with this link can access the project in read mode。
这句话非常值得抠字眼:
- 它说的是 access,不是 collaboration role
- 它说的是 read mode,不是 full sharing
也就是说,公开链接更像“只读入口壳”,而不是项目协作模型的主体。
真正的长期协作关系,依旧靠:
privacy_visibilityproject.collaborator- follower 订阅
如果把 public link 当主方案,用久了通常会碰到两个问题:
- 对方能看,但无法沉淀成稳定协作者
- 一旦要升级到可编辑协作,还得再补 collaborator 和 follower
最容易踩的三个误区
误区一:把 follower 当“通知名单”
在 Odoo 项目共享里,follower 不是单纯通知名单,它还是门户可见性和任务协作入口的一部分。
误区二:把 collaborator 当“唯一权限源”
collaborator 很重要,但如果没有 follower 这层订阅补齐,实际体验往往不完整。
误区三:以为 limited 只是 UI 上的文案差异
limited_access 会继续影响前端行为和后续操作边界,不是随便起的名字。
出问题时怎么排
建议按这个顺序查:
- 项目 privacy_visibility 是不是 portal / invited_users
- 这个外部人是否在
project.collaborator - 如果只是只读,他是否仍在 project / task followers
- 任务是不是也同步订阅了,而不是只有项目层订阅
- 是否曾切换过共享模式,遗留了旧 follower 或旧 collaborator
这个顺序好处是:先判“入口”,再判“角色”,最后判“消息链”。
一句话记忆
Odoo 项目共享不是发出一个链接,而是把访问模式、协作者记录和 follower 订阅同时对齐。
DISCUSSION
评论区