7

Odoo16—权限控制 - HeavenSpring

 4 months ago
source link: https://www.cnblogs.com/heavenspring/p/odoo-access-control.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

odoo的权限控制是通过用户组来实现的,在用户组中配置控制权限,然后再添加用户到用户组中,从而实现对用户的访问和操作权限控制。一个用户可以属于多个用户组,用户最终的权限范围取决于所属用户组权限的并集。

在用户组中可以声明哪些数据的控制权限呢?我们打开开发者模式,通过“设置-用户&公司-用户组”导航到用户组,点击任一用户组,打开如下截图界面:

1044257-20231220171752977-1651646818.png

我们看到可以为一个用户组配置以下几方面的控制:菜单、视图、访问权限、记录规则。既然如此,那就赶快创建一个用户组,然后配置权限,然后添加用户,然后……不就可以达到我想要的权限控制目的了吗。在进行下一步操作之前,我们先介绍几个概念,还是用图片来说明吧:

1044257-20231220171851676-416631038.png

1.用户组分类

我们创建用户组的时候,通常希望把用户组放在自定义的权限组分类中,以便管理维护;但是发现在odoo系统中没有创建用户组分类的地方,怎么办呢?原来odoo的用户组分类只能通过配置文件创建。

接下来我们就参考odoo自身模块,通过xml配置文件创建,大致有三个步骤:

1.在模块的security目录中创建xml配置文件:logistics_security.xml

2.在manifest.py清单文件中引入logistics_security.xml文件

1044257-20231220171926432-877040869.png

 3.编辑配置文件:

1 <?xml version="1.0" encoding="utf-8"?>
2 <odoo>
3     <record id="category_custom_logistic" model="ir.module.category">
4         <field name="name">物流管理</field><!--用户组分类名称-->
5         <field name="sequence">1</field> <!--组分类显示顺序、优先级-->
6     </record>
7 </odoo>

以上配置完成后,执行模块升级操作,我们就可以看到新创建的用户组分类了。

1044257-20231220172034948-467750505.png
1044257-20231220172044332-684904910.png

2.用户组

odoo将用户类型分成3种,在创建用户的时候可以看到;3种用户类型分别对应3种不同的内置用户组:

1044257-20231220172106085-1884919785.png
  • 内部用户:base.group_user
  • 门户用户:base.group_portal
  • 公开用户:base.group_public

这3个是系统内置的用户组,可以通过odoo管理系统查看:

1044257-20231220172333426-464258708.png

自定义用户组有两种创建方式,一种是直接在odoo管理系统中进行配置,通过“设置-用户&公司-用户组”菜单导航,即可进行操作;另一种依然是通过xml配置文件进行配置操作。通常我们希望在模块安装后就可以直接使用,故此我们略过第一种创建方式,这里只介绍第二种通过xml配置文件创建用户组的方式。

1.分别添加管理员组和普通用户组的配置,编辑security/logistics_security.xml文件:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <odoo>
 3     <record id="category_custom_logistic" model="ir.module.category">
 4         <field name="name">物流管理</field>        <!--用户组分类名称-->
 5         <field name="sequence">1</field>        <!--组分类显示顺序、优先级-->
 6     </record>
 7     <record id="groups_logistic_manager" model="res.groups">
 8         <field name="name">管理员</field>
 9         <field name="category_id" ref="category_custom_logistic"/>
10     </record>
11     <record id="groups_logistic_user" model="res.groups">
12         <field name="name">员工</field>
13         <field name="category_id" ref="category_custom_logistic"/>
14     </record>
15 </odoo>

2.执行模块升级操作,即可看到新添加的用户组数据:

1044257-20231220172428397-1466237378.png

用户名和密码我们一般是通过odoo管理系统进行创建,因为我们不能提前确定好到底用什么用户名和密码,只有在实施的时候才能确定。管理系统如何创建用户,如何添加到用户组,操作简单,就不做介绍了。这里我们介绍下odoo系统中base.user_root和 base.user_admin这两个特殊用户的的别:

  • base.user_root:odoo中的超级用户,在系统中具有最高级别的权限。通常用于系统的初始化和特殊的管理任务,具有对系统中所有对象和功能的完全访问权限,而不受用户组的权限限制。
  • base.user_admin:odoo中的管理员用户,具有系统管理权限,例如安装/卸载模块、配置用户权限、管理数据库等。但这个用户受用户组的权限限制。

为什么说它们是用户而不是用户组呢,可以参考odoo基础模块中对他们的定义;以下截图的最顶部是代码文件的相对路径:

1044257-20231220172447632-868413655.png
1044257-20231220172455331-1160646323.png

