Appearance
Odoo 权限管理实战指南
本文挡聚焦于通过 Odoo 原生设置界面配置用户权限,不涉及代码层面的 ir.model.access.csv 或 security.xml 编写。关联篇 Odoo 权限开发实战。
一、核心概念:权限组(Groups)
权限组是 Odoo 访问控制体系的核心载体。所有权限最终都必须通过权限组进行分配,包括菜单可见性、模型操作权限(CRUD)、记录级过滤规则。 Odoo 在初始化时会为内置角色(如 "销售/用户: 仅查看自己的线索")自动绑定默认权限组。这些基础组位于 设置 → 用户和公司 → 用户组 中,不建议直接修改,而应通过继承方式扩展。

⚠️ 前置条件:超级管理员权限 并非所有用户都能看到权限管理菜单。只有 管理员权限选项设置为【设置】(即
Administration: Settings组)的超级管理员,才能访问 技术菜单 和全局设置参数。

二、创建与配置权限组
2.1 激活开发者模式
配置权限前,必须先激活开发者模式:
- 进入设置 -> 一般设置
- 找到开发者工具区域,点击激活开发者模式
- 刷新页面,顶部会出现 🐞图标,表示已经激活。

2.1 创建权限组
导航路径:设置 -> 用户和公司 -> 用户组 -> 新建。
关键字段解析:
| 字段 | 技术名 | 说明 |
|---|---|---|
| 应用 | category_id | 决定该组在用户权限表单中显示的位置(分类标题)。此字段与模块 __manifest__.py 中的 "category" 键自动关联。 |
权限继承机制(Inheritance) 在继承选项卡中添加权限组,可实现权限的层级传递。
- 权限叠加: 本组自动获得所有继承组的 ACL(模型权限)、菜单权限和记录规则。
- 用户自动加入: 将用户分配到权限组时,Odoo 会自动将其同时加入所有被继承组的用户菜单。



场景示例: 创建 销售绩效-管理员 组,并使其继承 销售绩效-用户 组:
- 管理员自动拥有普通用户的所有权限。
- 只需为管理员组额外配置 创建、编辑、删除 权限即可。
- 分配到"管理员"组的用户,其用户详情页会自动勾选”管理员”组。

三、 模型级权限控制(ACL)
访问权限(ACL)控制的是“能对哪些模型做什么操作”,即CRUD(创建、读取、修改、删除)权限。
3.1 配置ACL
在权限组表单中,点击访问权限选项卡 -> 添加行:
| 配置项 | 说明 |
|---|---|
| 对象 | 选择模型(如 sale.performance.target) |
| 读权限 | 查看记录详情和列表 |
| 写权限 | 修改现有记录 |
| 创建权限 | 新建记录 |
| 删除权限 | 删除记录 |
实践建议:
- 遵循 最小权限原则:基础组(如"用户")仅授予 读权限,高级组(如"管理员")才授予 写/创建/删除。
- 权限继承的传递:若组B继承组A,且组A拥有模型M的读权限,则组B的用户自动拥有对模型M的读权限,无需重复配置。
普通用户(读取权限): 

管理员(操作权限): 

3.2 ACL的局限性
无法控制按钮可见性:如果模型操作是通过按钮触发的 Wizard(向导),单纯添加模型 ACL 不能 控制该按钮的显示与隐藏。按钮权限需通过
groups属性在视图 XML 中控制。


