Skip to content

Security Rules

Record Rules

Basic Record Rule

xml
<record id="rule_model_name" model="ir.rule">
    <field name="name">Model Name Rule</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="domain_force">[('user_id', '=', user.id)]</field>
    <field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>

Multi-Company Rule

xml
<record id="rule_model_name_multi_company" model="ir.rule">
    <field name="name">Model Name Multi-Company</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
    <field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>

Department Based Rule

xml
<record id="rule_model_name_department" model="ir.rule">
    <field name="name">Model Name Department</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="domain_force">[('department_id', 'in', user.department_ids.ids)]</field>
    <field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>

Access Rights

Basic Access Rights

xml
<record id="module_category_name" model="ir.module.category">
    <field name="name">Category Name</field>
    <field name="description">Category Description</field>
    <field name="sequence">20</field>
</record>

<record id="group_user" model="res.groups">
    <field name="name">User</field>
    <field name="category_id" ref="module_category_name"/>
</record>

<record id="group_manager" model="res.groups">
    <field name="name">Manager</field>
    <field name="category_id" ref="module_category_name"/>
    <field name="implied_ids" eval="[(4, ref('group_user'))]"/>
</record>

Model Access Rights

xml
<record id="access_model_name_user" model="ir.model.access">
    <field name="name">model.name.user</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="group_id" ref="group_user"/>
    <field name="perm_read" eval="True"/>
    <field name="perm_write" eval="True"/>
    <field name="perm_create" eval="True"/>
    <field name="perm_unlink" eval="False"/>
</record>

<record id="access_model_name_manager" model="ir.model.access">
    <field name="name">model.name.manager</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="group_id" ref="group_manager"/>
    <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>

Field Access

Field Level Security

xml
<record id="view_model_name_form" model="ir.ui.view">
    <field name="name">model.name.form</field>
    <field name="model">model.name</field>
    <field name="arch" type="xml">
        <form>
            <sheet>
                <group>
                    <field name="name"/>
                    <field name="sensitive_field" groups="group_manager"/>
                </group>
            </sheet>
        </form>
    </field>
</record>

Button Security

xml
<record id="view_model_name_form" model="ir.ui.view">
    <field name="name">model.name.form</field>
    <field name="model">model.name</field>
    <field name="arch" type="xml">
        <form>
            <header>
                <button name="action_confirm" 
                        string="Confirm" 
                        type="object" 
                        groups="group_manager"/>
            </header>
            <sheet>
                <group>
                    <field name="name"/>
                </group>
            </sheet>
        </form>
    </field>
</record>

Common Patterns

User Based Access

xml
<record id="rule_model_name_user" model="ir.rule">
    <field name="name">Model Name User Rule</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="domain_force">[
        '|',
        ('user_id', '=', user.id),
        ('user_id', '=', False)
    ]</field>
    <field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>

Team Based Access

xml
<record id="rule_model_name_team" model="ir.rule">
    <field name="name">Model Name Team Rule</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="domain_force">[
        '|',
        ('team_id', 'in', user.team_ids.ids),
        ('team_id', '=', False)
    ]</field>
    <field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>

State Based Access

xml
<record id="rule_model_name_state" model="ir.rule">
    <field name="name">Model Name State Rule</field>
    <field name="model_id" ref="model_model_name"/>
    <field name="domain_force">[
        '|',
        ('state', 'in', ['draft', 'sent']),
        ('user_id', '=', user.id)
    ]</field>
    <field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>

Best Practices

Rule Naming

xml
<!-- Good -->
<record id="rule_sale_order_user" model="ir.rule">
    <field name="name">Sale Order: User Rule</field>
    ...
</record>

<!-- Bad -->
<record id="rule_1" model="ir.rule">
    <field name="name">Rule 1</field>
    ...
</record>

Rule Organization

xml
<!-- Group related rules together -->
<record id="rule_sale_order_user" model="ir.rule">
    <field name="name">Sale Order: User Rule</field>
    ...
</record>

<record id="rule_sale_order_manager" model="ir.rule">
    <field name="name">Sale Order: Manager Rule</field>
    ...
</record>

<record id="rule_sale_order_team" model="ir.rule">
    <field name="name">Sale Order: Team Rule</field>
    ...
</record>

Rule Documentation

xml
<record id="rule_sale_order_user" model="ir.rule">
    <field name="name">Sale Order: User Rule</field>
    <field name="model_id" ref="model_sale_order"/>
    <!-- 
    Rule Description:
    - Users can only see their own orders
    - Managers can see all orders
    - Team members can see team orders
    -->
    <field name="domain_force">[
        '|',
        ('user_id', '=', user.id),
        ('team_id', 'in', user.team_ids.ids)
    ]</field>
    <field name="groups" eval="[(4, ref('base.group_user'))]"/>
</record>