diff --git a/keychain/README.rst b/keychain/README.rst index b8d2ed6..a10fda3 100644 --- a/keychain/README.rst +++ b/keychain/README.rst @@ -209,7 +209,7 @@ help us smashing it by providing a detailed and welcomed feedback. Credits ======= -`Akretion `_ +* `Akretion `_ Contributors @@ -222,7 +222,7 @@ Funders The development of this module has been financially supported by: -* `Akretion `_ +* Akretion Maintainer ---------- diff --git a/keychain/models/__init__.py b/keychain/models/__init__.py index b84bb91..9f0d06e 100644 --- a/keychain/models/__init__.py +++ b/keychain/models/__init__.py @@ -1 +1,2 @@ -from . import keychain \ No newline at end of file +from . import keychain +from . import keychain_backend diff --git a/keychain/models/keychain.py b/keychain/models/keychain.py index 723d132..a94ffb2 100644 --- a/keychain/models/keychain.py +++ b/keychain/models/keychain.py @@ -200,71 +200,3 @@ class KeychainAccount(models.Model): "Use a key similar to: %s" % (envs[0], Fernet.generate_key()) )) return MultiFernet(keys) - - -class KeychainBackend(models.AbstractModel): - _name = 'keychain.backend' - _backend_name = None - - name = fields.Char(required=True) - password = fields.Char( - compute="_compute_password", - inverse="_inverse_password", - required=True) - data = fields.Serialized( - compute="_compute_keychain", - inverse="_inverse_keychain") - - def _get_technical_name(self): - return '%s,%s' % (self._name, self.id) - - def _get_existing_keychain(self): - self.ensure_one() - return self.env['keychain.account'].retrieve([ - ('namespace', '=', self._backend_name), - ('technical_name', '=', self._get_technical_name()) - ]) - - def _prepare_keychain(self): - env = config.get('running_env') - return { - 'name': "%s %s" % (self.name, env), - 'technical_name': self._get_technical_name(), - 'namespace': self._backend_name, - 'environment': env, - } - - def _get_keychain_account(self): - self.ensure_one() - account = self._get_existing_keychain() - if not account: - vals = self._prepare_keychain() - account = self.env['keychain.account'].create(vals) - return account - - def _inverse_password(self): - for record in self: - account = self._get_keychain_account() - if record.password and record.password != '******': - account.clear_password = record.password - - def _compute_password(self): - for record in self: - account = record._get_existing_keychain() - if account and account.password: - record.password = "******" - else: - record.password = "" - - def _inverse_keychain(self): - for record in self: - account = record._get_keychain_account() - account.data = account._serialize_data(record.data) - - def _compute_keychain(self): - for record in self: - account = record._get_existing_keychain() - if account: - record.data = account.get_data() - else: - record.data = {} diff --git a/keychain/models/keychain_backend.py b/keychain/models/keychain_backend.py new file mode 100644 index 0000000..1e909a8 --- /dev/null +++ b/keychain/models/keychain_backend.py @@ -0,0 +1,74 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion Sebastien Beau +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields +from odoo.tools.config import config + + +class KeychainBackend(models.AbstractModel): + _name = 'keychain.backend' + _backend_name = None + + name = fields.Char(required=True) + password = fields.Char( + compute="_compute_password", + inverse="_inverse_password", + required=True) + data = fields.Serialized( + compute="_compute_keychain", + inverse="_inverse_keychain") + + def _get_technical_name(self): + return '%s,%s' % (self._name, self.id) + + def _get_existing_keychain(self): + self.ensure_one() + return self.env['keychain.account'].retrieve([ + ('namespace', '=', self._backend_name), + ('technical_name', '=', self._get_technical_name()) + ]) + + def _prepare_keychain(self): + env = config.get('running_env') + return { + 'name': "%s %s" % (self.name, env), + 'technical_name': self._get_technical_name(), + 'namespace': self._backend_name, + 'environment': env, + } + + def _get_keychain_account(self): + self.ensure_one() + account = self._get_existing_keychain() + if not account: + vals = self._prepare_keychain() + account = self.env['keychain.account'].create(vals) + return account + + def _inverse_password(self): + for record in self: + account = self._get_keychain_account() + if record.password and record.password != '******': + account.clear_password = record.password + + def _compute_password(self): + for record in self: + account = record._get_existing_keychain() + if account and account.password: + record.password = "******" + else: + record.password = "" + + def _inverse_keychain(self): + for record in self: + account = record._get_keychain_account() + account.data = account._serialize_data(record.data) + + def _compute_keychain(self): + for record in self: + account = record._get_existing_keychain() + if account: + record.data = account.get_data() + else: + record.data = {} diff --git a/keychain/tests/__init__.py b/keychain/tests/__init__.py index 779cc40..5ac20c9 100644 --- a/keychain/tests/__init__.py +++ b/keychain/tests/__init__.py @@ -1 +1,2 @@ -from . import test_keychain \ No newline at end of file +from . import test_keychain +from . import test_keychain_backend \ No newline at end of file diff --git a/keychain/tests/test_keychain.py b/keychain/tests/test_keychain.py index 170abf6..d5fd522 100644 --- a/keychain/tests/test_keychain.py +++ b/keychain/tests/test_keychain.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# © 2016 Akretion Raphaël REVERDY, Mourad EL HADJ MIMOUNE +# © 2016 Akretion Raphaël REVERDY # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). from odoo.tests.common import TransactionCase @@ -23,7 +23,6 @@ class TestKeychain(TransactionCase): super(TestKeychain, self).setUp() self.keychain = self.env['keychain.account'] - self.keychain_backend = self.env['keychain.backend'] config['keychain_key'] = Fernet.generate_key() self.old_running_env = config.get('running_env', '') @@ -40,20 +39,12 @@ class TestKeychain(TransactionCase): return 'c' in data keychain_clss = self.keychain.__class__ - keychain_clss._test_backend_init_data = _init_data keychain_clss._keychain_test_init_data = _init_data keychain_clss._keychain_test_validate_data = _validate_data - keychain_clss._test_backend_validate_data = _validate_data - - keychain_backend_clss = self.keychain_backend.__class__ - keychain_backend_clss._backend_name = 'test_backend' self.keychain._fields['namespace'].selection.append( ('keychain_test', 'test') ) - self.keychain._fields['namespace'].selection.append( - ('test_backend', 'test backend') - ) def tearDown(self): config['running_env'] = self.old_running_env @@ -230,40 +221,3 @@ class TestKeychain(TransactionCase): self.assertTrue(True, 'Should validate json') except: self.assertTrue(False, 'It should validate a good json') - - def test_keychain_bakend(self): - """It should work with valid data.""" - config['keychain_key_dev'] = Fernet.generate_key() - config['running_env'] = 'dev' - vals = { - 'name': 'backend_test', - 'password': 'test', - 'data': '{"a": "o", "c": "b"}' - } - # we use new because keychain.backend is an abstract model - backend = self.keychain_backend.new(vals) - backend._inverse_keychain() - account = backend._get_existing_keychain() - self.assertEqual( - account.data, '{"a": "o", "c": "b"}', - 'Account data is not correct') - backend._inverse_password() - self.assertTrue(account, 'Account was not created') - self.assertEqual( - account.clear_password, u'test', - 'Account clear password is not correct') - self.assertEqual(backend.password, u'test') - backend._compute_password() - self.assertEqual( - backend.password, u'******', 'Backend password was not computed') - self.assertEqual( - account.name, u'backend_test dev', 'Account name is not correct') - self.assertEqual( - account.namespace, u'test_backend', - 'Account namespace is not correct') - self.assertEqual( - account.environment, u'dev', 'Account environment is not correct') - self.assertEqual( - account.technical_name, '%s,%s' % (backend._name, backend.id), - 'Account technical_name is not correct') - diff --git a/keychain/tests/test_keychain_backend.py b/keychain/tests/test_keychain_backend.py new file mode 100644 index 0000000..f20b796 --- /dev/null +++ b/keychain/tests/test_keychain_backend.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# © 2016 Akretion Mourad EL HADJ MIMOUNE +# 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: + _logger.debug(err) + + +class TestKeychain(TransactionCase): + + def setUp(self): + super(TestKeychain, self).setUp() + + self.keychain = self.env['keychain.account'] + self.keychain_backend = self.env['keychain.backend'] + + def _init_data(self): + return { + "c": True, + "a": "b", + "d": "", + } + + def _validate_data(self, data): + return 'c' in data + + keychain_clss = self.keychain.__class__ + keychain_clss._test_backend_init_data = _init_data + keychain_clss._test_backend_validate_data = _validate_data + + keychain_backend_clss = self.keychain_backend.__class__ + keychain_backend_clss._backend_name = 'test_backend' + + self.keychain._fields['namespace'].selection.append( + ('test_backend', 'test backend') + ) + + def test_keychain_bakend(self): + """It should work with valid data.""" + config['keychain_key_dev'] = Fernet.generate_key() + config['running_env'] = 'dev' + vals = { + 'name': 'backend_test', + 'password': 'test', + 'data': '{"a": "o", "c": "b"}' + } + # we use new because keychain.backend is an abstract model + backend = self.keychain_backend.new(vals) + backend._inverse_keychain() + account = backend._get_existing_keychain() + self.assertEqual( + account.data, '{"a": "o", "c": "b"}', + 'Account data is not correct') + backend._inverse_password() + self.assertTrue(account, 'Account was not created') + self.assertEqual( + account.clear_password, u'test', + 'Account clear password is not correct') + self.assertEqual(backend.password, u'test') + backend._compute_password() + self.assertEqual( + backend.password, u'******', 'Backend password was not computed') + self.assertEqual( + account.name, u'backend_test dev', 'Account name is not correct') + self.assertEqual( + account.namespace, u'test_backend', + 'Account namespace is not correct') + self.assertEqual( + account.environment, u'dev', 'Account environment is not correct') + self.assertEqual( + account.technical_name, '%s,%s' % (backend._name, backend.id), + 'Account technical_name is not correct') +