[IMP] base: properties, do not allow to select transient models

Purpose
=======
Do not allow to select transient models in relational properties.

Task-3032464

Part-of: odoo/odoo#103510
This commit is contained in:
std-odoo
2023-09-08 09:46:56 +00:00
parent 6c566c2814
commit 88f4c4dd36
6 changed files with 57 additions and 6 deletions
+11 -5
View File
@@ -19,7 +19,7 @@ class IrModel(models.Model):
accessible_models = []
not_accessible_models = []
for model in models:
if self._check_model_access(model):
if self._is_valid_for_model_selector(model):
accessible_models.append(model)
else:
not_accessible_models.append({"display_name": model, "model": model})
@@ -34,9 +34,15 @@ class IrModel(models.Model):
} for model in records]
@api.model
def _check_model_access(self, model):
return (self.env.user._is_internal() and model in self.env
and self.env[model].check_access_rights("read", raise_exception=False))
def _is_valid_for_model_selector(self, model):
model = self.env.get(model)
return (
self.env.user._is_internal()
and model is not None
and model.check_access_rights("read", raise_exception=False)
and not model._transient
and not model._abstract
)
@api.model
def get_available_models(self):
@@ -44,5 +50,5 @@ class IrModel(models.Model):
Return the list of models the current user has access to, with their
corresponding display name.
"""
accessible_models = [model for model in self.pool.keys() if self._check_model_access(model)]
accessible_models = [model for model in self.pool if self._is_valid_for_model_selector(model)]
return self._display_name_for(accessible_models)
+9
View File
@@ -63,3 +63,12 @@ class IrModelAccessTest(TransactionCase):
# non existent model comes after existent model
result = self.env['ir.model'].display_name_for(["res.company", "unexistent"])
self.assertEqual(result, [{"display_name": "Companies", "model": "res.company"}, {"display_name": "unexistent", "model": "unexistent"}])
# transient models
result = self.env['ir.model'].display_name_for(["res.company", "base.language.export"])
self.assertEqual(result, [{"display_name": "Companies", "model": "res.company"}, {"display_name": "base.language.export", "model": "base.language.export"}])
# do not return results for transient models
result = self.env['ir.model'].get_available_models()
result = {values["model"] for values in result}
self.assertIn("res.company", result)
self.assertNotIn("base.language.export", result)
@@ -962,6 +962,11 @@ class RequiredM2OTransient(models.TransientModel):
bar = fields.Many2one('res.country', required=True)
class TestTransient(models.TransientModel):
_name = 'test_new_api.transient_model'
_description = 'Transient Model'
class Attachment(models.Model):
_name = 'test_new_api.attachment'
_description = 'Attachment'
@@ -114,3 +114,4 @@ access_test_new_api_unsearchable_o2m_employee,access_test_new_api_unsearchable_o
access_test_new_api_any_parent,access_test_new_api_any_parent,model_test_new_api_any_parent,base.group_user,1,0,0,0
access_test_new_api_any_child,access_test_new_api_any_child,model_test_new_api_any_child,base.group_user,1,0,0,0
access_test_new_api_any_tag,access_test_new_api_any_tag,model_test_new_api_any_tag,base.group_user,1,0,0,0
access_test_new_api_transient_model,access_test_new_api_transient_model,model_test_new_api_transient_model,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
114 access_test_new_api_any_parent access_test_new_api_any_parent model_test_new_api_any_parent base.group_user 1 0 0 0
115 access_test_new_api_any_child access_test_new_api_any_child model_test_new_api_any_child base.group_user 1 0 0 0
116 access_test_new_api_any_tag access_test_new_api_any_tag model_test_new_api_any_tag base.group_user 1 0 0 0
117 access_test_new_api_transient_model access_test_new_api_transient_model model_test_new_api_transient_model base.group_user 1 1 1 1
@@ -740,6 +740,21 @@ class PropertiesCase(TestPropertiesMixin):
self.assertEqual(properties[1]['value'], (self.partner_2.id, self.partner_2.display_name))
self.assertEqual(properties[1]['comodel'], 'test_new_api.partner')
# should not be able to set a transient model
with self.assertRaises(ValueError):
self.message_2.attributes = [{
"name": "moderator_partner_id",
"type": "many2one",
"comodel": "test_new_api.transient_model",
"definition_changed": True,
}]
with self.assertRaises(ValueError):
self.discussion_1.attributes_definition = [{
"name": "moderator_partner_id",
"type": "many2one",
"comodel": "test_new_api.transient_model",
}]
@mute_logger('odoo.models.unlink', 'odoo.fields')
def test_properties_field_many2one_unlink(self):
"""Test the case where we unlink the many2one record."""
@@ -1232,6 +1247,21 @@ class PropertiesCase(TestPropertiesMixin):
'value': [(partners[9].id, partners[9].display_name)],
}])
# should not be able to set a transient model
with self.assertRaises(ValueError):
self.message_2.attributes = [{
"name": "partner_ids",
"type": "many2many",
"comodel": "test_new_api.transient_model",
"definition_changed": True,
}]
with self.assertRaises(ValueError):
self.discussion_1.attributes_definition = [{
"name": "partner_ids",
"type": "many2many",
"comodel": "test_new_api.transient_model",
}]
@users('test')
@mute_logger('odoo.addons.base.models.ir_rule', 'odoo.fields')
def test_properties_field_many2many_filtering(self):
+1 -1
View File
@@ -3964,7 +3964,7 @@ class PropertiesDefinition(Field):
raise ValueError(f'Wrong property type {property_type!r}.')
model = property_definition.get('comodel')
if model and model not in env:
if model and (model not in env or env[model].is_transient() or env[model]._abstract):
raise ValueError(f'Invalid model name {model!r}')
property_selection = property_definition.get('selection')