[FIX] tests: make sure that a failed tests does not leave the environment dirty
[odoo/odoo.git] / openerp / addons / base / tests / test_acl.py
1 import unittest2
2 from lxml import etree
3
4 import openerp
5 from openerp.tools.misc import mute_logger
6 from openerp.tests import common
7
8 # test group that demo user should not have
9 GROUP_TECHNICAL_FEATURES = 'base.group_no_one'
10
11
12 class TestACL(common.TransactionCase):
13
14     def setUp(self):
15         super(TestACL, self).setUp()
16         self.res_currency = self.registry('res.currency')
17         self.res_partner = self.registry('res.partner')
18         self.res_users = self.registry('res.users')
19         _, self.demo_uid = self.registry('ir.model.data').get_object_reference(self.cr, self.uid, 'base', 'user_demo')
20         self.tech_group = self.registry('ir.model.data').get_object(self.cr, self.uid,
21                                                                     *(GROUP_TECHNICAL_FEATURES.split('.')))
22
23     def _set_field_groups(self, model, field_name, groups):
24         field = model._fields[field_name]
25         column = model._columns[field_name]
26         old_groups = field.groups
27         old_prefetch = column._prefetch
28     
29         field.groups = groups
30         column.groups = groups
31         column._prefetch = False
32
33         @self.addCleanup
34         def cleanup():
35             field.groups = old_groups
36             column.groups = old_groups
37             column._prefetch = old_prefetch
38
39     def test_field_visibility_restriction(self):
40         """Check that model-level ``groups`` parameter effectively restricts access to that
41            field for users who do not belong to one of the explicitly allowed groups"""
42         # Verify the test environment first
43         original_fields = self.res_currency.fields_get(self.cr, self.demo_uid, [])
44         form_view = self.res_currency.fields_view_get(self.cr, self.demo_uid, False, 'form')
45         view_arch = etree.fromstring(form_view.get('arch'))
46         has_tech_feat = self.res_users.has_group(self.cr, self.demo_uid, GROUP_TECHNICAL_FEATURES)
47         self.assertFalse(has_tech_feat, "`demo` user should not belong to the restricted group before the test")
48         self.assertTrue('accuracy' in original_fields, "'accuracy' field must be properly visible before the test")
49         self.assertNotEquals(view_arch.xpath("//field[@name='accuracy']"), [],
50                              "Field 'accuracy' must be found in view definition before the test")
51
52         # restrict access to the field and check it's gone
53         self._set_field_groups(self.res_currency, 'accuracy', GROUP_TECHNICAL_FEATURES)
54
55         fields = self.res_currency.fields_get(self.cr, self.demo_uid, [])
56         form_view = self.res_currency.fields_view_get(self.cr, self.demo_uid, False, 'form')
57         view_arch = etree.fromstring(form_view.get('arch'))
58         self.assertFalse('accuracy' in fields, "'accuracy' field should be gone")
59         self.assertEquals(view_arch.xpath("//field[@name='accuracy']"), [],
60                           "Field 'accuracy' must not be found in view definition")
61
62         # Make demo user a member of the restricted group and check that the field is back
63         self.tech_group.write({'users': [(4, self.demo_uid)]})
64         has_tech_feat = self.res_users.has_group(self.cr, self.demo_uid, GROUP_TECHNICAL_FEATURES)
65         fields = self.res_currency.fields_get(self.cr, self.demo_uid, [])
66         form_view = self.res_currency.fields_view_get(self.cr, self.demo_uid, False, 'form')
67         view_arch = etree.fromstring(form_view.get('arch'))
68         #import pprint; pprint.pprint(fields); pprint.pprint(form_view)
69         self.assertTrue(has_tech_feat, "`demo` user should now belong to the restricted group")
70         self.assertTrue('accuracy' in fields, "'accuracy' field must be properly visible again")
71         self.assertNotEquals(view_arch.xpath("//field[@name='accuracy']"), [],
72                              "Field 'accuracy' must be found in view definition again")
73
74         #cleanup
75         self.tech_group.write({'users': [(3, self.demo_uid)]})
76
77     @mute_logger('openerp.models')
78     def test_field_crud_restriction(self):
79         "Read/Write RPC access to restricted field should be forbidden"
80         # Verify the test environment first
81         has_tech_feat = self.res_users.has_group(self.cr, self.demo_uid, GROUP_TECHNICAL_FEATURES)
82         self.assertFalse(has_tech_feat, "`demo` user should not belong to the restricted group")
83         self.assert_(self.res_partner.read(self.cr, self.demo_uid, [1], ['bank_ids']))
84         self.assert_(self.res_partner.write(self.cr, self.demo_uid, [1], {'bank_ids': []}))
85
86         # Now restrict access to the field and check it's forbidden
87         self._set_field_groups(self.res_partner, 'bank_ids', GROUP_TECHNICAL_FEATURES)
88
89         with self.assertRaises(openerp.osv.orm.except_orm):
90             self.res_partner.read(self.cr, self.demo_uid, [1], ['bank_ids'])
91         with self.assertRaises(openerp.osv.orm.except_orm):
92             self.res_partner.write(self.cr, self.demo_uid, [1], {'bank_ids': []})
93
94         # Add the restricted group, and check that it works again
95         self.tech_group.write({'users': [(4, self.demo_uid)]})
96         has_tech_feat = self.res_users.has_group(self.cr, self.demo_uid, GROUP_TECHNICAL_FEATURES)
97         self.assertTrue(has_tech_feat, "`demo` user should now belong to the restricted group")
98         self.assert_(self.res_partner.read(self.cr, self.demo_uid, [1], ['bank_ids']))
99         self.assert_(self.res_partner.write(self.cr, self.demo_uid, [1], {'bank_ids': []}))
100
101         #cleanup
102         self.tech_group.write({'users': [(3, self.demo_uid)]})
103
104     @mute_logger('openerp.models')
105     def test_fields_browse_restriction(self):
106         """Test access to records having restricted fields"""
107         self._set_field_groups(self.res_partner, 'email', GROUP_TECHNICAL_FEATURES)
108
109         pid = self.res_partner.search(self.cr, self.demo_uid, [], limit=1)[0]
110         part = self.res_partner.browse(self.cr, self.demo_uid, pid)
111         # accessing fields must no raise exceptions...
112         part.name
113         # ... except if they are restricted
114         with self.assertRaises(openerp.exceptions.AccessError):
115             with mute_logger('openerp.models'):
116                 part.email
117
118 if __name__ == '__main__':
119     unittest2.main()
120
121 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: