When writing business logic code, you may have to perform some actions with a different security context. A typical case is performing an action with the rights of the Administrator, who bypasses security checks.
This recipe shows how to let normal users modify the phone number of a company by using sudo()
.
We will be working on records of the res.company
model. By default, only members of the Administration/Access Rights user group can modify records of res.company
, but in our case, we need to provide an access point to change only the phone number to users who are not necessarily members of that group.
In order to let normal users modify the phone number of a company, you need to perform the following steps:
res.company
model:class ResCompany(models.Model): _inherit = 'res.company'
update_phone_number()
:@api.multi def update_phone_number(self, new_number):
self.ensure_one()
company_as_superuser = self.sudo()
company_as_superuser.phone = new_number
In step 4, we call self.sudo()
. This method returns a new recordset with a new environment in which the user is not the same as the one in self
. When called without an argument, sudo()
will link the Odoo superuser, Administrator, to the environment. All method calls via the returned recordset are made with the new environment, and therefore with superuser privileges.
If you need a specific user, you can pass either a recordset containing that user or the database id
of the user. The following snippet allows you to search books that are visible, using the public
user:
public_user = self.env.ref('base.public_user') public_book = self.env['library.book'].sudo(public_user)
Caution when using sudo()
There is no traceability of the action; the author of the last modification of the company in our recipe will be Administrator, not the user originally calling update_phone_number
.
The community addon, base_suspend_security
, found at https://github.com/OCA/server-tools/ can be used to work around this limitation.
When using sudo()
without an argument, you set the user of the context to the Odoo superuser. This superuser bypasses all the security rules of Odoo, both the access control lists and the record rules. By default, this user also has a company_id
field set to the main company of the instance (the one with id 1
). This can be problematic in a multi company instance:
Using sudo()
also involves creating a new Environment
instance. This environment will have an initially empty recordset cache, and that cache will evolve independently from the cache of self.env
. This can cause spurious database queries. In any case, you should avoid creating new environment inside loops, and try to move these environment creations to the outmost possible scope.