From 9608d4551d2ef9c2774c2d9574181f2c98923005 Mon Sep 17 00:00:00 2001 From: Romain Derie Date: Tue, 12 Mar 2019 10:07:04 +0000 Subject: [PATCH] [FIX] website_sale: prevent compute search to be run in sudo Before this commit, when accessing an user's pricelist, it would raise a 500 error in multi-company environment. Indeed, when doing `self.env.user.partner_id.property_product_pricelist`, even if self.env is not un sudo mode, the compute from `property_product_pricelist` is executed as sudo. Since this method is then doing a `search()`, it won't use the multi-company pricelist ir.rule. It will return all the pricelist, including the ones from other companies. Then, when trying to read that pricelist, it will raise an access error. Now, we correctly execute the compute (and so the search) in the user env, it won't get pricelists from other companies. --- addons/website_sale/models/website.py | 4 ++-- .../tests/test_website_sale_pricelist.py | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/addons/website_sale/models/website.py b/addons/website_sale/models/website.py index c781f36d977..14365a77dd8 100644 --- a/addons/website_sale/models/website.py +++ b/addons/website_sale/models/website.py @@ -68,7 +68,7 @@ class Website(models.Model): if not show_visible or group_pricelists.selectable or group_pricelists.id in (current_pl, order_pl): pricelists |= group_pricelists - partner = self.env.user.partner_id + partner = self.env.user.partner_id.sudo(user=self.env.user) is_public = self.user_id.id == self.env.user.id if not is_public and (not pricelists or (partner_pl or partner.property_product_pricelist.id) != website_pl): # `property_product_pricelist` is already multi-website compliant @@ -104,7 +104,7 @@ class Website(models.Model): isocountry = request and request.session.geoip and request.session.geoip.get('country_code') or False partner = self.env.user.partner_id last_order_pl = partner.last_website_so_id.pricelist_id - partner_pl = partner.property_product_pricelist + partner_pl = partner.sudo(user=self.env.user).property_product_pricelist pricelists = website._get_pl_partner_order(isocountry, show_visible, website.user_id.sudo().partner_id.property_product_pricelist.id, request and request.session.get('website_sale_current_pl') or None, diff --git a/addons/website_sale/tests/test_website_sale_pricelist.py b/addons/website_sale/tests/test_website_sale_pricelist.py index 46ae0e56a28..31d66a094c1 100644 --- a/addons/website_sale/tests/test_website_sale_pricelist.py +++ b/addons/website_sale/tests/test_website_sale_pricelist.py @@ -136,6 +136,29 @@ def simulate_frontend_context(self, website_id=1): self.addCleanup(patcher.stop) +class TestWebsitePriceListHttp(HttpCase): + def test_get_pricelist_available_multi_company(self): + ''' Test that the `property_product_pricelist` of `res.partner` is not + computed as SUPERUSER_ID. + Indeed, `property_product_pricelist` is a _compute that ends up + doing a search on `product.pricelist` that woule bypass the + pricelist multi-company `ir.rule`. Then it would return pricelists + from another company and the code would raise an access error when + reading that `property_product_pricelist`. + ''' + test_company = self.env['res.company'].create({'name': 'Test Company'}) + self.env['product.pricelist'].create({ + 'name': 'Backend Pricelist For "Test Company"', + 'website_id': False, + 'company_id': test_company.id, + 'sequence': 1, + }) + + self.authenticate('portal', 'portal') + r = self.url_open('/shop') + self.assertEqual(r.status_code, 200, "The page should not raise an access error because of reading pricelists from other companies") + + class TestWebsitePriceListMultiCompany(TransactionCase): def setUp(self): ''' Create a basic multi-company pricelist environment: