OD401 model-without-access¶
A new model has no ir.model.access rule, or from saas~19.4 no ir.access rule with a group.
| Category | Severity | Series | Needs the index |
|---|---|---|---|
| Security | Warning, Info from saas~19.4 | all | yes |
What it reports¶
A class that defines a new model, as a Model or a TransientModel, when no indexed module grants
access to it: no row of ir.model.access, or of ir.access with a group, in a CSV file or an XML
record that Odoo loads, names the model. A row grants nothing until its file loads, so only a file
that counts as loaded, as OD310 spells out, can hold one. The model is the class's
_name, or for a class without one the name Odoo gives it from its class, as OD209
describes. The message names ir.access from saas~19.4 and ir.model.access before it and in a
module of unknown series, while a row of either model counts on every series.
Why it matters¶
Odoo refuses every operation on a model to a user that no access row lets through. Only the
superuser and code running under sudo() can use a model without rows, so its menus, views and
wizards fail with an access error for everyone else. Odoo 18.0 logs The models [...] have no
access rules when it installs or updates such a module, and its own superuser-only models carry
a row with every permission set to 0 to say so on purpose.
From saas~19.4 Odoo replaces ir.model.access and ir.rule with ir.access, loaded from
security/ir.access.csv. A row's operation is a non-empty subset of crud, so no row can say
"nobody", and a model meant for the superuser alone has no row at all. From saas~19.4 the finding
is therefore Info: a hotspot to review, which is a bug only when someone other than the superuser
is meant to use the model. An ir.access row without a group restricts every user rather than
granting, so it does not count as access.
Before saas~13.2 Odoo checks no access row for a TransientModel, so such a class is not reported
on those series.
Abstract models and classes that only extend an existing model are not reported. Nor is a class
whose own body sets _register false, since Odoo keeps it out of the registry; a subclass that does
not set it is registered and reported. A loaded row in any indexed module counts, so a model that
another module grants access to is not reported either. For the same reason, neither is a model
when an unread data file that may hold the row is in the module or in a module that
depends on it.
Example¶
class LibraryLoan(models.Model):
_name = "library.loan"
_description = "Book loan"
partner_id = fields.Many2one("res.partner", required=True)
due_date = fields.Date()
The module ships no access row for library.loan, so internal users get an access error on it.
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_library_loan_user,library.loan user,model_library_loan,base.group_user,1,1,1,1
List the file in the manifest's data. From saas~19.4 the same grant reads:
id,name,model_id,group_id/id,operation
access_library_loan_user,library.loan user,library.loan,base.group_user,crud