暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Odoo丨一文让你弄懂Odoo的用户、组与权限

400





Odoo

神州数码云基地

在 Odoo 上的尝试、调研与分享




本期内容 

 Odoo中的权限规则的使用 



Odoo是基于Python语言编写的全球流行的开源管理套件,它的各个应用程序能完美集成在一起,能实现业务流程自动化,省时省力,用户体验好。


Odoo的能力很强大,可以实现很多功能嫁接,本期我们将从规则权限带大家详细地了解如何在Odoo中使用,灵活的分配用户权限。




权限的介绍 


为了熟悉权限,首先我们需要了解用户,Odoo中的用户分为三类:



  • 内部用户: 企业内部的用户,拥有对系统内部的访问权限,具体根据不同的角色权限不同而不同。


  • 门户用户: 非企业内部用户,通常为业务合作伙伴用户,拥有有限的资源访问权限。


  • 公共用户: 面向公众的权限,可以理解为游客权限。


管理员登录系统,激活开发者模式,即可在设置-用户详情对用户类型进行编辑:



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


这里我们需要了解用户组(group),用户组为多个用户的集合,一个用户可以属于多个用户组,一个用户组也可以有多个用户。


权限与用户组关联,通过对用户组的控制可以完成对于菜单,页面,表,数据,字段,按钮等权限的控制。


以上三种用户类型,即属于三个用户组:


  • 内部用户:base.group_user

  • 门户用户:base.group_portal

  • 公共用户:base.group_public


同样,我们在下文中自己定义的用户组,在用户详情页面也可以进行查看、编辑,并为用户分配不同的用户组:



此外,多个用户组(group)可以属于一个用户组分类(category),这方便我们对用户组进行操作管理。



  • category与group:权限分为category(组分类)与group(用户组),每一个group都属于一个category,一个category可以有多个group,属于一对多的关系。


  • 页面中管理用户组:用户组管理页面:设置-用户与公司-群组,在debug模式下可以管理员在管理页面中管理全部的用户组,通过用户组可以限制用户对于菜单,视图,某个模型增删改查,以及配置权限规则对于某些模型中的数据进行过滤。


  • 对于视图中具体字段的管理需要在代码层面进行实现,例:某个字段对于某些用户组可编辑,对于另外的用户组是只读。


  • 组与组之间的关系:group之间可以互相继承,该group中的用户也将自动加入继承的group,如果一个用户属于多个group,用户的权限则会取group的并集,因此设计用户组权限时一定要考虑好组与组之间权限是否会发生冲突。



创建权限 


 通过配置security下的 

xml文件创建权限: 


# xml中的权限配置


    <odoo>
      <data>
       <record id="base_material_page_category" model="ir.module.category">
          <!--id标签:设置id的值,在代码或者xml中可以通过id来引用该标签,model标签:ir.module.category是odoo的category模型-->
         <field name="name">物料管理-页面</field> <!--组的名字,如:员工-->
       </record>
       <record id="base_material_search_group" model="res.groups">
          <field name="category_id" ref="base_material_page_category"/>
          <!--指定该group属于哪一个category-->
         <field name="name">物料管理-查询</field>
         <field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
          <!--定义该用户组继承自那些group,也就是说这个组也拥有这些继承组的权限-->
         <field name="users" eval="[(4, ref('base.user_root')), (4, ref('base.user_admin'))]"/>
         <!--为该用户组添加用户-->
       </record>
     </data>
    </odoo>


    # eval语法:


    · (0, 0, {values}) 根据values的值新建一条记录


    · (2, ID, {values}) 更新id=ID的记录,(写入values的值)


    · (2, ID) 删除id=ID这条记录,(调用unlink方法,删除数据及整个主从数据链接关系)


    · (3, ID) 切断主从数据的链接关系但是不删除这个记录


    · (4, ID) 为id=ID的数据添加主从链接关系


    · (5) 删除所有的从数据的链接关系,也就是向所有的从数据调用(3, ID)


    · (6, 0, [IDs]}) 用IDs中的记录替换原来的记录(相当于先执行(5)在循环执行(4, ID))



    修改xml后在升级应用,可以在设置中某个用户下看见此页面效果:


    权限下拉框效果:


    在页面中实现权限下拉框,需逐级继承上级Group,最后一级Group拥有以上所以Group权限。



     代码中新建权限:


    Group数据存在数据库中res_group表中,Category 存在数据库中 ir_module_category 表中.代码中新建Group与Category直接往 ir_module_category 表与 res_group 表中插入数据即可。


    需要在代码和 xml 中以 eval 引用Group时,需要权限的ID(如上图base.group_user),此ID保存在ir_model_data 表中。


    创建Group与Category时,向该表插入一条数据,即可通过ID引用Group或者Category。


    # 新建Category:


      #操作ir.module.category需要管理员权限,如果提示权限不足,可以使用sudo()切换至超级用户
      category = self.env['ir.module.category'].create({
      'create_uid': self.env.user['id'],
      'name': field_name,
      'visible': 't',
      })


      # 新建group:


        group = self.env['res.groups'].sudo().create({
        'name': 'name',#group名称
        'category_id': category.id,#对应的category的id,可以使用ref取得,例:self.env.ref("xc_material.extend_material_tree_view").id
        'create_uid': self.env.user['id'],
        })


        需要在代码中直接以权限组名字使用新增的Category以及Group,则需要 ir.model.data 中新增一条数据:


        向 ir_model_data 中插入


          request.env['ir.model.data'].create({
             'noupdate': 'f',
             'name': '',#这里的name即为xml中<record>标签的id属性
             'module': 'xc_material',#自定义
             'model': 'ir.module.category',
             'res_id': category.id,#对应group的id或者category的id
          })




          表级别权限 


          表级别权限,也就是对象的访问权限,是定义在 security/ir.model.access.csv 文件中的。


            id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_base_material,access_base_material,model_base_material,base.group_user,1,1,1,1 access_extend_material,access_extend_material,model_extend_material,base.group_user,1,1,1,1



            • ID:可以随便取,但是在一个模块中是唯一的,一般取名为 access_模型名_特定用户组名(用下划线连起来)


            • Name: 可以随便取,一般命名沿用模型名用“.”连接加 用户组名


            • Model:id:要做权限控制的Model,格式写法是 模块名.model_模块名(中间的‘.’换成‘_’),如果model在此模块中,可以省略模块名,如product.model_product_product


            • Group:id:组的ID,不是本模块的组,要在前面加上模块名,如:account.group_account_user


            • perm_read,perm_write,perm_create,perm_unlink:这些就是具体的权限:读写增删,1 有权限,0 无权限




            记录级别权限 


            记录级别权限就是记录规则。记录规则的权限存放在 "ir.rule "中,我们通过管理 ir_rul e表中的记录,即可以控制记录的权限。


            # xml新建权限规则


              <record id="quotation_group_pre_sale_rule" model="ir.rule">
              <field name="name">售前权限</field><!--记录规则名称-->
              <field name="model_id" ref="model_quotation"/><!--模型id,ref可以理解为一个函数用来获取模型的id-->
              <field name="domain_force">[('create_uid', '=', user.id)]</field><!--domain_force,记录规则查看条件-->
              <field name="groups" eval="[(4, ref('quotation_group_pre_sale'))]"/><!--指定权限,可以是多个,定义的权限组的id-->
              <field name="perm_read" eval="True"/>
              <field name="perm_write" eval="True"/>
              <field name="perm_create" eval="True"/>
              <field name="perm_unlink" eval="True"/><!--增删改查权限-->
              </record>


              同上,如果在代码中定义权限规则,直接向 ir.rule 表中以及 ir.model.data 中插入一条数据即可。




              菜单权限 


               第一种 


              所有的记录,都可以用这种方法添加及修改,如果ID存在则修改这条记录,如果不存在ID,就添加该记录。


                <record id="menu_finance" model="ir.ui.menu">
                       <field name="name">Invoicing</field>
                       <field name="web_icon">account,static/description/icon.png</field>
                       <field name="sequence">40</field>
                       <field name="groups_id" eval="[(6, 0, [ref('account.group_account_user'), ref('account.group_account_manager'), ref('account.group_account_invoice')])]"/>
                </record>


                 第二种 


                简洁写法:


                  <menuitem name="Invoicing" id="menu_finance" groups="group_account_user,group_account_manager,group_account_invoice" web_icon="account,static/description/icon.png" sequence="40"/>


                  上面的2个xml表示menu_finance这个菜单只能被group_account_user,group_account_manager,group_account_invoice 三个用户组访问。


                  有上级菜单,加parent属性,如果上级菜单不在本模块中,需要加模块名如:account.menu_finance:


                    <menuitem id="menu_finance_reports" name="Reports" parent="menu_finance" sequence="5" groups="group_account_invoice"/>




                    字段权限  


                     field标签有一个Groups属性 


                    field标签有一个groups属性,可以是一个或多个权限角色,多个权限角色使用逗号分隔。


                    对拥有Groups权限组的人可见。值是定义的权限组的ID,例如:


                      def fields_view_get(self, view_id=None, view_type='tree', toolbar=False,submenu=False):
                      res = super(ExtendMaterial, self).fields_view_get(
                      view_id=view_id, view_type=view_type, toolbar=toolbar,
                      submenu=submenu)
                      doc = etree.XML(res['arch'])
                      if res['name'] == "base.material.manage" or res['name'] == "base.material":
                      all_fields = doc.xpath("//field")
                      for field in all_fields:
                      name = field.get('name', False)
                      if self.env.user.has_group("xc_material." + name + "_invisible_group"):
                      # 只读权限
                      if self.env.user.has_group("xc_material." + name + "_read_group"):
                      # 没有编辑权限
                      if not self.env.user.has_group("xc_material." + name + "_edit_group"):
                      field.set('modifiers', '{"readonly":true}')
                      else:
                      # field.set('modifiers', "{'invisible':true}")
                      doc.remove(field)
                      res['fields'].pop(name)
                      else:
                      doc.remove(field)
                      res['fields'].pop(name)
                      res['arch'] = etree.tostring(doc)
                      return res




                      按钮权限  


                      自定义按钮权限,需要在form视图上增加自定义的按钮,另外需要在模型文件中添加一个name属性值相同的方法。例如:



                      说明:


                      <button>标签有一个Groups属性,可以是一个或多个权限角色,多个权限角色使用逗号分隔,对拥有Groups权限组的人可见


                      如果是Odoo框架自带的按钮,那么直接在视图里,继承过来改写一下即可。这里是form视图,隐藏了创建和编辑的按钮。例如:



                      或者直接在视图标签上,添加也可以达到同样效果。



                      以上就是关于Odoo中的权限问题,我们非常详实的介绍了各类权限的使用规则,希望能够在项目中帮助到你!~









                      掌握了Odoo权限规则

                      就能灵活的配置用户


                      如有更好的办法或疑问

                      欢迎加入社群一起讨论哦⬇

                      本期作者 

                      许文博 



                      更多精彩内容 





                      了解云基地,就现在!


                      IT技术哪家

                      神州数码最在行

                      行业新星后起之秀

                      历史虽不长,但实 力 强




                      文章转载自神州数码云基地,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                      评论