[IMP] odoo: prevent unsafe import from file
It's possible to specify an existing module as the xml id prefix when importing records from a file. This will result in `ir_module_data` records being created with `noupdate` set to False. When the module is upgraded, these records will be deleted. This can lead to undesired side effects like journal items for accounts imported this way being deleted. This change prevents creating new records linked to existing modules when importing from a file. Instead, the user should either use no prefix or the name of a non-existent module, like `__import__`. opw-3231987 closes odoo/odoo#133263 X-original-commit: 8f12d14c4c4354a63c94f14e7a89abc6048525f9 Signed-off-by: Merel Geens <mege@odoo.com>
This commit is contained in:
@@ -571,11 +571,12 @@ class test_m2o(ImporterCase):
|
||||
# 1 x SAVEPOINT load
|
||||
# 3 x name_search
|
||||
# 1 x SAVEPOINT _load_records
|
||||
# 3 x insert
|
||||
# 1 x select on list of existing modules
|
||||
# 1 x insert
|
||||
# 1 x RELEASE SAVEPOINT _load_records
|
||||
# 1 x RELEASE SAVEPOINT load
|
||||
# => 10
|
||||
with self.assertQueryCount(8):
|
||||
# => 9
|
||||
with self.assertQueryCount(9):
|
||||
result = self.import_(['value'], [
|
||||
# import by display_name
|
||||
[record1.display_name],
|
||||
|
||||
@@ -1225,6 +1225,10 @@ class BaseModel(metaclass=MetaModel):
|
||||
# Failed to write, log to messages, rollback savepoint (to
|
||||
# avoid broken transaction) and keep going
|
||||
errors += 1
|
||||
except UserError as e:
|
||||
info = rec_data['info']
|
||||
messages.append(dict(info, type='error', message=str(e)))
|
||||
errors += 1
|
||||
except Exception as e:
|
||||
_logger.debug("Error while loading record", exc_info=True)
|
||||
info = rec_data['info']
|
||||
@@ -4655,6 +4659,17 @@ class BaseModel(metaclass=MetaModel):
|
||||
if data.get('xml_id') and not data['xml_id'].startswith(prefix):
|
||||
_logger.warning("Creating record %s in module %s.", data['xml_id'], module)
|
||||
|
||||
if self.env.context.get('import_file'):
|
||||
existing_modules = self.env['ir.module.module'].search([]).mapped('name')
|
||||
for data in to_create:
|
||||
xml_id = data.get('xml_id')
|
||||
if xml_id:
|
||||
module_name, sep, record_id = xml_id.partition('.')
|
||||
if sep and module_name in existing_modules:
|
||||
raise UserError(
|
||||
_("The record %(xml_id)s has the module prefix %(module_name)s. This is the part before the '.' in the external id. Because the prefix refers to an existing module, the record would be deleted when the module is upgraded. Use either no prefix and no dot or a prefix that isn't an existing module. For example, __import__, resulting in the external id __import__.%(record_id)s.",
|
||||
xml_id=xml_id, module_name=module_name, record_id=record_id))
|
||||
|
||||
# create records
|
||||
if to_create:
|
||||
records = self._load_records_create([data['values'] for data in to_create])
|
||||
|
||||
Reference in New Issue
Block a user