From af6c56711fd282a72d0fd8118ac7f0fc49e263f6 Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Mon, 16 Nov 2020 11:50:19 +0000 Subject: [PATCH] [FIX] core: avoid access error when flushing This patch guarantees that computed fields with `compute_sudo=True` do not cause access errors when fetched from database. This fixes a non-deterministic access error upon `commit`, where fields are recomputed and flushed with some random environment. The method `recompute` performs its duty by accessing the fields to recompute. The compute method of a field is called but does not assign it. As the field is not in cache, its value is read from database. However, as the latter is not done in superuser mode, it may cause some access error. closes odoo/odoo#61842 X-original-commit: cfb942ab5902e0992434eb2c7db2940526df404e Signed-off-by: Raphael Collet (rco) --- .../test_new_api/tests/test_new_fields.py | 23 +++++++++++++++++++ odoo/fields.py | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/odoo/addons/test_new_api/tests/test_new_fields.py b/odoo/addons/test_new_api/tests/test_new_fields.py index a25c555cab5..7e033cfac37 100644 --- a/odoo/addons/test_new_api/tests/test_new_fields.py +++ b/odoo/addons/test_new_api/tests/test_new_fields.py @@ -636,6 +636,29 @@ class TestFields(TransactionCaseWithUserDemo): self.assertEqual(record.bars, False) self.assertEqual(record.bares, False) + def test_16_compute_unassigned_access_error(self): + # create a real record + record = self.env['test_new_api.compute.unassigned'].create({}) + record.flush() + + # alter access rights: regular users cannot read 'record' + access = self.env.ref('test_new_api.access_test_new_api_compute_unassigned') + access.perm_read = False + + # switch to environment with user demo + record = record.with_user(self.user_demo) + record.env.cache.invalidate() + + # check that the record is not accessible + with self.assertRaises(AccessError): + record.bars + + # modify the record and flush() changes with the current environment: + # this should not trigger an access error, even if unassigned computed + # fields are fetched from database + record.foo = "X" + record.flush() + def test_20_float(self): """ test rounding of float fields """ record = self.env['test_new_api.mixed'].create({}) diff --git a/odoo/fields.py b/odoo/fields.py index 04dddd4013c..1aec507f21a 100644 --- a/odoo/fields.py +++ b/odoo/fields.py @@ -929,6 +929,7 @@ class Field(MetaField('DummyField', (object,), {})): # only a single record may be accessed record.ensure_one() + recomputed = False if self.compute and (record.id in env.all.tocompute.get(self, ())) \ and not env.is_protected(self, record): # self must be computed on record @@ -941,6 +942,7 @@ class Field(MetaField('DummyField', (object,), {})): self.compute_value(recs) except (AccessError, MissingError): self.compute_value(record) + recomputed = True try: value = env.cache.get(record, self) @@ -949,6 +951,8 @@ class Field(MetaField('DummyField', (object,), {})): if self.store and record.id: # real record: fetch from database recs = record._in_cache_without(self) + if recomputed and self.compute_sudo: + recs = recs.sudo() try: recs._fetch_field(self) except AccessError: