\n"
"Language-Team: none\n"
"Language: it\n"
@@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 5.10.4\n"
+"X-Generator: Weblate 5.15.2\n"
#. module: fs_storage
#: model_terms:ir.ui.view,arch_db:fs_storage.fs_storage_form_view
@@ -26,6 +26,14 @@ msgstr "Opzioni disponibili"
msgid "Available properties"
msgstr "Proprietà disponibili"
+#. module: fs_storage
+#. odoo-python
+#: code:addons/fs_storage/models/fs_storage.py:0
+msgid "Calling fs.storage.%(reason)s is not allowed in a safe_eval context."
+msgstr ""
+"La chiamata a fs.storage.%(reason)s non è consentita in un contesto "
+"safe_eval."
+
#. module: fs_storage
#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__check_connection_method
#: model:ir.model.fields,field_description:fs_storage.field_fs_test_connection__check_connection_method
@@ -140,8 +148,8 @@ msgstr "Campo"
msgid ""
"Field %(field)s already stored in another FS storage ('%(other_storage)s')"
msgstr ""
-"Il campo %(field)s è già archiviato in un altro deposito FS "
-"('%(other_storage)s')"
+"Il campo %(field)s è già archiviato in un altro deposito FS ('%"
+"(other_storage)s')"
#. module: fs_storage
#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__field_xmlids
@@ -286,8 +294,8 @@ msgstr "Modello"
msgid ""
"Model %(model)s already stored in another FS storage ('%(other_storage)s')"
msgstr ""
-"Il modello %(model)s è già archiviato in un altro deposito FS "
-"('%(other_storage)s')"
+"Il modello %(model)s è già archiviato in un altro deposito FS ('%"
+"(other_storage)s')"
#. module: fs_storage
#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__model_xmlids
@@ -400,8 +408,9 @@ msgstr "Deposito"
msgid ""
"Technical code used to identify the storage backend into the code.This code "
"must be unique. This code is used for example to define the storage backend "
-"to store the attachments via the configuration parameter 'ir_attachment."
-"storage.force.database' when the module 'fs_attachment' is installed."
+"to store the attachments via the configuration parameter "
+"'ir_attachment.storage.force.database' when the module 'fs_attachment' is "
+"installed."
msgstr ""
"Codice tecnico usato per identificare il backend deposito nel codice. Questo "
"codice deve essere univoco. Questo codice è utilizzato per esempio per "
diff --git a/fs_storage/i18n/zh_CN.po b/fs_storage/i18n/zh_CN.po
index 83909c7966..8271d52cd8 100644
--- a/fs_storage/i18n/zh_CN.po
+++ b/fs_storage/i18n/zh_CN.po
@@ -26,6 +26,12 @@ msgstr "可用选项"
msgid "Available properties"
msgstr "可用属性"
+#. module: fs_storage
+#. odoo-python
+#: code:addons/fs_storage/models/fs_storage.py:0
+msgid "Calling fs.storage.%(reason)s is not allowed in a safe_eval context."
+msgstr ""
+
#. module: fs_storage
#: model:ir.model.fields,field_description:fs_storage.field_fs_storage__check_connection_method
#: model:ir.model.fields,field_description:fs_storage.field_fs_test_connection__check_connection_method
@@ -367,12 +373,13 @@ msgstr ""
msgid ""
"Technical code used to identify the storage backend into the code.This code "
"must be unique. This code is used for example to define the storage backend "
-"to store the attachments via the configuration parameter 'ir_attachment."
-"storage.force.database' when the module 'fs_attachment' is installed."
+"to store the attachments via the configuration parameter "
+"'ir_attachment.storage.force.database' when the module 'fs_attachment' is "
+"installed."
msgstr ""
"用于在代码中标识存储后端的技术代码。此代码必须是唯一的。例如,当安"
-"装'fs_attachment'模块时,此代码用于通过配置参数'ir_attachment.storage.force."
-"database'定义存储附件的存储后端。"
+"装'fs_attachment'模块时,此代码用于通过配置参"
+"数'ir_attachment.storage.force.database'定义存储附件的存储后端。"
#. module: fs_storage
#: model_terms:ir.ui.view,arch_db:fs_storage.fs_test_connection_form_view
diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py
index b36a0dbbab..0e60422123 100644
--- a/fs_storage/models/fs_storage.py
+++ b/fs_storage/models/fs_storage.py
@@ -61,6 +61,32 @@ def new_func1(*args, **kwargs):
return decorator
+def prevent_call_from_safe_eval(reason):
+ """Decorator to prevent the call to the method in the context of a
+ safe_eval.
+ """
+
+ def deorator(func):
+ @functools.wraps(func)
+ def wrapper(self, *args, **kwargs):
+ for frame_info in inspect.stack():
+ filename = frame_info.filename or ""
+ function = frame_info.function or ""
+ if "safe_eval" in filename or function == "safe_eval":
+ raise ValidationError(
+ _(
+ "Calling fs.storage.%(reason)s is not allowed "
+ "in a safe_eval context.",
+ reason=reason,
+ )
+ )
+ return func(self, *args, **kwargs)
+
+ return wrapper
+
+ return deorator
+
+
class FSStorage(models.Model):
_name = "fs.storage"
_inherit = "server.env.mixin"
@@ -288,11 +314,30 @@ def _server_env_fields(self):
"check_connection_method": {},
}
+ @api.model_create_multi
+ @prevent_call_from_safe_eval("create")
+ def create(self, vals_list):
+ return super().create(vals_list)
+
+ @prevent_call_from_safe_eval("create")
+ def _create(self, data_list):
+ return super()._create(data_list)
+
+ @prevent_call_from_safe_eval("write")
def write(self, vals):
self.__fs = None
self.env.registry.clear_cache()
return super().write(vals)
+ @prevent_call_from_safe_eval("write")
+ def _write_multi(self, vals_list):
+ return super()._write_multi(vals_list)
+
+ @api.ondelete(at_uninstall=False)
+ @prevent_call_from_safe_eval("unlink")
+ def _check_no_safe_eval_call(self):
+ pass
+
def get_directory_path(self):
"""Returns directory path with substitution done."""
return (
diff --git a/fs_storage/static/description/index.html b/fs_storage/static/description/index.html
index b54e96619f..3104d3767c 100644
--- a/fs_storage/static/description/index.html
+++ b/fs_storage/static/description/index.html
@@ -372,7 +372,7 @@ Filesystem Storage Backend
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-!! source digest: sha256:56e35c5816f37443d3bfb1ac7d6ebd4451e7b8c6e3d7c94a0f176f2b7d38b520
+!! source digest: sha256:b12a9e0e041121ef9301a2e54de2547c3a8a49408067c074b4fdfea8e5d0d74c
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

This addon is a technical addon that allows you to define filesystem
diff --git a/fs_storage/tests/test_fs_storage.py b/fs_storage/tests/test_fs_storage.py
index 4e72cec8dc..631ce4f250 100644
--- a/fs_storage/tests/test_fs_storage.py
+++ b/fs_storage/tests/test_fs_storage.py
@@ -5,7 +5,7 @@
from odoo.exceptions import ValidationError
from odoo.tests import Form
-from odoo.tools import mute_logger
+from odoo.tools import mute_logger, safe_eval
from .common import TestFSStorageCase
@@ -246,3 +246,61 @@ def test_directory_path_substitution(self):
self.backend.directory_path = template
# Assert different (db name should be replaced)
self.assertNotEqual(template, self.backend.get_directory_path())
+
+ def test_no_create_in_safe_eval(self):
+ # check that we can't create a file in safe_eval
+ with self.assertRaisesRegex(
+ ValidationError,
+ "Calling fs.storage.create is not allowed in a safe_eval context.",
+ ):
+ safe_eval.safe_eval(
+ "env['fs.storage'].create({'name': 'test', 'code': 'test'})",
+ {"env": self.env},
+ )
+
+ with self.assertRaisesRegex(
+ ValidationError,
+ "Calling fs.storage.create is not allowed in a safe_eval context.",
+ ):
+ safe_eval.safe_eval(
+ "env['fs.storage']._create({'name': 'test', 'code': 'test'})",
+ {"env": self.env},
+ )
+
+ def test_no_write_in_safe_eval(self):
+ # check that we can't write a file in safe_eval
+ with self.assertRaisesRegex(
+ ValidationError,
+ "Calling fs.storage.write is not allowed in a safe_eval context.",
+ ):
+ safe_eval.safe_eval(
+ "env['fs.storage'].search([]).write({'name': 'test'})",
+ {"env": self.env},
+ )
+ with self.assertRaisesRegex(
+ ValidationError,
+ "Calling fs.storage.write is not allowed in a safe_eval context.",
+ ):
+ safe_eval.safe_eval(
+ "env['fs.storage'].search([])._write({'name': 'test'})",
+ {"env": self.env},
+ )
+
+ with self.assertRaisesRegex(
+ ValidationError,
+ "Calling fs.storage.write is not allowed in a safe_eval context.",
+ ):
+ safe_eval.safe_eval(
+ "env['fs.storage'].search([])._write_multi([{'name': 'test'}])",
+ {"env": self.env},
+ )
+
+ def test_no_unlink_in_safe_eval(self):
+ # check that we can't unlink a file in safe_eval
+ with self.assertRaisesRegex(
+ ValidationError,
+ "Calling fs.storage.unlink is not allowed in a safe_eval context.",
+ ):
+ safe_eval.safe_eval(
+ "env['fs.storage'].search([]).unlink()", {"env": self.env}
+ )
diff --git a/storage_thumbnail/tests/test_thumbnail.py b/storage_thumbnail/tests/test_thumbnail.py
index 954cced924..29e17bc3fc 100644
--- a/storage_thumbnail/tests/test_thumbnail.py
+++ b/storage_thumbnail/tests/test_thumbnail.py
@@ -14,6 +14,7 @@ def setUpClass(cls):
res = super().setUpClass()
cls.loader = FakeModelLoader(cls.env, cls.__module__)
cls.loader.backup_registry()
+ cls.addClassCleanup(cls.loader.restore_registry)
from .models import ModelTest
cls.loader.update_registry((ModelTest,))
@@ -25,19 +26,10 @@ def setUpClass(cls):
cls.filename = "akretion-logo.png"
return res
- def setUp(self):
- res = super().setUp()
- # Remove check_attrs cleanup if exists to avoid conflict with FakeModelLoader.
+ def check_attrs(self):
+ # Deactivate check_attrs to avoid conflict with FakeModelLoader.
# since superClass uses it for its own puposes not relevant for our tests.
- check_attrs = (getattr(self, "check_attrs", None), tuple(), {})
- if check_attrs in self._cleanups:
- self._cleanups.remove(check_attrs)
- return res
-
- @classmethod
- def tearDownClass(cls):
- cls.loader.restore_registry()
- return super().tearDownClass()
+ pass
def _create_thumbnail(self):
# create thumbnail