diff --git a/openerp/osv/orm.py b/openerp/osv/orm.py index 499a21f8555..5e19ebc6aed 100644 --- a/openerp/osv/orm.py +++ b/openerp/osv/orm.py @@ -383,6 +383,7 @@ class browse_record(object): raise KeyError(error_msg) # if the field is a classic one or a many2one, we'll fetch all classic and many2one fields + fields_to_fetch = [] if col._prefetch: # gen the list of "local" (ie not inherited) fields which are classic or many2one fields_to_fetch = filter(lambda x: x[1]._classic_write and x[1]._prefetch, self._table._columns.items()) @@ -390,9 +391,14 @@ class browse_record(object): inherits = map(lambda x: (x[0], x[1][2]), self._table._inherit_fields.items()) # complete the field list with the inherited fields which are classic or many2one fields_to_fetch += filter(lambda x: x[1]._classic_write and x[1]._prefetch, inherits) - # otherwise we fetch only that field - else: + + # filter out non accessible fields + accessible_fields = self._table.check_field_access_rights(self._cr, self._uid, 'read', fields=None, context=self._context) + fields_to_fetch = [f for f in fields_to_fetch if f[0] in accessible_fields] + + if not fields_to_fetch: fields_to_fetch = [(name, col)] + ids = filter(lambda id: name not in self._data[id], self._data.keys()) # read the results field_names = map(lambda x: x[0], fields_to_fetch) diff --git a/openerp/tests/test_acl.py b/openerp/tests/test_acl.py index 9f9019e5db9..b3a7f123888 100644 --- a/openerp/tests/test_acl.py +++ b/openerp/tests/test_acl.py @@ -9,6 +9,7 @@ import common # test group that demo user should not have GROUP_TECHNICAL_FEATURES = 'base.group_no_one' + class TestACL(common.TransactionCase): def setUp(self): @@ -22,7 +23,7 @@ class TestACL(common.TransactionCase): def test_field_visibility_restriction(self): """Check that model-level ``groups`` parameter effectively restricts access to that - field for users who do not belong to one of the explicitly allowed groups""" + field for users who do not belong to one of the explicitly allowed groups""" # Verify the test environment first original_fields = self.res_currency.fields_get(self.cr, self.demo_uid, []) form_view = self.res_currency.fields_view_get(self.cr, self.demo_uid, False, 'form') @@ -40,7 +41,7 @@ class TestACL(common.TransactionCase): view_arch = etree.fromstring(form_view.get('arch')) self.assertFalse('accuracy' in fields, "'accuracy' field should be gone") self.assertEquals(view_arch.xpath("//field[@name='accuracy']"), [], - "Field 'accuracy' must not be found in view definition") + "Field 'accuracy' must not be found in view definition") # Make demo user a member of the restricted group and check that the field is back self.tech_group.write({'users': [(4, self.demo_uid)]}) @@ -65,7 +66,7 @@ class TestACL(common.TransactionCase): has_tech_feat = self.res_users.has_group(self.cr, self.demo_uid, GROUP_TECHNICAL_FEATURES) self.assertFalse(has_tech_feat, "`demo` user should not belong to the restricted group") self.assert_(self.res_partner.read(self.cr, self.demo_uid, [1], ['bank_ids'])) - self.assert_(self.res_partner.write(self.cr, self.demo_uid, [1], {'bank_ids': []})) + self.assert_(self.res_partner.write(self.cr, self.demo_uid, [1], {'bank_ids': []})) # Now restrict access to the field and check it's forbidden self.res_partner._columns['bank_ids'].groups = GROUP_TECHNICAL_FEATURES @@ -79,12 +80,29 @@ class TestACL(common.TransactionCase): has_tech_feat = self.res_users.has_group(self.cr, self.demo_uid, GROUP_TECHNICAL_FEATURES) self.assertTrue(has_tech_feat, "`demo` user should now belong to the restricted group") self.assert_(self.res_partner.read(self.cr, self.demo_uid, [1], ['bank_ids'])) - self.assert_(self.res_partner.write(self.cr, self.demo_uid, [1], {'bank_ids': []})) - + self.assert_(self.res_partner.write(self.cr, self.demo_uid, [1], {'bank_ids': []})) + #cleanup self.tech_group.write({'users': [(3, self.demo_uid)]}) self.res_partner._columns['bank_ids'].groups = False + def test_fields_browse_restriction(self): + """Test access to records having restricted fields""" + self.res_partner._columns['email'].groups = GROUP_TECHNICAL_FEATURES + try: + P = self.res_partner + pid = P.search(self.cr, self.demo_uid, [], limit=1)[0] + part = P.browse(self.cr, self.demo_uid, pid) + # accessing fields must no raise exceptions... + part.name + # ... except they are restricted + with self.assertRaises(AttributeError): + part.email + + finally: + self.res_partner._columns['email'].groups = False + + if __name__ == '__main__': unittest2.main()