record rules问题-没写权限也可以修改记录
-
在odoo10里我有一个model,该model有且仅有一条record rule,该record rule设置没有写权限,具体是这样定义的:
<record id="todo_task_user_rule" model="ir.rule"> <field name="name">rule1</field> <field name="model_id" ref="model_todo_task"/> <field name="domain_force">[('create_uid','!=',user.id)]</field> <field name="groups" eval="[(4,ref('base.group_user'))]"/> <field eval="0" name="perm_unlink"/> <field eval="0" name="perm_write"/> <field eval="1" name="perm_read"/> <field eval="1" name="perm_create"/> </record>
该条record rule生效后,测试发现用户还可以修改满足('create_uid','!=',user.id)条件的记录。经过反复测试和对比已有的模块,发现需要给同组用户添加一个perm_write=True(当然,domain为不一样)的record rule才能实现该组的用户无法修改记录,我添加的record rule如下:
<record id="todo_task_user_rule" model="ir.rule"> <field name="name">rule2</field> <field name="model_id" ref="model_todo_task"/> <field name="domain_force">[('create_uid','=',user.id)]</field> <field name="groups" eval="[(4,ref('base.group_user'))]"/> <field eval="0" name="perm_unlink"/> <field eval="1" name="perm_write"/> <field eval="1" name="perm_read"/> <field eval="1" name="perm_create"/> </record>
之后查看源代码,发现odoo/odoo/addons/base/ir/ir_rule.py的_compute_domain()处理逻辑,当找不到ir.rule记录时,则检查权限当通过处理,而其SQL语句是这样的:
query = """ SELECT r.id FROM ir_rule r JOIN ir_model m ON (r.model_id=m.id) WHERE m.model=%s AND r.active AND r.perm_{mode} AND (r.id IN (SELECT rule_group_id FROM rule_group_rel rg JOIN res_groups_users_rel gu ON (rg.group_id=gu.gid) WHERE gu.uid=%s) OR r.global) """.format(mode=mode)
问题在于where条件r.perm_{mode}(我的例子,这里就是r.perm_write),当数据库中没有perm_write=True的记录的记录时,这里的不可能查到任何ir.rule记录。这样就会导致我例子中出现的问题。
是不是哪里有问题?odoo这样的设计真是非常的奇怪。。
-
谢谢楼主,其实你已经分析到源码了。
因为odoo的权限的组成是权限组
,访问规则
,记录规则
。用户能否增删查改某个模型是通过该用户的权限组里判断有没有对应的模型访问规则。如果有系统就认为该用户有权限访问该模型。下一步就到记录规则的判断,对于很多基础数据模型是没有记录规则的,所以他这里判断是“有规则”才做限制,这里说的“有规则”是针对增,删,查,改独立查找规则(就像你上面的代码一样),如果找到对某个模型有写的规则,则根据domain再进行运算,如果没有找到则证明这个写动作没有限制。
换个说法记录规则其实可以理解为授权,你授权了这个domain的用户有什么权限。所以你第一段的是授权了创建人可以对不属于自己的todo.task,read和create的权限,第二段则是授权了属于自己的todo.task,read,create,write权限。 -
@Joshua 在 record rules问题-没写权限也可以修改记录 中说:
多基础数据模型是没有记录规则的
谢谢@Joshua !
如果odoo设计就是如此的话,这样的设计完全不符合正常逻辑。其实访问规则ACL已经对用户组“授权”。这样的设计会对权限控制带来一些不必要的麻烦,比如我上面加了两条记录规则后,虽然两条规则的perm_unlink都是False,我还是可以成功删除记录。我必须要告诉系统,用户组能删除哪些条件的记录后,系统才知道除此条件之外的记录不能删除,如果我不想让这个组的用户删除任何记录呢?我还需要定义一条perm_unlink为True,并且domain条件为[(1, '!=', 1)]的记录规则。。。 -
@Joshua ,谢谢,基本上明白了。简单归纳如下,不知道还有没有理解错误或偏差。
- perm_write = False时不表示该条record rule的用户组没有write权限(我想这也是界面上Record Rule记录对应的字段label叫做“Apply for Write ”而不是直接叫“Write”的原因)
- 要控制用户组对某些记录无法Write,则需要定义用户组对哪些条件(condition1)的记录可以Write,除去condition1之外的所有记录就不能Write了。
- 如果用户A属于不同的组,并且这些组中有多条record rule都对同一个model定义了能Write的条件(比如rule1可以Write的条件为condition1的记录,比如rule2可以Write的条件为condition2的记录),则用户A可以Write (condition1 OR condition2)的记录,不能write除 (condition1 OR condition2)之外的----也就是[not (condition1 OR condition2)]----记录。
不过。。。如果odoo直接设计成 perm_write = False的记录就无法Write,是不是更好理解一些??