From 0e0595f441b5949060004bfb3cd7a4799bdaf8a5 Mon Sep 17 00:00:00 2001
From: Florian da Costa
Date: Thu, 11 Apr 2019 17:13:51 +0200
Subject: [PATCH 01/14] [12.0] Add data_encryption This module come from the
previous module keychain. It has been heavely refactored to be compatible
with server_environment module. For this it has been split into 2 modules
data_encryption and server_environment_data_encryption
---
data_encryption/__init__.py | 1 +
data_encryption/__manifest__.py | 24 ++++
data_encryption/models/__init__.py | 1 +
data_encryption/models/encrypted_data.py | 138 +++++++++++++++++++
data_encryption/readme/CONFIGURE.rst | 21 +++
data_encryption/readme/CONTRIBUTORS.rst | 2 +
data_encryption/readme/DESCRIPTION.rst | 3 +
data_encryption/readme/ROADMAP.rst | 5 +
data_encryption/security/ir.model.access.csv | 2 +
data_encryption/tests/__init__.py | 1 +
data_encryption/tests/common.py | 39 ++++++
data_encryption/tests/test_data_encrypt.py | 99 +++++++++++++
12 files changed, 336 insertions(+)
create mode 100644 data_encryption/__init__.py
create mode 100644 data_encryption/__manifest__.py
create mode 100644 data_encryption/models/__init__.py
create mode 100644 data_encryption/models/encrypted_data.py
create mode 100644 data_encryption/readme/CONFIGURE.rst
create mode 100644 data_encryption/readme/CONTRIBUTORS.rst
create mode 100644 data_encryption/readme/DESCRIPTION.rst
create mode 100644 data_encryption/readme/ROADMAP.rst
create mode 100644 data_encryption/security/ir.model.access.csv
create mode 100644 data_encryption/tests/__init__.py
create mode 100644 data_encryption/tests/common.py
create mode 100644 data_encryption/tests/test_data_encrypt.py
diff --git a/data_encryption/__init__.py b/data_encryption/__init__.py
new file mode 100644
index 0000000..0650744
--- /dev/null
+++ b/data_encryption/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/data_encryption/__manifest__.py b/data_encryption/__manifest__.py
new file mode 100644
index 0000000..501f45a
--- /dev/null
+++ b/data_encryption/__manifest__.py
@@ -0,0 +1,24 @@
+# Copyright <2019> Akretion
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+{
+ "name": "Encryption data",
+ "summary": "Store accounts and credentials encrypted by environment",
+ "version": "12.0.1.0.0",
+ "development_status": 'Alpha',
+ "category": "Tools",
+ "website": "https://github/oca/server-env",
+ "author": "Akretion, Odoo Community Association (OCA)",
+ "license": "AGPL-3",
+ "application": False,
+ "installable": True,
+ "external_dependencies": {
+ "python": [
+ 'cryptography'],
+ },
+ "depends": [
+ "base",
+ ],
+ "data": [
+ "security/ir.model.access.csv",
+ ],
+}
diff --git a/data_encryption/models/__init__.py b/data_encryption/models/__init__.py
new file mode 100644
index 0000000..da8f5b3
--- /dev/null
+++ b/data_encryption/models/__init__.py
@@ -0,0 +1 @@
+from . import encrypted_data
diff --git a/data_encryption/models/encrypted_data.py b/data_encryption/models/encrypted_data.py
new file mode 100644
index 0000000..5e103b6
--- /dev/null
+++ b/data_encryption/models/encrypted_data.py
@@ -0,0 +1,138 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+import logging
+import json
+
+from odoo import api, fields, models
+from odoo.exceptions import AccessError, ValidationError
+from odoo.tools.config import config
+from odoo.tools.translate import _
+from odoo.tools import ormcache
+
+_logger = logging.getLogger(__name__)
+
+try:
+ from cryptography.fernet import Fernet, InvalidToken
+except ImportError as err: # pragma: no cover
+ _logger.debug(err)
+
+
+class EncryptedData(models.Model):
+ """Model to store encrypted data by environment (prod, preprod...)"""
+
+ _name = 'encrypted.data'
+ _description = 'Store any encrypted data by environment'
+
+ name = fields.Char(
+ required=True, readonly=True, index=True,
+ help="Technical name")
+ environment = fields.Char(
+ required=True,
+ index=True,
+ help="Concerned Odoo environment (prod, preprod...)")
+ encrypted_data = fields.Binary()
+
+ _sql_constraints = [
+ ('name_environment_uniq', 'unique (name, environment)',
+ 'You can not store multiple encrypted data for the same record and \
+ environment')
+ ]
+
+ def _decrypt_data(self, env):
+ self.ensure_one()
+ cipher = self._get_cipher(env)
+ try:
+ return cipher.decrypt(self.encrypted_data).decode()
+ except InvalidToken:
+ raise ValidationError(_(
+ "Password has been encrypted with a different "
+ "key. Unless you can recover the previous key, "
+ "this password is unreadable."))
+
+ @api.model
+ @ormcache('self._uid', 'name', 'env')
+ def _encrypted_get(self, name, env=None):
+ if self.env.context.get('bin_size'):
+ self = self.with_context(bin_size=False)
+ if not self.env.user._is_superuser():
+ raise AccessError(
+ _("Encrypted data can only be read as superuser"))
+ if not env:
+ env = self._retrieve_env()
+ encrypted_rec = self.search(
+ [('name', '=', name), ('environment', '=', env)])
+ if not encrypted_rec:
+ return None
+ return encrypted_rec._decrypt_data(env)
+
+ @api.model
+ @ormcache('self._uid', 'name', 'env')
+ def _encrypted_read_json(self, name, env=None):
+ data = self._encrypted_get(name, env=env)
+ if not data:
+ return {}
+ try:
+ return json.loads(data)
+ except (ValueError, TypeError):
+ raise ValidationError(
+ _("The data you are trying to read are not in a json format"))
+
+ @staticmethod
+ def _retrieve_env():
+ """Return the current environment
+ Raise if none is found
+ """
+ current = config.get('running_env', False)
+ if not current:
+ raise ValidationError(
+ _('No environment found, please check your running_env '
+ 'entry in your config file.'))
+ return current
+
+ @classmethod
+ def _get_cipher(cls, env):
+ """Return a cipher using the key of environment.
+ force_env = name of the env key.
+ Useful for encoding against one precise env
+ """
+ key_name = 'encryption_key_%s' % env
+ key_str = config.get(key_name)
+ if not key_str:
+ raise ValidationError(_(
+ "No '%s' entry found in config file. "
+ "Use a key similar to: %s") % (key_name, Fernet.generate_key())
+ )
+ # key should be in bytes format
+ key = key_str.encode()
+ return Fernet(key)
+
+ @api.model
+ def _encrypt_data(self, data, env):
+ cipher = self._get_cipher(env)
+ if not isinstance(data, bytes):
+ data = data.encode()
+ return cipher.encrypt(data or '')
+
+ @api.model
+ def _encrypted_store(self, name, data, env=None):
+ if not self.env.user._is_superuser():
+ raise AccessError(
+ _("You can only encrypt data as superuser"))
+ if not env:
+ env = self._retrieve_env()
+ encrypted_data = self._encrypt_data(data, env)
+ existing_data = self.search(
+ [('name', '=', name), ('environment', '=', env)])
+ if existing_data:
+ existing_data.write({'encrypted_data': encrypted_data})
+ else:
+ self.create({
+ 'name': name,
+ 'environment': env,
+ 'encrypted_data': encrypted_data,
+ })
+ self._encrypted_get.clear_cache(self)
+ self._encrypted_read_json.clear_cache(self)
+
+ @api.model
+ def _encrypted_store_json(self, name, json_data, env=None):
+ return self._encrypted_store(name, json.dumps(json_data), env=env)
diff --git a/data_encryption/readme/CONFIGURE.rst b/data_encryption/readme/CONFIGURE.rst
new file mode 100644
index 0000000..69b4773
--- /dev/null
+++ b/data_encryption/readme/CONFIGURE.rst
@@ -0,0 +1,21 @@
+To configure this module, you need to edit the main configuration file
+of your instance, and add a directive called ``running_env``. Commonly
+used values are 'dev', 'test', 'production'::
+
+ [options]
+ running_env=dev
+
+
+You also need to set the encryption key(s). The main idea is to have different
+encryption keys for your different environment, to avoid the possibility to retrieve
+crucial information from the production environment in a developement environment, for instance.
+So, if your running environment is 'dev'::
+
+ [options]
+ encryption_key_dev=fyeMIx9XVPBBky5XZeLDxVc9dFKy7Uzas3AoyMarHPA=
+
+In the configuration file of your production environment, you may want to configure
+all your other environments encryption key. This way, from production you can encrypt and decrypt
+data for all environments.
+
+You can generate keys with python -c 'from cryptography.fernet import Fernet; print Fernet.generate_key()'.
diff --git a/data_encryption/readme/CONTRIBUTORS.rst b/data_encryption/readme/CONTRIBUTORS.rst
new file mode 100644
index 0000000..3017ba2
--- /dev/null
+++ b/data_encryption/readme/CONTRIBUTORS.rst
@@ -0,0 +1,2 @@
+* Raphaël Reverdy
+* Florian da Costa
diff --git a/data_encryption/readme/DESCRIPTION.rst b/data_encryption/readme/DESCRIPTION.rst
new file mode 100644
index 0000000..9c4dc15
--- /dev/null
+++ b/data_encryption/readme/DESCRIPTION.rst
@@ -0,0 +1,3 @@
+This module allows to encrypt and decrypt data. This module is not usable
+by itself, it is a low level module which should work as a base for others.
+An example is the module server_environment_data_encryption
diff --git a/data_encryption/readme/ROADMAP.rst b/data_encryption/readme/ROADMAP.rst
new file mode 100644
index 0000000..71a6a12
--- /dev/null
+++ b/data_encryption/readme/ROADMAP.rst
@@ -0,0 +1,5 @@
+For now the encryption is dependent on the environment. It has been designed
+to store the same kind of data with different values depending on the environement
+(dev, preprod, prod...).
+An improvement could be to split this in 2 modules. But the environment stuff
+is not a big constraint.
diff --git a/data_encryption/security/ir.model.access.csv b/data_encryption/security/ir.model.access.csv
new file mode 100644
index 0000000..ddbd5f7
--- /dev/null
+++ b/data_encryption/security/ir.model.access.csv
@@ -0,0 +1,2 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+access_encrypted_data,access_encrypted_data,model_encrypted_data,base.group_system,0,0,0,0
diff --git a/data_encryption/tests/__init__.py b/data_encryption/tests/__init__.py
new file mode 100644
index 0000000..d686b32
--- /dev/null
+++ b/data_encryption/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_data_encrypt
diff --git a/data_encryption/tests/common.py b/data_encryption/tests/common.py
new file mode 100644
index 0000000..f044569
--- /dev/null
+++ b/data_encryption/tests/common.py
@@ -0,0 +1,39 @@
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+from odoo.tests.common import TransactionCase
+from odoo.tools.config import config
+
+
+import logging
+
+_logger = logging.getLogger(__name__)
+
+try:
+ from cryptography.fernet import Fernet
+except ImportError as err: # pragma: no cover
+ _logger.debug(err)
+
+
+class CommonDataEncrypted(TransactionCase):
+
+ def setUp(self):
+ super().setUp()
+
+ self.encrypted_data = self.env['encrypted.data']
+ self.set_new_key_env('test')
+ self.old_running_env = config.get('running_env', '')
+ config['running_env'] = 'test'
+ self.crypted_data_name = 'test_model,1'
+
+ def set_new_key_env(self, 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['encryption_key_{}'.format(environment)] = \
+ crypting_key.decode()
+
+ def tearDown(self):
+ config['running_env'] = self.old_running_env
+ return super().tearDown()
diff --git a/data_encryption/tests/test_data_encrypt.py b/data_encryption/tests/test_data_encrypt.py
new file mode 100644
index 0000000..6e42722
--- /dev/null
+++ b/data_encryption/tests/test_data_encrypt.py
@@ -0,0 +1,99 @@
+# © 2016 Akretion Raphaël REVERDY
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+
+from .common import CommonDataEncrypted
+from odoo.tools.config import config
+from odoo.exceptions import AccessError, ValidationError
+
+
+import logging
+
+_logger = logging.getLogger(__name__)
+
+try:
+ from cryptography.fernet import Fernet
+except ImportError as err: # pragma: no cover
+ _logger.debug(err)
+
+
+class TestDataEncrypted(CommonDataEncrypted):
+
+ def test_store_data_no_superuser(self):
+ # only superuser can use this model
+ admin = self.env.ref('base.user_admin')
+ with self.assertRaises(AccessError):
+ self.encrypted_data.sudo(admin.id)._encrypted_store(
+ self.crypted_data_name, "My config")
+
+ def test_store_data_noenv_set(self):
+ config.pop('running_env', None)
+ with self.assertRaises(ValidationError):
+ self.encrypted_data.sudo()._encrypted_store(
+ self.crypted_data_name, "My config")
+
+ def test_store_data_nokey_set(self):
+ config.pop('encryption_key_test', None)
+ with self.assertRaises(ValidationError):
+ self.encrypted_data.sudo()._encrypted_store(
+ self.crypted_data_name, "My config")
+
+ def test_get_data_decrypted_and_cache(self):
+ self.encrypted_data.sudo()._encrypted_store(
+ 'test_model,1', "My config")
+ data = self.encrypted_data.sudo()._encrypted_get(
+ self.crypted_data_name)
+ self.assertEqual(data, "My config")
+
+ # Test cache really depends on user (super user) else any user could
+ # access the data
+ admin = self.env.ref('base.user_admin')
+ with self.assertRaises(AccessError):
+ self.encrypted_data.sudo(admin)._encrypted_get(
+ self.crypted_data_name)
+
+ # Change value should invalidate cache
+ self.encrypted_data.sudo()._encrypted_store(
+ 'test_model,1', "Other Config")
+ new_data = self.encrypted_data.sudo()._encrypted_get(
+ self.crypted_data_name)
+ self.assertEqual(new_data, "Other Config")
+
+ def test_get_data_wrong_key(self):
+ self.encrypted_data.sudo()._encrypted_store(
+ 'test_model,1', "My config")
+ new_key = Fernet.generate_key()
+ config['encryption_key_test'] = new_key.decode()
+ with self.assertRaises(ValidationError):
+ self.encrypted_data.sudo()._encrypted_get(
+ self.crypted_data_name)
+
+ def test_get_empty_data(self):
+ empty_data = self.encrypted_data.sudo()._encrypted_get(
+ self.crypted_data_name)
+ self.assertEqual(empty_data, None)
+
+ def test_get_wrong_json(self):
+ self.encrypted_data.sudo()._encrypted_store(
+ self.crypted_data_name, 'config')
+ with self.assertRaises(ValidationError):
+ self.encrypted_data.sudo()._encrypted_read_json(
+ self.crypted_data_name)
+
+ def test_get_good_json(self):
+ self.encrypted_data.sudo()._encrypted_store_json(
+ self.crypted_data_name, {'key': 'value'})
+ data = self.encrypted_data.sudo()._encrypted_read_json(
+ self.crypted_data_name)
+ self.assertEqual(data, {'key': 'value'})
+
+ def test_get_empty_json(self):
+ data = self.encrypted_data.sudo()._encrypted_read_json(
+ self.crypted_data_name)
+ self.assertEqual(data, {})
+
+ def test_get_data_with_bin_size_context(self):
+ self.encrypted_data.sudo()._encrypted_store(
+ self.crypted_data_name, "test")
+ data = self.encrypted_data.sudo().with_context(bin_size=True).\
+ _encrypted_get(self.crypted_data_name)
+ self.assertEqual(data, "test")
From a66d0237fbd2a59a19eedd3ba034f25cd7dced18 Mon Sep 17 00:00:00 2001
From: oca-travis
Date: Fri, 27 Mar 2020 16:50:14 +0000
Subject: [PATCH 02/14] [UPD] Update data_encryption.pot
---
data_encryption/i18n/data_encryption.pot | 121 +++++++++++++++++++++++
1 file changed, 121 insertions(+)
create mode 100644 data_encryption/i18n/data_encryption.pot
diff --git a/data_encryption/i18n/data_encryption.pot b/data_encryption/i18n/data_encryption.pot
new file mode 100644
index 0000000..38f2f21
--- /dev/null
+++ b/data_encryption/i18n/data_encryption.pot
@@ -0,0 +1,121 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * data_encryption
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.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: data_encryption
+#: model:ir.model.fields,help:data_encryption.field_encrypted_data__environment
+msgid "Concerned Odoo environment (prod, preprod...)"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__encrypted_data
+msgid "Encrypted Data"
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:58
+#, python-format
+msgid "Encrypted data can only be read as superuser"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__environment
+msgid "Environment"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__id
+msgid "ID"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__name
+msgid "Name"
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:100
+#, python-format
+msgid "No '%s' entry found in config file. Use a key similar to: %s"
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:87
+#, python-format
+msgid "No environment found, please check your running_env entry in your config file."
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:46
+#, python-format
+msgid "Password has been encrypted with a different key. Unless you can recover the previous key, this password is unreadable."
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model,name:data_encryption.model_encrypted_data
+msgid "Store any encrypted data by environment"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,help:data_encryption.field_encrypted_data__name
+msgid "Technical name"
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:77
+#, python-format
+msgid "The data you are trying to read are not in a json format"
+msgstr ""
+
+#. module: data_encryption
+#: sql_constraint:encrypted.data:0
+msgid "You can not store multiple encrypted data for the same record and environment"
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:119
+#, python-format
+msgid "You can only encrypt data as superuser"
+msgstr ""
+
From 185f0c1e995d485383b2a507be35570368f3adce Mon Sep 17 00:00:00 2001
From: OCA-git-bot
Date: Fri, 27 Mar 2020 16:59:06 +0000
Subject: [PATCH 03/14] [UPD] README.rst
---
data_encryption/README.rst | 115 +++++
data_encryption/static/description/index.html | 460 ++++++++++++++++++
2 files changed, 575 insertions(+)
create mode 100644 data_encryption/README.rst
create mode 100644 data_encryption/static/description/index.html
diff --git a/data_encryption/README.rst b/data_encryption/README.rst
new file mode 100644
index 0000000..837afa9
--- /dev/null
+++ b/data_encryption/README.rst
@@ -0,0 +1,115 @@
+===============
+Encryption data
+===============
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! This file is generated by oca-gen-addon-readme !!
+ !! changes will be overwritten. !!
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+.. |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/12.0/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-12-0/server-env-12-0-data_encryption
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+ :target: https://runbot.odoo-community.org/runbot/254/12.0
+ :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This module allows to encrypt and decrypt data. This module is not usable
+by itself, it is a low level module which should work as a base for others.
+An example is the module server_environment_data_encryption
+
+.. 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
+=============
+
+To configure this module, you need to edit the main configuration file
+of your instance, and add a directive called ``running_env``. Commonly
+used values are 'dev', 'test', 'production'::
+
+ [options]
+ running_env=dev
+
+
+You also need to set the encryption key(s). The main idea is to have different
+encryption keys for your different environment, to avoid the possibility to retrieve
+crucial information from the production environment in a developement environment, for instance.
+So, if your running environment is 'dev'::
+
+ [options]
+ encryption_key_dev=fyeMIx9XVPBBky5XZeLDxVc9dFKy7Uzas3AoyMarHPA=
+
+In the configuration file of your production environment, you may want to configure
+all your other environments encryption key. This way, from production you can encrypt and decrypt
+data for all environments.
+
+You can generate keys with python -c 'from cryptography.fernet import Fernet; print Fernet.generate_key()'.
+
+Known issues / Roadmap
+======================
+
+For now the encryption is dependent on the environment. It has been designed
+to store the same kind of data with different values depending on the environement
+(dev, preprod, prod...).
+An improvement could be to split this in 2 modules. But the environment stuff
+is not a big constraint.
+
+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 smashing it by providing a detailed and welcomed
+`feedback `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Akretion
+
+Contributors
+~~~~~~~~~~~~
+
+* Raphaël Reverdy
+* Florian da Costa
+
+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.
+
+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/data_encryption/static/description/index.html b/data_encryption/static/description/index.html
new file mode 100644
index 0000000..b832f77
--- /dev/null
+++ b/data_encryption/static/description/index.html
@@ -0,0 +1,460 @@
+
+
+
+
+
+
+Encryption data
+
+
+
+
+
Encryption data
+
+
+

+
This module allows to encrypt and decrypt data. This module is not usable
+by itself, it is a low level module which should work as a base for others.
+An example is the module server_environment_data_encryption
+
+
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
+
+
+
+
To configure this module, you need to edit the main configuration file
+of your instance, and add a directive called running_env. Commonly
+used values are ‘dev’, ‘test’, ‘production’:
+
+[options]
+running_env=dev
+
+
You also need to set the encryption key(s). The main idea is to have different
+encryption keys for your different environment, to avoid the possibility to retrieve
+crucial information from the production environment in a developement environment, for instance.
+So, if your running environment is ‘dev’:
+
+[options]
+encryption_key_dev=fyeMIx9XVPBBky5XZeLDxVc9dFKy7Uzas3AoyMarHPA=
+
+
In the configuration file of your production environment, you may want to configure
+all your other environments encryption key. This way, from production you can encrypt and decrypt
+data for all environments.
+
You can generate keys with python -c ‘from cryptography.fernet import Fernet; print Fernet.generate_key()’.
+
+
+
+
For now the encryption is dependent on the environment. It has been designed
+to store the same kind of data with different values depending on the environement
+(dev, preprod, prod…).
+An improvement could be to split this in 2 modules. But the environment stuff
+is not a big constraint.
+
+
+
+
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 smashing it by providing a detailed and welcomed
+feedback.
+
Do not contact contributors directly about support or help with technical issues.
+
+
+
+
+
+
+
+
This module is maintained by the OCA.
+

+
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.
+
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.
+
+
+
+
+
From 36016cbff108a2754f7a307810060dd964188a36 Mon Sep 17 00:00:00 2001
From: OCA-git-bot
Date: Fri, 27 Mar 2020 16:59:06 +0000
Subject: [PATCH 04/14] [ADD] icon.png
---
data_encryption/static/description/icon.png | Bin 0 -> 9455 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 data_encryption/static/description/icon.png
diff --git a/data_encryption/static/description/icon.png b/data_encryption/static/description/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d
GIT binary patch
literal 9455
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
z
z?n?eq1XP>p-IM$Z^C;2L3itnbJZAip*Zo0aw2bs8@(s^~*8T9go!%dHcAz2lM;`yp
zD=7&xjFV$S&5uDaiScyD?B-i1ze`+CoRtz`Wn+Zls4&}MO{@N!ufrzjG$B79)Y2d3tBk&)TxUTw@QS0TEL_?njX|@vq?Uz(nBFK5Pq7*xj#u*R&i|?7+6#
z+|r_n#SW&LXhtheZdah{ZVoqwyT{D>MC3nkFF#N)xLi{p7J1jXlmVeb;cP5?e(=f#
zuT7fvjSbjS781v?7{)-X3*?>tq?)Yd)~|1{BDS(pqC
zC}~H#WXlkUW*H5CDOo<)#x7%RY)A;ShGhI5s*#cRDA8YgqG(HeKDx+#(ZQ?386dv!
zlXCO)w91~Vw4AmOcATuV653fa9R$fyK8ul%rG
z-wfS
zihugoZyr38Im?Zuh6@RcF~t1anQu7>#lPpb#}4cOA!EM11`%f*07RqOVkmX{p~KJ9
z^zP;K#|)$`^Rb{rnHGH{~>1(fawV0*Z#)}M`m8-?ZJV<+e}s9wE#
z)l&az?w^5{)`S(%MRzxdNqrs1n*-=jS^_jqE*5XDrA0+VE`5^*p3CuM<&dZEeCjoz
zR;uu_H9ZPZV|fQq`Cyw4nscrVwi!fE6ciMmX$!_hN7uF;jjKG)d2@aC4ropY)8etW=xJvni)8eHi`H$%#zn^WJ5NLc-rqk|u&&4Z6fD_m&JfSI1Bvb?b<*n&sfl0^t
z=HnmRl`XrFvMKB%9}>PaA`m-fK6a0(8=qPkWS5bb4=v?XcWi&hRY?O5HdulRi4?fN
zlsJ*N-0Qw+Yic@s0(2uy%F@ib;GjXt01Fmx5XbRo6+n|pP(&nodMoap^z{~q
ziEeaUT@Mxe3vJSfI6?uLND(CNr=#^W<1b}jzW58bIfyWTDle$mmS(|x-0|2UlX+9k
zQ^EX7Nw}?EzVoBfT(-LT|=9N@^hcn-_p&sqG
z&*oVs2JSU+N4ZD`FhCAWaS;>|wH2G*Id|?pa#@>tyxX`+4HyIArWDvVrX)2WAOQff
z0qyHu&-S@i^MS-+j--!pr4fPBj~_8({~e1bfcl0wI1kaoN>mJL6KUPQm5N7lB(ui1
zE-o%kq)&djzWJ}ob<-GfDlkB;F31j-VHKvQUGQ3sp`CwyGJk_i!y^sD0fqC@$9|jO
zOqN!r!8-p==F@ZVP=U$qSpY(gQ0)59P1&t@y?5rvg<}E+GB}26NYPp4f2YFQrQtot5mn3wu_qprZ=>Ig-$
zbW26Ws~IgY>}^5w`vTB(G`PTZaDiGBo5o(tp)qli|NeV(
z@H_=R8V39rt5J5YB2Ky?4eJJ#b`_iBe2ot~6%7mLt5t8Vwi^Jy7|jWXqa3amOIoRb
zOr}WVFP--DsS`1WpN%~)t3R!arKF^Q$e12KEqU36AWwnCBICpH4XCsfnyrHr>$I$4
z!DpKX$OKLWarN7nv@!uIA+~RNO)l$$w}p(;b>mx8pwYvu;dD_unryX_NhT8*Tj>BTrTTL&!?O+%Rv;b?B??gSzdp?6Uug9{
zd@V08Z$BdI?fpoCS$)t4mg4rT8Q_I}h`0d-vYZ^|dOB*Q^S|xqTV*vIg?@fVFSmMpaw0qtTRbx}
z({Pg?#{2`sc9)M5N$*N|4;^t$+QP?#mov
zGVC@I*lBVrOU-%2y!7%)fAKjpEFsgQc4{amtiHb95KQEwvf<(3T<9-Zm$xIew#P22
zc2Ix|App^>v6(3L_MCU0d3W##AB0M~3D00EWoKZqsJYT(#@w$Y_H7G22M~ApVFTRHMI_3be)Lkn#0F*V8Pq
zc}`Cjy$bE;FJ6H7p=0y#R>`}-m4(0F>%@P|?7fx{=R^uFdISRnZ2W_xQhD{YuR3t<
z{6yxu=4~JkeA;|(J6_nv#>Nvs&FuLA&PW^he@t(UwFFE8)|a!R{`E`K`i^ZnyE4$k
z;(749Ix|oi$c3QbEJ3b~D_kQsPz~fIUKym($a_7dJ?o+40*OLl^{=&oq$<#Q(yyrp
z{J-FAniyAw9tPbe&IhQ|a`DqFTVQGQ&Gq3!C2==4x{6EJwiPZ8zub-iXoUtkJiG{}
zPaR&}_fn8_z~(=;5lD-aPWD3z8PZS@AaUiomF!G8I}Mf>e~0g#BelA-5#`cj;O5>N
Xviia!U7SGha1wx#SCgwmn*{w2TRX*I
literal 0
HcmV?d00001
From df274a2e4125dde7d3a05b92cddf0f5264442284 Mon Sep 17 00:00:00 2001
From: Thomas Binsfeld
Date: Fri, 2 Oct 2020 11:21:36 +0200
Subject: [PATCH 05/14] [REF] data_encryption: Black python code
---
data_encryption/__manifest__.py | 15 +---
data_encryption/models/encrypted_data.py | 90 +++++++++++++---------
data_encryption/tests/common.py | 16 ++--
data_encryption/tests/test_data_encrypt.py | 71 ++++++++++-------
4 files changed, 109 insertions(+), 83 deletions(-)
diff --git a/data_encryption/__manifest__.py b/data_encryption/__manifest__.py
index 501f45a..292f6f0 100644
--- a/data_encryption/__manifest__.py
+++ b/data_encryption/__manifest__.py
@@ -4,21 +4,14 @@
"name": "Encryption data",
"summary": "Store accounts and credentials encrypted by environment",
"version": "12.0.1.0.0",
- "development_status": 'Alpha',
+ "development_status": "Alpha",
"category": "Tools",
"website": "https://github/oca/server-env",
"author": "Akretion, Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
"installable": True,
- "external_dependencies": {
- "python": [
- 'cryptography'],
- },
- "depends": [
- "base",
- ],
- "data": [
- "security/ir.model.access.csv",
- ],
+ "external_dependencies": {"python": ["cryptography"],},
+ "depends": ["base",],
+ "data": ["security/ir.model.access.csv",],
}
diff --git a/data_encryption/models/encrypted_data.py b/data_encryption/models/encrypted_data.py
index 5e103b6..3353c53 100644
--- a/data_encryption/models/encrypted_data.py
+++ b/data_encryption/models/encrypted_data.py
@@ -19,22 +19,26 @@ except ImportError as err: # pragma: no cover
class EncryptedData(models.Model):
"""Model to store encrypted data by environment (prod, preprod...)"""
- _name = 'encrypted.data'
- _description = 'Store any encrypted data by environment'
+ _name = "encrypted.data"
+ _description = "Store any encrypted data by environment"
name = fields.Char(
- required=True, readonly=True, index=True,
- help="Technical name")
+ required=True, readonly=True, index=True, help="Technical name"
+ )
environment = fields.Char(
required=True,
index=True,
- help="Concerned Odoo environment (prod, preprod...)")
+ help="Concerned Odoo environment (prod, preprod...)",
+ )
encrypted_data = fields.Binary()
_sql_constraints = [
- ('name_environment_uniq', 'unique (name, environment)',
- 'You can not store multiple encrypted data for the same record and \
- environment')
+ (
+ "name_environment_uniq",
+ "unique (name, environment)",
+ "You can not store multiple encrypted data for the same record and \
+ environment",
+ )
]
def _decrypt_data(self, env):
@@ -43,29 +47,34 @@ class EncryptedData(models.Model):
try:
return cipher.decrypt(self.encrypted_data).decode()
except InvalidToken:
- raise ValidationError(_(
- "Password has been encrypted with a different "
- "key. Unless you can recover the previous key, "
- "this password is unreadable."))
+ raise ValidationError(
+ _(
+ "Password has been encrypted with a different "
+ "key. Unless you can recover the previous key, "
+ "this password is unreadable."
+ )
+ )
@api.model
- @ormcache('self._uid', 'name', 'env')
+ @ormcache("self._uid", "name", "env")
def _encrypted_get(self, name, env=None):
- if self.env.context.get('bin_size'):
+ if self.env.context.get("bin_size"):
self = self.with_context(bin_size=False)
if not self.env.user._is_superuser():
raise AccessError(
- _("Encrypted data can only be read as superuser"))
+ _("Encrypted data can only be read as superuser")
+ )
if not env:
env = self._retrieve_env()
encrypted_rec = self.search(
- [('name', '=', name), ('environment', '=', env)])
+ [("name", "=", name), ("environment", "=", env)]
+ )
if not encrypted_rec:
return None
return encrypted_rec._decrypt_data(env)
@api.model
- @ormcache('self._uid', 'name', 'env')
+ @ormcache("self._uid", "name", "env")
def _encrypted_read_json(self, name, env=None):
data = self._encrypted_get(name, env=env)
if not data:
@@ -74,18 +83,22 @@ class EncryptedData(models.Model):
return json.loads(data)
except (ValueError, TypeError):
raise ValidationError(
- _("The data you are trying to read are not in a json format"))
+ _("The data you are trying to read are not in a json format")
+ )
@staticmethod
def _retrieve_env():
"""Return the current environment
Raise if none is found
"""
- current = config.get('running_env', False)
+ current = config.get("running_env", False)
if not current:
raise ValidationError(
- _('No environment found, please check your running_env '
- 'entry in your config file.'))
+ _(
+ "No environment found, please check your running_env "
+ "entry in your config file."
+ )
+ )
return current
@classmethod
@@ -94,12 +107,15 @@ class EncryptedData(models.Model):
force_env = name of the env key.
Useful for encoding against one precise env
"""
- key_name = 'encryption_key_%s' % env
+ key_name = "encryption_key_%s" % env
key_str = config.get(key_name)
if not key_str:
- raise ValidationError(_(
- "No '%s' entry found in config file. "
- "Use a key similar to: %s") % (key_name, Fernet.generate_key())
+ raise ValidationError(
+ _(
+ "No '%s' entry found in config file. "
+ "Use a key similar to: %s"
+ )
+ % (key_name, Fernet.generate_key())
)
# key should be in bytes format
key = key_str.encode()
@@ -110,26 +126,28 @@ class EncryptedData(models.Model):
cipher = self._get_cipher(env)
if not isinstance(data, bytes):
data = data.encode()
- return cipher.encrypt(data or '')
+ return cipher.encrypt(data or "")
@api.model
- def _encrypted_store(self, name, data, env=None):
+ def _encrypted_store(self, name, data, env=None):
if not self.env.user._is_superuser():
- raise AccessError(
- _("You can only encrypt data as superuser"))
+ raise AccessError(_("You can only encrypt data as superuser"))
if not env:
env = self._retrieve_env()
encrypted_data = self._encrypt_data(data, env)
existing_data = self.search(
- [('name', '=', name), ('environment', '=', env)])
+ [("name", "=", name), ("environment", "=", env)]
+ )
if existing_data:
- existing_data.write({'encrypted_data': encrypted_data})
+ existing_data.write({"encrypted_data": encrypted_data})
else:
- self.create({
- 'name': name,
- 'environment': env,
- 'encrypted_data': encrypted_data,
- })
+ self.create(
+ {
+ "name": name,
+ "environment": env,
+ "encrypted_data": encrypted_data,
+ }
+ )
self._encrypted_get.clear_cache(self)
self._encrypted_read_json.clear_cache(self)
diff --git a/data_encryption/tests/common.py b/data_encryption/tests/common.py
index f044569..0ab30b8 100644
--- a/data_encryption/tests/common.py
+++ b/data_encryption/tests/common.py
@@ -15,15 +15,14 @@ except ImportError as err: # pragma: no cover
class CommonDataEncrypted(TransactionCase):
-
def setUp(self):
super().setUp()
- self.encrypted_data = self.env['encrypted.data']
- self.set_new_key_env('test')
- self.old_running_env = config.get('running_env', '')
- config['running_env'] = 'test'
- self.crypted_data_name = 'test_model,1'
+ self.encrypted_data = self.env["encrypted.data"]
+ self.set_new_key_env("test")
+ self.old_running_env = config.get("running_env", "")
+ config["running_env"] = "test"
+ self.crypted_data_name = "test_model,1"
def set_new_key_env(self, environment):
crypting_key = Fernet.generate_key()
@@ -31,9 +30,8 @@ class CommonDataEncrypted(TransactionCase):
# 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['encryption_key_{}'.format(environment)] = \
- crypting_key.decode()
+ config["encryption_key_{}".format(environment)] = crypting_key.decode()
def tearDown(self):
- config['running_env'] = self.old_running_env
+ config["running_env"] = self.old_running_env
return super().tearDown()
diff --git a/data_encryption/tests/test_data_encrypt.py b/data_encryption/tests/test_data_encrypt.py
index 6e42722..1cbb997 100644
--- a/data_encryption/tests/test_data_encrypt.py
+++ b/data_encryption/tests/test_data_encrypt.py
@@ -17,83 +17,100 @@ except ImportError as err: # pragma: no cover
class TestDataEncrypted(CommonDataEncrypted):
-
def test_store_data_no_superuser(self):
# only superuser can use this model
- admin = self.env.ref('base.user_admin')
+ admin = self.env.ref("base.user_admin")
with self.assertRaises(AccessError):
self.encrypted_data.sudo(admin.id)._encrypted_store(
- self.crypted_data_name, "My config")
+ self.crypted_data_name, "My config"
+ )
def test_store_data_noenv_set(self):
- config.pop('running_env', None)
+ config.pop("running_env", None)
with self.assertRaises(ValidationError):
self.encrypted_data.sudo()._encrypted_store(
- self.crypted_data_name, "My config")
+ self.crypted_data_name, "My config"
+ )
def test_store_data_nokey_set(self):
- config.pop('encryption_key_test', None)
+ config.pop("encryption_key_test", None)
with self.assertRaises(ValidationError):
self.encrypted_data.sudo()._encrypted_store(
- self.crypted_data_name, "My config")
+ self.crypted_data_name, "My config"
+ )
def test_get_data_decrypted_and_cache(self):
self.encrypted_data.sudo()._encrypted_store(
- 'test_model,1', "My config")
+ "test_model,1", "My config"
+ )
data = self.encrypted_data.sudo()._encrypted_get(
- self.crypted_data_name)
+ self.crypted_data_name
+ )
self.assertEqual(data, "My config")
# Test cache really depends on user (super user) else any user could
# access the data
- admin = self.env.ref('base.user_admin')
+ admin = self.env.ref("base.user_admin")
with self.assertRaises(AccessError):
self.encrypted_data.sudo(admin)._encrypted_get(
- self.crypted_data_name)
+ self.crypted_data_name
+ )
# Change value should invalidate cache
self.encrypted_data.sudo()._encrypted_store(
- 'test_model,1', "Other Config")
+ "test_model,1", "Other Config"
+ )
new_data = self.encrypted_data.sudo()._encrypted_get(
- self.crypted_data_name)
+ self.crypted_data_name
+ )
self.assertEqual(new_data, "Other Config")
def test_get_data_wrong_key(self):
self.encrypted_data.sudo()._encrypted_store(
- 'test_model,1', "My config")
+ "test_model,1", "My config"
+ )
new_key = Fernet.generate_key()
- config['encryption_key_test'] = new_key.decode()
+ config["encryption_key_test"] = new_key.decode()
with self.assertRaises(ValidationError):
- self.encrypted_data.sudo()._encrypted_get(
- self.crypted_data_name)
+ self.encrypted_data.sudo()._encrypted_get(self.crypted_data_name)
def test_get_empty_data(self):
empty_data = self.encrypted_data.sudo()._encrypted_get(
- self.crypted_data_name)
+ self.crypted_data_name
+ )
self.assertEqual(empty_data, None)
def test_get_wrong_json(self):
self.encrypted_data.sudo()._encrypted_store(
- self.crypted_data_name, 'config')
+ self.crypted_data_name, "config"
+ )
with self.assertRaises(ValidationError):
self.encrypted_data.sudo()._encrypted_read_json(
- self.crypted_data_name)
+ self.crypted_data_name
+ )
def test_get_good_json(self):
self.encrypted_data.sudo()._encrypted_store_json(
- self.crypted_data_name, {'key': 'value'})
+ self.crypted_data_name, {"key": "value"}
+ )
data = self.encrypted_data.sudo()._encrypted_read_json(
- self.crypted_data_name)
- self.assertEqual(data, {'key': 'value'})
+ self.crypted_data_name
+ )
+ self.assertEqual(data, {"key": "value"})
def test_get_empty_json(self):
data = self.encrypted_data.sudo()._encrypted_read_json(
- self.crypted_data_name)
+ self.crypted_data_name
+ )
self.assertEqual(data, {})
def test_get_data_with_bin_size_context(self):
self.encrypted_data.sudo()._encrypted_store(
- self.crypted_data_name, "test")
- data = self.encrypted_data.sudo().with_context(bin_size=True).\
- _encrypted_get(self.crypted_data_name)
+ self.crypted_data_name, "test"
+ )
+ data = (
+ self.encrypted_data.sudo()
+ .with_context(bin_size=True)
+ ._encrypted_get(self.crypted_data_name)
+ )
self.assertEqual(data, "test")
From 2e3f0e6b9950674845933b81db0fef353a8159b1 Mon Sep 17 00:00:00 2001
From: Thomas Binsfeld
Date: Fri, 2 Oct 2020 11:21:36 +0200
Subject: [PATCH 06/14] [MIG] data_encryption: Migration to 13.0
---
data_encryption/__manifest__.py | 8 +--
data_encryption/models/encrypted_data.py | 43 ++++++----------
data_encryption/tests/common.py | 5 +-
data_encryption/tests/test_data_encrypt.py | 60 +++++++---------------
4 files changed, 39 insertions(+), 77 deletions(-)
diff --git a/data_encryption/__manifest__.py b/data_encryption/__manifest__.py
index 292f6f0..afec603 100644
--- a/data_encryption/__manifest__.py
+++ b/data_encryption/__manifest__.py
@@ -3,7 +3,7 @@
{
"name": "Encryption data",
"summary": "Store accounts and credentials encrypted by environment",
- "version": "12.0.1.0.0",
+ "version": "13.0.1.0.0",
"development_status": "Alpha",
"category": "Tools",
"website": "https://github/oca/server-env",
@@ -11,7 +11,7 @@
"license": "AGPL-3",
"application": False,
"installable": True,
- "external_dependencies": {"python": ["cryptography"],},
- "depends": ["base",],
- "data": ["security/ir.model.access.csv",],
+ "external_dependencies": {"python": ["cryptography"]},
+ "depends": ["base"],
+ "data": ["security/ir.model.access.csv"],
}
diff --git a/data_encryption/models/encrypted_data.py b/data_encryption/models/encrypted_data.py
index 3353c53..f49b9b7 100644
--- a/data_encryption/models/encrypted_data.py
+++ b/data_encryption/models/encrypted_data.py
@@ -1,12 +1,12 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-import logging
import json
+import logging
from odoo import api, fields, models
from odoo.exceptions import AccessError, ValidationError
+from odoo.tools import ormcache
from odoo.tools.config import config
from odoo.tools.translate import _
-from odoo.tools import ormcache
_logger = logging.getLogger(__name__)
@@ -22,15 +22,11 @@ class EncryptedData(models.Model):
_name = "encrypted.data"
_description = "Store any encrypted data by environment"
- name = fields.Char(
- required=True, readonly=True, index=True, help="Technical name"
- )
+ name = fields.Char(required=True, readonly=True, index=True, help="Technical name")
environment = fields.Char(
- required=True,
- index=True,
- help="Concerned Odoo environment (prod, preprod...)",
+ required=True, index=True, help="Concerned Odoo environment (prod, preprod...)",
)
- encrypted_data = fields.Binary()
+ encrypted_data = fields.Binary(attachment=False)
_sql_constraints = [
(
@@ -60,15 +56,13 @@ class EncryptedData(models.Model):
def _encrypted_get(self, name, env=None):
if self.env.context.get("bin_size"):
self = self.with_context(bin_size=False)
- if not self.env.user._is_superuser():
+ if not self.env.su:
raise AccessError(
- _("Encrypted data can only be read as superuser")
+ _("Encrypted data can only be read with suspended security (sudo)")
)
if not env:
env = self._retrieve_env()
- encrypted_rec = self.search(
- [("name", "=", name), ("environment", "=", env)]
- )
+ encrypted_rec = self.search([("name", "=", name), ("environment", "=", env)])
if not encrypted_rec:
return None
return encrypted_rec._decrypt_data(env)
@@ -111,10 +105,7 @@ class EncryptedData(models.Model):
key_str = config.get(key_name)
if not key_str:
raise ValidationError(
- _(
- "No '%s' entry found in config file. "
- "Use a key similar to: %s"
- )
+ _("No '%s' entry found in config file. " "Use a key similar to: %s")
% (key_name, Fernet.generate_key())
)
# key should be in bytes format
@@ -130,23 +121,19 @@ class EncryptedData(models.Model):
@api.model
def _encrypted_store(self, name, data, env=None):
- if not self.env.user._is_superuser():
- raise AccessError(_("You can only encrypt data as superuser"))
+ if not self.env.su:
+ raise AccessError(
+ _("You can only encrypt data with suspended security (sudo)")
+ )
if not env:
env = self._retrieve_env()
encrypted_data = self._encrypt_data(data, env)
- existing_data = self.search(
- [("name", "=", name), ("environment", "=", env)]
- )
+ existing_data = self.search([("name", "=", name), ("environment", "=", env)])
if existing_data:
existing_data.write({"encrypted_data": encrypted_data})
else:
self.create(
- {
- "name": name,
- "environment": env,
- "encrypted_data": encrypted_data,
- }
+ {"name": name, "environment": env, "encrypted_data": encrypted_data}
)
self._encrypted_get.clear_cache(self)
self._encrypted_read_json.clear_cache(self)
diff --git a/data_encryption/tests/common.py b/data_encryption/tests/common.py
index 0ab30b8..a57377d 100644
--- a/data_encryption/tests/common.py
+++ b/data_encryption/tests/common.py
@@ -1,11 +1,10 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+import logging
+
from odoo.tests.common import TransactionCase
from odoo.tools.config import config
-
-import logging
-
_logger = logging.getLogger(__name__)
try:
diff --git a/data_encryption/tests/test_data_encrypt.py b/data_encryption/tests/test_data_encrypt.py
index 1cbb997..7f25053 100644
--- a/data_encryption/tests/test_data_encrypt.py
+++ b/data_encryption/tests/test_data_encrypt.py
@@ -1,13 +1,13 @@
# © 2016 Akretion Raphaël REVERDY
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
-from .common import CommonDataEncrypted
-from odoo.tools.config import config
-from odoo.exceptions import AccessError, ValidationError
-
-
import logging
+from odoo.exceptions import AccessError, ValidationError
+from odoo.tools.config import config
+
+from .common import CommonDataEncrypted
+
_logger = logging.getLogger(__name__)
try:
@@ -21,7 +21,7 @@ class TestDataEncrypted(CommonDataEncrypted):
# only superuser can use this model
admin = self.env.ref("base.user_admin")
with self.assertRaises(AccessError):
- self.encrypted_data.sudo(admin.id)._encrypted_store(
+ self.encrypted_data.with_user(admin.id)._encrypted_store(
self.crypted_data_name, "My config"
)
@@ -40,74 +40,50 @@ class TestDataEncrypted(CommonDataEncrypted):
)
def test_get_data_decrypted_and_cache(self):
- self.encrypted_data.sudo()._encrypted_store(
- "test_model,1", "My config"
- )
- data = self.encrypted_data.sudo()._encrypted_get(
- self.crypted_data_name
- )
+ self.encrypted_data.sudo()._encrypted_store("test_model,1", "My config")
+ data = self.encrypted_data.sudo()._encrypted_get(self.crypted_data_name)
self.assertEqual(data, "My config")
# Test cache really depends on user (super user) else any user could
# access the data
admin = self.env.ref("base.user_admin")
with self.assertRaises(AccessError):
- self.encrypted_data.sudo(admin)._encrypted_get(
- self.crypted_data_name
- )
+ self.encrypted_data.with_user(admin)._encrypted_get(self.crypted_data_name)
# Change value should invalidate cache
- self.encrypted_data.sudo()._encrypted_store(
- "test_model,1", "Other Config"
- )
- new_data = self.encrypted_data.sudo()._encrypted_get(
- self.crypted_data_name
- )
+ self.encrypted_data.sudo()._encrypted_store("test_model,1", "Other Config")
+ new_data = self.encrypted_data.sudo()._encrypted_get(self.crypted_data_name)
self.assertEqual(new_data, "Other Config")
def test_get_data_wrong_key(self):
- self.encrypted_data.sudo()._encrypted_store(
- "test_model,1", "My config"
- )
+ self.encrypted_data.sudo()._encrypted_store("test_model,1", "My config")
new_key = Fernet.generate_key()
config["encryption_key_test"] = new_key.decode()
with self.assertRaises(ValidationError):
self.encrypted_data.sudo()._encrypted_get(self.crypted_data_name)
def test_get_empty_data(self):
- empty_data = self.encrypted_data.sudo()._encrypted_get(
- self.crypted_data_name
- )
+ empty_data = self.encrypted_data.sudo()._encrypted_get(self.crypted_data_name)
self.assertEqual(empty_data, None)
def test_get_wrong_json(self):
- self.encrypted_data.sudo()._encrypted_store(
- self.crypted_data_name, "config"
- )
+ self.encrypted_data.sudo()._encrypted_store(self.crypted_data_name, "config")
with self.assertRaises(ValidationError):
- self.encrypted_data.sudo()._encrypted_read_json(
- self.crypted_data_name
- )
+ self.encrypted_data.sudo()._encrypted_read_json(self.crypted_data_name)
def test_get_good_json(self):
self.encrypted_data.sudo()._encrypted_store_json(
self.crypted_data_name, {"key": "value"}
)
- data = self.encrypted_data.sudo()._encrypted_read_json(
- self.crypted_data_name
- )
+ data = self.encrypted_data.sudo()._encrypted_read_json(self.crypted_data_name)
self.assertEqual(data, {"key": "value"})
def test_get_empty_json(self):
- data = self.encrypted_data.sudo()._encrypted_read_json(
- self.crypted_data_name
- )
+ data = self.encrypted_data.sudo()._encrypted_read_json(self.crypted_data_name)
self.assertEqual(data, {})
def test_get_data_with_bin_size_context(self):
- self.encrypted_data.sudo()._encrypted_store(
- self.crypted_data_name, "test"
- )
+ self.encrypted_data.sudo()._encrypted_store(self.crypted_data_name, "test")
data = (
self.encrypted_data.sudo()
.with_context(bin_size=True)
From 54ec240e93f97e49a87c7ebedd4220a20652bbd4 Mon Sep 17 00:00:00 2001
From: Mourad
Date: Mon, 12 Oct 2020 14:07:41 +0200
Subject: [PATCH 07/14] [IMP] server_environment_data_encryption,
data_encryption: black, isort, prettier
---
data_encryption/models/encrypted_data.py | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/data_encryption/models/encrypted_data.py b/data_encryption/models/encrypted_data.py
index f49b9b7..d9dbc67 100644
--- a/data_encryption/models/encrypted_data.py
+++ b/data_encryption/models/encrypted_data.py
@@ -24,7 +24,9 @@ class EncryptedData(models.Model):
name = fields.Char(required=True, readonly=True, index=True, help="Technical name")
environment = fields.Char(
- required=True, index=True, help="Concerned Odoo environment (prod, preprod...)",
+ required=True,
+ index=True,
+ help="Concerned Odoo environment (prod, preprod...)",
)
encrypted_data = fields.Binary(attachment=False)
@@ -83,7 +85,7 @@ class EncryptedData(models.Model):
@staticmethod
def _retrieve_env():
"""Return the current environment
- Raise if none is found
+ Raise if none is found
"""
current = config.get("running_env", False)
if not current:
From bcf6c5d08ded201f004b7ee35d5d2eb11dec49ac Mon Sep 17 00:00:00 2001
From: Mourad
Date: Mon, 12 Oct 2020 15:32:19 +0200
Subject: [PATCH 08/14] [MIG] server_environment_data_encryption,
data_encryption: Migration to 14.0
note: exclude tests/fixtures from pre-commit check
---
data_encryption/__manifest__.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/data_encryption/__manifest__.py b/data_encryption/__manifest__.py
index afec603..3655a5d 100644
--- a/data_encryption/__manifest__.py
+++ b/data_encryption/__manifest__.py
@@ -3,10 +3,10 @@
{
"name": "Encryption data",
"summary": "Store accounts and credentials encrypted by environment",
- "version": "13.0.1.0.0",
+ "version": "14.0.1.0.0",
"development_status": "Alpha",
"category": "Tools",
- "website": "https://github/oca/server-env",
+ "website": "https://github.com/OCA/server-env",
"author": "Akretion, Odoo Community Association (OCA)",
"license": "AGPL-3",
"application": False,
From 55f08d50784335b80fbee5bb0bf20a1010bc1840 Mon Sep 17 00:00:00 2001
From: oca-travis
Date: Fri, 5 Mar 2021 10:42:49 +0000
Subject: [PATCH 09/14] [UPD] Update data_encryption.pot
---
data_encryption/i18n/data_encryption.pot | 37 ++++++++++++++----------
1 file changed, 21 insertions(+), 16 deletions(-)
diff --git a/data_encryption/i18n/data_encryption.pot b/data_encryption/i18n/data_encryption.pot
index 38f2f21..b330981 100644
--- a/data_encryption/i18n/data_encryption.pot
+++ b/data_encryption/i18n/data_encryption.pot
@@ -1,12 +1,12 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
-# * data_encryption
+# * data_encryption
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 12.0\n"
+"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: <>\n"
+"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -39,9 +39,9 @@ msgid "Encrypted Data"
msgstr ""
#. module: data_encryption
-#: code:addons/data_encryption/models/encrypted_data.py:58
+#: code:addons/data_encryption/models/encrypted_data.py:0
#, python-format
-msgid "Encrypted data can only be read as superuser"
+msgid "Encrypted data can only be read with suspended security (sudo)"
msgstr ""
#. module: data_encryption
@@ -75,21 +75,25 @@ msgid "Name"
msgstr ""
#. module: data_encryption
-#: code:addons/data_encryption/models/encrypted_data.py:100
+#: code:addons/data_encryption/models/encrypted_data.py:0
#, python-format
msgid "No '%s' entry found in config file. Use a key similar to: %s"
msgstr ""
#. module: data_encryption
-#: code:addons/data_encryption/models/encrypted_data.py:87
+#: code:addons/data_encryption/models/encrypted_data.py:0
#, python-format
-msgid "No environment found, please check your running_env entry in your config file."
+msgid ""
+"No environment found, please check your running_env entry in your config "
+"file."
msgstr ""
#. module: data_encryption
-#: code:addons/data_encryption/models/encrypted_data.py:46
+#: code:addons/data_encryption/models/encrypted_data.py:0
#, python-format
-msgid "Password has been encrypted with a different key. Unless you can recover the previous key, this password is unreadable."
+msgid ""
+"Password has been encrypted with a different key. Unless you can recover the"
+" previous key, this password is unreadable."
msgstr ""
#. module: data_encryption
@@ -103,19 +107,20 @@ msgid "Technical name"
msgstr ""
#. module: data_encryption
-#: code:addons/data_encryption/models/encrypted_data.py:77
+#: code:addons/data_encryption/models/encrypted_data.py:0
#, python-format
msgid "The data you are trying to read are not in a json format"
msgstr ""
#. module: data_encryption
-#: sql_constraint:encrypted.data:0
-msgid "You can not store multiple encrypted data for the same record and environment"
+#: model:ir.model.constraint,message:data_encryption.constraint_encrypted_data_name_environment_uniq
+msgid ""
+"You can not store multiple encrypted data for the same record and "
+"environment"
msgstr ""
#. module: data_encryption
-#: code:addons/data_encryption/models/encrypted_data.py:119
+#: code:addons/data_encryption/models/encrypted_data.py:0
#, python-format
-msgid "You can only encrypt data as superuser"
+msgid "You can only encrypt data with suspended security (sudo)"
msgstr ""
-
From c70713f488c7222d5de90bcfd7d8681e2c5c2385 Mon Sep 17 00:00:00 2001
From: OCA-git-bot
Date: Fri, 5 Mar 2021 10:47:35 +0000
Subject: [PATCH 10/14] [UPD] README.rst
---
data_encryption/README.rst | 10 +++++-----
data_encryption/static/description/index.html | 6 +++---
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/data_encryption/README.rst b/data_encryption/README.rst
index 837afa9..bf41e95 100644
--- a/data_encryption/README.rst
+++ b/data_encryption/README.rst
@@ -14,13 +14,13 @@ Encryption data
: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/12.0/data_encryption
+ :target: https://github.com/OCA/server-env/tree/14.0/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-12-0/server-env-12-0-data_encryption
+ :target: https://translation.odoo-community.org/projects/server-env-14-0/server-env-14-0-data_encryption
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/254/12.0
+ :target: https://runbot.odoo-community.org/runbot/254/14.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -79,7 +79,7 @@ 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 smashing it by providing a detailed and welcomed
-`feedback `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -110,6 +110,6 @@ 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.
-This module is part of the `OCA/server-env `_ project on GitHub.
+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/data_encryption/static/description/index.html b/data_encryption/static/description/index.html
index b832f77..e35494d 100644
--- a/data_encryption/static/description/index.html
+++ b/data_encryption/static/description/index.html
@@ -367,7 +367,7 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-

+

This module allows to encrypt and decrypt data. This module is not usable
by itself, it is a low level module which should work as a base for others.
An example is the module server_environment_data_encryption
@@ -426,7 +426,7 @@ is not a big constraint.
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 smashing it by providing a detailed and welcomed
-feedback.
+feedback.
Do not contact contributors directly about support or help with technical issues.
@@ -451,7 +451,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
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.
-
This module is part of the OCA/server-env project on GitHub.
+
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.
From d9eb1d7ff7c324f2413bb9ba91af1b942b76d209 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dept=2E=20T=C3=A9cnico?=
Date: Wed, 16 Feb 2022 11:37:42 +0000
Subject: [PATCH 11/14] Added translation using Weblate (Catalan)
---
data_encryption/i18n/ca.po | 127 +++++++++++++++++++++++++++++++++++++
1 file changed, 127 insertions(+)
create mode 100644 data_encryption/i18n/ca.po
diff --git a/data_encryption/i18n/ca.po b/data_encryption/i18n/ca.po
new file mode 100644
index 0000000..266b4bb
--- /dev/null
+++ b/data_encryption/i18n/ca.po
@@ -0,0 +1,127 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * 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: data_encryption
+#: model:ir.model.fields,help:data_encryption.field_encrypted_data__environment
+msgid "Concerned Odoo environment (prod, preprod...)"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__create_uid
+msgid "Created by"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__create_date
+msgid "Created on"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__encrypted_data
+msgid "Encrypted Data"
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:0
+#, python-format
+msgid "Encrypted data can only be read with suspended security (sudo)"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__environment
+msgid "Environment"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__id
+msgid "ID"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__write_uid
+msgid "Last Updated by"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__write_date
+msgid "Last Updated on"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,field_description:data_encryption.field_encrypted_data__name
+msgid "Name"
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:0
+#, python-format
+msgid "No '%s' entry found in config file. Use a key similar to: %s"
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:0
+#, python-format
+msgid ""
+"No environment found, please check your running_env entry in your config "
+"file."
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:0
+#, python-format
+msgid ""
+"Password has been encrypted with a different key. Unless you can recover the"
+" previous key, this password is unreadable."
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model,name:data_encryption.model_encrypted_data
+msgid "Store any encrypted data by environment"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.fields,help:data_encryption.field_encrypted_data__name
+msgid "Technical name"
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:0
+#, python-format
+msgid "The data you are trying to read are not in a json format"
+msgstr ""
+
+#. module: data_encryption
+#: model:ir.model.constraint,message:data_encryption.constraint_encrypted_data_name_environment_uniq
+msgid ""
+"You can not store multiple encrypted data for the same record and "
+"environment"
+msgstr ""
+
+#. module: data_encryption
+#: code:addons/data_encryption/models/encrypted_data.py:0
+#, python-format
+msgid "You can only encrypt data with suspended security (sudo)"
+msgstr ""
From 949674d06c6c10ed61b95160336886cebe0ae153 Mon Sep 17 00:00:00 2001
From: Florian da Costa
Date: Sun, 9 Oct 2022 16:25:46 +0200
Subject: [PATCH 12/14] [IMP] data_encryption: black, isort, prettier
---
data_encryption/models/encrypted_data.py | 15 +++++++++------
requirements.txt | 2 ++
setup/data_encryption/odoo/addons/data_encryption | 1 +
setup/data_encryption/setup.py | 6 ++++++
4 files changed, 18 insertions(+), 6 deletions(-)
create mode 100644 requirements.txt
create mode 120000 setup/data_encryption/odoo/addons/data_encryption
create mode 100644 setup/data_encryption/setup.py
diff --git a/data_encryption/models/encrypted_data.py b/data_encryption/models/encrypted_data.py
index d9dbc67..2e95265 100644
--- a/data_encryption/models/encrypted_data.py
+++ b/data_encryption/models/encrypted_data.py
@@ -44,14 +44,14 @@ class EncryptedData(models.Model):
cipher = self._get_cipher(env)
try:
return cipher.decrypt(self.encrypted_data).decode()
- except InvalidToken:
+ except InvalidToken as exc:
raise ValidationError(
_(
"Password has been encrypted with a different "
"key. Unless you can recover the previous key, "
"this password is unreadable."
)
- )
+ ) from exc
@api.model
@ormcache("self._uid", "name", "env")
@@ -77,10 +77,10 @@ class EncryptedData(models.Model):
return {}
try:
return json.loads(data)
- except (ValueError, TypeError):
+ except (ValueError, TypeError) as exc:
raise ValidationError(
_("The data you are trying to read are not in a json format")
- )
+ ) from exc
@staticmethod
def _retrieve_env():
@@ -107,8 +107,11 @@ class EncryptedData(models.Model):
key_str = config.get(key_name)
if not key_str:
raise ValidationError(
- _("No '%s' entry found in config file. " "Use a key similar to: %s")
- % (key_name, Fernet.generate_key())
+ _(
+ "No '%(key_name)s' entry found in config file. "
+ "Use a key similar to: %(key)s"
+ )
+ % {"key_name": key_name, "key": Fernet.generate_key()}
)
# key should be in bytes format
key = key_str.encode()
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..368c5c2
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+# generated from manifests external_dependencies
+cryptography
diff --git a/setup/data_encryption/odoo/addons/data_encryption b/setup/data_encryption/odoo/addons/data_encryption
new file mode 120000
index 0000000..2aee058
--- /dev/null
+++ b/setup/data_encryption/odoo/addons/data_encryption
@@ -0,0 +1 @@
+../../../../data_encryption
\ No newline at end of file
diff --git a/setup/data_encryption/setup.py b/setup/data_encryption/setup.py
new file mode 100644
index 0000000..28c57bb
--- /dev/null
+++ b/setup/data_encryption/setup.py
@@ -0,0 +1,6 @@
+import setuptools
+
+setuptools.setup(
+ setup_requires=['setuptools-odoo'],
+ odoo_addon=True,
+)
From 069323b40f2ff5653029bb7922f9736d6a6caa06 Mon Sep 17 00:00:00 2001
From: Florian da Costa
Date: Sun, 9 Oct 2022 16:31:28 +0200
Subject: [PATCH 13/14] [16][MIG] Migration of data_encryption
---
data_encryption/__manifest__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/data_encryption/__manifest__.py b/data_encryption/__manifest__.py
index 3655a5d..fac10cb 100644
--- a/data_encryption/__manifest__.py
+++ b/data_encryption/__manifest__.py
@@ -3,7 +3,7 @@
{
"name": "Encryption data",
"summary": "Store accounts and credentials encrypted by environment",
- "version": "14.0.1.0.0",
+ "version": "16.0.1.0.0",
"development_status": "Alpha",
"category": "Tools",
"website": "https://github.com/OCA/server-env",
From 2e2fef10560697805658c0713fb671fa81f054cd Mon Sep 17 00:00:00 2001
From: David Beal
Date: Thu, 28 Jul 2022 12:17:07 +0200
Subject: [PATCH 14/14] FIX data_encryption: typo
---
data_encryption/README.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/data_encryption/README.rst b/data_encryption/README.rst
index bf41e95..6356515 100644
--- a/data_encryption/README.rst
+++ b/data_encryption/README.rst
@@ -62,7 +62,7 @@ In the configuration file of your production environment, you may want to config
all your other environments encryption key. This way, from production you can encrypt and decrypt
data for all environments.
-You can generate keys with python -c 'from cryptography.fernet import Fernet; print Fernet.generate_key()'.
+You can generate keys with python -c 'from cryptography.fernet import Fernet; print(Fernet.generate_key())'.
Known issues / Roadmap
======================