前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >odoo 权限管理学习总结

odoo 权限管理学习总结

作者头像
授客
发布于 2023-03-14 01:53:08
发布于 2023-03-14 01:53:08
10.5K00
代码可运行
举报
文章被收录于专栏:授客的专栏授客的专栏
运行总次数:0
代码可运行

环境

odoo-14.0.post20221212.tar

base_user_role-12.0.2.1.2.zip

下载地址:

https://apps.odoo.com/apps/modules/12.0/base_user_role/

权限管理

简介

为了更好的熟悉权限,我们先来了解下用户,odoo中的用户分为三类:

  • 内部用户(Internal User): 企业内部的用户,拥有对系统内部的访问权限,也就是说有odoo后端的访问权限。
  • 门户用户(Portal): 非企业内部用户,通常为业务合作伙伴用户,拥有有限的资源访问权限。
  • 公共用户(Public): 面向公众的权限,可以理解为游客权限。

提示:管理员登录系统,激活开发者模式,即可在设置-用户详情页对用户类型进行编辑(Settings -> Users & Companies -> Users)

以上三类用户的信息都存在res_userres_partner表中,那么在odoo中如何区分用户类型以及如何做权限控制的呢?

为了解决上述问题,odoo采用了用户组机制。将用户划分为不同的组(一个用户可以归属多个用户组,一个用户组也可以拥有多个用户),然后给组分配权限,从而实现用户权限的管控及用户类型识别。

以上三种用户分别归属以下用户组:

  • 内部用户:base.group_user
  • 门户用户:base.group_portal
  • 公共用户:base.group_public

odoo也支持自定义用户组(Settings -> Users & Companies -> Groups),并为用户分配不同的用户组,及设置相关权限(菜单权限,视图权限,访问权限,记录规则)

此外,为了更方便的管理用户组,odoo还支持对用户组(group)进行分类:将多个用户组划分为一个用户组分类(category)。

  • 用户组和用户组分类:一个用户组分类可以拥有多个用户组,一个用户组仅归属一个用户组分类,属于1对多的关系。
  • 用户组和用户组的关系:用户组可以被用户组继承(伪继承),当继承某个用户组时,本组用户也会自动加入继承的用户组。如果一个用户属于多个用户组,那么该用户权限为用户组权限的并集,因此设计用户组权限时一定要考虑好组与组之间权限是否会发生冲突。

定义用户组(权限组)

示例:xml数据文件的方式定义菜单权限用户组

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<odoo>
    <data noupdate="1">
         <record id="estate_property_menu_groups" model="ir.module.category"><!-- id:供代码或者xml中引用,model:odoo的category模型-->         
             <field name="name">[房地产]模块菜单权限</field><!--用户组分类名称--> 
             <field name="sequence">1</field><!--组分类显示顺序、优先级-->
         </record>

         <!--########################
         [房地产]模块菜单
         ########################-->
        <record id="group_estate_property_root_menu" model="res.groups">
            <field name="name">Real Estate</field><!--用户组名称,阐明组的角色/目的-->
            <field name="category_id" ref="estate_property_menu_groups"/><!--指定用户组所属组分类-->
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/><!--定义用户组继承自哪些组,也就是说该用户组也拥有这些继承组的权限-->
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/><!--为用户组添加用户 base.user_root root用户 -->   
        </record>
    </data> 
</odoo>

说明:

noupdate:如果数据文件的内容预期只应用一次(只加载一次,安装或者更新模块时),则可以将noupdate设置为1。如果文件中的部分数据需要应用一次,则可以将文件的这部分放在<data-noupdate="1">中,如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<odoo>
    <data noupdate="1">
        <!-- Only loaded when installing the module (odoo-bin -i module) -->
        <operation/>
    </data>
    <!-- (Re)Loaded at install and update (odoo-bin -i/-u) -->
    <operation/>
</odoo>

参考连接:https://www.odoo.com/documentation/14.0/zh_CN/developer/reference/addons/data.html?highlight=noupdate

