Change the user performing an action

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().

Getting ready

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.

How to do it…

In order to let normal users modify the phone number of a company, you need to perform the following steps:

  1. Define a model extending the res.company model:
    class ResCompany(models.Model):
        _inherit = 'res.company'
  2. Add a method called update_phone_number():
        @api.multi
        def update_phone_number(self, new_number):
  3. In the method, ensure we are acting on a single record:
           self.ensure_one()
  4. Modify the user of the environment:
           company_as_superuser = self.sudo()
    
  5. Write the new phone number:
           company_as_superuser.phone = new_number

How it works…

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)

Note

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.

There is more…

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:

  • If you are not careful, new records created in this environment will be linked to the company of the superuser
  • If you are not careful, records searched in this environment may be linked to any company present in the database, which means that you may be leaking information to the real user, or worse, you may be silently corrupting the database by linking together records belonging to different companies

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.

See also

  • The Obtain an empty recordset for a model recipe in Chapter 5, Basic Server Side Development, explains what the environment is.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.175.148