summaryrefslogtreecommitdiff
path: root/odoo
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-02-14 18:42:19 +0100
committerChristophe Simonis <chs@odoo.com>2019-02-14 18:42:19 +0100
commitb277705e52232e5d28c5ec5fc381631fcb1964f8 (patch)
tree437ed09707b32b9fa4ed5eb678214d9b46e6b598 /odoo
parent38be857b4016f120e3cf119a94ca92d035bdab31 (diff)
parentc0f24d54cfab764c0b89df977757e06974a658c6 (diff)
[MERGE] forward port branch saas-15 up to c0f24d54cfa
Diffstat (limited to 'odoo')
-rw-r--r--odoo/addons/test_new_api/tests/test_new_fields.py40
-rw-r--r--odoo/fields.py16
-rw-r--r--odoo/models.py7
3 files changed, 60 insertions, 3 deletions
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 83a359ac951..b86b4ce5953 100644
--- a/odoo/addons/test_new_api/tests/test_new_fields.py
+++ b/odoo/addons/test_new_api/tests/test_new_fields.py
@@ -281,6 +281,16 @@ class TestFields(common.TransactionCase):
self.assertEqual(record.bar, 'Ho')
self.assertEqual(record.counts, {'compute': 0, 'inverse': 1})
+ def test_13_inverse_access(self):
+ """ test access rights on inverse fields """
+ foo = self.env['test_new_api.category'].create({'name': 'Foo'})
+ user = self.env['res.users'].create({'name': 'Foo', 'login': 'foo'})
+ self.assertFalse(user.has_group('base.group_system'))
+ # add group on non-stored inverse field
+ self.patch(type(foo).display_name, 'groups', 'base.group_system')
+ with self.assertRaises(AccessError):
+ foo.sudo(user).display_name = 'Forbidden'
+
def test_14_search(self):
""" test search on computed fields """
discussion = self.env.ref('test_new_api.discussion_0')
@@ -586,6 +596,10 @@ class TestFields(common.TransactionCase):
self.env['ir.property'].create({'name': 'foo', 'fields_id': field_tag_id.id,
'value': tag0, 'type': 'many2one'})
+ # assumption: users don't have access to 'ir.property'
+ accesses = self.env['ir.model.access'].search([('model_id.model', '=', 'ir.property')])
+ accesses.write(dict.fromkeys(['perm_read', 'perm_write', 'perm_create', 'perm_unlink'], False))
+
# create/modify a record, and check the value for each user
record = self.env['test_new_api.company'].create({
'foo': 'main',
@@ -639,6 +653,13 @@ class TestFields(common.TransactionCase):
self.assertEqual(record.sudo(user1).foo, False)
self.assertEqual(record.sudo(user2).foo, 'default')
+ # set field with 'force_company' in context
+ record.sudo(user0).with_context(force_company=company1.id).foo = 'beta'
+ record.invalidate_cache()
+ self.assertEqual(record.sudo(user0).foo, 'main')
+ self.assertEqual(record.sudo(user1).foo, 'beta')
+ self.assertEqual(record.sudo(user2).foo, 'default')
+
# create company record and attribute
company_record = self.env['test_new_api.company'].create({'foo': 'ABC'})
attribute_record = self.env['test_new_api.company.attr'].create({
@@ -658,6 +679,25 @@ class TestFields(common.TransactionCase):
self.assertEqual(attribute_record.bar, 'DEFDEF')
self.assertFalse(self.env.has_todo())
+ # add group on company-dependent field
+ self.assertFalse(user0.has_group('base.group_system'))
+ self.patch(type(record).foo, 'groups', 'base.group_system')
+ with self.assertRaises(AccessError):
+ record.sudo(user0).foo = 'forbidden'
+
+ user0.write({'groups_id': [(4, self.env.ref('base.group_system').id)]})
+ record.sudo(user0).foo = 'yes we can'
+
+ # add ir.rule to prevent access on record
+ self.assertTrue(user0.has_group('base.group_user'))
+ rule = self.env['ir.rule'].create({
+ 'model_id': self.env['ir.model']._get_id(record._name),
+ 'groups': [self.env.ref('base.group_user').id],
+ 'domain_force': str([('id', '!=', record.id)]),
+ })
+ with self.assertRaises(AccessError):
+ record.sudo(user0).foo = 'forbidden'
+
def test_30_read(self):
""" test computed fields as returned by read(). """
discussion = self.env.ref('test_new_api.discussion_0')
diff --git a/odoo/fields.py b/odoo/fields.py
index 24683bbd0c8..b0100d4f549 100644
--- a/odoo/fields.py
+++ b/odoo/fields.py
@@ -622,13 +622,25 @@ class Field(MetaField('DummyField', (object,), {})):
return model.env['ir.property'].get(self.name, self.model_name)
def _compute_company_dependent(self, records):
- Property = records.env['ir.property']
+ # read property as superuser, as the current user may not have access
+ context = records.env.context
+ if 'force_company' not in context:
+ field_id = records.env['ir.model.fields']._get_id(self.model_name, self.name)
+ company = records.env['res.company']._company_default_get(self.model_name, field_id)
+ context = dict(context, force_company=company.id)
+ Property = records.env(user=SUPERUSER_ID, context=context)['ir.property']
values = Property.get_multi(self.name, self.model_name, records.ids)
for record in records:
record[self.name] = values.get(record.id)
def _inverse_company_dependent(self, records):
- Property = records.env['ir.property']
+ # update property as superuser, as the current user may not have access
+ context = records.env.context
+ if 'force_company' not in context:
+ field_id = records.env['ir.model.fields']._get_id(self.model_name, self.name)
+ company = records.env['res.company']._company_default_get(self.model_name, field_id)
+ context = dict(context, force_company=company.id)
+ Property = records.env(user=SUPERUSER_ID, context=context)['ir.property']
values = {
record.id: self.convert_to_write(record[self.name], record)
for record in records
diff --git a/odoo/models.py b/odoo/models.py
index 1fc937f8f5e..bedf7fec10e 100644
--- a/odoo/models.py
+++ b/odoo/models.py
@@ -3102,10 +3102,15 @@ class BaseModel(MetaModel('DummyModel', (object,), {'_register': False})):
protected_fields = [self._fields[n] for n in new_vals]
with self.env.protecting(protected_fields, self):
# write old-style fields with (low-level) method _write
- if old_vals:
+ if old_vals or new_vals:
+ # if log_access is enabled, this updates 'write_date' and
+ # 'write_uid' and check access rules, even when old_vals is
+ # empty
self._write(old_vals)
if new_vals:
+ self.check_field_access_rights('write', list(new_vals))
+
self.modified(set(new_vals) - set(old_vals))
# put the values of fields into cache, and inverse them