跳至内容

第4章 模型访问权限 ACL

4.1 ACL 回答什么问题

ACL 回答的是:用户对整个模型是否拥有某种 CRUD 能力? 它不关心具体记录、状态或部门。

Odoo 的四种标准操作是:

Odoo 名称 通常含义
read 读取、搜索、打开
write 修改已有记录
create 创建记录
unlink 删除记录

“确认订单”“审批费用”“会计过账”不是第五种 ACL,必须由业务方法控制。

4.2 ir.model.access 的重要字段

模型定义在 odoo/addons/base/models/ir_model.py:2006-2019

字段 说明
name ACL 名称
active 禁用时不参与判定;比删除原生 ACL 更适合临时停用
model_id 目标 ir.model
group_id 适用组;空值代表所有用户
perm_read 是否授予 read
perm_write 是否授予 write
perm_create 是否授予 create
perm_unlink 是否授予 unlink

4.3 ACL 是 grant 的并集

运行时 _get_allowed_models(uid, mode) 直接查询所有 active 且 perm_mode=True 的 ACL,只要 group_id 为空或属于用户组就把模型加入允许集合,见 ir_model.py:2067-2086

假设用户同时拥有 A、B 两组:

Read Write Create Unlink
A 1 0 1 0
B 0 1 0 0
最终有效权限 1 1 1 0

B 组中的 Read=0 不是拒绝 read,只是 B 没有授予 read;A 的 grant 仍然生效。原生 ACL 没有 deny、优先级或“经理组覆盖用户组”的概念。

4.4 CSV 配置

标准文件为 security/ir.model.access.csv

id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_document_user,document.user,model_demo_document,demo.group_document_user,1,1,1,0
access_document_manager,document.manager,model_demo_document,demo.group_document_manager,1,1,1,1

注意:

  • model_demo_document 是模型 _name = 'demo.document' 自动生成的 external ID。
  • group_id 要使用稳定 XML ID。
  • Manager 若 implied User,两条 ACL 都会匹配,最终仍是并集。
  • 删除模块自带 ACL 后,模块升级可能重建;需要停用时优先考虑 active=False,并评估升级数据策略。

4.5 无组 ACL 的风险

group_id 为空会给所有用户类型授权,包括门户或公共用户,只要后续规则没有限制。Odoo 18 仍支持它,但在创建有权限勾选的无组 ACL 时会输出 deprecated 警告,源码见 ir_model.py:2131-2141

新模块应始终明确组。特别是网站模型,不要因为“控制器里会判断 token”就给整个模型一个无组 write/create ACL。

4.6 ACL 的源码调用

recordset.check_access(operation)
  -> recordset._check_access(operation)
      -> env['ir.model.access'].check(model_name, operation)
          -> _get_allowed_models(uid, operation)  # 有缓存

核心位置:

  • 统一入口:odoo/models.py:4370-4428
  • ACL 检查:ir_model.py:2088-2102
  • 拒绝信息和可授权组:ir_model.py:2104-2121
  • ACL 变更清缓存:ir_model.py:2123-2149

Odoo 18 中 check_access_rights() 已废弃,推荐使用空 recordset 的新统一 API:

self.browse().check_access("create")
can_read = self.browse().has_access("read")

check_access_rule()_filter_access_rules() 也已废弃,分别改用 check_access()_filtered_access()

4.7 ACL 不能表达的事情

ACL 无法表达:

  • 只能看自己的订单;
  • 草稿可以改,已审批不能改;
  • 金额超过十万元需总经理;
  • 不能审批自己提交的费用;
  • 只能修改备注,不能修改金额;
  • 临时授权到某日失效。

前两类部分可由记录规则表达,复杂状态、字段写策略和职责分离必须进入业务代码或增强策略层。

老赵解读

ACL 的定位很朴素:只回答某类用户能否对某个模型做增删改查。它是能力底座,不是数据范围,也不是审批制度。设计时宁可让 ACL 保持少而稳定,再用记录规则和业务方法补足范围与条件;不要为了表达每一种组织范围,复制出大量近似 ACL 和用户组。

额定值
0 0

目前没有任何评论。

成为第一个发表评论的人。