菜单权限可以通过odoo管理系统进行添加,也可以通过配置文件进行初始化,通常我们会选择后者。目前最常用的方式就是在菜单定义的地方添加用户组即可实现,比如我们为档案管理菜单添加上面定义的两个用户组:

1044257-20231220172511878-582160546.png

 执行模块升级操作,就可以发现这两个用户组下面有了档案管理的菜单权限。

1044257-20231220172527615-728022550.png

 与此同时,我们发现管理员用户没有了档案管理的菜单权限,如下图:

1044257-20231220172545424-1766511174.png

 出现这种情况的原因是因为管理员账号本身受用户组权限的影响,我们把档案管理的菜单权限只分配给了以上定义的两个用户组,管理员账号不在当前的两个用户组中,所以就无法访问了。如果我们想要管理员拥有档案管理菜单的访问权限,我们可以在定义用户组的时候,初始管理员账号,代码如下:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <odoo>
 3     <record id="category_custom_logistic" model="ir.module.category">
 4         <field name="name">物流管理</field>        <!--用户组分类名称-->
 5         <field name="sequence">1</field>        <!--组分类显示顺序、优先级-->
 6     </record>
 7     <record id="groups_logistic_manager" model="res.groups">
 8         <field name="name">管理员</field>
 9         <field name="category_id" ref="category_custom_logistic"/>
10         <field name="users" eval="[(4, ref('base.user_admin'))]"/><!--为用户组添加管理员用户 -->  
11     </record>
12     <record id="groups_logistic_user" model="res.groups">
13         <field name="name">员工</field>
14         <field name="category_id" ref="category_custom_logistic"/>
15         <field name="users" eval="[(4, ref('base.user_admin'))]"/><!--为用户组添加管理员用户 -->  
16     </record>
17 </odoo>

执行模块升级操作,此时管理员已经有了档案管理菜单的访问权限:

1044257-20231220172627377-222188252.png

两个用户组中也有了初始的管理员用户:

1044257-20231220172645990-456874572.png

在这里我们对eval中的表达式做简要的说明:

  • (0, 0, values) 从提供的valueS字典创建新记录
  • (2, ID, values) 使用values字典中的值更新id值=ID的现有记录
  • (2, ID) 删除id=ID这条记录(调用unlink方法,删除数据及整个主从数据链接关系)
  • (3, ID) 删除主从数据的链接关系但是不删除这个记录
  • (4, ID) 为id=ID的数据添加主从链接关系
  • (5) 去除所有的链接关系,也就是循环所有的从数据且调用(3,ID)
  • (6, 0, [IDs]) 用IDs中的记录替换原来链接的记录(相当于先执行(5)再循环执行(4, ID))

在odoo自带的模块中,最常用的就是4,其它的偶尔会用到;大家在具体的使用场景中,更容易理解。

视图权限的配置在odoo系统中很少用到。在odoo中,视图权限通常是通过模型权限继承获得的。如果已经为模型设置了权限,那么这些权限通常会自动应用到相关的视图上,无需额外的配置。

这里我们对QWeb视图的权限配置做简要说明,因为QWeb通常用于网页和报表,和模型之间没有依赖关系,所以就无法通过模型权限的继承来获取。我们来看odoo自带模块中的代码:

1 <!--代码路径:odoo\addons\web\views\lazy_assets.xml-->
2 <?xml version="1.0" encoding="utf-8"?>
3 <odoo>
4   <!--表示为内部用户添加assets_backend_legacy_lazy视图的访问权限-->
5   <template id="assets_backend_legacy_lazy" name="Lazy assets for legacy Views" groups="base.group_user">
6     <t t-call-assets="web.assets_backend_legacy_lazy" />
7   </template>
8 </odoo>

就是通过为视图指定所属的组来实现的,与菜单的配置方式相似。这里为内部用户添加了assets_backend_legacy_lazy视图的访问权限,可以在截图中看到效果。

1044257-20231220172928145-623741850.png

6.访问权限

访问权限就是以上提到的模型权限,权限配置有读取访问、写入访问、创建访问、删除访问4个方面,如下截图:

1044257-20231220172955085-2038970265.png

 可以在odoo管理系统中添加,也可以通过配置文件在模块安装的时候初始化,这里我们介绍通过配置文件添加的方式。在模块的security目录中创建ir.model.access.csv文件,配置内容主要是以下选项:

  • id 自定义外部标识,模块中保持唯一,一般命名为 access_模型名称_用户组名称
  • name 自定义ir.model.access的名称,一般命名沿用id取值即可
  • model_id:id 标准格式为 model_name,其中name 为模块中模型名称替换 . 为 _ 后的值
  • group_id:id 权限组id
  • perm_read 读取访问,1表示有访问权限,0表示无权限
  • perm_write 写入访问,1表示有访问权限,0表示无权限
  • perm_create 创建访问,1表示有访问权限,0表示无权限
  • perm_unlink 删除访问,1表示有访问权限,0表示无权限

