From a4472b104bb98507ef000896a98eac4a29e752f6 Mon Sep 17 00:00:00 2001 From: Martin Trigaux Date: Tue, 19 May 2020 10:30:12 +0200 Subject: [PATCH] [FIX] *: use sudo when accessing ir.property Add sudo in base to allow a unpriviledged user to interact with ir.property in a safe way usingsetters and getters. By making them callable without sudo, we encourage to use these methods instead of making CRUD requests on ir.property directly For other specific search where no native method exists, add sudo --- addons/account/models/account_account.py | 7 +++++-- addons/account/models/account_payment_term.py | 5 +++-- addons/account/models/chart_template.py | 6 +++--- addons/product/models/res_company.py | 4 ++-- addons/product/models/res_partner.py | 2 +- addons/stock/models/res_company.py | 4 ++-- addons/stock_account/__init__.py | 5 +++-- odoo/addons/base/models/ir_property.py | 12 ++++++------ 8 files changed, 25 insertions(+), 20 deletions(-) diff --git a/addons/account/models/account_account.py b/addons/account/models/account_account.py index c9d2de963bd..d4def8834aa 100644 --- a/addons/account/models/account_account.py +++ b/addons/account/models/account_account.py @@ -432,9 +432,12 @@ class AccountAccount(models.Model): raise UserError(_('You cannot perform this action on an account that contains journal items.')) #Checking whether the account is set as a property to any Partner or not values = ['account.account,%s' % (account_id,) for account_id in self.ids] - partner_prop_acc = self.env['ir.property'].search([('value_reference', 'in', values)], limit=1) + partner_prop_acc = self.env['ir.property'].sudo().search([('value_reference', 'in', values)], limit=1) if partner_prop_acc: - raise UserError(_('You cannot remove/deactivate an account which is set on a customer or vendor.')) + account_name = partner_prop_acc.get_by_record().display_name + raise UserError( + _('You cannot remove/deactivate the account %s which is set on a customer or vendor.') % account_name + ) return super(AccountAccount, self).unlink() def action_read_account(self): diff --git a/addons/account/models/account_payment_term.py b/addons/account/models/account_payment_term.py index bb918807168..c7d8dd8d734 100644 --- a/addons/account/models/account_payment_term.py +++ b/addons/account/models/account_payment_term.py @@ -71,8 +71,9 @@ class AccountPaymentTerm(models.Model): for terms in self: if self.env['account.move'].search([('invoice_payment_term_id', 'in', terms.ids)]): raise UserError(_('You can not delete payment terms as other records still reference it. However, you can archive it.')) - property_recs = self.env['ir.property'].search([('value_reference', 'in', ['account.payment.term,%s'%payment_term.id for payment_term in terms])]) - property_recs.unlink() + self.env['ir.property'].sudo().search( + [('value_reference', 'in', ['account.payment.term,%s'%payment_term.id for payment_term in terms])] + ).unlink() return super(AccountPaymentTerm, self).unlink() diff --git a/addons/account/models/chart_template.py b/addons/account/models/chart_template.py index 202aa38b291..ebe926d3fc7 100644 --- a/addons/account/models/chart_template.py +++ b/addons/account/models/chart_template.py @@ -207,9 +207,9 @@ class AccountChartTemplate(models.Model): existing_journals = self.env['account.journal'].search([('company_id', '=', company.id)]) if existing_journals: prop_values.extend(['account.journal,%s' % (journal_id,) for journal_id in existing_journals.ids]) - accounting_props = self.env['ir.property'].search([('value_reference', 'in', prop_values)]) - if accounting_props: - accounting_props.sudo().unlink() + self.env['ir.property'].sudo().search( + [('value_reference', 'in', prop_values)] + ).unlink() # delete account, journal, tax, fiscal position and reconciliation model models_to_delete = ['account.reconcile.model', 'account.fiscal.position', 'account.tax', 'account.move', 'account.journal', 'account.group'] diff --git a/addons/product/models/res_company.py b/addons/product/models/res_company.py index 323d722fb87..5a44de1afc1 100644 --- a/addons/product/models/res_company.py +++ b/addons/product/models/res_company.py @@ -18,7 +18,7 @@ class ResCompany(models.Model): 'name': _("Default %(currency)s pricelist") % params, 'currency_id': new_company.currency_id.id, }) - self.env['ir.property'].sudo()._set_default( + self.env['ir.property']._set_default( 'property_product_pricelist', 'res.partner', pricelist, @@ -54,7 +54,7 @@ class ResCompany(models.Model): 'name': _("Default %(currency)s pricelist") % params, 'currency_id': currency_id, }) - self.env['ir.property'].sudo()._set_default( + self.env['ir.property']._set_default( 'property_product_pricelist', 'res.partner', pricelist, diff --git a/addons/product/models/res_partner.py b/addons/product/models/res_partner.py index f76c0e4da63..5b641d5f811 100644 --- a/addons/product/models/res_partner.py +++ b/addons/product/models/res_partner.py @@ -33,7 +33,7 @@ class Partner(models.Model): # update at each change country, and so erase old pricelist if partner.property_product_pricelist or (actual and default_for_country and default_for_country.id != actual.id): # keep the company of the current user before sudo - self.env['ir.property'].sudo()._set_multi( + self.env['ir.property']._set_multi( 'property_product_pricelist', partner._name, {partner.id: partner.property_product_pricelist or default_for_country.id}, diff --git a/addons/stock/models/res_company.py b/addons/stock/models/res_company.py index 2e7c5bd474c..fea6cbb88c8 100644 --- a/addons/stock/models/res_company.py +++ b/addons/stock/models/res_company.py @@ -130,7 +130,7 @@ class Company(models.Model): def create_missing_inventory_loss_location(self): company_ids = self.env['res.company'].search([]) inventory_loss_product_template_field = self.env['ir.model.fields'].search([('model','=','product.template'),('name','=','property_stock_inventory')]) - companies_having_property = self.env['ir.property'].search([('fields_id', '=', inventory_loss_product_template_field.id)]).mapped('company_id') + companies_having_property = self.env['ir.property'].sudo().search([('fields_id', '=', inventory_loss_product_template_field.id)]).mapped('company_id') company_without_property = company_ids - companies_having_property company_without_property._create_inventory_loss_location() @@ -138,7 +138,7 @@ class Company(models.Model): def create_missing_production_location(self): company_ids = self.env['res.company'].search([]) production_product_template_field = self.env['ir.model.fields'].search([('model','=','product.template'),('name','=','property_stock_production')]) - companies_having_property = self.env['ir.property'].search([('fields_id', '=', production_product_template_field.id)]).mapped('company_id') + companies_having_property = self.env['ir.property'].sudo().search([('fields_id', '=', production_product_template_field.id)]).mapped('company_id') company_without_property = company_ids - companies_having_property company_without_property._create_production_location() diff --git a/addons/stock_account/__init__.py b/addons/stock_account/__init__.py index 558fd40f096..d4786823b49 100644 --- a/addons/stock_account/__init__.py +++ b/addons/stock_account/__init__.py @@ -16,8 +16,9 @@ def _configure_journals(cr, registry): for company_id in company_ids: # Check if property exists for stock account journal exists - properties = env['ir.property'].search([ - ('name', '=', 'property_stock_journal'), + field = env['ir.model.fields']._get("product.category", "property_stock_journal") + properties = env['ir.property'].sudo().search([ + ('fields_id', '=', field.id), ('company_id', '=', company_id.id)]) # If not, check if you can find a journal that is already there with the same name, otherwise create one diff --git a/odoo/addons/base/models/ir_property.py b/odoo/addons/base/models/ir_property.py index 02703383df4..d5b47d9a9ab 100644 --- a/odoo/addons/base/models/ir_property.py +++ b/odoo/addons/base/models/ir_property.py @@ -186,7 +186,7 @@ class Property(models.Model): """ field_id = self.env['ir.model.fields']._get(model, name).id company_id = int(company) if company else False - prop = self.search([ + prop = self.sudo().search([ ('fields_id', '=', field_id), ('company_id', '=', company_id), ('res_id', '=', False), @@ -194,7 +194,7 @@ class Property(models.Model): if prop: prop.write({'value': value}) else: - self.create({ + prop.create({ 'fields_id': field_id, 'company_id': company_id, 'res_id': False, @@ -243,8 +243,8 @@ class Property(models.Model): res_id = "%s,%s" % (model, res_id) domain = [('res_id', '=', res_id)] + domain #make the search with company_id asc to make sure that properties specific to a company are given first - return self.search(domain, limit=1, order='company_id') - return self.browse(()) + return self.sudo().search(domain, limit=1, order='company_id') + return self.sudo().browse(()) def _get_domain(self, prop_name, model): self._cr.execute("SELECT id FROM ir_model_fields WHERE name=%s AND model=%s", (prop_name, model)) @@ -347,7 +347,7 @@ class Property(models.Model): field_id = self._cr.fetchone()[0] company_id = self.env.company.id refs = {('%s,%s' % (model, id)): id for id in values} - props = self.search([ + props = self.sudo().search([ ('fields_id', '=', field_id), ('company_id', '=', company_id), ('res_id', 'in', list(refs)), @@ -379,7 +379,7 @@ class Property(models.Model): 'value': value, 'type': self.env[model]._fields[name].type, }) - self.create(vals_list) + self.sudo().create(vals_list) @api.model def search_multi(self, name, model, operator, value):