المملكة العربية السعودية | البحرين | الإمارات العربية المتحدة | الهند

Odoo 20 Security : How the New ir.access Model Works

Security is an important part of every Odoo custom module. It determines which users can create, view, update, or delete records and which records they are allowed to work with. In earlier Odoo versions, developers generally configured model-level access through ir.model.access and record-level filtering through ir.rule. Odoo 20 security brings these responsibilities together in a unified model called ir.access.

The change is more than a menu rename. It affects security files, access definitions, and migration work for custom modules. This guide explains the new approach and demonstrates the basic structure developers need to know.

What Changed in Odoo 20 security?

In Odoo 19 and earlier, developers generally used ir.model.access for model-level operations and ir.rule for record-level filtering. In Odoo 20, both are replaced by ir.access, which defines the model, operation, optional group, and optional domain in one record.

Earlier versions                         Odoo 20
ir.model.access  (model operations)  ->  ir.access (operations)
ir.rule          (record domains)    ->  ir.access (domain)
Separate access CSV + rule XML       ->  security/ir.access.csv

This unifies the configuration, but it does not remove the need to design and test security carefully. The meaning of a domain also depends on whether the access record grants permission to a group or applies as a global restriction.

How ir.access Works

An ir.access record describes the model, the operations, an optional user group, and an optional domain.

  • Model (model_id): The technical model name the access definition applies to, such as res.partner or library.book. In this CSV format, use the model name not the external ID such as model_library_book.
  • Group (group_id): When a group is specified, the entry grants the listed operations to members of that group, subject to the domain. A user may receive grants from more than one group.
  • Operations (operation): A sequence of operation letters: c = create, r = read, u = update/write, and d = delete. For example, crud means all four operations; r means read only; ru means read and update.
  • Domain (domain): An optional filter that determines which records are covered. Group-based permission domains combine permissively (a matching group rule can grant access), while global restrictions records without a group must all be satisfied.
  • Restriction without a group: When group_id is empty, the entry is a global restriction, not a permission grant. It applies to all users and limits access even if a group-based permission would otherwise allow it.

In short, group-based permissions can widen access, but they cannot override a global restriction. Multiple global restrictions intersect: a record must satisfy every applicable restriction for the operation being checked.

Figure 1. Odoo 20 Access Rights list showing model access entries, operation columns, domains, and whether each entry is a permission or restriction.

Example: Define Access in a Custom Module

Suppose a custom module defines a model named library.book and ordinary internal users should be able to create, read, update, and delete its records. In Odoo 20, the security file is named security/ir.access.csv.

Example file: security/ir.access.csv

id,name,model_id,group_id/id,operation,domain
access_library_book_user,library.book user access,library.book,base.group_user,crud,

This example grants create, read, update, and delete operations to internal users without adding a domain filter. Notice that model_id contains library.book, the technical model name, while group_id/id contains the group’s external ID. Use this broad grant only if every internal user should have full access to this model.

Load the Security File

Declare the file in the data list of the module manifest so Odoo loads it during installation or upgrade.

'data': [
    'security/ir.access.csv',
    # Other data files...
],

Keep the security file in the module’s security directory and ensure the path and filename match the manifest exactly. After changing the definition, upgrade the module and test it with users who have different group memberships.

Figure 2. Odoo 20 source code showing the security/ir.access.csv file and its access-definition entries.

 

Migrating from Odoo 19 to Odoo 20

When porting a custom module, do not simply rename a file and assume the security behaviour will remain identical. Review both the file format and the meaning of each access definition.

  1. Rename security/ir.model.access.csv to security/ir.access.csv.
  2. Update the CSV header to: id,name,model_id,group_id/id,operation,domain.
  3. Convert the old boolean CRUD columns into the operation string. For example, read and write only becomes ru.
  4. Migrate each old ir.rule definition into an ir.access entry, carrying over its domain and carefully preserving its group/global behaviour and operation scope. Do not copy the domain blindly: check how the old rule combined with other rules.
  5. Review old access records without a group carefully. In Odoo 20, a group-less ir.access entry is a global restriction, so verify that the migrated entry preserves the intended security behaviour.
  6. Search the module and its dependencies for old security references, then test installation and upgrades on a copy of the database.

Common Mistakes to Avoid

  • Keeping the old ir.model.access.csv filename or old CSV headers in an Odoo 20 module.
  • Leaving an old ir.rule XML record in a module that targets Odoo 20.
  • Assuming that no restriction means a user automatically has permission. An explicit grant is still required.
  • Creating a group-less entry when the intention is to grant access to a group. A group-less entry is treated as a restriction.
  • Testing only as an administrator. Test with a normal internal user and each relevant security group.
  • Forgetting multi-company boundaries or other domain requirements while migrating.

Testing Checklist

  • Install or upgrade the module in a development database.
  • Log in as a user who belongs to the intended group and verify the allowed operations.
  • Verify that users outside the group cannot perform operations that were not granted.
  • Test the domain against matching and non-matching records.
  • Check that restrictions still apply when a user belongs to multiple groups.
  • Test multi-company access if the model contains company-specific data.

Frequently Asked Questions

Does Odoo 20 still use ir.model.access and ir.rule for this security configuration?

Yes. In Odoo 20, ir.model.access and ir.rule are replaced by ir.access. Custom modules targeting Odoo 20 should use the new CSV format and review the meaning of each migrated domain.

What does crud mean in ir.access.csv?

It represents create, read, update, and delete operations. The letters can be combined to allow a subset, such as r for read only or ru for read and update.

What happens when group_id is empty?

It is a global restriction that applies to all users. To grant permissions to a particular user group, specify that group in group_id/id.

Can all security XML files be removed after migration?

No. Review each file and use case. The unified access model replaces the former ACL and record-rule definitions, but other security-related XML records may still be required.

Conclusion

Odoo 20 replaces the separate ir.model.access and ir.rule models with ir.access. When updating a custom module, use the new CSV structure, preserve the intended operation and domain behaviour, and test both group-based permissions and global restrictions. A module that installs successfully is not necessarily secure; validate the actual records and operations available to each user role.

Official References

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *