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