权限等级
-
第一级是
access rule
,即表级(对象)权限,控制用户组对某个对象是否有创建、读取、修改、删除的权限,一般是用
security/ir.model.access.csv
文件来管理。
-
第二级是
行级权限,控制用户组对表中数据行的访问权限,可以写在
views/views.xml
文件中。
- 第三级是字段级权限,一个对象或表上的某些字段的访问权限。
-
第四级是菜单级
权限
,不属于指定菜单所包含组的用户看不到该菜单。
其实简单的理解就是
对于数据表Table A
用户能不能看见这个表的内容(字段及数据),就是表级权限
用户能不能看见表A的某行(数据),就是行级权限(记录及权限)
用户是否能看见表A的字段(列),就是字段及权限
对于odoo的菜单,用户是否可见,就是菜单级权限
创建模块
版本:odoo8
(python 2.7
环境
)
python ./odoo.py scaffold academy ./openerp/addons_test
切换用户到开发者模式
右上角用户,点击关于,页面右上角“激活开发者模式”
更新模块列表
Settings->Modules->Update Modules List
安装模块
Settings->
右上角搜索模块名
一、表级权限
新建model
academy/models.py
class Teachers(models.Model):
_name = 'academy.teachers'
name = fields.Char('Teacher Name')
biography = fields.Html()
user_id = fields.Many2one('res.users', string="User", ondelete='cascade', required="true")
class Courses(models.Model):
_name = 'academy.courses'
name = fields.Char()
teacher_id = fields.Many2one('academy.teachers', string="Teacher")
course_ids = fields.One2many('academy.courses', 'teacher_id', string="Courses")
给两个表添加基本的视图以及新建两个菜单
academy/views.xml
<openerp>
<data>
<record id="action_academy_teachers" model="ir.actions.act_window">
<field name="name">Academy teachers</field>
<field name="res_model">academy.teachers</field>
</record>
<record id="academy_teacher_tree" model="ir.ui.view">
<field name="name">Academy teachers: tree</field>
<field name="model">academy.teachers</field>
<field name="arch" type="xml">
<tree>
<field name="user_id"/>
</tree>
</field>
</record>
<record id="academy_teacher_form" model="ir.ui.view">
<field name="name">Academy teachers: form</field>
<field name="model">academy.teachers</field>
<field name="arch" type="xml">
<form>
<sheet>
<label for="user_id"/> <field name="user_id"/>
<label for="biography"/>
<field name="biography"/>
</sheet>
</form>
</field>
</record>
<record id="action_academy_courses" model="ir.actions.act_window">
<field name="name">Academy courses</field>
<field name="res_model">academy.courses</field>
</record>
<record id="academy_course_search" model="ir.ui.view">
<field name="name">Academy courses: search</field>
<field name="model">academy.courses</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="teacher_id"/>
</search>
</field>
</record>
<record id="academy_course_list" model="ir.ui.view">
<field name="name">Academy courses: list</field>
<field name="model">academy.courses</field>
<field name="arch" type="xml">
<tree string="Courses">
<field name="name"/>
<field name="teacher_id"/>
</tree>
</field>
</record>
<record id="academy_course_form" model="ir.ui.view">
<field name="name">Academy courses: form</field>
<field name="model">academy.courses</field>
<field name="arch" type="xml">
<form>
<sheet>
<label for="name"/>
<field name="name"/>
<label for="teacher_id"/>
<field name="teacher_id"/>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<menuitem sequence="0" id="menu_academy" name="Academy"/>
<menuitem id="menu_academy_content"
parent="menu_academy"
name="Academy Content"/>
<menuitem id="menu_academy_content_teachers"
parent="menu_academy_content"
action="action_academy_teachers"/>
<menuitem id="menu_academy_content_courses"
parent="menu_academy_content"
action="action_academy_courses"/>
</data>
</openerp>
表级的权限控制文件在academy/security/ir.model.access.csv
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,0,0,0
如上的group_id没有加,就是对所有组公开了teacher表的读取权限,重启odoo并升级(admin),切换用户(非admin),可看到效果页面:
可以看到该用户对teacher仅有读取权,但添加、修改、删除不能操作。
二、行级权限
比如访问“客户”对象,业务员只能对自己创建的客户有访问权限,而经理可以访问其管辖的业务员所有的“客户”对象。在ir.rule模型中定义规则,存储在public.ir_rule表格里面。
新建规则文件security/academy_record_rules.xml,并注册到__openerp__.py的data的属性中。
security/academy_record_rules.xml
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="academy_user_rule" model="ir.rule">
<field name="name">Academy only for owner</field>
<field name="model_id" ref="model_academy_teachers"/>
<field name="domain_force">
[('create_uid','=',user.id)]
</field>
<!--<field name="groups" eval="[(4,ref('base.group_user'))]"/>-->
</record>
</data>
</openerp>
name 规则名称
model_id 对应的模型
global 是否是全局
domain_force 过滤条件,在创建id等于当前用户id时,显示该条记录
groups 属于哪个组
base.group_user
是所有组,可以不写
security/ir.model.access.csv
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_academy_teachers,access_academy_teachers,model_academy_teachers,,1,1,1,1
access_academy_courses,access_academy_courses,model_academy_courses,,1,0,0,0
先开放teacher模块对所有组的所有权限,重启Odoo并升级academy,登陆非admin用户,可以看到teacher可新建,并只能看见自己创建的数据。
注释
(4,ID)添加主从链接关系到id=ID的对象。
(3,ID)去除和id=ID的对象主从链接关系,但是不删除这个对象
(2,ID) 去除和id=ID的对象主从链接关系,并且删除这个对象(调用unlink方法)
(5) 去除所有的链接关系,也就是循环所有的从数据且调用(3,ID)
(6,0,[IDs]) 用IDs里面的记录替换原来链接的记录,即先执行(5)再循环IDs执行(4,ID)
三、字段级权限
创建用户的权限组使用record记录,存储在res.groups里
security/academy_groups.xml
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record model="ir.module.category" id="module_category_academy_test">
<field name="name">academy test</field>
</record>
<record id="academy_teachers_group" model="res.groups">
<field name="name">Academy teachers group</field>
<field name="comment">the comment of the group.</field>
<field name="category_id" ref="module_category_academy_test"/>
<!--<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>-->
<!--<field name="users" eval="[(4, ref('base.user_root'))]"/>-->
</record>
<record id="academy_managers_group" model="res.groups">
<field name="name">Academy managers group</field>
<field name="comment">the comment of the group.</field>
<field name="category_id" ref="module_category_academy_test"/>
</record>
</data>
</openerp>
首先定义了分组category,然后定义了两个组属于同一分组(也可以不写分组)。
注释
name 组名
comment 组的注释
category_id 所属于哪个模块
users 预定义属于该组的用户
implied_ids
在demo.xml中添加两条记录,创建两个用户
demo.xml
<record id="user_teacher_a" model="res.users">
<field name="name">teacherA</field>
<field name="login">teacher.a@email.com</field>
<field name="password">academy</field>
</record>
<record id="user_teacher_b" model="res.users">
<field name="name">teacherB</field>
<field name="login">teacher.b@email.com</field>
<field name="password">academy</field>
</record>
<record id="teacher_a" model="academy.teachers">
<field name="name">TeacherA</field>
<field name="work_email">teacher.a@academy.com</field>
<field name="user_id" ref="academy.user_teacher_a"/>
</record>
<record id="teacher_b" model="academy.teachers">
<field name="name">TeacherB</field>
<field name="work_email">teacher.b@academy.com</field>
<field name="user_id" ref="academy.user_teacher_b"/>
</record>
登陆admin给teacherA添加到academy_teachers_group组,设置->用户 找到teacherA编辑,会看到权限多了分组,勾选Academy teachers group。
给字段添加组权限有两个地方
在视图中给field加groups属性
academy/views.xml
<record id="academy_teacher_tree" model="ir.ui.view">
<field name="name">Academy teachers: tree</field>
<field name="model">academy.teachers</field>
<field name="arch" type="xml">
<tree>
<field name="user_id"/>
<field name="name"/>
<field name="biography" groups="academy.academy_teachers_group"/>
<field name="show_group_teacher"/>
</tree>
</field>
</record>
或者在字段定义的地方加groups属性
academy/models.py
class Teachers(models.Model):
_name = 'academy.teachers'
name = fields.Char('Teacher Name')
biography = fields.Html()
user_id = fields.Many2one('res.users', string="User", ondelete='cascade', required="true")
show_group_teacher = fields.Char('Show For Teacher', groups="academy.academy_teachers_group")
重启odoo并升级academy,可以登陆TeacherA和TeacherB查看效果。
四、菜单级权限
在菜单定义处加groups属性(或者groups_id)
academy/views.xml
<menuitem id="menu_academy_content_courses"
parent="menu_academy_content"
action="action_academy_courses"
groups="academy.academy_teachers_group"/>
重启odoo并升级academy,可以登陆TeacherA和TeacherB查看效果。