[FIX] ir.ui.view: properly validate newly created inheriting views

When a new inheriting view is imported during a module
    installation, it is validated thanks to the _constraints
    on the ir.ui.view model. However the validation uses
    a rather convoluted system for validating the whole
    view tree at once (root view + all inherited changes)
    while only taking into account the views that belong
    to modules that are currently loaded.

    This complicated system is necessary to be able to
    operate on-the-fly at any point during the registry
    loading/initialization.

    Now because _constraints are checked during create()
    this particular validation happens *before* the
    external ID (ir.model.data entry) of that new view
    can be created (it obviously needs to wait until
    the view record is inserted). As a consequence the
    view validation cannot determine the module to
    which that new view belongs, and was erroneously
    ignoring it.
    Changing the view filtering to also include views
    that have triggered this check.
    Manually created views are not check during registry
    update.

bzr revid: chs@openerp.com-20130912141018-qmcyase8zqov9d01
This commit is contained in:
Christophe Simonis 2013-09-12 16:10:18 +02:00
parent b17fd217bd
commit 1d91378ce2
4 changed files with 56 additions and 4 deletions

View File

@ -125,11 +125,15 @@ class view(osv.osv):
try:
fvg = self.pool.get(view.model).fields_view_get(cr, uid, view_id=view.id, view_type=view.type, context=context)
return fvg['arch']
except:
except Exception:
_logger.exception("Can't render view %s for model: %s", view.xml_id, view.model)
return False
def _check_xml(self, cr, uid, ids, context=None):
if context is None:
context = {}
context['check_view_ids'] = ids
for view in self.browse(cr, uid, ids, context):
# Sanity check: the view should not break anything upon rendering!
view_arch_utf8 = self._check_render_view(cr, uid, view, context=context)
@ -175,13 +179,15 @@ class view(osv.osv):
:rtype: list of tuples
:return: [(view_arch,view_id), ...]
"""
user_groups = frozenset(self.pool.get('res.users').browse(cr, 1, uid, context).groups_id)
if self.pool._init:
# Module init currently in progress, only consider views from modules whose code was already loaded
check_view_ids = context and context.get('check_view_ids') or (0,)
query = """SELECT v.id FROM ir_ui_view v LEFT JOIN ir_model_data md ON (md.model = 'ir.ui.view' AND md.res_id = v.id)
WHERE v.inherit_id=%s AND v.model=%s AND (md.module IS NULL or md.module in %s)
WHERE v.inherit_id=%s AND v.model=%s AND (md.module in %s OR v.id in %s)
ORDER BY priority"""
query_params = (view_id, model, tuple(self.pool._init_modules))
query_params = (view_id, model, tuple(self.pool._init_modules), tuple(check_view_ids))
else:
# Modules fully loaded, consider all views
query = """SELECT v.id FROM ir_ui_view v

View File

@ -4,6 +4,7 @@ import test_ir_attachment
import test_ir_values
import test_menu
import test_search
import test_views
checks = [
test_base,
@ -12,4 +13,5 @@ checks = [
test_ir_values,
test_menu,
test_search,
test_views,
]

View File

@ -0,0 +1,44 @@
import unittest2
import openerp.tests.common as common
from openerp.osv.orm import except_orm
from openerp.tools import mute_logger
class test_views(common.TransactionCase):
@mute_logger('openerp.osv.orm', 'openerp.addons.base.ir.ir_ui_view')
def test_00_init_check_views(self):
Views = self.registry('ir.ui.view')
self.assertTrue(Views.pool._init)
error_msg = "Invalid XML for View Architecture"
# test arch check is call for views without xmlid during registry initialization
with self.assertRaisesRegexp(except_orm, error_msg):
Views.create(self.cr, self.uid, {
'name': 'Test View #1',
'model': 'ir.ui.view',
'arch': """<?xml version="1.0"?>
<tree>
<field name="test_1"/>
</tree>
""",
})
# same for inherited views
with self.assertRaisesRegexp(except_orm, error_msg):
# Views.pudb = True
Views.create(self.cr, self.uid, {
'name': 'Test View #2',
'model': 'ir.ui.view',
'inherit_id': self.browse_ref('base.view_view_tree').id,
'arch': """<?xml version="1.0"?>
<xpath expr="//field[@name='name']" position="after">
<field name="test_2"/>
</xpath>
""",
})
if __name__ == '__main__':
unittest2.main()

View File

@ -2190,7 +2190,7 @@ class BaseModel(object):
are applied
"""
sql_inherit = self.pool.get('ir.ui.view').get_inheriting_views_arch(cr, user, inherit_id, self._name)
sql_inherit = self.pool.get('ir.ui.view').get_inheriting_views_arch(cr, user, inherit_id, self._name, context=context)
for (view_arch, view_id) in sql_inherit:
source = apply_inheritance_specs(source, view_arch, view_id)
source = apply_view_inheritance(cr, user, source, view_id)