base.user_adminadmin用户(ID为2的用户,用户数据定义在odoo\addons\base\data\res_users_data.xml

base.user_root__system__用户(ID为1的用户,technical admin )

category定义相关数据存储ir_module_category表中

添加的group,可以在Settings -> Users & Groups -> Groups界面看到,组定义相关数据存储在res_groups表中

eval语法说明
  • (0, 0, values) 从提供的valueS字典创建新记录,形如(0, 0, {'author': user_root.id, 'body': 'one'})
  • (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中有个特殊的组base.group_no_one,需要开启Debug模式才可获取该组权限。可以利用该特性实现隐藏对象需求,比如针对一些常规下不需要显示的特殊字段,为其设置属性groups = "base.group_no_one",可以实现在非Debug模式下隐藏字段在视图中的显示。

菜单访问权限

应用实例

estate/security/security_estate_property_menu_groups.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<odoo>
    <data noupdate="1">
         <record id="estate_property_menu_groups" model="ir.module.category">
             <field name="name">[房地产]模块菜单权限</field>
             <field name="sequence">1</field>
         </record>

         <!--########################
         [房地产]模块菜单
         ########################-->
        <record id="group_estate_property_root_menu" model="res.groups">
            <field name="name">Real Estate</field>
            <field name="category_id" ref="estate_property_menu_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>

        <record id="group_estate_property_advertisements_menu" model="res.groups">
            <field name="name">Real Estate -> Advertisements</field>
            <field name="category_id" ref="estate_property_menu_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>

        <record id="group_estate_property_advertisements_properties_menu" model="res.groups">
            <field name="name">Real Estate -> Advertisements -> Properties</field>
            <field name="category_id" ref="estate_property_menu_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>
    </data>
</odoo>

estate/__manifest__.py

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding:utf-8 -*-
{
    'name': 'estate',
    'depends': ['base'],
    'data':[
        'security/security_estate_property_menu_groups.xml',
        //...略
    ]
}
菜单配置

views/estate_menus.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0"?>
<odoo>
    <menuitem id="test_menu_root" name="Real Estate" web_icon="estate,static/img/icon.png"
    groups="group_estate_property_root_menu">
        <menuitem id="test_first_level_menu" name="Advertisements" groups="group_estate_property_advertisements_menu">
            <menuitem id="estate_property_menu_action" action="link_estate_property_action" groups="group_estate_property_advertisements_properties_menu"/>
            <!---->
        </menuitem>
        <!---->
    </menuitem>
</odoo>

查看效果

注意:

实践时发现,通过界面点击,访问一些菜单界面时,会在菜单访问URL(参见菜单访问自动生成的URL)中自动添加model,view_type等参数,也就是说会自动访问模块相关模型,如果此时没有对应模型的访问权限(至少需要 read权限),那么即便拥有对应菜单的访问权限,界面上也看不到对应的菜单,笔者尝试过在浏览器中直接通过菜单链接(形如二级导航菜单http://localhost:8888/web#action=85&cids=1&menu_id=127)访问菜单,发现界面上不会显示任何菜单。

菜单访问自动生成的URL

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
http://localhost:8888/web#action=85&model=estate.property&view_type=kanban&cids=1&menu_id=70

通过上述方式实现的菜单访问权限控制,实际是通过控制是否隐藏菜单实现的,也就说,如果知道未授权菜单ID,还是可以通过菜单ID拼接菜单URL进行未授权访问。

模型访问权限(Access Rights,表级别)

当模型中没有定义任何访问权限时,odoo会认为没有任何用户可以访问数据,并在日志中打印:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
2022-12-14 09:01:38,994 32508 WARNING odoo odoo.modules.loading: The model estate.property has no access rules, consider adding one. E.g. access_estate_property,access_estate_property,model_estate_property,base.group_user,1,0,0,0 

访问权限被定义为ir.model.access 模型记录。每个访问权限关联一个模型,一个group(针对全局访问,没有组) 和一系列权限:create, read, writeunlink(等同于delete)。这些访问权限通常定义在security/ir.model.access.csv文件中。

test.model模型访问权限配置示例

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
access_test_model,access_test_model,model_test_model,base.group_user,1,0,0,0
  • id 自定义外部标识,模块中保持唯一,一般命名为 access_模型名称_用户组名称
  • name 自定义ir.model.access的名称,一般命名沿用id取值即可
  • model_id/idmodel_id:id 代指需要应用访问权限的模型。标准格式为 model_<model_name>,其中, <model_name>为模块中_name 替换._后的_name 的值
  • group_id/idgroup_id:id 代指需应用访问权限的组,即指定哪个组拥有如下访问权限,如果指定组不是在当前模块中定义的组,需要指定模块名称,形如module_name.groupName。组名一般命名为group_模型名称_权限,形如group_estate_property_read 。如果 group_id为空,则意味着授权给所有用户(非雇员(employees) ,比如 portal 或者public用户).
  • perm_read,perm_write,perm_create,perm_unlink: 分别代表create(创建), read(只读/查询), write (编辑/更新)和unlink(删除)权限,1表示有访问权限,0-表示无权限

具体到实际应用时,为了更灵活的权限管理,一般会为模型的增删改查操作分别定义权限。

授权给用户的模型访问权限,可通过点击Settings -> Users & Groups -> Users用户详情页Access Rights按钮查看。

应用实例

xml数据文件的方式定义房地产模型访问权限

estate/security/security_estate_property_model_groups.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<odoo>
    <data noupdate="1">
         <record id="estate_property_model_groups" model="ir.module.category">
             <field name="name">[房地产]模型权限</field>
             <field name="sequence">1</field>
         </record>


         <!--########################
         [房地产]模型
         ########################-->
        <!-- [房地产]模型 增删改查 -->
        <record id="group_estate_property_read" model="res.groups">
            <field name="name">[房地产]模型 只读</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>

        <record id="group_estate_property_write" model="res.groups">
            <field name="name">[房地产]模型 更新</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>

        <record id="group_estate_property_create" model="res.groups">
            <field name="name">[房地产]模型 创建</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>

        <record id="group_estate_property_delete" model="res.groups">
            <field name="name">[房地产]模型 删除</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>
    </data>
</odoo>

estate/security/ir.model.access.csv

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
access_estate_property_group_estate_property_read,access_estate_property_group_estate_property_read,model_estate_property,group_estate_property_read,1,0,0,0
access_estate_property_group_estate_property_write,access_estate_property_group_estate_property_write,model_estate_property,group_estate_property_write,1,1,0,0
access_estate_property_group_estate_property_create,access_estate_property_group_estate_property_create,model_estate_property,group_estate_property_create,1,0,1,0
access_estate_property_group_estate_property_delete,access_estate_property_group_estate_property_delete,model_estate_property,group_estate_property_delete,1,0,0,1

estate/__manifest__.py

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding:utf-8 -*-
{
    'name': 'estate',
    'depends': ['base'],
    'data':[
        'security/security_estate_property_menu_groups.xml',
        'security/security_estate_property_model_groups.xml',
        'security/ir.model.access.csv', 
        //...略
    ]
}
查看效果

打开用户编辑界面

记录规则(Record Rules,记录级别)

记录规则是允许某个操作必须满足的条件。记录规则按照访问权限逐条记录评估。

默认允许的记录规则:如果授予模型访问权限(Access Rights),并且没有规则适用于用户的操作和模型,则授予访问权限

记录规则保存在ir.rule模型表里,我们通过管理ir_rule表中的记录,即可控制记录的访问权限

定义规则

示例:xml数据文件的方式定义房地产模型记录访问规则

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<odoo>
    <data noupdate="0">
        <!--########################
        [房地产]模型记录规则
        ########################-->
        <record id="estate_property_record_read_rule" model="ir.rule"><!--id:外部规则id,供代码或者xml中引用 -->
            <field name="name">[房地产]模型记录规则</field>
            <field name="model_id" ref="model_estate_property"/>
            <field name="domain_force">[('create_uid', '=', user.id)]</field><!--仅显示用户自己创建的记录-->
            <field name="groups" eval="[(4, ref('group_estate_property_record_read'))]"/>
            <!--操作权限(仅作用于经domain_force滤后的记录)-->
            <field name="perm_read" eval="1"/>
            <field name="perm_write" eval="1"/>
            <field name="perm_create" eval="1"/>
            <field name="perm_unlink" eval="1"/>
        </record>
    </data>
</odoo>
  • name 规则名称
  • model_id 需要应用规则的模型,标准格式为 model_<model_name>,其中, <model_name>为模块中_name 替换._后值
  • groups 指定规则需要作用、不作用于哪些组(res.groups)。可以指定多个组。如果未指定组,规则为gobal规则。规则与组的关联关系存在rule_group_rel表中
  • global 根据“groups”计算,提供了对规则是否全局状态的轻松访问。eval="True"eval="1"则表示全局规则,eval="False"eval="0"则表示非全局规则
  • domain_force 指定为 domain的谓词,如果该domain与记录匹配,则规则允许所选操作,否则禁止。可以简单的理解为指定过滤条件,用户只能访问符合本过滤条件的记录,配置为 [(1,'=',1)]则表示匹配所有记录。domain是一个可以使用以下变量的python表达式:
    • time Python的 time 模块
    • user 以单例记录集(singleton recordset)表示的当前用户
    • company_id 当前用户,当前所选的公司的公司id(非记录集)。
    • company_ids 当前用户可以访问的公司ID列表(非记录集)。 查看Security rules 获取更多详细信息。

官方文档:

The perm_method have completely different semantics than for ir.model.access: for rules, they specify which operation the rules applies for. If an operation is not selected, then the rule is not checked for it, as if the rule did not exist. All operations are selected by default

译文:

perm_method 具有与 ir.model.access完全不同的语义:对于规则,它们指定规则需要应用的操作。如果(规则)未选择某个操作,则不会为该操作检查规则,就像该规则不存在一样。 规则默认适用所有操作。

笔者实践发现:

  • 如果创建了规则,但是没有授权给用户,那对于该用户来说,该规则不起作用,就像该规则不存在一样
  • perm_methodeval值不能同时为"False""0",否则会违反 ir_rule表的检查约束ir_rule_no_access_rightsCHECK (perm_read!=False or perm_write!=False or perm_create!=False or perm_unlink!=False)
  • 将任意一个perm_method设置为eval="True"eval="1" ,并将规则授权给用户,规则生效,所以我个人理解,目前记录规则,就是用于过滤记录的,通过domain_force控制哪些记录可以显示给用户

规则默认适用所有操作。

  • perm_create
  • ``perm_read`
  • perm_write
  • perm_unlink
  • 授权给用户的记录访问规则,可通过点击Settings -> Users & Groups -> Users用户详情页Record Rules按钮查看。
全局规则(Global rules) VS 组规则(group rules)

全局规则和组规则在组成和组合方式上存在很大差异:

  • 全局规则和全局规则之间取交集,如果两个全局规则都生效,则必须满足两者才能授予访问权限,这意味着添加全局规则总是会进一步限制访问。
  • 组规则和组规则之间取并集,如果两个组规则都生效,则满足其中之一就可以授予访问权限。这意味着添加组规则可以扩展访问,但不能超出全局规则定义的范围。
  • 全局规则集和组规则集之间取交集,这意味着添加到给定全局规则集的第一个组规则将限制访问。

危险提示

创建多个全局规则是有风险的,因为可能创建不重叠的规则集,这将删除所有访问权限

应用实例

estate/security/security_estate_property_model_groups.xml,新增group_estate_property_record_query

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<odoo>
    <data noupdate="1">
         <record id="estate_property_model_groups" model="ir.module.category">
             <field name="name">[房地产]模型权限</field>
             <field name="sequence">1</field>
         </record>


         <!--########################
         [房地产]模型
         ########################-->
        <!-- [房地产]模型 增删改查 -->
        <record id="group_estate_property_read" model="res.groups">
            <field name="name">[房地产]模型 只读</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>

        <record id="group_estate_property_write" model="res.groups">
            <field name="name">[房地产]模型 更新</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>

        <record id="group_estate_property_create" model="res.groups">
            <field name="name">[房地产]模型 创建</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>

        <record id="group_estate_property_delete" model="res.groups">
            <field name="name">[房地产]模型 删除</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>
    </data>
  
    <data noupdate="0">
        <!--########################
         [房地产]模型记录
         ########################-->
        <record id="group_estate_property_record_query" model="res.groups">
            <field name="name">[房地产]模型记录 查询</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>       
    </data>
</odoo>

estate/security/security_estate_property_model_record_rules.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<odoo>
    <data noupdate="0">
        <!--########################
        [房地产]模型记录规则
        ########################-->
        <record id="estate_property_record_read_rule" model="ir.rule">
            <field name="name">[房地产]模型记录规则</field>
            <field name="model_id" ref="model_estate_property"/>
            <field name="domain_force">[('create_uid', '=', user.id)]</field>
            <field name="groups" eval="[(4, ref('group_estate_property_record_read'))]"/>
            <field name="perm_read" eval="1"/>
            <field name="perm_write" eval="1"/>
            <field name="perm_create" eval="1"/>
            <field name="perm_unlink" eval="1"/>
        </record>
    </data>
</odoo>

estate/__manifest__.py

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#!/usr/bin/env python
# -*- coding:utf-8 -*-
{
    'name': 'estate',
    'depends': ['base'],
    'data':[        
        'security/security_estate_property_menu_groups.xml',
        'security/security_estate_property_model_groups.xml',
        'security/security_estate_property_model_record_rules.xml''security/ir.model.access.csv',
        //...略
    ]
}

查看效果

参考连接:https://www.odoo.com/documentation/14.0/zh_CN/developer/reference/addons/security.html#record-rules

字段权限(Field Access,字段级别)

ORM字段可以具有提供组列表的groups属性(值为逗号分隔的组XML ID列表,如groups='base.group_user,base.group_system'注意:groups属性值格式:moduleName.groupName,其中moduleNamegroupName组所在模块名称,必不可少

如果当前用户不在列出的组中,他将无权访问该字段:

  • 将自动从请求的视图中删除受限制的字段
  • fields_get()响应中删除受限制的字段

尝试(显式的)读取或写入受限字段会导致访问错误

修改estate\security\security_estate_property_model_groups.xml,添加group_estate_property_selling_price_field

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    <data noupdate="0">
        <!--########################
         [房地产]模型记录
         ########################-->
        <record id="group_estate_property_selling_price_field" model="res.groups">
            <field name="name">[房地产]模型 售价字段</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>
        <record id="group_estate_property_record_query" model="res.groups">
            <field name="name">[房地产]模型记录 查询</field>
            <field name="category_id" ref="estate_property_model_groups"/>
            <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
            <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
        </record>
    </data>

查看效果

修改estate\views\estate_property_views.xml视图selling_price字段,添加groups属性

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<field name="selling_price" string="Selling Price" groups="estate.group_estate_property_selling_price_field"/>

验证,发现界面上,未授权上述框选权限的用户已经看不到上述字段了

注意:通过为当前视图中目标字段添加groups属性实现的权限控制仅作用于当前视图,如果希望当前视图模型(Model)的所有视图中,对该字段实现统一的权限控制话,需要在模型定义中,为目标字段添加groups属性,如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
selling_price = fields.Float('selling price', digits=(8, 2), readonly=True, copy=False, groups="estate.group_estate_property_selling_price_field")

参考连接:https://www.odoo.com/documentation/14.0/zh_CN/developer/reference/addons/security.html#field-access

扩展:在页面从数据库加载视图时,会通过load_view接口,会调用fields_view_get方法,可以重写此方法以控制xml显示的效果(参考网络资料,未实践验证)

按钮权限(按钮级别)

类似字段权限控制,仅需在在对应视图中,为目标按钮<button>元素,添加groups属性即可。

角色定义

新增并安装base_user_role模块

base_user_role模块的作用可以简单理解为,按自定义维度将所需权限组组合在一起,组成角色,实现批量授权的功能。

解压下载的base_user_role-12.0.2.1.2.zip文件,对解压后的部分文件做如下修改:

base_user_role\models\user.pybase_user_role\models\role.py

去除上述两个文件中的所有@api.multi修饰符,解决安装报错问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
AttributeError: module 'odoo.api' has no attribute 'multi'

说明:Odoo 13.0开始,移除multimulti作为默认实现。

base_user_role/views/role.xml

修改

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<record model="ir.actions.act_window" id="action_res_users_role_tree">
    <field name="name">Roles</field>
    <field name="type">ir.actions.act_window</field>
    <field name="res_model">res.users.role</field>
    <field name="view_type">form</field>
    <field name="view_id" ref="view_res_users_role_tree"/>
</record>

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<record model="ir.actions.act_window" id="action_res_users_role_tree">
    <field name="name">Roles</field>
    <field name="type">ir.actions.act_window</field>
    <field name="res_model">res.users.role</field>
    <field name="view_mode">form</field>
    <field name="view_id" ref="view_res_users_role_tree"/>
</record>

解决安装报错问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
odoo.tools.convert.ParseError: while parsing file:/d:/codepojects/odoo14/custom/base_user_role/views/role.xml:63, near

然后,将解压目录下base_user_role整个文件夹拷贝odoo14\custom目录下,最后,重启服务并安装该模块。

安装成功后,Settings -> Users & Companies菜单下,将新增Roles子菜单(笔者实践发现无法通过该页面新增角色并关联用户),Settings -> Users & Companies -> Users 用户记录详情页将新增Roles Tab页

新增并安装estate_role模块

为了统一管理权限组,考虑新增一个单独的应用模块estate_role,模块文件组织结构如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
custom/estate_role
│  __init__.py
│  __manifest__.py
│
├─security
│      security_estate_property_menu_groups.xml
│      security_estate_property_model_groups.xml
│      security_roles.xml
│
└─views

odoo14\custom\estate_role\security\security_roles.xml

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<odoo>
    <data noupdate="1">
        <record id="group_role_base_user" model="res.users.role">
            <field name="name">基础用户</field>
            <field name="implied_ids" eval="[
                    (4, ref('base.group_user')),
                ]"/>
        </record>

        <record id="group_role_multi_company" model="res.users.role">
            <field name="name">多公司</field>
            <field name="implied_ids" eval="[
                    (4, ref('base.group_multi_company')),
                ]"/>
        </record>

        <record id="group_role_devops" model="res.users.role">
            <field name="name">运维</field>
            <field name="implied_ids" eval="[
                    (4, ref('estate_role.group_estate_property_root_menu')),
                    (4, ref('estate_role.group_estate_property_advertisements_menu')),
                    (4, ref('estate_role.group_estate_property_advertisements_properties_menu')),
                    (4, ref('estate_role.group_estate_property_read')),
                    (4, ref('estate_role.group_estate_property_write')),
                    (4, ref('estate_role.group_estate_property_create'))
                ]"/>
        </record>
    </data>
</odoo>

odoo14\custom\estate_role\__init__.py

文件内容为空

odoo14\custom\estate_role\__manifest__.py

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
    "name": "Estate Roles",
    "license": "LGPL-3",
    "depends": ["base_user_role"],
    "data": [
        "security/security_estate_property_menu_groups.xml",
        "security/security_estate_property_model_groups.xml",
        "security/security_roles.xml"
    ],
    "installable": True,
}

说明:odoo14\custom\estate\__manifest__.py data列表中已去除上述两个groups文件

重启服务并安装estate_role模块

查看效果

用户详情页面,查看用户权限,发现新增 User Roles

编辑用户,勾选图中的角色,保存,发现和角色关联的权限组都会被自动勾选了。

注意:

  • 取消勾选已授予的角色,并保存,不会自动取消勾选角色关联的权限组,即取消授予角色操作,不会取消通过授予角色授予给用户的权限组
  • 已授予角色给用户的情况下,取消勾选某个权限组并保存,如果该权限组和授予给用户的角色关联,则无法取消勾选的权限组,因为角色关联了该权限组
  • 权限页面勾选并保存的角色,不会在用户详情页的Roles Tab页中显示
  • 除了通过在用户详情页-权限(Access Rights)Tab页面,选取角色为用户批量授权外,还可以在用户详情页的Roles Tab页中为用户添加角色来实现批量授权。

参考连接

https://www.odoo.com/documentation/14.0/zh_CN/developer/reference/addons/security.html

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
odoo 开发入门教程系列-模型之间的关系(Relations Between Models)
上一章介绍了为包含基本字段的模型创建自定义视图。然而,在任何真实的业务场景中,我们都需要不止一个模型。此外,模型之间的链接是必要的。人们可以很容易地想象一个模型包含客户,另一个模型则包含用户列表。你可能需要参考任何现有业务模型上的客户或用户。
授客
2023/04/01
4.7K0
odoo 开发入门教程系列-模型之间的关系(Relations Between Models)
odoo 开发入门教程系列-安全-简介
前一章中我们已经创建了第一个打算用于存储业务数据的表。在odoo这样的一个商业应用中,第一个考虑的问题就是谁(Odoo 用户(或者组用户))可以访问数据。odoo为指定用户组用户提供了一个安全的数据访问机制。
授客
2023/03/26
1K0
Odoo 菜单定义和修改学习总结
指定菜单图标,格式:模块名称,图标路径,形如estate,static/img/icon.png 意为estate模块下的static/img/icon.png图标。其中图标路径,一般是相对于模块根目录的相对路径
授客
2023/02/26
1.5K0
odoo 开发入门教程系列-继承(Inheritance)
Odoo的一个强大方面是它的模块化。模块专用于业务需求,但模块也可以相互交互。这对于扩展现有模块的功能非常有用。例如,在我们的房地产场景中,我们希望在常规用户视图中直接显示销售人员的财产列表。
授客
2023/04/23
2.5K0
odoo 开发入门教程系列-继承(Inheritance)
odoo ORM API学习总结兼orm学习教程
默认的,字段的标签(Lable,即用户可见字段名称)为对应字段名称开头字母改成大写后的值,可通过 string 字段属性改成修改字段Label
授客
2023/03/12
14K0
odoo ORM API学习总结兼orm学习教程
odoo 开发入门教程系列-QWeb简史
到目前为止,我们的房地产模块的界面设计相当有限。构建列表视图很简单,因为只需要字段列表。表单视图也是如此:尽管使用了一些标记,如<group>或<page>,但在设计方面几乎没有什么可做的。
授客
2023/04/28
2.4K0
odoo 开发入门教程系列-QWeb简史
odoo 开发入门教程系列-计算的字段和变更(Computed Fields And Onchanges)
模型之间的关系是任何Odoo模块的关键组成部分。它们对于任何业务案例的建模都是必要的。然而,我们可能需要给定模型中字段之间的链接。有时,一个字段的值是根据其他字段的值确定的,有时我们希望帮助用户输入数据。
授客
2023/04/02
3.4K0
odoo 开发入门教程系列-计算的字段和变更(Computed Fields And Onchanges)
odoo wizard界面显示带复选框列表及勾选数据获取
如下图(非实际项目界面截图,仅用于介绍本文主题),打开记录详情页(form视图),点击某个按钮(图中的"选取ffers"按钮),弹出一个向导(wizard)界面,并将详情页中内联tree视图("Offers" Tab页)的列表记录展示到向导界面,且要支持复选框,用于选取目标记录,然执行目标操作。
授客
2023/05/24
5.6K0
odoo wizard界面显示带复选框列表及勾选数据获取
odoo 开发入门教程系列-一个新应用
form视图顶层区域概括了房产的重要信息,比如name,Property Type, Postcode等等。
授客
2023/03/25
1.4K0
odoo 开发入门教程系列-一个新应用
odoo 开发入门教程系列-一些用户界面
上一章,我们通过CSV文件添加了数据。当需要添加数据格式简单时,用CSV格式还是很方便的,当数据格式更复杂时(比如视图架构或者一个邮件模板),我们使用XML格式。比如包含HTML tags的 help field。虽然可以通过CSV文件加载这样的数据,但是使用XML更方便。
授客
2023/03/26
3.3K0
odoo 开发入门教程系列-一些用户界面
odoo context上下文用法总结
Model.with_context([context][, **overrides]) -> records[源代码]
授客
2023/03/09
2.3K0
odoo 给列表视图添加按钮实现数据文件导入
odoo14\custom\estate\models\estate_customer.py
授客
2023/02/26
3.7K0
odoo 给列表视图添加按钮实现数据文件导入
odoo 开发入门教程系列-模块交互
在上一章中,我们使用继承来修改模块的行为。在我们的房地产场景中,我们希望更进一步,能够为客户生成发票。Odoo提供了一个开发票模块,因此直接从我们的房地产模块创建发票是很简单的,也就是说,一旦某个房产设置为“已售出”,就会在Invoicing应用程序中创建发票
授客
2023/04/24
1.9K0
odoo 开发入门教程系列-模块交互
odoo 开发入门教程系列-基本视图
在上一章中已经看到,odoo能够为给定模型生成默认视图。实际上,默认视图对于业务应用程序来说是不可接受的。相反,我们至少应该以逻辑的方式组织各个字段。
授客
2023/03/27
3.6K0
odoo 开发入门教程系列-基本视图
odoo Actions学习总结
action可以存储在数据库中,也可以作为字典直接返回,例如按钮方法。所有Action都有两个强制属性:
授客
2023/03/09
2.9K0
odoo 开发入门教程系列-模型和基本字段
在上一章的末尾,我们创建一个odoo模块。然而,此时它仍然是一个空壳,不允许我们存储任何数据。在我们的房地产模块中,我们希望将与房地产相关的信息(名称(name)、描述(description)、价格(price)、居住面积(living area)…)存储在数据库中。odoo框架提供了数据库交互的工具
授客
2023/03/25
2.6K0
odoo 开发入门教程系列-模型和基本字段
odoo 开发入门教程系列-约束(Constraints)
上一章介绍了向模型中添加一些业务逻辑的能力。我们现在可以将按钮链接到业务代码,但如何防止用户输入错误的数据?例如,在我们的房地产模块中,没有什么可以阻止用户设置负预期价格。
授客
2023/04/08
1.7K0
odoo 开发入门教程系列-约束(Constraints)
odoo 给form表单视图内联列表添加按钮
odoo14\custom\estate\models\estate_customer.py
授客
2023/02/26
1.6K0
odoo 给form表单视图内联列表添加按钮
Salesforce学习 权限管理
Salesforce 对于权限的管理是非常严谨的并且支持不同维度的权限控制。常用的有Profiles(简档)、Permissions Set(权限集)、Role Hierarchy(角色层级结构)和Organization-Wide(组织范围)这四项用来控制控制相应的权限。
repick
2020/01/23
2.4K0
odoo 为form表单视图添加chatter功能
如图,给表单新增一个类似聊天的窗口,当记录一些表单活动(本例为自动记录当前记录状态变化)
授客
2023/02/26
8690
odoo 为form表单视图添加chatter功能
相关推荐
odoo 开发入门教程系列-模型之间的关系(Relations Between Models)
更多 >
LV.1
家里蹲网络科技公司高级软件测试工程师
目录
  • 环境
  • 权限管理
    • 简介
    • 定义用户组(权限组)
      • eval语法说明
    • 菜单访问权限
      • 应用实例
    • 模型访问权限(Access Rights,表级别)
      • 应用实例
    • 记录规则(Record Rules,记录级别)
      • 定义规则
      • 全局规则(Global rules) VS 组规则(group rules)
      • 应用实例
    • 字段权限(Field Access,字段级别)
    • 按钮权限(按钮级别)
    • 角色定义
      • 新增并安装base_user_role模块
      • 新增并安装estate_role模块
      • 查看效果
  • 参考连接
加入讨论
的问答专区 >
1先锋会员擅长3个领域
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档