Odoo Record Rules

Record Rules are an important part of security in Odoo.  They control which records users can access.  For example, sales users can only access their own quotations and sales orders (see below).

  • Record Rules can make it easier to develop functionality in Odoo (because the rules have already been setup)
  • However, they can cause problems if there are multiple requirements related to one Model (database table).
    • So it is possible that installing another app or module (or just enabling another feature, such as Private Addresses) can have unexpected results.

Quick Guide

  1. Users are members of application access groups (e.g. Peter Lee might be a Purchase Manager and an Inventory User).
  2. Each of those access groups may “inherit” access from a related group, for example
    • Purchase Manager inherits the Purchase User rights
    • Purchase User inherits the Internal User rights
  3. Users will also be members of ‘technical’ access groups, each of which has a specific purpose, for example:
    • Manage multiple units of measure
    • Analytic accounting
  4. Each of the access groups (both types) will grant access to:
    1. Database
      1. Models
      2. Records (through Record Rules)
      3. Fields (not normally used) 
    2. Views 
    3. Menus
    4. Windows Actions
    5. Other elements (Buttons, Filters, Wizards)
  5. Access from all these groups is combined, so a user could have Read access from one group and Write access from another group (see Permissions below).
  6. If there are no Record Rules, there are no record-level restrictions.
  7. In Odoo version 11 and earlier, the Administrator account was not subject to Record Rules.  In Odoo 12 and later, the Administrator account is a member of all Access Groups and subject to Record Rules, but it is also possible to become a “Superuser” and bypass access rules. 

Record Rules

Record Rules make use of domain to specify which records can be selected.

There are two types of Record Rule:

  1. Global rules (with no access group specified).
    • These restrict access, and cannot be bypassed by other Record Rules.
    • They are generally used for multi-company restrictions.
    • They are quite easy to understand!
  2. Group-specific rules (for one or more access groups – e.g. Purchase Manager)
    • These grant permission (subject to the restrictions imposed by the Global Rules).
    • If there are multiple Group-specific rules then access is granted if ANY of the conditions are satisfied.
      • This can make Group-specific rules more difficult to understand, and care needs to be taken when using them.

Example

The access group “Sales / User: Own Documents Only” has a Record Rule on Sales Orders (and Quotations) with this domain:

['|',
   ('user_id','=',user.id),
   ('user_id','=',False)
] 

This will only allow access to:

  • the user’s own orders / quotations (where salesman = current user)
  • orders with no salesman (user_id) specified).

Alongside this, the group “Sales / User: All Documents” has a Record Rule with this domain:

 [(1,'=',1)] 

This will grant access to ALL Sales Orders / Quotations.

Note: there are identical Record Rules for Leads (the field names are the same).

Group Record Rules are almost always in sets of two, one to restrict access, one to grant full access (a set of three or more rules is also possible).

Permissions

Record Rules grant permission for one or all of the following actions:

  1. Read
  2. Write (update)
  3. Create
  4. Delete

Note that Read access is required in order to have any access!

There are several possible types of access, including:

  • Read-Only
  • Read and Write (but not create and delete)
  • Read, Write and Create but not delete
  • Full access

This can be done either through Model access or Record Rules, and there is an important difference between the two:

  1. If Read Access is not specified for a Model and user group, the user(s) will not have Read Access to that Model*
  2. If Read Access is not specified for a Record Rule (for a user group), the domain in that Rule will not apply, and so will not restrict user access*.
    • However, if there are other Record Rules for Read access they would apply.

* Note that in both the above examples, users may be members of other user groups that will either grant or restrict access.

Using Sales Order and Quotations (sale.order) as an example:

  • As standard, only the Sales Manager can delete Sales Orders (this is from the Model Access)
  • As explained above, some sales users can only access their own orders (through Record Rules)
  • You could add record rules so that:
    1. Only supervisors or managers can cancel confirmed Sales Orders
    2. All sales users can cancel Quotations (draft Sales Orders)
      • A cancelled Sales Order is still in the Odoo database, and a manager would be able to delete it.

Challenges

It’s easy to have problems with Record Rules because of the way they interact with each other. These can be in either direction:

  • access is allowed when it should not be,
  • users are not allowed do something they should be able to do

Here’s one example:

Private addresses

Odoo 12 introduced a Record Rule that was designed to limit access to “private addresses”. It’s on the Contacts model (res.partner).

Just like the above example, there are a pair of Record Rules:

1.  Allow access to “private addresses” for selected users

[('type', '=', 'private')]

2. Allow access for all users to other “non-private addresses”

['|', 
('type', '!=', 'private'),
('type', '=', False)
]

This Record Rule grants access to all internal users through the “Internal User” access group (“Employee” in earlier versions). This group is inherited by all application access groups.