不直接等于菜单权限:对于不绑定模型的菜单,在未设置菜单权限之前,登录用户都可以看得见(如自定义统计页面);对于绑定模型的菜单,拥有模型的读取权限,就能看见菜单。
四、记录级权限控制(Record Rules)
记录规则(Record Rules) 解决的是 "能看哪些记录" 的问题。即使拥有模型的读权限,记录规则也会进一步过滤可见的数据范围。
4.1 典型场景
需求场景:
- 普通用户:只能查看自己的销售绩效目标记录。
- 管理员:可以查看、修改所有人的记录。
配置步骤:
- 进入 销售绩效-用户 组的表单视图。
- 切换到 记录规则 选项卡 → 添加行。
- 填写规则:
- 名称:例如“仅限查看自己的绩效“。
- 模型:销售绩效目标 (
sale.performance.target)。 - 应用于: ✅ 读取(仅勾选读权限)。
- 规则定义域(Domain):
[(‘user_id', '=', user.id)](只能访问自己的数据)。
- 为 销售绩效-管理员 组创建另一条规则:
- 名称:查看所有绩效记录。
- 规则定义域:
[(1, '=', 1)]或留空(表示无限制)。 - 应用于: ✅ 读取 ✅ 写入 ✅ 创建 ✅ 删除。
未配置前配置页面和数据展示(未配置记录规则前,普通用户可以看到所有数据): 

配置后配置页面和数据展示(配置规则后,普通用户只能看到自己的数据): 

4.2 严重注意事项:删除记录规则的陷阱
⚠️危险操作警告: 如果你在权限组表单中,直接在 记录规则 的列表行上点击删除(垃圾桶图标),会出现 "幽灵规则" 现象:
- 现象:规则从当前组消失,但权限限制依然生效,甚至影响到所有用户。
- 根本原因:界面的删除按钮实际发送的是
Command.unlink(解除绑定),而非Command.delete(物理删除)。该记录规则在数据库ir.rule表中依然存在,只是不再关联特定组。 根据 Odoo 安全机制:任何不隶属于特定组(groups 字段为空)的记录规则,会被系统视为全局规则(Global Rule),对所有用户生效!
正确删除方式:
- 前往 设置 → 技术 → 安全 → 记录规则 (Record Rules)。
- 在列表中找到该规则(可通过名称或模型过滤)。
- 打开记录 → 点击 操作 → 删除(或点击表单中的删除按钮)。
删除组的访问规则后查询数据(记录规则列表已经删除,但是还只能查看自己的数据,应该可以查看所有数据): 

验证及真正删除访问规则后的数据展示(从用户组的记录规则中删除规则,并没有改变数据权限,需要从正确的菜单中删除,下面是验证的过程): 



五、菜单权限控制
菜单权限控制用户能看到哪些导航项。
5.1 基础配置
配置路径:在权限组表单的 菜单 选项卡中添加:
- 点击 添加行。
- 从菜单树中选择需要开放的菜单项(支持多选)。
- 父子级联特性:添加父级菜单时,其所有子菜单会自动附带给该组。

移除菜单: 若需隐藏特定菜单(如"销售绩效统计图表"),直接在 菜单 选项卡中删除对应行即可,用户刷新页面后将看不到该入口。
5.2 严重注意事项:One2many删除陷阱
⚠️危险操作警告: 在权限组表单的 菜单 选项卡中,存在危险的 One2many 关系机制:
- 错误操作:添加父菜单后,试图通过删除其子菜单行来限制权限。
- 灾难性后果:在 Odoo 的表单视图中,对
One2many明细行执行删除,系统发送的是Command.delete(物理删除)!这将从数据库中 永久删除该菜单定义,而不仅仅是解除当前组的权限! - 影响范围:所有依赖该菜单的组、所有引用该菜单的代码、所有子菜单项都会失效或被级联删除。
- 恢复方式:必须通过 更新模块(
Upgrade Module)重新加载菜单定义,或在数据库层面恢复ir.ui.menu记录。


正确做法:
- 仅添加需要的子菜单:不要添加父菜单然后删子项,而是直接勾选需要的子菜单。

六、关联模型的权限处理策略
在实际业务中,常遇到主表-子表(One2many)结构的权限设计。建议根据业务敏感性采用不同策略:
| 场景 | 模型示例 | 处理方式 | 理由 |
|---|---|---|---|
| 配置型子表 | 阶梯配置 (ladder) | 继承父表权限 | 无独立业务意义,仅作为主表的配置项,随父表权限控制即可 |
| 业务数据子表 | 佣金明细 (commission.line) | 独立 ACL + 记录规则 | 包含敏感薪资数据,需防止通过 RPC 直接访问子表模型,必须独立配置读写权限 |
七、权限体系的边界与限制
7.1 无原生字段级权限
Odoo 标准功能 不支持 通过界面配置字段级权限(如隐藏特定用户的"成本"字段)。 原因(来自 Odoo 官方逻辑): 视图渲染高度依赖字段存在(JS 框架会计算字段属性、触发 onchange)。如果通过权限将字段对特定用户"彻底移除"(而非仅隐藏),可能导致前端 JavaScript 运行时错误:"字段 X 未在视图中定义"。 替代方案:
- 视图层面:使用
invisible属性结合groups限制(需开发模式编辑 XML)。 - 模型层面:使用
groups属性在字段定义级别限制(需写代码)。
7.2 无原生按钮级权限
按钮的可见性无法通过权限组界面配置。必须在视图 XML 中为按钮添加 groups 属性,例如:
xml
<button name="confirm_order" string="确认"
groups="sales_performance.group_manager"/>