Skip to content

Odoo 权限管理实战指南

本文挡聚焦于通过 Odoo 原生设置界面配置用户权限,不涉及代码层面的 ir.model.access.csvsecurity.xml 编写。关联篇 Odoo 权限开发实战

一、核心概念:权限组(Groups)

权限组是 Odoo 访问控制体系的核心载体。所有权限最终都必须通过权限组进行分配,包括菜单可见性、模型操作权限(CRUD)、记录级过滤规则。 Odoo 在初始化时会为内置角色(如 "销售/用户: 仅查看自己的线索")自动绑定默认权限组。这些基础组位于 设置 → 用户和公司 → 用户组 中,不建议直接修改,而应通过继承方式扩展。

初始组列表

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

二、创建与配置权限组

2.1 激活开发者模式

配置权限前,必须先激活开发者模式:

  1. 进入设置 -> 一般设置
  2. 找到开发者工具区域,点击激活开发者模式
  3. 刷新页面,顶部会出现 🐞图标,表示已经激活。

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的局限性

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

  2. 不直接等于菜单权限:对于不绑定模型的菜单,在未设置菜单权限之前,登录用户都可以看得见(如自定义统计页面);对于绑定模型的菜单,拥有模型的读取权限,就能看见菜单。

四、记录级权限控制(Record Rules)

记录规则(Record Rules) 解决的是 "能看哪些记录" 的问题。即使拥有模型的读权限,记录规则也会进一步过滤可见的数据范围。

4.1 典型场景

需求场景:

  • 普通用户:只能查看自己的销售绩效目标记录。
  • 管理员:可以查看、修改所有人的记录。

配置步骤:

  1. 进入 销售绩效-用户 组的表单视图。
  2. 切换到 记录规则 选项卡 → 添加行
  3. 填写规则:
    • 名称:例如“仅限查看自己的绩效“。
    • 模型:销售绩效目标 (sale.performance.target)。
    • 应用于: ✅ 读取(仅勾选读权限)。
    • 规则定义域(Domain)[(‘user_id', '=', user.id)](只能访问自己的数据)。
  4. 销售绩效-管理员 组创建另一条规则:
    • 名称:查看所有绩效记录。
    • 规则定义域[(1, '=', 1)] 或留空(表示无限制)。
    • 应用于: ✅ 读取 ✅ 写入 ✅ 创建 ✅ 删除。

未配置前配置页面和数据展示(未配置记录规则前,普通用户可以看到所有数据):

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

4.2 严重注意事项:删除记录规则的陷阱

⚠️危险操作警告: 如果你在权限组表单中,直接在 记录规则 的列表行上点击删除(垃圾桶图标),会出现 "幽灵规则" 现象:

  • 现象:规则从当前组消失,但权限限制依然生效,甚至影响到所有用户。
  • 根本原因:界面的删除按钮实际发送的是 Command.unlink(解除绑定),而非 Command.delete(物理删除)。该记录规则在数据库 ir.rule表中依然存在,只是不再关联特定组。
根据 Odoo 安全机制:任何不隶属于特定组(groups 字段为空)的记录规则,会被系统视为全局规则(Global Rule),对所有用户生效!

正确删除方式

  1. 前往 设置 → 技术 → 安全 → 记录规则 (Record Rules)。
  2. 在列表中找到该规则(可通过名称或模型过滤)。
  3. 打开记录 → 点击 操作 → 删除(或点击表单中的删除按钮)。

删除组的访问规则后查询数据(记录规则列表已经删除,但是还只能查看自己的数据,应该可以查看所有数据):

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

五、菜单权限控制

菜单权限控制用户能看到哪些导航项。

5.1 基础配置

配置路径:在权限组表单的 菜单 选项卡中添加:

  1. 点击 添加行
  2. 从菜单树中选择需要开放的菜单项(支持多选)。
  3. 父子级联特性:添加父级菜单时,其所有子菜单会自动附带给该组。

移除菜单: 若需隐藏特定菜单(如"销售绩效统计图表"),直接在 菜单 选项卡中删除对应行即可,用户刷新页面后将看不到该入口。

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"/>