diff --git a/data_encryption/tests/common.py b/data_encryption/tests/common.py index 82cf60f6b..b6d281b7c 100644 --- a/data_encryption/tests/common.py +++ b/data_encryption/tests/common.py @@ -14,23 +14,33 @@ class CommonDataEncrypted(TransactionCase): - def setUp(self): - super().setUp() + @classmethod + def setUpClass(cls): + super().setUpClass() - self.encrypted_data = self.env["encrypted.data"] - self.set_new_key_env("test") - self.old_running_env = config.get("running_env", "") + cls.encrypted_data = cls.env["encrypted.data"] + cls.set_new_key_env("test") + old_running_env = config.get("running_env", "") + + def reset_running_env(): + config["running_env"] = old_running_env + + cls.addClassCleanup(reset_running_env) config["running_env"] = "test" - self.crypted_data_name = "test_model,1" + cls.crypted_data_name = "test_model,1" - def set_new_key_env(self, environment): + @classmethod + def set_new_key_env(cls, environment): crypting_key = Fernet.generate_key() # The key is encoded to bytes in the module, because in real life # the key com from the config file and is not in a binary format. # So we decode here to avoid having a special behavior because of # the tests. - config[f"encryption_key_{environment}"] = crypting_key.decode() + encryption_key_environment_config_name = f"encryption_key_{environment}" + old_key = config.get(encryption_key_environment_config_name, "") + + def reset_config_key(): + config[encryption_key_environment_config_name] = old_key - def tearDown(self): - config["running_env"] = self.old_running_env - return super().tearDown() + cls.addClassCleanup(reset_config_key) + config[encryption_key_environment_config_name] = crypting_key.decode() diff --git a/server_environment_data_encryption/README.rst b/server_environment_data_encryption/README.rst new file mode 100644 index 000000000..76149e586 --- /dev/null +++ b/server_environment_data_encryption/README.rst @@ -0,0 +1,128 @@ +================================== +Server Environment Data Encryption +================================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:d332eb4ca40eb79923ed865b069723db1c2f7be0946a840d9e1cd3197939915e + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--env-lightgray.png?logo=github + :target: https://github.com/OCA/server-env/tree/17.0/server_environment_data_encryption + :alt: OCA/server-env +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-env-17-0/server-env-17-0-server_environment_data_encryption + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/server-env&target_branch=17.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module changes a little the behavior of server_environment modules. +When Odoo does not find the value of the field in the configuration +file, it will fallback on a Odoo encrypted field instead. Also it allows +you to configure the environment dependent fields for all your +environments from the production server. + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Configuration +============= + +In order to use this module properly, each environment should have their +own encryption key and the production environment should have the keys +of all environments. + +Example : Development environment : + +:: + + [options] + running_env=dev + encryption_key_dev=XXX + +Pre-production environment : + +:: + + [options] + running_env=preprod + encryption_key_preprod=YYY + +Production environment : + +:: + + [options] + running_env=prod + encryption_key_dev=XXX + encryption_key_preprod=YYY + encryption_key_prod=ZZZ + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* Akretion + +Contributors +------------ + +- Florian da Costa +- Sébastien Beau +- Benoît Guillot + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-florian-dacosta| image:: https://github.com/florian-dacosta.png?size=40px + :target: https://github.com/florian-dacosta + :alt: florian-dacosta + +Current `maintainer `__: + +|maintainer-florian-dacosta| + +This module is part of the `OCA/server-env `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/server_environment_data_encryption/__init__.py b/server_environment_data_encryption/__init__.py new file mode 100644 index 000000000..0650744f6 --- /dev/null +++ b/server_environment_data_encryption/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/server_environment_data_encryption/__manifest__.py b/server_environment_data_encryption/__manifest__.py new file mode 100644 index 000000000..8f3126d70 --- /dev/null +++ b/server_environment_data_encryption/__manifest__.py @@ -0,0 +1,13 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +{ + "name": "Server Environment Data Encryption", + "version": "17.0.1.0.0", + "development_status": "Alpha", + "maintainers": ["florian-dacosta"], + "category": "Tools", + "website": "https://github.com/OCA/server-env", + "author": "Akretion, Odoo Community Association (OCA)", + "license": "AGPL-3", + "installable": True, + "depends": ["server_environment", "data_encryption"], +} diff --git a/server_environment_data_encryption/i18n/ca.po b/server_environment_data_encryption/i18n/ca.po new file mode 100644 index 000000000..dd74eadef --- /dev/null +++ b/server_environment_data_encryption/i18n/ca.po @@ -0,0 +1,49 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * server_environment_data_encryption +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "Define values for " +msgstr "" + +#. module: server_environment_data_encryption +#: model:ir.model,name:server_environment_data_encryption.model_server_env_mixin +msgid "Mixin to add server environment in existing models" +msgstr "" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "Modify values for {} environment" +msgstr "" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "The encryption key for current environement is not defined" +msgstr "" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "" +"you need to define the running_env entry in your odoo configuration file" +msgstr "" diff --git a/server_environment_data_encryption/i18n/es.po b/server_environment_data_encryption/i18n/es.po new file mode 100644 index 000000000..4869999e3 --- /dev/null +++ b/server_environment_data_encryption/i18n/es.po @@ -0,0 +1,53 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * server_environment_data_encryption +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-07-25 13:10+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "Define values for " +msgstr "Definir valores para " + +#. module: server_environment_data_encryption +#: model:ir.model,name:server_environment_data_encryption.model_server_env_mixin +msgid "Mixin to add server environment in existing models" +msgstr "Combinación para añadir entorno de servidor en modelos existentes" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "Modify values for {} environment" +msgstr "Modificar los valores del entorno {}" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "The encryption key for current environement is not defined" +msgstr "La clave de encriptación para el entorno actual no está definida" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "" +"you need to define the running_env entry in your odoo configuration file" +msgstr "" +"necesitas definir la entrada running_env en tu archivo de configuración de " +"odoo" diff --git a/server_environment_data_encryption/i18n/it.po b/server_environment_data_encryption/i18n/it.po new file mode 100644 index 000000000..685d1d8b7 --- /dev/null +++ b/server_environment_data_encryption/i18n/it.po @@ -0,0 +1,51 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * server_environment_data_encryption +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2024-01-03 14:36+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "Define values for " +msgstr "Definire valori per " + +#. module: server_environment_data_encryption +#: model:ir.model,name:server_environment_data_encryption.model_server_env_mixin +msgid "Mixin to add server environment in existing models" +msgstr "Mixin per aggiungere l'ambiente server in modelli esistenti" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "Modify values for {} environment" +msgstr "Modificare valori per ambiente {}" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "The encryption key for current environement is not defined" +msgstr "La chiave di criptazione per l'ambiente attuale non è definita" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +#, python-format +msgid "" +"you need to define the running_env entry in your odoo configuration file" +msgstr "bisogna definire il valore running_env nel file di configruazione odoo" diff --git a/server_environment_data_encryption/i18n/server_environment_data_encryption.pot b/server_environment_data_encryption/i18n/server_environment_data_encryption.pot new file mode 100644 index 000000000..4cadd8193 --- /dev/null +++ b/server_environment_data_encryption/i18n/server_environment_data_encryption.pot @@ -0,0 +1,44 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * server_environment_data_encryption +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 18.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +msgid "Define values for " +msgstr "" + +#. module: server_environment_data_encryption +#: model:ir.model,name:server_environment_data_encryption.model_server_env_mixin +msgid "Mixin to add server environment in existing models" +msgstr "" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +msgid "Modify values for {} environment" +msgstr "" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +msgid "The encryption key for current environement is not defined" +msgstr "" + +#. module: server_environment_data_encryption +#. odoo-python +#: code:addons/server_environment_data_encryption/models/server_env_mixin.py:0 +msgid "" +"you need to define the running_env entry in your odoo configuration file" +msgstr "" diff --git a/server_environment_data_encryption/models/__init__.py b/server_environment_data_encryption/models/__init__.py new file mode 100644 index 000000000..6bd869a1e --- /dev/null +++ b/server_environment_data_encryption/models/__init__.py @@ -0,0 +1 @@ +from . import server_env_mixin diff --git a/server_environment_data_encryption/models/server_env_mixin.py b/server_environment_data_encryption/models/server_env_mixin.py new file mode 100644 index 000000000..b85bbb212 --- /dev/null +++ b/server_environment_data_encryption/models/server_env_mixin.py @@ -0,0 +1,222 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import logging + +from lxml import etree + +from odoo import _, api, models +from odoo.exceptions import ValidationError +from odoo.tools.config import config + +_logger = logging.getLogger(__name__) + + +class ServerEnvMixin(models.AbstractModel): + _inherit = "server.env.mixin" + + def _current_env_encrypted_key_exists(self): + env = self.env["encrypted.data"]._retrieve_env() + key_name = f"encryption_key_{env}" + key_str = config.get(key_name) + key_exists = key_str and True or False + if not key_exists: + logging.warning( + "The minimal configuration is missing. You need at least to add an " + "encryption key for the current environment : %s. While the " + "configuration is missing, the module has no effect", + env, + ) + return key_exists + + @api.depends_context("environment") + def _compute_server_env(self): + return super()._compute_server_env() + + def _compute_server_env_from_default(self, field_name, options): + """First return database encrypted value then default value""" + # in case of bad configuration (no encryption key for current env) the module + # is useless, we do fallback directly on serven_environement behavior + if not self._current_env_encrypted_key_exists(): + return super()._compute_server_env_from_default(field_name, options) + encrypted_data_name = f"{self._name},{self.id}" + env = self.env.context.get("environment", None) + + vals = ( + self.env["encrypted.data"] + .sudo() + ._encrypted_read_json(encrypted_data_name, env=env) + ) + if vals.get(field_name): + self[field_name] = vals[field_name] + else: + return super()._compute_server_env_from_default(field_name, options) + + def _inverse_server_env(self, field_name): + """ + When this module is installed, we store values into encrypted data + env instead of a default field in database (not env dependent). + """ + # in case of bad configuration (no encryption key for current env) the module + # is useless, we do fallback directly on serven_environement behavior + if not self._current_env_encrypted_key_exists(): + return super()._inverse_server_env(field_name) + is_editable_field = self._server_env_is_editable_fieldname(field_name) + encrypted_data_obj = self.env["encrypted.data"].sudo() + env = self.env.context.get("environment", None) + for record in self: + if record[is_editable_field]: + encrypted_data_name = f"{record._name},{record.id}" + values = encrypted_data_obj._encrypted_read_json( + encrypted_data_name, env=env + ) + new_val = {field_name: record[field_name]} + values.update(new_val) + encrypted_data_obj._encrypted_store_json( + encrypted_data_name, values, env=env + ) + + def action_change_env_data_encrypted_fields(self): + action_id = self.env.context.get("params", {}).get("action") + if not action_id: + # We don't know which action we are using... take default one + action = self.get_formview_action() + else: + action = ( + self.env["ir.actions.act_window"].browse(action_id).sudo().read()[0] + ) + action["view_mode"] = "form" + action["res_id"] = self.id + views_form = [] + for view_id, view_type in action.get("views", []): + if view_type == "form": + views_form.append((view_id, view_type)) + action["views"] = views_form + return action + + def _get_extra_environment_info_div(self, current_env, all_environments): + # if the module configuration is missing (no current env encryption key) + # display a warning instead as the module has no effect. + if not self._current_env_encrypted_key_exists(): + button_div = "
" + warning_string = _( + "The encryption key for current environement is not defined" + ) + elem = etree.fromstring( + """ +
+
+ {} +
+
+ """.format("alert-danger", warning_string) + ) + return elem + + elem_string = """
""" + for environment in all_environments: + alert_type = ( + environment == config.get("running_env") + and "alert-info" + or "alert-warning" + ) + alert_string = _("Modify values for {} environment").format(environment) + elem_string += f""" +
+ {alert_string} +
+ """ + button_div = """
""" + button_string = _("Define values for ") + for environment in all_environments: + button = """ +
" + elem_string += button_div + elem_string += "
" + elem = etree.fromstring(elem_string) + return elem + + def _set_button_invisible_form_view(self, doc, current_env, all_environments): + """ + Hide button from view when we are in the context of an environment different + than the running one. + """ + invisible_condition = ( + f"""context.get("environment", '{current_env}') != '{current_env}'""" + ) + for button in doc.iter("button"): + button.attrib["invisible"] = invisible_condition + + def _set_readonly_form_view(self, doc, current_env, all_environments): + readonly_condition = ( + f"""context.get("environment", '{current_env}') != '{current_env}'""" + ) + for field in doc.iter("field"): + env_fields = self._server_env_fields.keys() + field_name = field.get("name") + if field_name in env_fields: + continue + current_readonly_cond = field.attrib.get("readonly", "") + current_readonly_cond = ( + current_readonly_cond + and f"({current_readonly_cond}) or {readonly_condition}" + or f"{readonly_condition}" + ) + field.attrib["readonly"] = current_readonly_cond + + def _update_form_view_from_env(self, arch, view_type): + if view_type != "form": + return arch + current_env = self.env.context.get("environment") or config.get("running_env") + + if not current_env: + raise ValidationError( + _( + "you need to define the running_env entry in your odoo " + "configuration file" + ) + ) + current_env = config.get("running_env") + # Important to keep this list sorted. It makes sure the button to + # switch environment will always be in the same order. (more user + # friendly) and the test would fail without it as the order could + # change randomly and the view would then also change randomly + other_environments = sorted( + [ + key[15:] + for key, val in config.options.items() + if key.startswith("encryption_key_") and val and key[15:] != current_env + ] + ) + all_environments = other_environments.copy() + all_environments.insert(0, current_env) + + node = arch.xpath("//sheet") + if node: + self._set_button_invisible_form_view(arch, current_env, all_environments) + self._set_readonly_form_view(arch, current_env, all_environments) + node = node[0] + elem = self._get_extra_environment_info_div(current_env, all_environments) + node.insert(0, elem) + else: + _logger.error(f"Missing sheet for form view on object {self._name}") + return arch + + @api.model + def _get_view(self, view_id=None, view_type="form", **options): + arch, view = super()._get_view(view_id=view_id, view_type=view_type, **options) + arch = self._update_form_view_from_env(arch, view_type) + return arch, view diff --git a/server_environment_data_encryption/pyproject.toml b/server_environment_data_encryption/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/server_environment_data_encryption/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/server_environment_data_encryption/readme/CONFIGURE.md b/server_environment_data_encryption/readme/CONFIGURE.md new file mode 100644 index 000000000..122c47aae --- /dev/null +++ b/server_environment_data_encryption/readme/CONFIGURE.md @@ -0,0 +1,23 @@ +In order to use this module properly, each environment should have their +own encryption key and the production environment should have the keys +of all environments. + +Example : Development environment : + + [options] + running_env=dev + encryption_key_dev=XXX + +Pre-production environment : + + [options] + running_env=preprod + encryption_key_preprod=YYY + +Production environment : + + [options] + running_env=prod + encryption_key_dev=XXX + encryption_key_preprod=YYY + encryption_key_prod=ZZZ diff --git a/server_environment_data_encryption/readme/CONTRIBUTORS.md b/server_environment_data_encryption/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..f118df03f --- /dev/null +++ b/server_environment_data_encryption/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- Florian da Costa \<\> +- Sébastien Beau \<\> +- Benoît Guillot \<\> diff --git a/server_environment_data_encryption/readme/DESCRIPTION.md b/server_environment_data_encryption/readme/DESCRIPTION.md new file mode 100644 index 000000000..08f335b22 --- /dev/null +++ b/server_environment_data_encryption/readme/DESCRIPTION.md @@ -0,0 +1,5 @@ +This module changes a little the behavior of server_environment modules. +When Odoo does not find the value of the field in the configuration +file, it will fallback on a Odoo encrypted field instead. Also it allows +you to configure the environment dependent fields for all your +environments from the production server. diff --git a/server_environment_data_encryption/static/description/icon.png b/server_environment_data_encryption/static/description/icon.png new file mode 100644 index 000000000..3a0328b51 Binary files /dev/null and b/server_environment_data_encryption/static/description/icon.png differ diff --git a/server_environment_data_encryption/static/description/index.html b/server_environment_data_encryption/static/description/index.html new file mode 100644 index 000000000..9917a2278 --- /dev/null +++ b/server_environment_data_encryption/static/description/index.html @@ -0,0 +1,464 @@ + + + + + +Server Environment Data Encryption + + + +
+

Server Environment Data Encryption

+ + +

Alpha License: AGPL-3 OCA/server-env Translate me on Weblate Try me on Runboat

+

This module changes a little the behavior of server_environment modules. +When Odoo does not find the value of the field in the configuration +file, it will fallback on a Odoo encrypted field instead. Also it allows +you to configure the environment dependent fields for all your +environments from the production server.

+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+
+

Table of contents

+ +
+

Configuration

+

In order to use this module properly, each environment should have their +own encryption key and the production environment should have the keys +of all environments.

+

Example : Development environment :

+
+[options]
+running_env=dev
+encryption_key_dev=XXX
+
+

Pre-production environment :

+
+[options]
+running_env=preprod
+encryption_key_preprod=YYY
+
+

Production environment :

+
+[options]
+running_env=prod
+encryption_key_dev=XXX
+encryption_key_preprod=YYY
+encryption_key_prod=ZZZ
+
+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

florian-dacosta

+

This module is part of the OCA/server-env project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/server_environment_data_encryption/tests/__init__.py b/server_environment_data_encryption/tests/__init__.py new file mode 100644 index 000000000..83ac8b859 --- /dev/null +++ b/server_environment_data_encryption/tests/__init__.py @@ -0,0 +1 @@ +from . import test_server_environment_data_encrypt diff --git a/server_environment_data_encryption/tests/fixtures/base.xml b/server_environment_data_encryption/tests/fixtures/base.xml new file mode 100644 index 000000000..d9bc3716c --- /dev/null +++ b/server_environment_data_encryption/tests/fixtures/base.xml @@ -0,0 +1,13 @@ +
+
+
+ + + + + + + + +
diff --git a/server_environment_data_encryption/tests/models.py b/server_environment_data_encryption/tests/models.py new file mode 100644 index 000000000..b2a76f2ba --- /dev/null +++ b/server_environment_data_encryption/tests/models.py @@ -0,0 +1,22 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import api, models + +# pylint: disable=consider-merging-classes-inherited + + +class FakePartner(models.Model): + _name = "res.partner" + _inherit = ["res.partner", "server.env.mixin"] + + @property + def _server_env_fields(self): + base_fields = super()._server_env_fields + partner_fields = { + "city": {}, + } + partner_fields.update(base_fields) + return partner_fields + + @api.model + def _server_env_global_section_name(self): + return "partner" diff --git a/server_environment_data_encryption/tests/test_server_environment_data_encrypt.py b/server_environment_data_encryption/tests/test_server_environment_data_encrypt.py new file mode 100644 index 000000000..b4f530d76 --- /dev/null +++ b/server_environment_data_encryption/tests/test_server_environment_data_encrypt.py @@ -0,0 +1,112 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from pathlib import Path + +from lxml import etree +from odoo_test_helper import FakeModelLoader + +from odoo.addons.data_encryption.tests.common import CommonDataEncrypted + + +class TestServerEnvDataEncrypted(CommonDataEncrypted): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.loader = FakeModelLoader(cls.env, cls.__module__) + cls.loader.backup_registry() + + # The fake class is imported here !! After the backup_registry + from .models import FakePartner + + cls.loader.update_registry((FakePartner,)) + cls.set_new_key_env("prod") + cls.set_new_key_env("preprod") + + @classmethod + def tearDownClass(cls): + cls.loader.restore_registry() + super().tearDownClass() + + def test_env_dependent_value(self): + partner = self.env["res.partner"].create( + {"name": "Fake name", "city": "test city"} + ) + self.assertFalse(partner.with_context(environment="prod").city) + partner.with_context(environment="prod").write({"city": "prod city"}) + self.assertEqual(partner.with_context(environment=False).city, "test city") + self.assertEqual(partner.with_context(environment="test").city, "test city") + self.assertEqual(partner.with_context(environment="prod").city, "prod city") + + def test_view_with_env_update(self): + self.maxDiff = None + # common class already set test environment (as default) + mixin_obj = self.env["server.env.mixin"] + base_path = Path(__file__).parent / "fixtures" / "base.xml" + xml_str = base_path.read_text() + xml = etree.XML(xml_str) + res_xml = mixin_obj._update_form_view_from_env(xml, "form") + + # check we have 3 alert div for our 3 environments + env_div_xml = res_xml.find("sheet").find("div").findall("div") + # 3 alert div + 1 button div + self.assertEqual(len(env_div_xml), 4) + # test first alert test div + test_alert_div = env_div_xml[0] + self.assertEqual( + test_alert_div.get("invisible"), + "context.get('environment', 'test') != 'test'", + ) + self.assertEqual( + test_alert_div.find("strong").text, "Modify values for test environment" + ) + # test preprod div + preprod_alert_div = env_div_xml[1] + self.assertEqual( + preprod_alert_div.get("invisible"), + "context.get('environment', 'test') != 'preprod'", + ) + self.assertEqual( + preprod_alert_div.find("strong").text, + "Modify values for preprod environment", + ) + # test buttons + button_div = env_div_xml[-1] + # 3 buttons for 3 env + self.assertEqual(len(button_div.findall("button")), 3) + test_button = button_div.findall("button")[0] + # test env button + self.assertEqual( + test_button.get("invisible"), "context.get('environment', 'test') == 'test'" + ) + self.assertEqual( + test_button.get("name"), "action_change_env_data_encrypted_fields" + ) + self.assertEqual(test_button.get("string"), "Define values for test") + # preprod button + preprod_button = button_div.findall("button")[1] + self.assertEqual( + preprod_button.get("invisible"), + "context.get('environment', 'test') == 'preprod'", + ) + self.assertEqual(preprod_button.get("string"), "Define values for preprod") + self.assertEqual(preprod_button.get("context"), "{'environment': 'preprod'}") + # test normal field with pre-existing readonly condition + test2_field = res_xml.find("sheet").findall(".//field[@name='test2']")[0] + self.assertEqual( + test2_field.get("readonly"), + "(not type_env_is_editable) or context.get(\"environment\", 'test') != " + "'test'", + ) + # test normal field without pre-existing readonly condition + test_field = res_xml.find("sheet").findall(".//field[@name='test']")[0] + self.assertEqual( + test_field.get("readonly"), "context.get(\"environment\", 'test') != 'test'" + ) + + # test that buttons are invisible in the context of env different than the + # running one. + confirm_button = res_xml.find("header").find("button") + self.assertEqual( + confirm_button.get("invisible"), + "context.get(\"environment\", 'test') != 'test'", + )