From 3907d0ace74eb6f93f82bbb7bd10b0649fa72b2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Wed, 11 Apr 2018 13:17:44 +0200 Subject: [PATCH 01/58] [REF] split sftp backend in a separated module --- storage_backend_sftp/README.rst | 42 +++++++++++ storage_backend_sftp/__init__.py | 4 ++ storage_backend_sftp/__manifest__.py | 26 +++++++ storage_backend_sftp/components/__init__.py | 3 + .../components/sftp_adapter.py | 72 +++++++++++++++++++ storage_backend_sftp/models/__init__.py | 3 + .../models/storage_backend.py | 27 +++++++ storage_backend_sftp/tests/__init__.py | 3 + storage_backend_sftp/tests/test_sftp.py | 44 ++++++++++++ .../views/backend_storage_view.xml | 17 +++++ 10 files changed, 241 insertions(+) create mode 100644 storage_backend_sftp/README.rst create mode 100644 storage_backend_sftp/__init__.py create mode 100644 storage_backend_sftp/__manifest__.py create mode 100644 storage_backend_sftp/components/__init__.py create mode 100644 storage_backend_sftp/components/sftp_adapter.py create mode 100644 storage_backend_sftp/models/__init__.py create mode 100644 storage_backend_sftp/models/storage_backend.py create mode 100644 storage_backend_sftp/tests/__init__.py create mode 100644 storage_backend_sftp/tests/test_sftp.py create mode 100644 storage_backend_sftp/views/backend_storage_view.xml diff --git a/storage_backend_sftp/README.rst b/storage_backend_sftp/README.rst new file mode 100644 index 0000000000..082eef5149 --- /dev/null +++ b/storage_backend_sftp/README.rst @@ -0,0 +1,42 @@ + +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +===================== +Storage backend SFTP +===================== + +Add the possibility to store and get data from an SFTP for your storage backend + + + +Installation +============ + +To install this module, you need to: + +#. (root) pip install paramiko + + +Known issues / Roadmap +====================== + +Update README with the last model of README when migration to v11 in OCA + + +Credits +======= + + +Contributors +------------ + +* Sebastien Beau +* Raphaël Reverdy + + +Maintainer +---------- + +* Akretion diff --git a/storage_backend_sftp/__init__.py b/storage_backend_sftp/__init__.py new file mode 100644 index 0000000000..3fbae039c0 --- /dev/null +++ b/storage_backend_sftp/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- + +from . import models +from . import components diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py new file mode 100644 index 0000000000..851fcc656c --- /dev/null +++ b/storage_backend_sftp/__manifest__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Akretion (http://www.akretion.com). +# @author Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Storage Backend SFTP", + "summary": "Implement SFTP Storage", + "version": "10.0.1.0.0", + "category": "Storage", + "website": "www.akretion.com", + "author": " Akretion", + "license": "AGPL-3", + 'installable': True, + "external_dependencies": { + "python": [ + "paramiko", + ], + }, + "depends": [ + "storage_backend", + ], + "data": [ + "views/backend_storage_view.xml", + ], +} diff --git a/storage_backend_sftp/components/__init__.py b/storage_backend_sftp/components/__init__.py new file mode 100644 index 0000000000..8bfded8d81 --- /dev/null +++ b/storage_backend_sftp/components/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import sftp_adapter diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py new file mode 100644 index 0000000000..5bfe3bf2a2 --- /dev/null +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Akretion (http://www.akretion.com). +# @author Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +import base64 +import os +import errno + +from contextlib import contextmanager +from odoo.addons.component.core import Component + + +logger = logging.getLogger(__name__) + +try: + import paramiko +except ImportError as err: + logger.debug(err) + + +def sftp_mkdirs(client, path, mode=511): + try: + client.mkdir(path, mode) + except IOError, e: + if e.errno == errno.ENOENT and path: + sftp_mkdirs(client, os.path.dirname(path), mode=mode) + client.mkdir(path, mode) + else: + raise + + +@contextmanager +def sftp(backend): + account = backend._get_keychain_account() + password = account._get_password() + transport = paramiko.Transport((backend.sftp_server, backend.sftp_port)) + transport.connect(username=backend.sftp_login, password=password) + client = paramiko.SFTPClient.from_transport(transport) + yield client + transport.close() + + +class SftpStorageBackend(Component): + _name = 'sftp.adapter' + _inherit = 'base.storage.adapter' + _usage = 'sftp' + + def store_data(self, relative_path, datas, **kwargs): + with sftp(self.collection) as client: + full_path = self._fullpath(relative_path) + dirname = os.path.dirname(full_path) + if dirname: + try: + client.stat(dirname) + except IOError, e: + if e.errno == errno.ENOENT: + sftp_mkdirs(client, dirname) + else: + raise + remote_file = client.open(full_path, 'w+b') + remote_file.write(datas) + remote_file.close() + + def retrieve_data(self, relative_path, **kwargs): + full_path = self._fullpath(relative_path) + with sftp(self.collection) as client: + file_data = client.open(full_path, 'rb') + datas = file_data.read() + datas_encoded = datas and base64.b64encode(datas) or False + return datas_encoded diff --git a/storage_backend_sftp/models/__init__.py b/storage_backend_sftp/models/__init__.py new file mode 100644 index 0000000000..4731534aa1 --- /dev/null +++ b/storage_backend_sftp/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import storage_backend diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py new file mode 100644 index 0000000000..f68f201a57 --- /dev/null +++ b/storage_backend_sftp/models/storage_backend.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Akretion (http://www.akretion.com). +# @author Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class StorageBackend(models.Model): + _inherit = 'storage.backend' + + backend_type = fields.Selection( + selection_add=[('sftp', 'SFTP')]) + sftp_password = fields.Char( + related="password", + string="Password") + sftp_login = fields.Char( + string='Login', + help='Login to connect to sftp server', + sparse="data") + sftp_server = fields.Char( + string='Host', + sparse="data") + sftp_port = fields.Integer( + string='Port', + default=22, + sparse="data") diff --git a/storage_backend_sftp/tests/__init__.py b/storage_backend_sftp/tests/__init__.py new file mode 100644 index 0000000000..4018ddba1f --- /dev/null +++ b/storage_backend_sftp/tests/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +from . import test_sftp diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py new file mode 100644 index 0000000000..6ef0449268 --- /dev/null +++ b/storage_backend_sftp/tests/test_sftp.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Copyright 2017 Akretion (http://www.akretion.com). +# @author Sébastien BEAU +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +# pylint: disable=missing-manifest-dependency +# disable warning on 'vcr' missing in manifest: this is only a dependency for +# dev/tests + +from odoo.addons.storage_backend.tests.common import Common +import os +import base64 +import logging +_logger = logging.getLogger(__name__) + + +class SftpCase(Common): + + def setUp(self): + super(SftpCase, self).setUp() + self.backend = self.env.ref('storage_backend.default_storage_backend') + self.backend.write({ + 'backend_type': 'sftp', + 'sftp_login': 'foo', + 'sftp_password': 'pass', + 'sftp_server': os.environ.get('SFTP_HOST', 'localhost'), + 'sftp_port': os.environ.get('SFTP_PORT', '2222'), + 'directory_path': 'upload', + }) + + def test_00_setting_and_reading_data_from_root(self): + self.backend.store( + self.filename, self.filedata, + is_base64=False, mimetype=u'text/plain') + data = self.backend.retrieve_data(self.filename) + self.assertEqual(base64.b64decode(data), self.filedata) + + def test_10_setting_and_reading_data_from_directory(self): + self.backend.directory_path = 'upload/subdirectory/here' + self.backend.store( + self.filename, self.filedata, + is_base64=False, mimetype=u'text/plain') + data = self.backend.retrieve_data(self.filename) + self.assertEqual(base64.b64decode(data), self.filedata) diff --git a/storage_backend_sftp/views/backend_storage_view.xml b/storage_backend_sftp/views/backend_storage_view.xml new file mode 100644 index 0000000000..b046d295e2 --- /dev/null +++ b/storage_backend_sftp/views/backend_storage_view.xml @@ -0,0 +1,17 @@ + + + + storage.backend + + + + + + + + + + + + + From 31dbb52de706fded649daa9746cbd70285ef5f85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Wed, 11 Apr 2018 19:42:42 +0200 Subject: [PATCH 02/58] [REF] rename method store and retrieve by more explicit method add/get with the specifiation of the type of file binary or base64 --- .../components/sftp_adapter.py | 12 +++++------- storage_backend_sftp/tests/test_sftp.py | 19 ++++++++----------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 5bfe3bf2a2..4224989e0a 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -4,7 +4,6 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import logging -import base64 import os import errno @@ -47,7 +46,7 @@ class SftpStorageBackend(Component): _inherit = 'base.storage.adapter' _usage = 'sftp' - def store_data(self, relative_path, datas, **kwargs): + def add(self, relative_path, data, **kwargs): with sftp(self.collection) as client: full_path = self._fullpath(relative_path) dirname = os.path.dirname(full_path) @@ -60,13 +59,12 @@ def store_data(self, relative_path, datas, **kwargs): else: raise remote_file = client.open(full_path, 'w+b') - remote_file.write(datas) + remote_file.write(data) remote_file.close() - def retrieve_data(self, relative_path, **kwargs): + def get(self, relative_path, **kwargs): full_path = self._fullpath(relative_path) with sftp(self.collection) as client: file_data = client.open(full_path, 'rb') - datas = file_data.read() - datas_encoded = datas and base64.b64encode(datas) or False - return datas_encoded + data = file_data.read() + return data diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index 6ef0449268..7e2af058f1 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -9,7 +9,6 @@ from odoo.addons.storage_backend.tests.common import Common import os -import base64 import logging _logger = logging.getLogger(__name__) @@ -29,16 +28,14 @@ def setUp(self): }) def test_00_setting_and_reading_data_from_root(self): - self.backend.store( - self.filename, self.filedata, - is_base64=False, mimetype=u'text/plain') - data = self.backend.retrieve_data(self.filename) - self.assertEqual(base64.b64decode(data), self.filedata) + self.backend.add_b64_data( + self.filename, self.filedata, mimetype=u'text/plain') + data = self.backend.get_b64_data(self.filename) + self.assertEqual(data, self.filedata) def test_10_setting_and_reading_data_from_directory(self): self.backend.directory_path = 'upload/subdirectory/here' - self.backend.store( - self.filename, self.filedata, - is_base64=False, mimetype=u'text/plain') - data = self.backend.retrieve_data(self.filename) - self.assertEqual(base64.b64decode(data), self.filedata) + self.backend.add_b64_data( + self.filename, self.filedata, mimetype=u'text/plain') + data = self.backend.get_b64_data(self.filename) + self.assertEqual(data, self.filedata) From 9289c35098f2f631a41a014c1aa7caacd84e6f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Wed, 11 Apr 2018 19:42:42 +0200 Subject: [PATCH 03/58] [REF] refactor test in order to use the same test between the different backend --- storage_backend_sftp/tests/test_sftp.py | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index 7e2af058f1..9efe481b9c 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -7,17 +7,16 @@ # disable warning on 'vcr' missing in manifest: this is only a dependency for # dev/tests -from odoo.addons.storage_backend.tests.common import Common +from odoo.addons.storage_backend.tests.common import Common, GenericStoreCase import os import logging _logger = logging.getLogger(__name__) -class SftpCase(Common): +class SftpCase(Common, GenericStoreCase): def setUp(self): super(SftpCase, self).setUp() - self.backend = self.env.ref('storage_backend.default_storage_backend') self.backend.write({ 'backend_type': 'sftp', 'sftp_login': 'foo', @@ -26,16 +25,4 @@ def setUp(self): 'sftp_port': os.environ.get('SFTP_PORT', '2222'), 'directory_path': 'upload', }) - - def test_00_setting_and_reading_data_from_root(self): - self.backend.add_b64_data( - self.filename, self.filedata, mimetype=u'text/plain') - data = self.backend.get_b64_data(self.filename) - self.assertEqual(data, self.filedata) - - def test_10_setting_and_reading_data_from_directory(self): - self.backend.directory_path = 'upload/subdirectory/here' - self.backend.add_b64_data( - self.filename, self.filedata, mimetype=u'text/plain') - data = self.backend.get_b64_data(self.filename) - self.assertEqual(data, self.filedata) + self.case_with_subdirectory = 'upload/subdirectory/here' From cfa071c3a16a3428b5b6a676c66047baf0365993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Fri, 13 Apr 2018 11:46:58 +0200 Subject: [PATCH 04/58] [IMP] add method for listing directory and deleting file on storage.backend --- storage_backend_sftp/components/sftp_adapter.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 4224989e0a..baf7dbbe2c 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -68,3 +68,20 @@ def get(self, relative_path, **kwargs): file_data = client.open(full_path, 'rb') data = file_data.read() return data + + def list(self, relative_path): + full_path = self._fullpath(relative_path) + with sftp(self.collection) as client: + try: + return client.listdir(full_path) + except IOError, e: + if e.errno == errno.ENOENT: + # The path do not exist return an empty list + return [] + else: + raise + + def delete(self, relative_path): + full_path = self._fullpath(relative_path) + with sftp(self.collection) as client: + return client.remove(full_path) From 2329bf9d5047351a9a04adf2fa9d44a0562a28f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Pigeon?= Date: Thu, 21 Jun 2018 10:18:30 +0200 Subject: [PATCH 05/58] [ADD] allow to connect SFTP using a ssh private key --- storage_backend_sftp/README.rst | 1 + storage_backend_sftp/components/sftp_adapter.py | 16 +++++++++++++++- storage_backend_sftp/models/storage_backend.py | 9 +++++++++ .../views/backend_storage_view.xml | 1 + 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/storage_backend_sftp/README.rst b/storage_backend_sftp/README.rst index 082eef5149..11af342fc0 100644 --- a/storage_backend_sftp/README.rst +++ b/storage_backend_sftp/README.rst @@ -34,6 +34,7 @@ Contributors * Sebastien Beau * Raphaël Reverdy +* Cédric Pigeon Maintainer diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index baf7dbbe2c..75f19e16e9 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -6,6 +6,7 @@ import logging import os import errno +from StringIO import StringIO from contextlib import contextmanager from odoo.addons.component.core import Component @@ -29,13 +30,26 @@ def sftp_mkdirs(client, path, mode=511): else: raise +def load_ssh_key(ssh_key_buffer): + for pkey_class in (paramiko.RSAKey, paramiko.DSSKey, + paramiko.ECDSAKey, paramiko.Ed25519Key): + try: + return pkey_class.from_private_key(ssh_key_buffer) + except paramiko.SSHException: + ssh_key_buffer.seek(0) # reset the buffer "file" + raise Exception("Invalid ssh private key") @contextmanager def sftp(backend): account = backend._get_keychain_account() password = account._get_password() transport = paramiko.Transport((backend.sftp_server, backend.sftp_port)) - transport.connect(username=backend.sftp_login, password=password) + if backend.sftp_auth_method == 'pwd': + transport.connect(username=backend.sftp_login, password=password) + elif backend.sftp_auth_method == 'ssh_key': + ssh_key_buffer = StringIO(password) + private_key = load_ssh_key(ssh_key_buffer) + transport.connect(username=backend.sftp_login, pkey=private_key) client = paramiko.SFTPClient.from_transport(transport) yield client transport.close() diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index f68f201a57..c1d297396c 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -25,3 +25,12 @@ class StorageBackend(models.Model): string='Port', default=22, sparse="data") + sftp_auth_method = fields.Selection( + string="Authentification Method", + selection=[ + ('pwd', 'Password'), + ('ssh_key', 'Private key') + ], + default='pwd', + required=True, + ) diff --git a/storage_backend_sftp/views/backend_storage_view.xml b/storage_backend_sftp/views/backend_storage_view.xml index b046d295e2..5f8de8d7d1 100644 --- a/storage_backend_sftp/views/backend_storage_view.xml +++ b/storage_backend_sftp/views/backend_storage_view.xml @@ -10,6 +10,7 @@ + From 190e2b7e291ef57de66477501cd3ba386296cf5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Tue, 31 Jul 2018 09:58:36 +0200 Subject: [PATCH 06/58] [PEP8] fix pep8 issue --- storage_backend_sftp/components/sftp_adapter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 75f19e16e9..ab5d6f3c4e 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -30,15 +30,17 @@ def sftp_mkdirs(client, path, mode=511): else: raise + def load_ssh_key(ssh_key_buffer): for pkey_class in (paramiko.RSAKey, paramiko.DSSKey, paramiko.ECDSAKey, paramiko.Ed25519Key): try: return pkey_class.from_private_key(ssh_key_buffer) except paramiko.SSHException: - ssh_key_buffer.seek(0) # reset the buffer "file" + ssh_key_buffer.seek(0) # reset the buffer "file" raise Exception("Invalid ssh private key") + @contextmanager def sftp(backend): account = backend._get_keychain_account() From 377f582081887031da24807fc5689d9f08a619e5 Mon Sep 17 00:00:00 2001 From: Benoit Date: Wed, 10 Apr 2019 18:27:35 +0200 Subject: [PATCH 07/58] [FIX] clean with pre-commit and pep 8 --- storage_backend_sftp/__manifest__.py | 16 +++------ .../components/sftp_adapter.py | 35 ++++++++++--------- .../models/storage_backend.py | 30 +++++----------- storage_backend_sftp/tests/test_sftp.py | 27 +++++++------- 4 files changed, 47 insertions(+), 61 deletions(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 851fcc656c..fe0659f55e 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -11,16 +11,8 @@ "website": "www.akretion.com", "author": " Akretion", "license": "AGPL-3", - 'installable': True, - "external_dependencies": { - "python": [ - "paramiko", - ], - }, - "depends": [ - "storage_backend", - ], - "data": [ - "views/backend_storage_view.xml", - ], + "installable": True, + "external_dependencies": {"python": ["paramiko"]}, + "depends": ["storage_backend"], + "data": ["views/backend_storage_view.xml"], } diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index ab5d6f3c4e..8b9eb90517 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -3,14 +3,13 @@ # @author Sébastien BEAU # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +import errno import logging import os -import errno -from StringIO import StringIO - from contextlib import contextmanager -from odoo.addons.component.core import Component +from odoo.addons.component.core import Component +from StringIO import StringIO logger = logging.getLogger(__name__) @@ -23,7 +22,7 @@ def sftp_mkdirs(client, path, mode=511): try: client.mkdir(path, mode) - except IOError, e: + except IOError as e: if e.errno == errno.ENOENT and path: sftp_mkdirs(client, os.path.dirname(path), mode=mode) client.mkdir(path, mode) @@ -32,8 +31,12 @@ def sftp_mkdirs(client, path, mode=511): def load_ssh_key(ssh_key_buffer): - for pkey_class in (paramiko.RSAKey, paramiko.DSSKey, - paramiko.ECDSAKey, paramiko.Ed25519Key): + for pkey_class in ( + paramiko.RSAKey, + paramiko.DSSKey, + paramiko.ECDSAKey, + paramiko.Ed25519Key, + ): try: return pkey_class.from_private_key(ssh_key_buffer) except paramiko.SSHException: @@ -46,9 +49,9 @@ def sftp(backend): account = backend._get_keychain_account() password = account._get_password() transport = paramiko.Transport((backend.sftp_server, backend.sftp_port)) - if backend.sftp_auth_method == 'pwd': + if backend.sftp_auth_method == "pwd": transport.connect(username=backend.sftp_login, password=password) - elif backend.sftp_auth_method == 'ssh_key': + elif backend.sftp_auth_method == "ssh_key": ssh_key_buffer = StringIO(password) private_key = load_ssh_key(ssh_key_buffer) transport.connect(username=backend.sftp_login, pkey=private_key) @@ -58,9 +61,9 @@ def sftp(backend): class SftpStorageBackend(Component): - _name = 'sftp.adapter' - _inherit = 'base.storage.adapter' - _usage = 'sftp' + _name = "sftp.adapter" + _inherit = "base.storage.adapter" + _usage = "sftp" def add(self, relative_path, data, **kwargs): with sftp(self.collection) as client: @@ -69,19 +72,19 @@ def add(self, relative_path, data, **kwargs): if dirname: try: client.stat(dirname) - except IOError, e: + except IOError as e: if e.errno == errno.ENOENT: sftp_mkdirs(client, dirname) else: raise - remote_file = client.open(full_path, 'w+b') + remote_file = client.open(full_path, "w+b") remote_file.write(data) remote_file.close() def get(self, relative_path, **kwargs): full_path = self._fullpath(relative_path) with sftp(self.collection) as client: - file_data = client.open(full_path, 'rb') + file_data = client.open(full_path, "rb") data = file_data.read() return data @@ -90,7 +93,7 @@ def list(self, relative_path): with sftp(self.collection) as client: try: return client.listdir(full_path) - except IOError, e: + except IOError as e: if e.errno == errno.ENOENT: # The path do not exist return an empty list return [] diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index c1d297396c..6746d43c57 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -7,30 +7,18 @@ class StorageBackend(models.Model): - _inherit = 'storage.backend' + _inherit = "storage.backend" - backend_type = fields.Selection( - selection_add=[('sftp', 'SFTP')]) - sftp_password = fields.Char( - related="password", - string="Password") + backend_type = fields.Selection(selection_add=[("sftp", "SFTP")]) + sftp_password = fields.Char(related="password", string="Password") sftp_login = fields.Char( - string='Login', - help='Login to connect to sftp server', - sparse="data") - sftp_server = fields.Char( - string='Host', - sparse="data") - sftp_port = fields.Integer( - string='Port', - default=22, - sparse="data") + string="Login", help="Login to connect to sftp server", sparse="data" + ) + sftp_server = fields.Char(string="Host", sparse="data") + sftp_port = fields.Integer(string="Port", default=22, sparse="data") sftp_auth_method = fields.Selection( string="Authentification Method", - selection=[ - ('pwd', 'Password'), - ('ssh_key', 'Private key') - ], - default='pwd', + selection=[("pwd", "Password"), ("ssh_key", "Private key")], + default="pwd", required=True, ) diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index 9efe481b9c..6faf3637d0 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -7,22 +7,25 @@ # disable warning on 'vcr' missing in manifest: this is only a dependency for # dev/tests -from odoo.addons.storage_backend.tests.common import Common, GenericStoreCase -import os import logging +import os + +from odoo.addons.storage_backend.tests.common import Common, GenericStoreCase + _logger = logging.getLogger(__name__) class SftpCase(Common, GenericStoreCase): - def setUp(self): super(SftpCase, self).setUp() - self.backend.write({ - 'backend_type': 'sftp', - 'sftp_login': 'foo', - 'sftp_password': 'pass', - 'sftp_server': os.environ.get('SFTP_HOST', 'localhost'), - 'sftp_port': os.environ.get('SFTP_PORT', '2222'), - 'directory_path': 'upload', - }) - self.case_with_subdirectory = 'upload/subdirectory/here' + self.backend.write( + { + "backend_type": "sftp", + "sftp_login": "foo", + "sftp_password": "pass", + "sftp_server": os.environ.get("SFTP_HOST", "localhost"), + "sftp_port": os.environ.get("SFTP_PORT", "2222"), + "directory_path": "upload", + } + ) + self.case_with_subdirectory = "upload/subdirectory/here" From 5d70620c3bc48e175f2af078a66df97de278cf81 Mon Sep 17 00:00:00 2001 From: Benoit Date: Fri, 12 Apr 2019 15:57:40 +0200 Subject: [PATCH 08/58] [IMP] add tests and support pilbox for thumbnail --- storage_backend_sftp/components/sftp_adapter.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 8b9eb90517..124c401c3e 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -15,7 +15,7 @@ try: import paramiko -except ImportError as err: +except ImportError as err: # pragma: no cover logger.debug(err) @@ -27,7 +27,7 @@ def sftp_mkdirs(client, path, mode=511): sftp_mkdirs(client, os.path.dirname(path), mode=mode) client.mkdir(path, mode) else: - raise + raise # pragma: no cover def load_ssh_key(ssh_key_buffer): @@ -76,7 +76,7 @@ def add(self, relative_path, data, **kwargs): if e.errno == errno.ENOENT: sftp_mkdirs(client, dirname) else: - raise + raise # pragma: no cover remote_file = client.open(full_path, "w+b") remote_file.write(data) remote_file.close() @@ -98,7 +98,7 @@ def list(self, relative_path): # The path do not exist return an empty list return [] else: - raise + raise # pragma: no cover def delete(self, relative_path): full_path = self._fullpath(relative_path) From e5870b8b9c3113b4d68a7242995277c75f9d7f35 Mon Sep 17 00:00:00 2001 From: Denis Roussel Date: Fri, 7 Jun 2019 11:55:47 +0200 Subject: [PATCH 09/58] [12.0] storage*: Make installable False --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index fe0659f55e..eb5981f12d 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -11,7 +11,7 @@ "website": "www.akretion.com", "author": " Akretion", "license": "AGPL-3", - "installable": True, + "installable": False, "external_dependencies": {"python": ["paramiko"]}, "depends": ["storage_backend"], "data": ["views/backend_storage_view.xml"], From ccdae664bc0ebcffd9e9589f88553c3d74b356c8 Mon Sep 17 00:00:00 2001 From: Florian da Costa Date: Thu, 27 Jun 2019 17:03:36 +0200 Subject: [PATCH 10/58] Migrate to storage_backend_sftp to v12 --- storage_backend_sftp/__init__.py | 2 -- storage_backend_sftp/__manifest__.py | 9 ++++----- storage_backend_sftp/components/__init__.py | 2 -- storage_backend_sftp/components/sftp_adapter.py | 6 ++---- storage_backend_sftp/models/__init__.py | 2 -- storage_backend_sftp/models/storage_backend.py | 9 ++++----- storage_backend_sftp/tests/__init__.py | 2 -- storage_backend_sftp/tests/test_sftp.py | 1 - storage_backend_sftp/views/backend_storage_view.xml | 2 +- 9 files changed, 11 insertions(+), 24 deletions(-) diff --git a/storage_backend_sftp/__init__.py b/storage_backend_sftp/__init__.py index 3fbae039c0..0f00a6730d 100644 --- a/storage_backend_sftp/__init__.py +++ b/storage_backend_sftp/__init__.py @@ -1,4 +1,2 @@ -# -*- coding: utf-8 -*- - from . import models from . import components diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index eb5981f12d..57d6164783 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Akretion (http://www.akretion.com). # @author Sébastien BEAU # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -6,12 +5,12 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "10.0.1.0.0", + "version": "12.0.1.0.0", "category": "Storage", - "website": "www.akretion.com", - "author": " Akretion", + "website": "https://github.com/OCA/storage", + "author": " Akretion,Odoo Community Association (OCA)", "license": "AGPL-3", - "installable": False, + "installable": True, "external_dependencies": {"python": ["paramiko"]}, "depends": ["storage_backend"], "data": ["views/backend_storage_view.xml"], diff --git a/storage_backend_sftp/components/__init__.py b/storage_backend_sftp/components/__init__.py index 8bfded8d81..76ddd15267 100644 --- a/storage_backend_sftp/components/__init__.py +++ b/storage_backend_sftp/components/__init__.py @@ -1,3 +1 @@ -# -*- coding: utf-8 -*- - from . import sftp_adapter diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 124c401c3e..4708591353 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Akretion (http://www.akretion.com). # @author Sébastien BEAU # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -7,9 +6,9 @@ import logging import os from contextlib import contextmanager +from io import StringIO from odoo.addons.component.core import Component -from StringIO import StringIO logger = logging.getLogger(__name__) @@ -46,8 +45,7 @@ def load_ssh_key(ssh_key_buffer): @contextmanager def sftp(backend): - account = backend._get_keychain_account() - password = account._get_password() + password = backend.sftp_password transport = paramiko.Transport((backend.sftp_server, backend.sftp_port)) if backend.sftp_auth_method == "pwd": transport.connect(username=backend.sftp_login, password=password) diff --git a/storage_backend_sftp/models/__init__.py b/storage_backend_sftp/models/__init__.py index 4731534aa1..f45f402268 100644 --- a/storage_backend_sftp/models/__init__.py +++ b/storage_backend_sftp/models/__init__.py @@ -1,3 +1 @@ -# -*- coding: utf-8 -*- - from . import storage_backend diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index 6746d43c57..0b2c0f8e69 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Akretion (http://www.akretion.com). # @author Sébastien BEAU # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). @@ -10,12 +9,12 @@ class StorageBackend(models.Model): _inherit = "storage.backend" backend_type = fields.Selection(selection_add=[("sftp", "SFTP")]) - sftp_password = fields.Char(related="password", string="Password") + sftp_password = fields.Char(string="Password") sftp_login = fields.Char( - string="Login", help="Login to connect to sftp server", sparse="data" + string="Login", help="Login to connect to sftp server" ) - sftp_server = fields.Char(string="Host", sparse="data") - sftp_port = fields.Integer(string="Port", default=22, sparse="data") + sftp_server = fields.Char(string="Host") + sftp_port = fields.Integer(string="Port", default=22) sftp_auth_method = fields.Selection( string="Authentification Method", selection=[("pwd", "Password"), ("ssh_key", "Private key")], diff --git a/storage_backend_sftp/tests/__init__.py b/storage_backend_sftp/tests/__init__.py index 4018ddba1f..c923f0a81e 100644 --- a/storage_backend_sftp/tests/__init__.py +++ b/storage_backend_sftp/tests/__init__.py @@ -1,3 +1 @@ -# -*- coding: utf-8 -*- - from . import test_sftp diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index 6faf3637d0..87be088fa3 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Copyright 2017 Akretion (http://www.akretion.com). # @author Sébastien BEAU # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). diff --git a/storage_backend_sftp/views/backend_storage_view.xml b/storage_backend_sftp/views/backend_storage_view.xml index 5f8de8d7d1..0f0f2d1c91 100644 --- a/storage_backend_sftp/views/backend_storage_view.xml +++ b/storage_backend_sftp/views/backend_storage_view.xml @@ -9,7 +9,7 @@ - + From 0f956f110f255e076a8fdb78c3af2a9f0a40e487 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Sun, 15 Sep 2019 19:41:11 +0000 Subject: [PATCH 11/58] [ADD] icon.png --- storage_backend_sftp/static/description/icon.png | Bin 0 -> 9455 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 storage_backend_sftp/static/description/icon.png diff --git a/storage_backend_sftp/static/description/icon.png b/storage_backend_sftp/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 From bc4bffe0b7eee6633bde3d2100475055f3a5c666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul=20=28ACSONE=29?= Date: Tue, 1 Oct 2019 22:35:35 +0200 Subject: [PATCH 12/58] pre-commit, black, isort --- storage_backend_sftp/models/storage_backend.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index 0b2c0f8e69..9f0b918f0d 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -10,9 +10,7 @@ class StorageBackend(models.Model): backend_type = fields.Selection(selection_add=[("sftp", "SFTP")]) sftp_password = fields.Char(string="Password") - sftp_login = fields.Char( - string="Login", help="Login to connect to sftp server" - ) + sftp_login = fields.Char(string="Login", help="Login to connect to sftp server") sftp_server = fields.Char(string="Host") sftp_port = fields.Integer(string="Port", default=22) sftp_auth_method = fields.Selection( From ffc2a695340d683df7912b709ae0102636a1e181 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Fri, 18 Oct 2019 11:06:53 +0000 Subject: [PATCH 13/58] [UPD] Update storage_backend_sftp.pot --- .../i18n/storage_backend_sftp.pot | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 storage_backend_sftp/i18n/storage_backend_sftp.pot diff --git a/storage_backend_sftp/i18n/storage_backend_sftp.pot b/storage_backend_sftp/i18n/storage_backend_sftp.pot new file mode 100644 index 0000000000..7cdaafa676 --- /dev/null +++ b/storage_backend_sftp/i18n/storage_backend_sftp.pot @@ -0,0 +1,72 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * storage_backend_sftp +# +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: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_auth_method +msgid "Authentification Method" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__backend_type +msgid "Backend Type" +msgstr "" + +#. module: storage_backend_sftp +#: selection:storage.backend,backend_type:0 +msgid "Filesystem" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_server +msgid "Host" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login +msgid "Login" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_login +msgid "Login to connect to sftp server" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_password +#: selection:storage.backend,sftp_auth_method:0 +msgid "Password" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_port +msgid "Port" +msgstr "" + +#. module: storage_backend_sftp +#: selection:storage.backend,sftp_auth_method:0 +msgid "Private key" +msgstr "" + +#. module: storage_backend_sftp +#: model_terms:ir.ui.view,arch_db:storage_backend_sftp.storage_backend_view_form +#: selection:storage.backend,backend_type:0 +msgid "SFTP" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model,name:storage_backend_sftp.model_storage_backend +msgid "storage.backend" +msgstr "" + From 112c9d7dae16c3e0249f36f0ae0909feb39fc006 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Wed, 16 Oct 2019 13:21:24 +0200 Subject: [PATCH 14/58] storage_backend_sftp: refactor tests w/ mock --- storage_backend_sftp/README.rst | 1 + .../components/sftp_adapter.py | 1 + storage_backend_sftp/tests/test_sftp.py | 63 +++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/storage_backend_sftp/README.rst b/storage_backend_sftp/README.rst index 11af342fc0..d7bf9c6200 100644 --- a/storage_backend_sftp/README.rst +++ b/storage_backend_sftp/README.rst @@ -35,6 +35,7 @@ Contributors * Sebastien Beau * Raphaël Reverdy * Cédric Pigeon +* Simone Orsi Maintainer diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 4708591353..ca089c0dbe 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -84,6 +84,7 @@ def get(self, relative_path, **kwargs): with sftp(self.collection) as client: file_data = client.open(full_path, "rb") data = file_data.read() + # TODO: shouldn't we close the file? return data def list(self, relative_path): diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index 87be088fa3..6e99fd97cb 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -1,18 +1,26 @@ # Copyright 2017 Akretion (http://www.akretion.com). # @author Sébastien BEAU +# Copyright 2019 Camptocamp (http://www.camptocamp.com). +# @author Simone Orsi # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # pylint: disable=missing-manifest-dependency # disable warning on 'vcr' missing in manifest: this is only a dependency for # dev/tests +import errno import logging import os +import mock + from odoo.addons.storage_backend.tests.common import Common, GenericStoreCase _logger = logging.getLogger(__name__) +MOD_PATH = "odoo.addons.storage_backend_sftp.components.sftp_adapter" +PARAMIKO_PATH = MOD_PATH + ".paramiko" + class SftpCase(Common, GenericStoreCase): def setUp(self): @@ -28,3 +36,58 @@ def setUp(self): } ) self.case_with_subdirectory = "upload/subdirectory/here" + + @mock.patch(MOD_PATH + ".sftp_mkdirs") + @mock.patch(PARAMIKO_PATH) + def test_add(self, mocked_paramiko, mocked_mkdirs): + client = mocked_paramiko.SFTPClient.from_transport() + # simulate errors + exc = IOError() + # general + client.stat.side_effect = exc + with self.assertRaises(IOError): + self.backend._add_bin_data("fake/path", b"fake data") + # not found + exc.errno = errno.ENOENT + client.stat.side_effect = exc + fakefile = open("/tmp/fakefile.txt", "w+b") + client.open.return_value = fakefile + self.backend._add_bin_data("fake/path", b"fake data") + # mkdirs has been called + mocked_mkdirs.assert_called() + # file has been written and closed + self.assertTrue(fakefile.closed) + with open("/tmp/fakefile.txt", "r") as thefile: + self.assertEqual(thefile.read(), "fake data") + + @mock.patch(PARAMIKO_PATH) + def test_get(self, mocked_paramiko): + client = mocked_paramiko.SFTPClient.from_transport() + with open("/tmp/fakefile2.txt", "w+b") as fakefile: + fakefile.write(b"filecontent") + client.open.return_value = open("/tmp/fakefile2.txt", "r") + self.assertEqual(self.backend._get_bin_data("fake/path"), "filecontent") + + @mock.patch(PARAMIKO_PATH) + def test_list(self, mocked_paramiko): + client = mocked_paramiko.SFTPClient.from_transport() + # simulate errors + exc = IOError() + # general + client.listdir.side_effect = exc + with self.assertRaises(IOError): + self.backend._list() + # not found + exc.errno = errno.ENOENT + client.listdir.side_effect = exc + self.assertEqual(self.backend._list(), []) + + def test_setting_and_getting_data_from_root(self): + # bypass as we tested all the methods mocked specifically above. + # Would be nice to have an integration test but is not feasible ATM. + pass + + def test_setting_and_getting_data_from_dir(self): + # bypass as we tested all the methods mocked specifically above + # Would be nice to have an integration test but is not feasible ATM. + pass From 45e6108891537fffe4112fe3f0c74f107b11d0d8 Mon Sep 17 00:00:00 2001 From: "Laurent Mignon (ACSONE)" Date: Mon, 21 Oct 2019 14:25:18 +0200 Subject: [PATCH 15/58] 13.0: Create branche --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 57d6164783..b9fc92574b 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -10,7 +10,7 @@ "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", "license": "AGPL-3", - "installable": True, + "installable": False, "external_dependencies": {"python": ["paramiko"]}, "depends": ["storage_backend"], "data": ["views/backend_storage_view.xml"], From 307c556854b14244a2d94af6d7a90db3c9a4a561 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Mon, 4 Nov 2019 15:12:52 +0000 Subject: [PATCH 16/58] [UPD] Update storage_backend_sftp.pot --- storage_backend_sftp/i18n/storage_backend_sftp.pot | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/storage_backend_sftp/i18n/storage_backend_sftp.pot b/storage_backend_sftp/i18n/storage_backend_sftp.pot index 7cdaafa676..576348c41a 100644 --- a/storage_backend_sftp/i18n/storage_backend_sftp.pot +++ b/storage_backend_sftp/i18n/storage_backend_sftp.pot @@ -13,6 +13,11 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" +#. module: storage_backend_sftp +#: selection:storage.backend,backend_type:0 +msgid "Amazon S3" +msgstr "" + #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_auth_method msgid "Authentification Method" From 76cf2249d368462ba57e70071ac3406f085b90e2 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 22 Nov 2019 16:05:45 +0100 Subject: [PATCH 17/58] Fix runbot warning on clashing labels --- storage_backend_sftp/models/storage_backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index 9f0b918f0d..4703bad590 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -11,7 +11,7 @@ class StorageBackend(models.Model): backend_type = fields.Selection(selection_add=[("sftp", "SFTP")]) sftp_password = fields.Char(string="Password") sftp_login = fields.Char(string="Login", help="Login to connect to sftp server") - sftp_server = fields.Char(string="Host") + sftp_server = fields.Char(string="SFTP Host") sftp_port = fields.Integer(string="Port", default=22) sftp_auth_method = fields.Selection( string="Authentification Method", From 31e30ccdaa49a4bfa90615d3fe3e4c49977b2cef Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 22 Nov 2019 18:31:41 +0100 Subject: [PATCH 18/58] Add server_env support --- storage_backend_sftp/models/storage_backend.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index 4703bad590..823083d4ef 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -1,5 +1,7 @@ # Copyright 2017 Akretion (http://www.akretion.com). # @author Sébastien BEAU +# Copyright 2019 Camptocamp SA (http://www.camptocamp.com). +# @author Simone Orsi # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import fields, models @@ -19,3 +21,17 @@ class StorageBackend(models.Model): default="pwd", required=True, ) + + @property + def _server_env_fields(self): + env_fields = super()._server_env_fields + env_fields.update( + { + "sftp_password": {}, + "sftp_login": {}, + "sftp_server": {}, + "sftp_port": {}, + "sftp_auth_method": {}, + } + ) + return env_fields From b2f242b348143e5b424fb14d50e4fbc71024ac20 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Mon, 25 Nov 2019 09:49:39 +0000 Subject: [PATCH 19/58] [UPD] Update storage_backend_sftp.pot --- storage_backend_sftp/i18n/storage_backend_sftp.pot | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/storage_backend_sftp/i18n/storage_backend_sftp.pot b/storage_backend_sftp/i18n/storage_backend_sftp.pot index 576348c41a..bd7e2e856a 100644 --- a/storage_backend_sftp/i18n/storage_backend_sftp.pot +++ b/storage_backend_sftp/i18n/storage_backend_sftp.pot @@ -33,11 +33,6 @@ msgstr "" msgid "Filesystem" msgstr "" -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_server -msgid "Host" -msgstr "" - #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login msgid "Login" @@ -70,6 +65,11 @@ msgstr "" msgid "SFTP" msgstr "" +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_server +msgid "SFTP Host" +msgstr "" + #. module: storage_backend_sftp #: model:ir.model,name:storage_backend_sftp.model_storage_backend msgid "storage.backend" From 6ce1f22b4e0192c7f543ceffdaaa81c263ab6704 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 25 Nov 2019 09:56:55 +0000 Subject: [PATCH 20/58] storage_backend_sftp 12.0.2.0.0 --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index b9fc92574b..42e9cbb7ab 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "12.0.1.0.0", + "version": "12.0.2.0.0", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From f918242ec384b2c1a3406ed4019dee52526e0ddb Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 17 Jan 2020 16:00:03 +0100 Subject: [PATCH 21/58] [REF] storage_backend_sftp: Black python code --- storage_backend_sftp/models/storage_backend.py | 4 +++- storage_backend_sftp/tests/test_sftp.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index 823083d4ef..83e384793a 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -12,7 +12,9 @@ class StorageBackend(models.Model): backend_type = fields.Selection(selection_add=[("sftp", "SFTP")]) sftp_password = fields.Char(string="Password") - sftp_login = fields.Char(string="Login", help="Login to connect to sftp server") + sftp_login = fields.Char( + string="Login", help="Login to connect to sftp server" + ) sftp_server = fields.Char(string="SFTP Host") sftp_port = fields.Integer(string="Port", default=22) sftp_auth_method = fields.Selection( diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index 6e99fd97cb..b019d3b28b 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -66,7 +66,9 @@ def test_get(self, mocked_paramiko): with open("/tmp/fakefile2.txt", "w+b") as fakefile: fakefile.write(b"filecontent") client.open.return_value = open("/tmp/fakefile2.txt", "r") - self.assertEqual(self.backend._get_bin_data("fake/path"), "filecontent") + self.assertEqual( + self.backend._get_bin_data("fake/path"), "filecontent" + ) @mock.patch(PARAMIKO_PATH) def test_list(self, mocked_paramiko): From ae0d243d2fee0c7ef97b19a786170ccd4377bf7a Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 17 Jan 2020 16:00:04 +0100 Subject: [PATCH 22/58] [MIG] storage_backend_sftp: Migration to 13.0 --- storage_backend_sftp/__manifest__.py | 4 ++-- storage_backend_sftp/tests/test_sftp.py | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 42e9cbb7ab..d022e54186 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,12 +5,12 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "12.0.2.0.0", + "version": "13.0.1.0.0", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", "license": "AGPL-3", - "installable": False, + "installable": True, "external_dependencies": {"python": ["paramiko"]}, "depends": ["storage_backend"], "data": ["views/backend_storage_view.xml"], diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index b019d3b28b..bf99bdc4fc 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -23,9 +23,10 @@ class SftpCase(Common, GenericStoreCase): - def setUp(self): - super(SftpCase, self).setUp() - self.backend.write( + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.backend.write( { "backend_type": "sftp", "sftp_login": "foo", @@ -35,7 +36,7 @@ def setUp(self): "directory_path": "upload", } ) - self.case_with_subdirectory = "upload/subdirectory/here" + cls.case_with_subdirectory = "upload/subdirectory/here" @mock.patch(MOD_PATH + ".sftp_mkdirs") @mock.patch(PARAMIKO_PATH) From 8b9d429117f8ea5887747dd3de098a28161c22be Mon Sep 17 00:00:00 2001 From: oca-travis Date: Mon, 8 Jun 2020 08:29:33 +0000 Subject: [PATCH 23/58] [UPD] Update storage_backend_sftp.pot --- .../i18n/storage_backend_sftp.pot | 25 ++++++------------- 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/storage_backend_sftp/i18n/storage_backend_sftp.pot b/storage_backend_sftp/i18n/storage_backend_sftp.pot index bd7e2e856a..86a0cc9652 100644 --- a/storage_backend_sftp/i18n/storage_backend_sftp.pot +++ b/storage_backend_sftp/i18n/storage_backend_sftp.pot @@ -1,23 +1,18 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * storage_backend_sftp +# * storage_backend_sftp # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 12.0\n" +"Project-Id-Version: Odoo Server 13.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" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" -#. module: storage_backend_sftp -#: selection:storage.backend,backend_type:0 -msgid "Amazon S3" -msgstr "" - #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_auth_method msgid "Authentification Method" @@ -28,11 +23,6 @@ msgstr "" msgid "Backend Type" msgstr "" -#. module: storage_backend_sftp -#: selection:storage.backend,backend_type:0 -msgid "Filesystem" -msgstr "" - #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login msgid "Login" @@ -45,7 +35,7 @@ msgstr "" #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_password -#: selection:storage.backend,sftp_auth_method:0 +#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__pwd msgid "Password" msgstr "" @@ -55,13 +45,13 @@ msgid "Port" msgstr "" #. module: storage_backend_sftp -#: selection:storage.backend,sftp_auth_method:0 +#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__ssh_key msgid "Private key" msgstr "" #. module: storage_backend_sftp +#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__backend_type__sftp #: model_terms:ir.ui.view,arch_db:storage_backend_sftp.storage_backend_view_form -#: selection:storage.backend,backend_type:0 msgid "SFTP" msgstr "" @@ -72,6 +62,5 @@ msgstr "" #. module: storage_backend_sftp #: model:ir.model,name:storage_backend_sftp.model_storage_backend -msgid "storage.backend" +msgid "Storage Backend" msgstr "" - From 87988fe1344d5935b8e789136efb25d29e148525 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 19 Jun 2020 11:58:10 +0200 Subject: [PATCH 24/58] storage_backend_sftp: add conn validation --- storage_backend_sftp/components/sftp_adapter.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index ca089c0dbe..8abada0716 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -7,7 +7,6 @@ import os from contextlib import contextmanager from io import StringIO - from odoo.addons.component.core import Component logger = logging.getLogger(__name__) @@ -103,3 +102,7 @@ def delete(self, relative_path): full_path = self._fullpath(relative_path) with sftp(self.collection) as client: return client.remove(full_path) + + def validate_config(self): + with sftp(self.collection) as client: + client.listdir() From b9fd9dd0754b83bfebe9ad779fa6b0d060bc1bef Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Fri, 19 Jun 2020 14:09:57 +0200 Subject: [PATCH 25/58] storage_backend_sftp: fix SSH key auth For the SSH key a text field is required. The Char field elininates all newline chars making the key invalid. --- storage_backend_sftp/components/sftp_adapter.py | 5 ++--- storage_backend_sftp/models/storage_backend.py | 15 +++++++++++---- .../views/backend_storage_view.xml | 7 +++++-- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 8abada0716..761781b989 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -44,12 +44,11 @@ def load_ssh_key(ssh_key_buffer): @contextmanager def sftp(backend): - password = backend.sftp_password transport = paramiko.Transport((backend.sftp_server, backend.sftp_port)) if backend.sftp_auth_method == "pwd": - transport.connect(username=backend.sftp_login, password=password) + transport.connect(username=backend.sftp_login, password=backend.sftp_password) elif backend.sftp_auth_method == "ssh_key": - ssh_key_buffer = StringIO(password) + ssh_key_buffer = StringIO(backend.sftp_ssh_private_key) private_key = load_ssh_key(ssh_key_buffer) transport.connect(username=backend.sftp_login, pkey=private_key) client = paramiko.SFTPClient.from_transport(transport) diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index 83e384793a..dec24bb898 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -11,10 +11,6 @@ class StorageBackend(models.Model): _inherit = "storage.backend" backend_type = fields.Selection(selection_add=[("sftp", "SFTP")]) - sftp_password = fields.Char(string="Password") - sftp_login = fields.Char( - string="Login", help="Login to connect to sftp server" - ) sftp_server = fields.Char(string="SFTP Host") sftp_port = fields.Integer(string="Port", default=22) sftp_auth_method = fields.Selection( @@ -23,6 +19,16 @@ class StorageBackend(models.Model): default="pwd", required=True, ) + sftp_login = fields.Char( + string="Login", help="Login to connect to sftp server" + ) + sftp_password = fields.Char(string="Password") + sftp_ssh_private_key = fields.Text( + string="SSH private key", + help="It's recommended to not store the key here " + "but to provide it via secret env variable. " + "See `server_environment` docs." + ) @property def _server_env_fields(self): @@ -34,6 +40,7 @@ def _server_env_fields(self): "sftp_server": {}, "sftp_port": {}, "sftp_auth_method": {}, + "sftp_ssh_private_key": {}, } ) return env_fields diff --git a/storage_backend_sftp/views/backend_storage_view.xml b/storage_backend_sftp/views/backend_storage_view.xml index 0f0f2d1c91..257e19d3ff 100644 --- a/storage_backend_sftp/views/backend_storage_view.xml +++ b/storage_backend_sftp/views/backend_storage_view.xml @@ -8,9 +8,12 @@ - - + + + From 6b91e65c1491406f048dc97e4ce5f35f5b86be02 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Thu, 2 Jul 2020 06:39:41 +0000 Subject: [PATCH 26/58] [UPD] Update storage_backend_sftp.pot --- storage_backend_sftp/i18n/storage_backend_sftp.pot | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/storage_backend_sftp/i18n/storage_backend_sftp.pot b/storage_backend_sftp/i18n/storage_backend_sftp.pot index 86a0cc9652..1f4aa7b054 100644 --- a/storage_backend_sftp/i18n/storage_backend_sftp.pot +++ b/storage_backend_sftp/i18n/storage_backend_sftp.pot @@ -23,6 +23,13 @@ msgstr "" msgid "Backend Type" msgstr "" +#. module: storage_backend_sftp +#: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key +msgid "" +"It's recommended to not store the key here but to provide it via secret env " +"variable. See `server_environment` docs." +msgstr "" + #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login msgid "Login" @@ -60,6 +67,11 @@ msgstr "" msgid "SFTP Host" msgstr "" +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key +msgid "SSH private key" +msgstr "" + #. module: storage_backend_sftp #: model:ir.model,name:storage_backend_sftp.model_storage_backend msgid "Storage Backend" From c7a2fdc3ac3911a1c074b9656e5c2db115403995 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 2 Jul 2020 06:45:45 +0000 Subject: [PATCH 27/58] storage_backend_sftp 13.0.1.1.0 --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index d022e54186..6256cdc485 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "13.0.1.0.0", + "version": "13.0.1.1.0", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From d0854d110ddf156164c20f657d65262683018ea8 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 29 Oct 2020 11:51:40 +0100 Subject: [PATCH 28/58] storage_backend: run permission tests explicitely --- storage_backend_sftp/tests/test_sftp.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index bf99bdc4fc..f5b5574994 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -14,7 +14,7 @@ import mock -from odoo.addons.storage_backend.tests.common import Common, GenericStoreCase +from odoo.addons.storage_backend.tests.common import CommonCase, BackendStorageTestMixin _logger = logging.getLogger(__name__) @@ -22,7 +22,8 @@ PARAMIKO_PATH = MOD_PATH + ".paramiko" -class SftpCase(Common, GenericStoreCase): +class SftpCase(CommonCase, BackendStorageTestMixin): + @classmethod def setUpClass(cls): super().setUpClass() @@ -85,12 +86,3 @@ def test_list(self, mocked_paramiko): client.listdir.side_effect = exc self.assertEqual(self.backend._list(), []) - def test_setting_and_getting_data_from_root(self): - # bypass as we tested all the methods mocked specifically above. - # Would be nice to have an integration test but is not feasible ATM. - pass - - def test_setting_and_getting_data_from_dir(self): - # bypass as we tested all the methods mocked specifically above - # Would be nice to have an integration test but is not feasible ATM. - pass From 38373e20ed3ac0a80d2bee9c73f8360e6a79e76c Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 29 Oct 2020 08:27:07 +0100 Subject: [PATCH 29/58] storage_backend_sftp: support adapter.move_files --- .../components/sftp_adapter.py | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 761781b989..81fba874fb 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -1,7 +1,10 @@ # Copyright 2017 Akretion (http://www.akretion.com). # @author Sébastien BEAU +# Copyright 2019 Camptocamp SA (http://www.camptocamp.com). +# Copyright 2020 ACSONE SA/NV () +# @author Simone Orsi # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). - +import re import errno import logging import os @@ -9,12 +12,12 @@ from io import StringIO from odoo.addons.component.core import Component -logger = logging.getLogger(__name__) +_logger = logging.getLogger(__name__) try: import paramiko except ImportError as err: # pragma: no cover - logger.debug(err) + _logger.debug(err) def sftp_mkdirs(client, path, mode=511): @@ -97,6 +100,22 @@ def list(self, relative_path): else: raise # pragma: no cover + def move_files(self, files, destination_path): + _logger.debug('mv %s %s', files, destination_path) + with sftp(self.collection) as client: + for sftp_file in files: + dest_file_path = os.path.join(destination_path, os.path.basename(sftp_file)) + # Remove existing file at the destination path (an error is raised + # otherwise) + try: + client.lstat(dest_file_path) + except FileNotFoundError: + _logger.debug("destination %s is free", dest_file_path) + else: + client.unlink(dest_file_path) + # Move the file + client.rename(sftp_file, dest_file_path) + def delete(self, relative_path): full_path = self._fullpath(relative_path) with sftp(self.collection) as client: From a3c9b64e7939f962bc00c4c83947ca112057e1ea Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 29 Oct 2020 12:46:35 +0100 Subject: [PATCH 30/58] storage_backend|_sftp: add test for find_files --- storage_backend_sftp/components/sftp_adapter.py | 2 +- storage_backend_sftp/tests/test_sftp.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 81fba874fb..f9e4f15445 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -59,7 +59,7 @@ def sftp(backend): transport.close() -class SftpStorageBackend(Component): +class SFTPStorageBackendAdapter(Component): _name = "sftp.adapter" _inherit = "base.storage.adapter" _usage = "sftp" diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index f5b5574994..d92b52e8c7 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -19,6 +19,7 @@ _logger = logging.getLogger(__name__) MOD_PATH = "odoo.addons.storage_backend_sftp.components.sftp_adapter" +ADAPTER_PATH = MOD_PATH + ".SFTPStorageBackendAdapter" PARAMIKO_PATH = MOD_PATH + ".paramiko" @@ -86,3 +87,17 @@ def test_list(self, mocked_paramiko): client.listdir.side_effect = exc self.assertEqual(self.backend._list(), []) + def test_find_files(self): + good_filepaths = [ + "somepath/file%d.good" % x for x in range(1, 10) + ] + bad_filepaths = [ + "somepath/file%d.bad" % x for x in range(1, 10) + ] + mocked_filepaths = bad_filepaths + good_filepaths + backend = self.backend.sudo() + expected = good_filepaths[:] + expected = [ + backend.directory_path + "/" + path for path in good_filepaths + ] + self._test_find_files(backend, ADAPTER_PATH, mocked_filepaths, r".*\.good$", expected) From 7a702919735f4c9b2559d8f7aba56778d33d5a9c Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Thu, 29 Oct 2020 13:49:14 +0100 Subject: [PATCH 31/58] storage_backend_sftp: add test for move_files --- storage_backend_sftp/tests/test_sftp.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index d92b52e8c7..0c55029e7a 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -101,3 +101,24 @@ def test_find_files(self): backend.directory_path + "/" + path for path in good_filepaths ] self._test_find_files(backend, ADAPTER_PATH, mocked_filepaths, r".*\.good$", expected) + + @mock.patch(PARAMIKO_PATH) + def test_move_files(self, mocked_paramiko): + client = mocked_paramiko.SFTPClient.from_transport() + # simulate file is not already there + client.lstat.side_effect = FileNotFoundError() + to_move = "move/from/path/myfile.txt" + to_path = "move/to/path" + self.backend._move_files([to_move], to_path) + # no need to delete it + client.unlink.assert_not_called() + # rename gets called + client.rename.assert_called_with(to_move, to_move.replace("from", "to")) + # now try to override destination + client.lstat.side_effect = None + client.lstat.return_value = True + self.backend._move_files([to_move], to_path) + # client will delete it first + client.unlink.assert_called_with(to_move.replace("from", "to")) + # then move it + client.rename.assert_called_with(to_move, to_move.replace("from", "to")) From 1be7e3fc770dfd63094c994d185604b999719368 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Mon, 23 Nov 2020 08:55:46 +0100 Subject: [PATCH 32/58] storage_backend_sftp bump 13.0.1.2.0 --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 6256cdc485..36662231be 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "13.0.1.1.0", + "version": "13.0.1.2.0", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From a40b28ee45b4db0b72e7c2ddcb03e90c9113aa68 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Tue, 24 Nov 2020 15:32:18 +0100 Subject: [PATCH 33/58] storage_backend_sftp: use public api --- storage_backend_sftp/tests/test_sftp.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index 0c55029e7a..61286e9269 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -49,13 +49,13 @@ def test_add(self, mocked_paramiko, mocked_mkdirs): # general client.stat.side_effect = exc with self.assertRaises(IOError): - self.backend._add_bin_data("fake/path", b"fake data") + self.backend.add("fake/path", b"fake data") # not found exc.errno = errno.ENOENT client.stat.side_effect = exc fakefile = open("/tmp/fakefile.txt", "w+b") client.open.return_value = fakefile - self.backend._add_bin_data("fake/path", b"fake data") + self.backend.add("fake/path", b"fake data") # mkdirs has been called mocked_mkdirs.assert_called() # file has been written and closed @@ -70,7 +70,7 @@ def test_get(self, mocked_paramiko): fakefile.write(b"filecontent") client.open.return_value = open("/tmp/fakefile2.txt", "r") self.assertEqual( - self.backend._get_bin_data("fake/path"), "filecontent" + self.backend.get("fake/path"), "filecontent" ) @mock.patch(PARAMIKO_PATH) @@ -81,11 +81,11 @@ def test_list(self, mocked_paramiko): # general client.listdir.side_effect = exc with self.assertRaises(IOError): - self.backend._list() + self.backend.list_files() # not found exc.errno = errno.ENOENT client.listdir.side_effect = exc - self.assertEqual(self.backend._list(), []) + self.assertEqual(self.backend.list_files(), []) def test_find_files(self): good_filepaths = [ @@ -109,7 +109,7 @@ def test_move_files(self, mocked_paramiko): client.lstat.side_effect = FileNotFoundError() to_move = "move/from/path/myfile.txt" to_path = "move/to/path" - self.backend._move_files([to_move], to_path) + self.backend.move_files([to_move], to_path) # no need to delete it client.unlink.assert_not_called() # rename gets called @@ -117,7 +117,7 @@ def test_move_files(self, mocked_paramiko): # now try to override destination client.lstat.side_effect = None client.lstat.return_value = True - self.backend._move_files([to_move], to_path) + self.backend.move_files([to_move], to_path) # client will delete it first client.unlink.assert_called_with(to_move.replace("from", "to")) # then move it From 4208a33a402102b43ff1c65f05701fe9fdc06ed1 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 25 Nov 2020 13:55:26 +0000 Subject: [PATCH 34/58] storage_backend_sftp 13.0.1.3.0 --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 36662231be..80eef04279 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "13.0.1.2.0", + "version": "13.0.1.3.0", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From 1150ba2b97835fb9d9d1eb4255e9566cc102c0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Sun, 6 Dec 2020 09:53:40 +0100 Subject: [PATCH 35/58] [ADD] add new V14 config --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 80eef04279..8f0997e267 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -10,7 +10,7 @@ "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", "license": "AGPL-3", - "installable": True, + "installable": False, "external_dependencies": {"python": ["paramiko"]}, "depends": ["storage_backend"], "data": ["views/backend_storage_view.xml"], From 113ba7ad4b307f80668befc3839842112b348007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Sun, 6 Dec 2020 10:10:22 +0100 Subject: [PATCH 36/58] [IMP] all: black, isort, prettier --- storage_backend_sftp/__manifest__.py | 2 +- .../components/sftp_adapter.py | 8 +++-- .../models/storage_backend.py | 8 ++--- storage_backend_sftp/tests/test_sftp.py | 27 +++++++---------- .../views/backend_storage_view.xml | 30 ++++++++++++------- 5 files changed, 39 insertions(+), 36 deletions(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 8f0997e267..80eef04279 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -10,7 +10,7 @@ "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", "license": "AGPL-3", - "installable": False, + "installable": True, "external_dependencies": {"python": ["paramiko"]}, "depends": ["storage_backend"], "data": ["views/backend_storage_view.xml"], diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index f9e4f15445..3a9f4cf1b6 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -4,12 +4,12 @@ # Copyright 2020 ACSONE SA/NV () # @author Simone Orsi # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -import re import errno import logging import os from contextlib import contextmanager from io import StringIO + from odoo.addons.component.core import Component _logger = logging.getLogger(__name__) @@ -101,10 +101,12 @@ def list(self, relative_path): raise # pragma: no cover def move_files(self, files, destination_path): - _logger.debug('mv %s %s', files, destination_path) + _logger.debug("mv %s %s", files, destination_path) with sftp(self.collection) as client: for sftp_file in files: - dest_file_path = os.path.join(destination_path, os.path.basename(sftp_file)) + dest_file_path = os.path.join( + destination_path, os.path.basename(sftp_file) + ) # Remove existing file at the destination path (an error is raised # otherwise) try: diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index dec24bb898..9e1066d1e2 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -19,15 +19,13 @@ class StorageBackend(models.Model): default="pwd", required=True, ) - sftp_login = fields.Char( - string="Login", help="Login to connect to sftp server" - ) + sftp_login = fields.Char(string="Login", help="Login to connect to sftp server") sftp_password = fields.Char(string="Password") sftp_ssh_private_key = fields.Text( string="SSH private key", help="It's recommended to not store the key here " - "but to provide it via secret env variable. " - "See `server_environment` docs." + "but to provide it via secret env variable. " + "See `server_environment` docs.", ) @property diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index 61286e9269..5e9fce21a7 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -14,17 +14,16 @@ import mock -from odoo.addons.storage_backend.tests.common import CommonCase, BackendStorageTestMixin +from odoo.addons.storage_backend.tests.common import BackendStorageTestMixin, CommonCase _logger = logging.getLogger(__name__) MOD_PATH = "odoo.addons.storage_backend_sftp.components.sftp_adapter" -ADAPTER_PATH = MOD_PATH + ".SFTPStorageBackendAdapter" +ADAPTER_PATH = MOD_PATH + ".SFTPStorageBackendAdapter" PARAMIKO_PATH = MOD_PATH + ".paramiko" class SftpCase(CommonCase, BackendStorageTestMixin): - @classmethod def setUpClass(cls): super().setUpClass() @@ -69,9 +68,7 @@ def test_get(self, mocked_paramiko): with open("/tmp/fakefile2.txt", "w+b") as fakefile: fakefile.write(b"filecontent") client.open.return_value = open("/tmp/fakefile2.txt", "r") - self.assertEqual( - self.backend.get("fake/path"), "filecontent" - ) + self.assertEqual(self.backend.get("fake/path"), "filecontent") @mock.patch(PARAMIKO_PATH) def test_list(self, mocked_paramiko): @@ -88,19 +85,15 @@ def test_list(self, mocked_paramiko): self.assertEqual(self.backend.list_files(), []) def test_find_files(self): - good_filepaths = [ - "somepath/file%d.good" % x for x in range(1, 10) - ] - bad_filepaths = [ - "somepath/file%d.bad" % x for x in range(1, 10) - ] + good_filepaths = ["somepath/file%d.good" % x for x in range(1, 10)] + bad_filepaths = ["somepath/file%d.bad" % x for x in range(1, 10)] mocked_filepaths = bad_filepaths + good_filepaths backend = self.backend.sudo() expected = good_filepaths[:] - expected = [ - backend.directory_path + "/" + path for path in good_filepaths - ] - self._test_find_files(backend, ADAPTER_PATH, mocked_filepaths, r".*\.good$", expected) + expected = [backend.directory_path + "/" + path for path in good_filepaths] + self._test_find_files( + backend, ADAPTER_PATH, mocked_filepaths, r".*\.good$", expected + ) @mock.patch(PARAMIKO_PATH) def test_move_files(self, mocked_paramiko): @@ -116,7 +109,7 @@ def test_move_files(self, mocked_paramiko): client.rename.assert_called_with(to_move, to_move.replace("from", "to")) # now try to override destination client.lstat.side_effect = None - client.lstat.return_value = True + client.lstat.return_value = True self.backend.move_files([to_move], to_path) # client will delete it first client.unlink.assert_called_with(to_move.replace("from", "to")) diff --git a/storage_backend_sftp/views/backend_storage_view.xml b/storage_backend_sftp/views/backend_storage_view.xml index 257e19d3ff..341631ffda 100644 --- a/storage_backend_sftp/views/backend_storage_view.xml +++ b/storage_backend_sftp/views/backend_storage_view.xml @@ -1,19 +1,29 @@ - + storage.backend - - - - - - - + + + + + + + From a40653ef0793be23af5af0692c566f07e0ae43e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Sun, 6 Dec 2020 10:17:45 +0100 Subject: [PATCH 37/58] [MIG] batch migration of modules --- storage_backend_sftp/__manifest__.py | 2 +- storage_backend_sftp/models/storage_backend.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 80eef04279..76e2606278 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "13.0.1.3.0", + "version": "14.0.1.0.0", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index 9e1066d1e2..e3dd5328b1 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -10,7 +10,9 @@ class StorageBackend(models.Model): _inherit = "storage.backend" - backend_type = fields.Selection(selection_add=[("sftp", "SFTP")]) + backend_type = fields.Selection( + selection_add=[("sftp", "SFTP")], ondelete={"sftp": "set default"} + ) sftp_server = fields.Char(string="SFTP Host") sftp_port = fields.Integer(string="Port", default=22) sftp_auth_method = fields.Selection( From 308f8f550e85f2b7c3aae70001d642051c871800 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 1 Mar 2021 12:20:27 +0000 Subject: [PATCH 38/58] storage_backend_sftp 14.0.1.0.1 --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 76e2606278..4eebad05a7 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "14.0.1.0.0", + "version": "14.0.1.0.1", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From 504cff7acd03e833ce04b2c5a17e5998fcd5cab2 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Wed, 9 Jun 2021 19:07:12 +0000 Subject: [PATCH 39/58] [UPD] Update storage_backend_sftp.pot --- .../i18n/storage_backend_sftp.pot | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/storage_backend_sftp/i18n/storage_backend_sftp.pot b/storage_backend_sftp/i18n/storage_backend_sftp.pot index 1f4aa7b054..b112fb8c64 100644 --- a/storage_backend_sftp/i18n/storage_backend_sftp.pot +++ b/storage_backend_sftp/i18n/storage_backend_sftp.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 13.0\n" +"Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" @@ -23,6 +23,16 @@ msgstr "" msgid "Backend Type" msgstr "" +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__display_name +msgid "Display Name" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__id +msgid "ID" +msgstr "" + #. module: storage_backend_sftp #: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key msgid "" @@ -30,6 +40,11 @@ msgid "" "variable. See `server_environment` docs." msgstr "" +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend____last_update +msgid "Last Modified on" +msgstr "" + #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login msgid "Login" From c94f08f83843c8687ae41783bf6f49d86ba132d7 Mon Sep 17 00:00:00 2001 From: Enric Tobella Date: Wed, 10 Mar 2021 15:36:45 +0100 Subject: [PATCH 40/58] [CHG] storage: Use more permissive licence: AGPL-> LGPL --- storage_backend_sftp/README.rst | 6 +++--- storage_backend_sftp/__manifest__.py | 4 ++-- storage_backend_sftp/components/sftp_adapter.py | 2 +- storage_backend_sftp/models/storage_backend.py | 2 +- storage_backend_sftp/tests/test_sftp.py | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/storage_backend_sftp/README.rst b/storage_backend_sftp/README.rst index d7bf9c6200..9f082d8cca 100644 --- a/storage_backend_sftp/README.rst +++ b/storage_backend_sftp/README.rst @@ -1,7 +1,7 @@ -.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg - :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html - :alt: License: AGPL-3 +.. image:: https://img.shields.io/badge/licence-LGPL--3-blue.svg + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 ===================== Storage backend SFTP diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 4eebad05a7..3f05985544 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -1,6 +1,6 @@ # Copyright 2017 Akretion (http://www.akretion.com). # @author Sébastien BEAU -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). { "name": "Storage Backend SFTP", @@ -9,7 +9,7 @@ "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", - "license": "AGPL-3", + "license": "LGPL-3", "installable": True, "external_dependencies": {"python": ["paramiko"]}, "depends": ["storage_backend"], diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 3a9f4cf1b6..a553d07943 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -3,7 +3,7 @@ # Copyright 2019 Camptocamp SA (http://www.camptocamp.com). # Copyright 2020 ACSONE SA/NV () # @author Simone Orsi -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). import errno import logging import os diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index e3dd5328b1..f63d11b365 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -2,7 +2,7 @@ # @author Sébastien BEAU # Copyright 2019 Camptocamp SA (http://www.camptocamp.com). # @author Simone Orsi -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). from odoo import fields, models diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index 5e9fce21a7..c99a6a1dd5 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -2,7 +2,7 @@ # @author Sébastien BEAU # Copyright 2019 Camptocamp (http://www.camptocamp.com). # @author Simone Orsi -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). # pylint: disable=missing-manifest-dependency # disable warning on 'vcr' missing in manifest: this is only a dependency for From 4f6a7dcb44a9213f988aeceb512a62c6ce94f1a1 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 2 Aug 2021 18:42:30 +0000 Subject: [PATCH 41/58] storage_backend_sftp 14.0.2.0.0 --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 3f05985544..b1b1ae7bd0 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "14.0.1.0.1", + "version": "14.0.2.0.0", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From 50dd05069630195e5edd41b88b2fcf2fd5cb0506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Honor=C3=A9?= Date: Sat, 10 Jul 2021 18:20:57 +0200 Subject: [PATCH 42/58] [13.0][ADD] storage_backend_ftp --- storage_backend_sftp/models/storage_backend.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/storage_backend_sftp/models/storage_backend.py b/storage_backend_sftp/models/storage_backend.py index f63d11b365..f79870fbc6 100644 --- a/storage_backend_sftp/models/storage_backend.py +++ b/storage_backend_sftp/models/storage_backend.py @@ -14,15 +14,17 @@ class StorageBackend(models.Model): selection_add=[("sftp", "SFTP")], ondelete={"sftp": "set default"} ) sftp_server = fields.Char(string="SFTP Host") - sftp_port = fields.Integer(string="Port", default=22) + sftp_port = fields.Integer(string="SFTP Port", default=22) sftp_auth_method = fields.Selection( - string="Authentification Method", + string="SFTP Authentification Method", selection=[("pwd", "Password"), ("ssh_key", "Private key")], default="pwd", required=True, ) - sftp_login = fields.Char(string="Login", help="Login to connect to sftp server") - sftp_password = fields.Char(string="Password") + sftp_login = fields.Char( + string="SFTP Login", help="Login to connect to sftp server" + ) + sftp_password = fields.Char(string="SFTP Password") sftp_ssh_private_key = fields.Text( string="SSH private key", help="It's recommended to not store the key here " From 6f8052b00b743f328b34ddeace6b664c793f37a7 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Tue, 30 Nov 2021 15:01:09 +0000 Subject: [PATCH 43/58] [UPD] Update storage_backend_sftp.pot --- .../i18n/storage_backend_sftp.pot | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/storage_backend_sftp/i18n/storage_backend_sftp.pot b/storage_backend_sftp/i18n/storage_backend_sftp.pot index b112fb8c64..63229d9144 100644 --- a/storage_backend_sftp/i18n/storage_backend_sftp.pot +++ b/storage_backend_sftp/i18n/storage_backend_sftp.pot @@ -13,11 +13,6 @@ msgstr "" "Content-Transfer-Encoding: \n" "Plural-Forms: \n" -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_auth_method -msgid "Authentification Method" -msgstr "" - #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__backend_type msgid "Backend Type" @@ -45,27 +40,16 @@ msgstr "" msgid "Last Modified on" msgstr "" -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login -msgid "Login" -msgstr "" - #. module: storage_backend_sftp #: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_login msgid "Login to connect to sftp server" msgstr "" #. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_password #: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__pwd msgid "Password" msgstr "" -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_port -msgid "Port" -msgstr "" - #. module: storage_backend_sftp #: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__ssh_key msgid "Private key" @@ -77,11 +61,31 @@ msgstr "" msgid "SFTP" msgstr "" +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_auth_method +msgid "SFTP Authentification Method" +msgstr "" + #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_server msgid "SFTP Host" msgstr "" +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login +msgid "SFTP Login" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_password +msgid "SFTP Password" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_port +msgid "SFTP Port" +msgstr "" + #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key msgid "SSH private key" From cbc13938b801edce1a93768239f3ea338bcbe346 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 30 Nov 2021 15:21:34 +0000 Subject: [PATCH 44/58] storage_backend_sftp 14.0.2.0.1 --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index b1b1ae7bd0..30142ceab3 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "14.0.2.0.0", + "version": "14.0.2.0.1", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From 6e5400f6c210fb4f56dd36e31a07d1886f1e3a3b Mon Sep 17 00:00:00 2001 From: Iryna Vyshnevska Date: Mon, 6 Dec 2021 00:37:04 +0200 Subject: [PATCH 45/58] [MIG][15.0] storage_backend_sftp --- storage_backend_sftp/__manifest__.py | 2 +- .../i18n/storage_backend_sftp.pot | 97 ------------------- 2 files changed, 1 insertion(+), 98 deletions(-) delete mode 100644 storage_backend_sftp/i18n/storage_backend_sftp.pot diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 30142ceab3..380b269ef2 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "14.0.2.0.1", + "version": "15.0.1.0.0", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", diff --git a/storage_backend_sftp/i18n/storage_backend_sftp.pot b/storage_backend_sftp/i18n/storage_backend_sftp.pot deleted file mode 100644 index 63229d9144..0000000000 --- a/storage_backend_sftp/i18n/storage_backend_sftp.pot +++ /dev/null @@ -1,97 +0,0 @@ -# Translation of Odoo Server. -# This file contains the translation of the following modules: -# * storage_backend_sftp -# -msgid "" -msgstr "" -"Project-Id-Version: Odoo Server 14.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: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__backend_type -msgid "Backend Type" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__display_name -msgid "Display Name" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__id -msgid "ID" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key -msgid "" -"It's recommended to not store the key here but to provide it via secret env " -"variable. See `server_environment` docs." -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend____last_update -msgid "Last Modified on" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_login -msgid "Login to connect to sftp server" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__pwd -msgid "Password" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__ssh_key -msgid "Private key" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__backend_type__sftp -#: model_terms:ir.ui.view,arch_db:storage_backend_sftp.storage_backend_view_form -msgid "SFTP" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_auth_method -msgid "SFTP Authentification Method" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_server -msgid "SFTP Host" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login -msgid "SFTP Login" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_password -msgid "SFTP Password" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_port -msgid "SFTP Port" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key -msgid "SSH private key" -msgstr "" - -#. module: storage_backend_sftp -#: model:ir.model,name:storage_backend_sftp.model_storage_backend -msgid "Storage Backend" -msgstr "" From d17ae6b517b6ebede0b378879370d487997af1eb Mon Sep 17 00:00:00 2001 From: SilvioC2C Date: Wed, 6 Apr 2022 14:04:56 +0200 Subject: [PATCH 46/58] [FIX] storage_backend_sftp: use full path in move_files() --- storage_backend_sftp/components/sftp_adapter.py | 5 +++-- storage_backend_sftp/tests/test_sftp.py | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index a553d07943..56a9677317 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -102,6 +102,7 @@ def list(self, relative_path): def move_files(self, files, destination_path): _logger.debug("mv %s %s", files, destination_path) + fp = self._fullpath with sftp(self.collection) as client: for sftp_file in files: dest_file_path = os.path.join( @@ -115,8 +116,8 @@ def move_files(self, files, destination_path): _logger.debug("destination %s is free", dest_file_path) else: client.unlink(dest_file_path) - # Move the file - client.rename(sftp_file, dest_file_path) + # Move the file using absolute filepaths + client.rename(fp(sftp_file), fp(dest_file_path)) def delete(self, relative_path): full_path = self._fullpath(relative_path) diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index c99a6a1dd5..26ec9c9df9 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -106,7 +106,9 @@ def test_move_files(self, mocked_paramiko): # no need to delete it client.unlink.assert_not_called() # rename gets called - client.rename.assert_called_with(to_move, to_move.replace("from", "to")) + client.rename.assert_called_with( + "upload/" + to_move, "upload/" + to_move.replace("from", "to") + ) # now try to override destination client.lstat.side_effect = None client.lstat.return_value = True @@ -114,4 +116,6 @@ def test_move_files(self, mocked_paramiko): # client will delete it first client.unlink.assert_called_with(to_move.replace("from", "to")) # then move it - client.rename.assert_called_with(to_move, to_move.replace("from", "to")) + client.rename.assert_called_with( + "upload/" + to_move, "upload/" + to_move.replace("from", "to") + ) From b430329ce0c815346a539f2d3a945c78e55776e5 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Mon, 11 Apr 2022 09:11:41 +0000 Subject: [PATCH 47/58] [UPD] Update storage_backend_sftp.pot --- .../i18n/storage_backend_sftp.pot | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 storage_backend_sftp/i18n/storage_backend_sftp.pot diff --git a/storage_backend_sftp/i18n/storage_backend_sftp.pot b/storage_backend_sftp/i18n/storage_backend_sftp.pot new file mode 100644 index 0000000000..52092a9b4d --- /dev/null +++ b/storage_backend_sftp/i18n/storage_backend_sftp.pot @@ -0,0 +1,82 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * storage_backend_sftp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.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: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__backend_type +msgid "Backend Type" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key +msgid "" +"It's recommended to not store the key here but to provide it via secret env " +"variable. See `server_environment` docs." +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_login +msgid "Login to connect to sftp server" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__pwd +msgid "Password" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__ssh_key +msgid "Private key" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__backend_type__sftp +#: model_terms:ir.ui.view,arch_db:storage_backend_sftp.storage_backend_view_form +msgid "SFTP" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_auth_method +msgid "SFTP Authentification Method" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_server +msgid "SFTP Host" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login +msgid "SFTP Login" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_password +msgid "SFTP Password" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_port +msgid "SFTP Port" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key +msgid "SSH private key" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model,name:storage_backend_sftp.model_storage_backend +msgid "Storage Backend" +msgstr "" From 6c8b2a6b527d1a85812c4baf9ba964d849c75a75 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Mon, 11 Apr 2022 09:14:19 +0000 Subject: [PATCH 48/58] storage_backend_sftp 15.0.1.0.1 --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 380b269ef2..e3ed27651d 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "15.0.1.0.0", + "version": "15.0.1.0.1", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From 5b63451094f47f70860bc7c20aa525070cf0cabc Mon Sep 17 00:00:00 2001 From: jcoux Date: Wed, 18 May 2022 12:05:06 +0200 Subject: [PATCH 49/58] storage_backend_sftp: Fix paramiko usage Previous code used the paramiko client open function with explicit binary mode. But, the explicit binary mode is now ignored by python. See the `open` function description into the paramiko documentation: https://docs.paramiko.org/en/stable/api/sftp.html ``` The Python 'b' flag is ignored, since SSH treats all files as binary. ``` But in fact, depending of the SFTP server we have an `OSError`. Then this PR remove the useless binary mode, and avoid to have errors. --- storage_backend_sftp/components/sftp_adapter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index 56a9677317..aaa65fe7f9 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -76,14 +76,14 @@ def add(self, relative_path, data, **kwargs): sftp_mkdirs(client, dirname) else: raise # pragma: no cover - remote_file = client.open(full_path, "w+b") + remote_file = client.open(full_path, "w") remote_file.write(data) remote_file.close() def get(self, relative_path, **kwargs): full_path = self._fullpath(relative_path) with sftp(self.collection) as client: - file_data = client.open(full_path, "rb") + file_data = client.open(full_path, "r") data = file_data.read() # TODO: shouldn't we close the file? return data From dd98b2c7d8f0efe52dfac447ebc049622e2a3ec3 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 25 May 2022 15:38:57 +0000 Subject: [PATCH 50/58] storage_backend_sftp 15.0.1.0.2 --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index e3ed27651d..8490e36225 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "15.0.1.0.1", + "version": "15.0.1.0.2", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From d32f944ee45d0f6586696e4c7f1f8a1de6ff6e3d Mon Sep 17 00:00:00 2001 From: Telmo Santos Date: Fri, 24 Feb 2023 10:58:01 +0100 Subject: [PATCH 51/58] [MIG] storage_backend_sftp: Migration to 16.0 --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 8490e36225..e96019e723 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "15.0.1.0.2", + "version": "16.0.1.0.0", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From 4010aff44d79762f4712cf7f2e52f56fff7540fb Mon Sep 17 00:00:00 2001 From: oca-ci Date: Fri, 9 Feb 2024 11:25:21 +0000 Subject: [PATCH 52/58] [UPD] Update storage_backend_sftp.pot --- storage_backend_sftp/i18n/storage_backend_sftp.pot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/i18n/storage_backend_sftp.pot b/storage_backend_sftp/i18n/storage_backend_sftp.pot index 52092a9b4d..74b5bb7c6e 100644 --- a/storage_backend_sftp/i18n/storage_backend_sftp.pot +++ b/storage_backend_sftp/i18n/storage_backend_sftp.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 15.0\n" +"Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" From 72b027a2008f734dff941cbcb4a6bbbdcdd77c5d Mon Sep 17 00:00:00 2001 From: mymage Date: Tue, 13 Feb 2024 06:48:41 +0000 Subject: [PATCH 53/58] Added translation using Weblate (Italian) --- storage_backend_sftp/i18n/it.po | 83 +++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 storage_backend_sftp/i18n/it.po diff --git a/storage_backend_sftp/i18n/it.po b/storage_backend_sftp/i18n/it.po new file mode 100644 index 0000000000..3414166dc5 --- /dev/null +++ b/storage_backend_sftp/i18n/it.po @@ -0,0 +1,83 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * storage_backend_sftp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\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" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__backend_type +msgid "Backend Type" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key +msgid "" +"It's recommended to not store the key here but to provide it via secret env " +"variable. See `server_environment` docs." +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_login +msgid "Login to connect to sftp server" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__pwd +msgid "Password" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__ssh_key +msgid "Private key" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__backend_type__sftp +#: model_terms:ir.ui.view,arch_db:storage_backend_sftp.storage_backend_view_form +msgid "SFTP" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_auth_method +msgid "SFTP Authentification Method" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_server +msgid "SFTP Host" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login +msgid "SFTP Login" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_password +msgid "SFTP Password" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_port +msgid "SFTP Port" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key +msgid "SSH private key" +msgstr "" + +#. module: storage_backend_sftp +#: model:ir.model,name:storage_backend_sftp.model_storage_backend +msgid "Storage Backend" +msgstr "" From c7ee144cb203a888fae09d161ca124a9447e4019 Mon Sep 17 00:00:00 2001 From: mymage Date: Fri, 16 Feb 2024 14:12:47 +0000 Subject: [PATCH 54/58] Translated using Weblate (Italian) Currently translated at 100.0% (13 of 13 strings) Translation: storage-16.0/storage-16.0-storage_backend_sftp Translate-URL: https://translation.odoo-community.org/projects/storage-16-0/storage-16-0-storage_backend_sftp/it/ --- storage_backend_sftp/i18n/it.po | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/storage_backend_sftp/i18n/it.po b/storage_backend_sftp/i18n/it.po index 3414166dc5..7863bab5b0 100644 --- a/storage_backend_sftp/i18n/it.po +++ b/storage_backend_sftp/i18n/it.po @@ -6,18 +6,20 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2024-02-16 16: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: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__backend_type msgid "Backend Type" -msgstr "" +msgstr "Tipo backend" #. module: storage_backend_sftp #: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key @@ -25,59 +27,61 @@ msgid "" "It's recommended to not store the key here but to provide it via secret env " "variable. See `server_environment` docs." msgstr "" +"Si raccomanda si non salvare qui la chiave ma di fornirla attraverso una " +"variabile di ambiente segreta. Vedere documentazione 'server_enviroment'." #. module: storage_backend_sftp #: model:ir.model.fields,help:storage_backend_sftp.field_storage_backend__sftp_login msgid "Login to connect to sftp server" -msgstr "" +msgstr "Accedere per collegarsi al server SFTP" #. module: storage_backend_sftp #: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__pwd msgid "Password" -msgstr "" +msgstr "Password" #. module: storage_backend_sftp #: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__sftp_auth_method__ssh_key msgid "Private key" -msgstr "" +msgstr "Chiave privata" #. module: storage_backend_sftp #: model:ir.model.fields.selection,name:storage_backend_sftp.selection__storage_backend__backend_type__sftp #: model_terms:ir.ui.view,arch_db:storage_backend_sftp.storage_backend_view_form msgid "SFTP" -msgstr "" +msgstr "SFTP" #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_auth_method msgid "SFTP Authentification Method" -msgstr "" +msgstr "Metodo autenticazione SFTP" #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_server msgid "SFTP Host" -msgstr "" +msgstr "Host SFTP" #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_login msgid "SFTP Login" -msgstr "" +msgstr "Accesso SFTP" #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_password msgid "SFTP Password" -msgstr "" +msgstr "Password SFTP" #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_port msgid "SFTP Port" -msgstr "" +msgstr "Porta SFTP" #. module: storage_backend_sftp #: model:ir.model.fields,field_description:storage_backend_sftp.field_storage_backend__sftp_ssh_private_key msgid "SSH private key" -msgstr "" +msgstr "Chiave privata SSH" #. module: storage_backend_sftp #: model:ir.model,name:storage_backend_sftp.model_storage_backend msgid "Storage Backend" -msgstr "" +msgstr "Backend deposito" From 3cbd0740bd3919652ab251aa9f451f0a3347f187 Mon Sep 17 00:00:00 2001 From: Simone Orsi Date: Wed, 4 Sep 2024 06:52:13 +0200 Subject: [PATCH 55/58] storage_*: fix test import of mock There's no need to depend on the additional lib mock. --- storage_backend_sftp/tests/test_sftp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index 26ec9c9df9..fb01fab642 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -11,8 +11,7 @@ import errno import logging import os - -import mock +from unittest import mock from odoo.addons.storage_backend.tests.common import BackendStorageTestMixin, CommonCase From d9bca492d2f3cee03f570df86a7307e6dfa0652b Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 4 Sep 2024 05:05:50 +0000 Subject: [PATCH 56/58] [BOT] post-merge updates --- storage_backend_sftp/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index e96019e723..7fcdbef3fc 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "16.0.1.0.0", + "version": "16.0.1.0.1", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", From d5484730674f4a42eed7b3aa15ea3ddec49f762f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Alan=20Ramos=20Rodr=C3=ADguez?= Date: Tue, 25 Feb 2025 18:59:14 -0600 Subject: [PATCH 57/58] [IMP] storage_backend_sftp: pre-commit auto fixes --- requirements.txt | 1 + storage_backend_sftp/components/sftp_adapter.py | 6 +++--- storage_backend_sftp/pyproject.toml | 3 +++ storage_backend_sftp/tests/test_sftp.py | 8 ++++---- 4 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 storage_backend_sftp/pyproject.toml diff --git a/requirements.txt b/requirements.txt index 4c5f1c7d04..105b9db01f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ # generated from manifests external_dependencies fsspec>=2024.5.0 +paramiko python_slugify diff --git a/storage_backend_sftp/components/sftp_adapter.py b/storage_backend_sftp/components/sftp_adapter.py index aaa65fe7f9..88decca5bf 100644 --- a/storage_backend_sftp/components/sftp_adapter.py +++ b/storage_backend_sftp/components/sftp_adapter.py @@ -23,7 +23,7 @@ def sftp_mkdirs(client, path, mode=511): try: client.mkdir(path, mode) - except IOError as e: + except OSError as e: if e.errno == errno.ENOENT and path: sftp_mkdirs(client, os.path.dirname(path), mode=mode) client.mkdir(path, mode) @@ -71,7 +71,7 @@ def add(self, relative_path, data, **kwargs): if dirname: try: client.stat(dirname) - except IOError as e: + except OSError as e: if e.errno == errno.ENOENT: sftp_mkdirs(client, dirname) else: @@ -93,7 +93,7 @@ def list(self, relative_path): with sftp(self.collection) as client: try: return client.listdir(full_path) - except IOError as e: + except OSError as e: if e.errno == errno.ENOENT: # The path do not exist return an empty list return [] diff --git a/storage_backend_sftp/pyproject.toml b/storage_backend_sftp/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/storage_backend_sftp/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/storage_backend_sftp/tests/test_sftp.py b/storage_backend_sftp/tests/test_sftp.py index fb01fab642..7994aee7dd 100644 --- a/storage_backend_sftp/tests/test_sftp.py +++ b/storage_backend_sftp/tests/test_sftp.py @@ -43,7 +43,7 @@ def setUpClass(cls): def test_add(self, mocked_paramiko, mocked_mkdirs): client = mocked_paramiko.SFTPClient.from_transport() # simulate errors - exc = IOError() + exc = OSError() # general client.stat.side_effect = exc with self.assertRaises(IOError): @@ -58,7 +58,7 @@ def test_add(self, mocked_paramiko, mocked_mkdirs): mocked_mkdirs.assert_called() # file has been written and closed self.assertTrue(fakefile.closed) - with open("/tmp/fakefile.txt", "r") as thefile: + with open("/tmp/fakefile.txt") as thefile: self.assertEqual(thefile.read(), "fake data") @mock.patch(PARAMIKO_PATH) @@ -66,14 +66,14 @@ def test_get(self, mocked_paramiko): client = mocked_paramiko.SFTPClient.from_transport() with open("/tmp/fakefile2.txt", "w+b") as fakefile: fakefile.write(b"filecontent") - client.open.return_value = open("/tmp/fakefile2.txt", "r") + client.open.return_value = open("/tmp/fakefile2.txt") self.assertEqual(self.backend.get("fake/path"), "filecontent") @mock.patch(PARAMIKO_PATH) def test_list(self, mocked_paramiko): client = mocked_paramiko.SFTPClient.from_transport() # simulate errors - exc = IOError() + exc = OSError() # general client.listdir.side_effect = exc with self.assertRaises(IOError): From 336d2099e50085c7234b78b9fdea0005fc8ecc1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Alan=20Ramos=20Rodr=C3=ADguez?= Date: Tue, 25 Feb 2025 19:04:58 -0600 Subject: [PATCH 58/58] [MIG] storage_backend_sftp: Migration to 17.0 --- storage_backend_sftp/__manifest__.py | 2 +- storage_backend_sftp/views/backend_storage_view.xml | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/storage_backend_sftp/__manifest__.py b/storage_backend_sftp/__manifest__.py index 7fcdbef3fc..a7277e85e5 100644 --- a/storage_backend_sftp/__manifest__.py +++ b/storage_backend_sftp/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Storage Backend SFTP", "summary": "Implement SFTP Storage", - "version": "16.0.1.0.1", + "version": "17.0.1.0.0", "category": "Storage", "website": "https://github.com/OCA/storage", "author": " Akretion,Odoo Community Association (OCA)", diff --git a/storage_backend_sftp/views/backend_storage_view.xml b/storage_backend_sftp/views/backend_storage_view.xml index 341631ffda..af6afd1386 100644 --- a/storage_backend_sftp/views/backend_storage_view.xml +++ b/storage_backend_sftp/views/backend_storage_view.xml @@ -5,11 +5,7 @@ - + @@ -17,12 +13,12 @@