The problem is that the second Record Rule would effectively override other Record Rules for Contacts.

  • For example, you might have used Record Rules to limit access to vendors (suppliers), but:
    • a user who had not had access to vendors would now be granted access (because type will be blank).
      • They would also be able to access private addresses for customers and other types of contact!

That’s because access is granted if the conditions for ANY of the Group-specific rules are satisfied – and these can come from multiple access groups.

The solution is either to remove the two “private address” rules or to replace them with several rules that cover all the combinations.

Alternatives

It is also possible to restrict access without using Record Rules.

The disadvantage of these methods is that it will normally require the restrictions to be applied in multiple places (which, of course, is what makes it more flexible). But it is easy to miss one or more views and then the user has access they should not have!

List of Record Rules for a user (Odoo 13)

Navigate to Settings / Users & Companies / Users

These “smart buttons” can be useful for troubleshooting, and you can use Filters to show information for one or more Models:

This shows us that the user has full access to their own sales order lines (from the “Sales / User: Own Documents Only” group) plus Read-Only access to Sales Order lines for projects (as the “Project Administrator”).

This is the domain for the second Record Rule:

['&', '&',
     ('state', 'in', ['sale', 'done']),
     ('is_service', '=', True),
    '|', ('project_id','!=', False), ('task_id','!=', False)]

This selects Sales Order Lines that are:

  • confirmed or locked, and
  • service items and
  • with either a project or task id

This will be used when billing from timesheets, so it logical that this access is available for a Project Administrator.

Note: there should be no conflict between these two Record Rules (sometimes the combination produces undesirable results, as explained above).

19 thoughts on “Odoo Record Rules

  1. Hi there,

    I want to setup record rule for sales men to only see his customers in contact model which identified in sales person field.

    but the sales manager can see all customers in contact model.

    I tried to change the record rule for res.partner but end up with huge bug as no one can sign in any more but this is not my problem because I tried it in the test database.

    please need your help.

    Liked by 2 people

    1. Remember that contact (res.partner) includes customers, suppliers and users. Limiting access could certainly cause problems.

      Like

    2. Hi Ahmer here you go… this works for Odoo 14 Enterprise and Odoo 15 Enterprise. I suspect it works for community but I’ve never tested it.

      Salesperson own contacts

      [‘|’, ‘|’, (‘create_uid’, ‘=’, user.partner_id.id), (‘user_id’, ‘=’, user.partner_id.id), (‘user_id’, ‘=’, user.id)]

      Liked by 1 person

      1. Hi Steven,

        I was looking for a similar rule. I tried the rule by assigning it to the group_sale_saleman group (See Own Documents) and created a test user in v15 Enterprise. However I can still see all contacts where the test user doesn’t meet the conditions. Any ideas?

        Like

      2. Yes, it’s most likely the private address rule. I went another route entirely since I ran into random issues with this rule I posted her a while ago.

        I’ll look for it and post the new one today.

        Like

      3. I don’t use that code I posted before because it started to become burdensome to manage when multiple contractors needed access to the same records.

        I threw together a module so you can see what I use now. Basically a tag on contacts that corresponds to res.users and provides access to each record. I only have it setup in contacts right now but it could be expanded on. It’s a lot easier for me to manage contacts this way.

        Let me know if you have any questions and I will try to help you out.
        https://github.com/netfxtech/misc_odoo_addons/tree/master/access_res_partner_contractor

        Like

  2. yeah that what I figured out.
    I tried to make filter in window actions but it doesn’t work.
    [(‘user_id’, ‘=’, user.id) ]
    please I need help.

    Liked by 1 person

    1. The same way that we use Record Rules for any other Model? If you have a specific question about it, maybe someone will offer some advice (not me, as I am quite busy!).

      Like

  3. How I can limit users to see only sales order made by sale team members? I have team which ID = 6 and I have tried like below but not succeed
    [(‘team_id’, ‘=’, 6)]

    Like

  4. i created those record rule to edit Purchase order at RFQ state only

    but it didn’t work
    Purchase Order [(‘state’, ‘in’,[False, ‘RFQ’])]
    Purchase Order Line [(‘order_id.state’, ‘in’,[False, ‘RFQ’])]

    Like

  5. Hi, I want to display PO and Stock Picking based on allowed branch in odoo. So if you log in as user Ana with allowed branch = Singapore, then the PO/Stock Picking that appear are only PO/Stock picking with the Singapore branch. if it’s like that, can it use ir.rule?

    Like

  6. I have Managers that have access to edit attendance. I want to restrict them to only editing attendance for their team and not themselves. There is a user: modify own attendance only record rule but how would I configure that to achieve my goal?

    Like

    1. I would probably look at the security groups in the sale module and replicate it. That would probably be the best way forward if you use sales teams or something equivalent.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s