Remove button if it is not allowed to access some of its dependant fields

issue7502
review47511002
This commit is contained in:
Sergi Almacellas Abellana
2018-08-01 10:44:06 +02:00
parent bc0799ece3
commit 3158279cb3
6 changed files with 101 additions and 16 deletions
+1
View File
@@ -1,3 +1,4 @@
* Remove button if it is not allowed to access some of its dependant fields
* Add support for Python 3.7
* Add transactional queue and workers
* Add __table_handler__ to ModelSQL
+27 -16
View File
@@ -409,22 +409,33 @@ class ModelView(Model):
fields_to_remove.add(name)
checked |= to_check
# Remove field without read access
for field in fields_to_remove:
xpath = ('//field[@name="%(field)s"] | //label[@name="%(field)s"]'
' | //page[@name="%(field)s"] | //group[@name="%(field)s"]'
' | //separator[@name="%(field)s"]') % {'field': field}
for i, element in enumerate(tree.xpath(xpath)):
if type == 'tree' or element.tag == 'page':
parent = element.getparent()
parent.remove(element)
elif type == 'form':
element.tag = 'label'
colspan = element.attrib.get('colspan')
element.attrib.clear()
element.attrib['id'] = 'hidden %s-%s' % (field, i)
if colspan is not None:
element.attrib['colspan'] = colspan
buttons_to_remove = set()
for name, definition in cls._buttons.items():
if fields_to_remove & set(definition.get('depends', [])):
buttons_to_remove.add(name)
field_xpath = ('//field[@name="%(name)s"]'
'| //label[@name="%(name)s"] | //page[@name="%(name)s"]'
'| //group[@name="%(name)s"] | //separator[@name="%(name)s"]')
button_xpath = '//button[@name="%(name)s"]'
# Remove field and button without read acces
for xpath, names in (
(field_xpath, fields_to_remove),
(button_xpath, buttons_to_remove),
):
for name in names:
path = xpath % {'name': name}
for i, element in enumerate(tree.xpath(path)):
if type == 'tree' or element.tag == 'page':
parent = element.getparent()
parent.remove(element)
elif type == 'form':
element.tag = 'label'
colspan = element.attrib.get('colspan')
element.attrib.clear()
element.attrib['id'] = 'hidden %s-%s' % (name, i)
if colspan is not None:
element.attrib['colspan'] = colspan
# Remove empty pages
if type == 'form':
+1
View File
@@ -51,6 +51,7 @@ def register():
ModelViewChangedValues,
ModelViewChangedValuesTarget,
ModelViewButton,
ModelViewButtonDepends,
ModelViewRPC,
ModelViewEmptyPage,
ModelViewCircularDepends,
+21
View File
@@ -9,6 +9,7 @@ __all__ = [
'ModelViewChangedValues',
'ModelViewChangedValuesTarget',
'ModelViewButton',
'ModelViewButtonDepends',
'ModelViewRPC',
'ModelViewEmptyPage',
'ModelViewCircularDepends',
@@ -58,6 +59,26 @@ class ModelViewButton(ModelView):
pass
class ModelViewButtonDepends(ModelView):
'ModelView Button Depends'
__name__ = 'test.modelview.button_depends'
value = fields.Integer("Value")
@classmethod
def __setup__(cls):
super(ModelViewButtonDepends, cls).__setup__()
cls._buttons = {
'test': {
'depends': ['value'],
},
}
@classmethod
@ModelView.button
def test(cls, records):
pass
class ModelViewRPC(ModelView):
'ModelView RPC'
__name__ = 'test.modelview.rpc'
+13
View File
@@ -16,4 +16,17 @@
]]>
</field>
</record>
<record model="ir.ui.view" id="test_modelview_button_view_form">
<field name="model">test.modelview.button_depends</field>
<field name="type">form</field>
<field name="arch" type="xml">
<![CDATA[
<form>
<label name="value"/>
<field name="value"/>
<button name="test"/>
</form>
]]>
</field>
</record>
</tryton>
+38
View File
@@ -350,6 +350,44 @@ class ModelView(unittest.TestCase):
self.assertEqual(fields, {})
@with_transaction(context={'_check_access': True})
def test_button_depends_access(self):
"Testing buttons are not removed when dependant fields are accesible"
pool = Pool()
Button = pool.get('test.modelview.button_depends')
arch = Button.fields_view_get(view_type='form')['arch']
parser = etree.XMLParser()
tree = etree.fromstring(arch, parser=parser)
buttons = tree.xpath('//button')
self.assertEqual(len(buttons), 1)
@with_transaction(context={'_check_access': True})
def test_button_depends_no_access(self):
"Testing buttons are removed when dependant fields are not accesible"
pool = Pool()
Button = pool.get('test.modelview.button_depends')
Field = pool.get('ir.model.field')
FieldAccess = pool.get('ir.model.field.access')
field, = Field.search([
('model.model', '=', Button.__name__),
('name', '=', 'value'),
])
FieldAccess.create([{
'field': field.id,
'group': None,
'perm_read': False,
}])
arch = Button.fields_view_get(view_type='form')['arch']
parser = etree.XMLParser()
tree = etree.fromstring(arch, parser=parser)
buttons = tree.xpath('//button')
self.assertEqual(len(buttons), 0)
def suite():
func = unittest.TestLoader().loadTestsFromTestCase