我们为先前创建的权限组定义不同的操作权限:

 1 id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
 2 access_waybill_manager,access.waybill.manager,model_waybill,groups_logistic_manager,1,1,1,1
 3 access_waybill_user,access.waybill.user,model_waybill,groups_logistic_user,1,1,1,1
 4 access_waybill_detail_manager,access.waybill.detail.manager,model_waybill_detail,groups_logistic_manager,1,1,1,1
 5 access_waybill_detail_user,access.waybill.detail.user,model_waybill_detail,groups_logistic_user,1,1,1,1
 6 access_goods_manager,access.goods.manager,model_goods,groups_logistic_manager,1,1,1,1
 7 access_goods_user,access.goods.user,model_goods,groups_logistic_user,1,1,1,0
 8 access_package_manager,access.package.manager,model_package,groups_logistic_manager,1,1,1,1
 9 access_package_user,access.package.user,model_package,groups_logistic_user,1,1,1,0
10 access_shipper_manager,access.shipper.manager,model_shipper,groups_logistic_manager,1,1,1,1
11 access_shipper_user,access.shipper.user,model_shipper,groups_logistic_user,1,1,1,0
12 access_receiver_manager,access.receiver.manager,model_receiver,groups_logistic_manager,1,1,1,1
13 access_receiver_user,access.receiver.user,model_receiver,groups_logistic_user,1,1,1,0
14 access_city_manager,access.city.manager,model_city,groups_logistic_manager,1,1,1,1
15 access_city_user,access.city.user,model_city,groups_logistic_user,1,1,1,0
16 access_rate_manager,access.rate.manager,model_rate,groups_logistic_manager,1,1,1,1
17 access_rate_user,access.rate.user,model_rate,groups_logistic_user,1,0,0,0

csv表格模式显示如下截图所示:

1044257-20231220173116691-1541292209.png

 执行模块升级操作,即可看到添加好的管理员员工这两个用户组的访问权限数据:

1044257-20231220173148264-1745419094.png
1044257-20231220173203270-1719576640.png

7.记录规则

记录规则是在访问权限的基础上,对数据访问的进一步限制;我们首先分析odoo自带模块中的配置代码:

 1     <!--代码所在文件相对路径:odoo\addons\mail\security\mail_security.xml-->
 2 
 3     <record id="res_users_settings_volumes_rule_user" model="ir.rule">
 4         <field name="name">res.users.settings.volumes: access their own entries</field>
 5         <field name="model_id" ref="model_res_users_settings_volumes"/>
 6         <field name="groups" eval="[Command.link(ref('base.group_user'))]"/>
 7         <field name="domain_force">[('user_setting_id.user_id', '=', user.id)]</field>
 8         <field name="perm_read" eval="True"/>
 9         <field name="perm_write" eval="True"/>
10         <field name="perm_create" eval="True"/>
11         <field name="perm_unlink" eval="True"/>
12     </record>

1.通过domain_force来限定模型数据的访问范围,domain_force是一个可以使用以下变量的python表达式:

  • time Python的 time 模块
  • user 标识当前用户
  • company_id 当前用户所选择的公司id
  • company_ids 当前用户可以访问的公司id列表
  • 官方文档参考地址:record-rules

2.通过groups来指定记录规则所属的用户组,如果记录规则未指定用户组,那么当前规则就是全局规则。全局规则会影响到所有的用户,不管用户属于哪个用户组。通过全局规则,可以在模型上设置默认的访问策略,例如限制用户只能访问属于自己公司的记录,配置如下所示:

1 <record id="global_rule" model="ir.rule">
2     <field name="name">Global Rule</field>
3     <field name="model_id" ref="your_module.your_model"/>
4     <field name="domain_force">[('company_id', '=', user.company_id.id)]</field>
5 </record>

关于跨公司数据共享或是只能访问公司自身数据的策略,可以参考官方说明文档:security-rules

3.通过perm_read/perm_write/perm_create/perm_unlink来控制过滤之后的数据的访问权限:

最后我们一起看下odoo自身的记录规则在系统中的显示:

1044257-20231220172816240-1350448406.png

 至于字段级别的控制,我们在此就不做介绍了,感兴趣的朋友异步odoo官方说明文档:field-access

点击阅读原文:菜园工程师


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK