In Odoo, ACL stands for Access Control List in Odoo, and it specifies access to your information in terms of who can perform certain actions on your data. It dictates who is allowed to perform any of the CRUD operations on certain models.
It is okay to manage the access control lists manually via the Odoo user interface when dealing with a few of those. What about the cases where there are dozens of departments, hundreds of users, and complex matrixes of permissions?
It would be a real challenge to generate ACLs manually in this case.
We will cover everything you need to know regarding batch import of ACLs from CSV:
- What ACLs are and how they work in Odoo 19
- How to structure a CSV file for ACL import
- Process of importing ACLs step-by-step
- Common pitfalls and how to avoid them
- Examples that fit various business cases
Whether you're setting up a new Odoo instance or reorganizing permissions after a company restructures, this guide will save you hours of manual work.
What Are ACLs in Odoo?
An ACL (Access Control List) is a rule that grants specific permissions to specific groups on specific models.
Breaking it down:
| Component | What it means | Example |
| Permission | What action is allowed | Create, Read, Write, Delete, Unlink |
| Group | Who can perform it | Sales Team, Managers, Warehouse Staff |
| Model | What data can they access | sale.order, stock.move, res.partner |
Example ACLs:
- Sales Team can read all Sale Orders
- Warehouse Manager can create Stock Moves
- Finance users can write Invoice lines
- Only the admin can delete products.
Without proper ACLs:
- Any user can delete critical data
- Sales reps can access Finance reports
- Interns see confidential customer info
Where Are ACLs Stored?
ACLs in Odoo are stored in the ir.model.access model. You can view them in:
Path: Settings > Technical > Security > Access Right
Each ACL record has these fields:
| Field | Required | Meaning |
| Name | Yes | A unique identifier for the ACL (e.g., "sale_order_user_read") |
| Model | Yes | The model the ACL applies to (e.g., sale.order) |
| Group | No | The user group this ACL applies to (leave blank = applies to all) |
| Permissions | Yes | Which actions are allowed: Read, Write, Create, Delete, Unlink |
Example record:
- Name: sale_order_sales_team_full_access
- Model: sale.order
- Group: Sales Team
- Permissions: can Read, can Write, can Create, cannot Delete, can Unlink
CSV File Format for ACL Import
To import ACLs via CSV, you need to structure your data properly. Odoo expects these columns:
| Column Name | Required | Allowed Values | Example |
| name | Yes | Any text (must be unique) | sale_order_user_read |
| model_id | Yes | Model name in dot notation | sale.order |
| group_id | No | Group name or ID | Sales Team / sales_team_group_id |
| perm_read | No | 1 (yes) or 0 (no) | 1 |
| perm_write | No | 1 (yes) or 0 (no) | 1 |
| perm_create | No | 1 (yes) or 0 (no) | 1 |
| perm_delete | No | 1 (yes) or 0 (no) | 0 |
| perm_unlink | No | 1 (yes) or 0 (no) | 0 |
Note: In Odoo 19, delete and unlink are often treated the same way. The unlink permission typically controls whether a record can be deleted permanently.
Example: Basic CSV for ACL Import
Let's create a practical CSV file for a small sales organization.
File: acl_import.csv
name,model_id,group_id,perm_read,perm_write,perm_create,perm_delete,perm_unlink
sale_order_user_read,sale.order,Sales Team,1,0,0,0,0
sale_order_user_create_write,sale.order,Sales Team,1,1,1,0,0
sale_order_manager_full,sale.order,Sales Manager,1,1,1,1,1
res_partner_user_read,res.partner,Sales Team,1,0,0,0,0
res_partner_user_write,res.partner,Sales Team,1,1,0,0,0
res_partner_manager_full,res.partner,Sales Manager,1,1,1,1,1
stock_move_warehouse_read,stock.move,Warehouse Staff,1,0,0,0,0
stock_move_warehouse_write,stock.move,Warehouse Staff,1,1,1,0,0
invoice_finance_full,account.move,Finance,1,1,1,1,1
What this means:
- Sales Team can read orders but can't create or edit
- Sales Team can read and edit partners but can't delete
- Sales Manager has full access to orders and partners
- Warehouse Staff can read and create stock moves
- Finance has full access to invoices
Step-by-Step: Importing ACLs from CSV
Step 1: Go to Access Controls
Path: Settings > Technical > Security > Access Right
This opens the ir.model.access list view.
Step 2: Prepare Your CSV File
First, create an export of an access record in XLSX or CSV format to get the template. In that template, we can add our ACLs in the correct format.
Step 3: Import the CSV
Click the Import button (usually in the top-left corner of the list view).
A dialog will appear asking you to:
- Select your CSV file
- Map columns: match your CSV columns to Odoo fields
Column mapping example:
- Your CSV column > Odoo Field
- name > name
- model_id > Model (ir.model)
- group_id > Group (res.groups)
- perm_read > Read permission
- perm_write > Write permission
- perm_create > Create permission
- perm_delete > Delete permission
- perm_unlink > Unlink permission
Step 4: Test Import (Preview)
Before finalizing, Odoo shows a preview of what will be imported. Check:
- All rows are recognized
- No error messages
- Field values look correct
- Group names are resolved correctly
Step 5: Import
Click Import to create all ACL records at once.
Success message: "1 record created" (or however many ACLs you imported)
Importing ACL Changes & Updates
Scenario: You Need to Update an Existing ACL
If you import a CSV with the same ACL name, Odoo will skip it (it already exists).
To update existing ACLs:
Option 1: Use Odoo UI
- Go to Settings > Technical > Security > Access Right
- Find the ACL
- Edit the permissions directly
Option 2: Use Python Script
# In Odoo backend or script
acl = env["ir.model.access"].search([("name", "=", "sale_order_user_read")])
acl.write({
"perm_write": True, # Grant write permission
"perm_create": False, # Revoke create permission
})
Option 3: Delete & Re-import
- Delete old ACLs
- Import updated CSV
Verifying Imported ACLs Work
After importing, test that permissions are actually enforced:
Test 1: Check ACL Records Created
Go to Settings > Technical > Security > Access Right
Filter by model or group name; you should see all imported ACLs.
Test 2: Login as a User in That Group
- Create a test user
- Add them to the group
- Logout and login as that user
- Try to access the restricted model
Expected behavior:
- Can see records if perm_read = 1
- Can edit if perm_write = 1
- Can create if perm_create = 1
- Cannot do actions if permission is 0
Test 3: Check Error Messages
If a user tries an action they're not allowed to do, Odoo shows:
AccessError: Access denied.
You don't have permission to perform this action.
This confirms ACLs are working.
Exporting Current ACLs (Backup)
Before making changes, export your current ACLs:
- Go to Settings > Technical > Security > Access Right
- Click Export (or use the ? menu)
- Select all fields
- Download as CSV
This gives you a backup to revert to if needed.
Troubleshooting: ACLs Not Working
Problem: Imported ACLs but users still see all data
Possible causes:
- User is in admin group > Admin bypasses all ACLs
- Solution: Remove user from Admin group
- ACL is for wrong group > User is not in the group specified
- Solution: Add user to correct group or modify ACL
- ACL name typo > Odoo can't find the rule
- Solution: Re-check ACL names and group names
- Module not installed > Some models require specific modules
- Solution: Install the module first, then create ACL
- Record rules applied too > ACLs control model access, Record Rules control record access
- Solution: Check both ACLs and Record Rules (Settings > Technical > Security > Record Rules)
ACLs vs Record Rules: What's the Difference?
In Odoo, both control access, but differently:
| Feature | ACLs | Record Rules |
| Scope | Which model to access | Which records of a model to access |
| Granularity | Coarse (entire model) | Fine (specific records) |
| Example | "Can read Sale Orders" | "Can read own Sale Orders only" |
| Use case | Department permissions | Territory/ownership-based access |
Real example:
- ACL: Sales Team can read sale.order model
- Record Rule: The Sales Team can read only orders assigned to them
Both must be satisfied for access to be granted.
Importing Access Control Lists (ACLs) from CSV in Odoo 19 is an incredibly efficient way to manage access rights. Rather than manually setting up ACLs using the user interface for hours, you will be able to:
- Define all of your access rights in a CSV file
- Import several hundred ACLs in just a few minutes.
- Use version control for access control rights.
- Recreate configurations in other instances of Odoo.
- Audit and modify permissions systematically.
Master the CSV format and avoid common mistakes, and your ACL management becomes fast, repeatable, and error-free.
Start with our example CSV files, customize them for your organization, and automate your security setup.
To read more about Best Practices for Access Control Lists (ACLs) in Odoo, refer to our blog Best Practices for Access Control Lists (ACLs) in Odoo.