From cfe050ce8eda2e6da95f55e00e88277af157d2c2 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 01/32] [13.0][ADD] storage_backend_ftp --- storage_backend_ftp/README.rst | 73 +++ storage_backend_ftp/__init__.py | 2 + storage_backend_ftp/__manifest__.py | 14 + storage_backend_ftp/components/__init__.py | 1 + storage_backend_ftp/components/ftp_adapter.py | 149 +++++++ storage_backend_ftp/models/__init__.py | 1 + storage_backend_ftp/models/storage_backend.py | 49 ++ storage_backend_ftp/readme/CONTRIBUTORS.rst | 1 + storage_backend_ftp/readme/DESCRIPTION.rst | 1 + .../static/description/index.html | 419 ++++++++++++++++++ storage_backend_ftp/tests/__init__.py | 1 + storage_backend_ftp/tests/test_ftp.py | 159 +++++++ .../views/backend_storage_view.xml | 28 ++ 13 files changed, 898 insertions(+) create mode 100644 storage_backend_ftp/README.rst create mode 100644 storage_backend_ftp/__init__.py create mode 100644 storage_backend_ftp/__manifest__.py create mode 100644 storage_backend_ftp/components/__init__.py create mode 100644 storage_backend_ftp/components/ftp_adapter.py create mode 100644 storage_backend_ftp/models/__init__.py create mode 100644 storage_backend_ftp/models/storage_backend.py create mode 100644 storage_backend_ftp/readme/CONTRIBUTORS.rst create mode 100644 storage_backend_ftp/readme/DESCRIPTION.rst create mode 100644 storage_backend_ftp/static/description/index.html create mode 100644 storage_backend_ftp/tests/__init__.py create mode 100644 storage_backend_ftp/tests/test_ftp.py create mode 100644 storage_backend_ftp/views/backend_storage_view.xml diff --git a/storage_backend_ftp/README.rst b/storage_backend_ftp/README.rst new file mode 100644 index 0000000000..5ff3bb30bc --- /dev/null +++ b/storage_backend_ftp/README.rst @@ -0,0 +1,73 @@ +=================== +Storage Backend FTP +=================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github + :target: https://github.com/OCA/storage/tree/13.0/storage_backend_ftp + :alt: OCA/storage +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/storage-13-0/storage-13-0-storage_backend_ftp + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/275/13.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Add FTP as storage backend + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Acsone SA/NV + +Contributors +~~~~~~~~~~~~ + +* François Honoré + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/storage `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/storage_backend_ftp/__init__.py b/storage_backend_ftp/__init__.py new file mode 100644 index 0000000000..0f00a6730d --- /dev/null +++ b/storage_backend_ftp/__init__.py @@ -0,0 +1,2 @@ +from . import models +from . import components diff --git a/storage_backend_ftp/__manifest__.py b/storage_backend_ftp/__manifest__.py new file mode 100644 index 0000000000..48108c4442 --- /dev/null +++ b/storage_backend_ftp/__manifest__.py @@ -0,0 +1,14 @@ +# Copyright 2021 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + "name": "Storage Backend FTP", + "summary": "Implement FTP Storage", + "version": "13.0.1.0.0", + "category": "Storage", + "website": "https://github.com/OCA/storage", + "author": " Acsone SA/NV,Odoo Community Association (OCA)", + "license": "LGPL-3", + "external_dependencies": {"python": ["pyftpdlib"]}, + "depends": ["storage_backend"], + "data": ["views/backend_storage_view.xml"], +} diff --git a/storage_backend_ftp/components/__init__.py b/storage_backend_ftp/components/__init__.py new file mode 100644 index 0000000000..72dbc3a308 --- /dev/null +++ b/storage_backend_ftp/components/__init__.py @@ -0,0 +1 @@ +from . import ftp_adapter diff --git a/storage_backend_ftp/components/ftp_adapter.py b/storage_backend_ftp/components/ftp_adapter.py new file mode 100644 index 0000000000..c6711a63a2 --- /dev/null +++ b/storage_backend_ftp/components/ftp_adapter.py @@ -0,0 +1,149 @@ +# Copyright 2021 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +import errno +import io +import logging +import os +import ssl +from contextlib import contextmanager +from io import StringIO + +from odoo.addons.component.core import Component + +_logger = logging.getLogger(__name__) + +try: + import ftplib +except ImportError as err: # pragma: no cover + _logger.debug(err) + + +def ftp_mkdirs(client, path): + try: + client.mkd(path) + except IOError as e: + if e.errno == errno.ENOENT and path: + ftp_mkdirs(client, os.path.dirname(path)) + client.mkd(path) + else: + raise # pragma: no cover + + +@contextmanager +def ftp(backend): + params = {} + security = None + if backend.ftp_encryption == "ftp": + ftp = ftplib.FTP + elif backend.ftp_encryption == "tls": + ftp = ftplib.FTP_TLS + # Due to a bug into between ftplib and ssl, this part (about ssl) might not work! + # https://bugs.python.org/issue31727 + security = None + if backend.ftp_security == "tls": + security = ssl.PROTOCOL_TLS + elif backend.ftp_security == "tlsv1": + security = ssl.PROTOCOL_TLSv1 + elif backend.ftp_security == "tlsv1_1": + security = ssl.PROTOCOL_TLSv1_1 + elif backend.ftp_security == "tlsv1_2": + security = ssl.PROTOCOL_TLSv1_2 + elif backend.ftp_security == "sslv2": + security = ssl.PROTOCOL_SSLv2 + elif backend.ftp_security == "sslv23": + security = ssl.PROTOCOL_SSLv23 + elif backend.ftp_security == "sslv3": + security = ssl.PROTOCOL_SSLv3 + if security: + ctx = ssl._create_stdlib_context(security) + params.update({"context": ctx}) + else: + raise NotImplementedError() + with ftp(**params) as client: + client.connect(host=backend.ftp_server, port=backend.ftp_port) + if security: + client.auth() + client.login(backend.ftp_login, backend.ftp_password) + if security: + client.ssl_version = security + client.prot_p() + if backend.ftp_passive: + client.set_pasv(True) + yield client + + +class FTPStorageBackendAdapter(Component): + _name = "ftp.adapter" + _inherit = "base.storage.adapter" + _usage = "ftp" + + def add(self, relative_path, data, **kwargs): + with ftp(self.collection) as client: + full_path = self._fullpath(relative_path) + dirname = os.path.dirname(full_path) + if dirname: + try: + client.cwd(dirname) + except IOError as e: + if e.errno == errno.ENOENT: + ftp_mkdirs(client, dirname) + else: + raise # pragma: no cover + with io.BytesIO(data) as tmp_file: + try: + client.storbinary("STOR " + full_path, tmp_file) + except ftplib.Error as e: + raise ValueError(repr(e)) + except OSError as e: + raise ValueError(repr(e)) + + def get(self, relative_path, **kwargs): + full_path = self._fullpath(relative_path) + with ftp(self.collection) as client, StringIO() as buff: + try: + client.retrlines("RETR " + full_path, buff.write) + except ftplib.Error as e: + raise FileNotFoundError(repr(e)) + buff.seek(0) + data = buff.read() + return data.encode() + + def list(self, relative_path): + full_path = self._fullpath(relative_path) + with ftp(self.collection) as client: + try: + return client.retrlines("LIST " + full_path) + except IOError as e: + if e.errno == errno.ENOENT: + # The path do not exist return an empty list + return [] + else: + raise # pragma: no cover + + def move_files(self, files, destination_path): + _logger.debug("mv %s %s", files, destination_path) + with ftp(self.collection) as client: + for ftp_file in files: + dest_file_path = os.path.join( + destination_path, os.path.basename(ftp_file) + ) + # Remove existing file at the destination path (an error is raised + # otherwise) + result = [] + try: + result = client.nlst(dest_file_path) + except ftplib.Error: + _logger.debug("destination %s is free", dest_file_path) + if result: + client.delete(dest_file_path) + # Move the file + client.rename(ftp_file, dest_file_path) + + def delete(self, relative_path): + full_path = self._fullpath(relative_path) + with ftp(self.collection) as client: + return client.delete(full_path) + + def validate_config(self): + with ftp(self.collection) as client: + client.getwelcome() diff --git a/storage_backend_ftp/models/__init__.py b/storage_backend_ftp/models/__init__.py new file mode 100644 index 0000000000..f45f402268 --- /dev/null +++ b/storage_backend_ftp/models/__init__.py @@ -0,0 +1 @@ +from . import storage_backend diff --git a/storage_backend_ftp/models/storage_backend.py b/storage_backend_ftp/models/storage_backend.py new file mode 100644 index 0000000000..9cb939ea5d --- /dev/null +++ b/storage_backend_ftp/models/storage_backend.py @@ -0,0 +1,49 @@ +# Copyright 2021 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo import fields, models + + +class StorageBackend(models.Model): + _inherit = "storage.backend" + + backend_type = fields.Selection(selection_add=[("ftp", "FTP")]) + ftp_server = fields.Char(string="FTP Host") + ftp_port = fields.Integer(string="FTP Port", default=21) + ftp_encryption = fields.Selection( + string="FTP Encryption method", + selection=[("ftp", "FTP"), ("tls", "FTP over TLS")], + default="ftp", + required=True, + ) + ftp_security = fields.Selection( + string="FTP security option", + selection=[ + ("none", "None"), + ("tlsv1", "TLS"), + ("tlsv1_1", "TLSv1_1"), + ("tlsv1_2", "TLSv1_2"), + ("sslv2", "SSLv2"), + ("sslv23", "SSLv23"), + ("sslv3", "SSLv3"), + ], + required=True, + ) + ftp_login = fields.Char(string="FTP Login", help="Login to connect to ftp server") + ftp_password = fields.Char(string="FTP Password") + ftp_passive = fields.Boolean(string="FTP Passive", default=False) + + @property + def _server_env_fields(self): + env_fields = super()._server_env_fields + env_fields.update( + { + "ftp_password": {}, + "ftp_login": {}, + "ftp_server": {}, + "ftp_port": {}, + "ftp_encryption": {}, + "ftp_security": {}, + "ftp_passive": {}, + } + ) + return env_fields diff --git a/storage_backend_ftp/readme/CONTRIBUTORS.rst b/storage_backend_ftp/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..ab1764c1c9 --- /dev/null +++ b/storage_backend_ftp/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* François Honoré diff --git a/storage_backend_ftp/readme/DESCRIPTION.rst b/storage_backend_ftp/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..b0b32036fc --- /dev/null +++ b/storage_backend_ftp/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Add FTP as storage backend diff --git a/storage_backend_ftp/static/description/index.html b/storage_backend_ftp/static/description/index.html new file mode 100644 index 0000000000..a3df4e58dc --- /dev/null +++ b/storage_backend_ftp/static/description/index.html @@ -0,0 +1,419 @@ + + + + + + +Storage Backend FTP + + + +
+

Storage Backend FTP

+ + +

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runbot

+

Add FTP as storage backend

+

Table of contents

+ +
+

Bug Tracker

+

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

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Acsone SA/NV
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

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

+

This module is part of the OCA/storage project on GitHub.

+

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

+
+
+
+ + diff --git a/storage_backend_ftp/tests/__init__.py b/storage_backend_ftp/tests/__init__.py new file mode 100644 index 0000000000..9ab6aa0f49 --- /dev/null +++ b/storage_backend_ftp/tests/__init__.py @@ -0,0 +1 @@ +from . import test_ftp diff --git a/storage_backend_ftp/tests/test_ftp.py b/storage_backend_ftp/tests/test_ftp.py new file mode 100644 index 0000000000..c3bd4a48d7 --- /dev/null +++ b/storage_backend_ftp/tests/test_ftp.py @@ -0,0 +1,159 @@ +# Copyright 2021 ACSONE SA/NV () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +# pylint: disable=missing-manifest-dependency +# disable warning on 'vcr' missing in manifest: this is only a dependency for +# dev/tests + +import errno +import ftplib +import logging +import os + +import mock + +from odoo.addons.storage_backend.tests.common import BackendStorageTestMixin, CommonCase + +_logger = logging.getLogger(__name__) + +MOD_PATH = "odoo.addons.storage_backend_ftp.components.ftp_adapter" +ADAPTER_PATH = MOD_PATH + ".FTPStorageBackendAdapter" +FTP_LIB_PATH = MOD_PATH + ".ftplib" + + +class FtpCase(CommonCase, BackendStorageTestMixin): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.backend.write( + { + "backend_type": "ftp", + "ftp_login": os.environ.get("FTP_LOGIN", "foo"), + "ftp_password": os.environ.get("FTP_PWD", "pass"), + "ftp_server": os.environ.get("FTP_HOST", "localhost"), + "ftp_port": os.environ.get("FTP_PORT", "21"), + "directory_path": "upload", + "ftp_encryption": "ftp", + } + ) + cls.case_with_subdirectory = "upload/subdirectory/here" + + @mock.patch(MOD_PATH + ".ftp_mkdirs") + @mock.patch(FTP_LIB_PATH) + def test_add(self, mocked_ftplib, mocked_mkdirs): + client = mocked_ftplib.FTP().__enter__() + # simulate errors + exc = IOError() + # general + client.cwd.side_effect = exc + with self.assertRaises(IOError): + self.backend.add("fake/path", b"fake data") + # not found + exc.errno = errno.ENOENT + client.cwd.side_effect = exc + file_data = b"fake data" + with mock.patch("io.BytesIO") as tmp_file: + self.backend.add("fake/path", file_data) + # mkdirs has been called + mocked_mkdirs.assert_called() + client.storbinary.assert_called() + tmp_file.assert_called() + tmp_file.assert_called_with(file_data) + client.storbinary.assert_called_with( + "STOR upload/fake/path", tmp_file().__enter__() + ) + + @mock.patch(FTP_LIB_PATH) + def test_get(self, mocked_ftplib): + client = mocked_ftplib.FTP().__enter__() + content = b"filecontent" + with open("/tmp/fakefile2.txt", "w+b") as fakefile: + fakefile.write(content) + + def side_effect_retrlines(*args, **kwargs): + """ + Mock function to read tmp file. + """ + cmd, buff_write = args + with open("/tmp/fakefile2.txt", "r") as tmp_file: + buff_write(tmp_file.read()) + + client.retrlines.side_effect = side_effect_retrlines + self.assertEqual(self.backend.get("fake/path"), content) + + @mock.patch(FTP_LIB_PATH) + def test_list(self, mocked_ftplib): + client = mocked_ftplib.FTP().__enter__() + # simulate errors + exc = IOError() + # general + client.retrlines.side_effect = exc + with self.assertRaises(IOError): + self.backend.list_files() + # not found + exc.errno = errno.ENOENT + client.retrlines.side_effect = exc + 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)] + 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 + ) + + # Do not patch the entire ftplib otherwise the error_perm Exception + # become also a mock and then a traceback is genrated on the "except ftplib.error_perm" + # because this ftplib.error_perm is not really an Exception (but a mock)! + @mock.patch(FTP_LIB_PATH + ".FTP") + def test_move_files(self, mocked_ftplib): + client = mocked_ftplib().__enter__() + # simulate file is not already there + client.nlst.side_effect = ftplib.error_perm() + 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.delete.assert_not_called() + # rename gets called + client.rename.assert_called_with(to_move, to_move.replace("from", "to")) + # now try to override destination + client.nlst.side_effect = None + client.nlst.return_value = True + self.backend.move_files([to_move], to_path) + # client will delete it first + client.delete.assert_called_with(to_move.replace("from", "to")) + # then move it + client.rename.assert_called_with(to_move, to_move.replace("from", "to")) + + @mock.patch(FTP_LIB_PATH) + def test_delete(self, mocked_ftplib): + client = mocked_ftplib.FTP().__enter__() + path = "delete/a/path" + self.backend.delete(path) + client.delete.assert_called_with( + os.path.join(self.backend.directory_path, path) + ) + + @mock.patch(FTP_LIB_PATH) + def test_validate_config(self, mocked_ftplib): + client = mocked_ftplib.FTP().__enter__() + self.backend.action_test_config() + client.getwelcome.assert_called() + + @mock.patch(FTP_LIB_PATH) + def test_mkd(self, mocked_ftplib): + client = mocked_ftplib.FTP().__enter__() + # simulate errors + exc = IOError() + exc.errno = errno.ENOENT + # general + client.cwd.side_effect = exc + client.mkd.side_effect = exc + with self.assertRaises(OSError): + self.backend.add("fake/path", b"fake data") + client.mkd.assert_called() diff --git a/storage_backend_ftp/views/backend_storage_view.xml b/storage_backend_ftp/views/backend_storage_view.xml new file mode 100644 index 0000000000..b20d0f87be --- /dev/null +++ b/storage_backend_ftp/views/backend_storage_view.xml @@ -0,0 +1,28 @@ + + + + storage.backend + + + + + + + + + + + + + + + + + From d18743c84f066e9d84db2f06825e35d684887caa Mon Sep 17 00:00:00 2001 From: Lois Rilo Date: Thu, 5 Aug 2021 10:08:05 +0200 Subject: [PATCH 02/32] [FIX] storage_backend_ftp: fix list and get * list should return a python list of files. * get should get and directly return the bynary from the FTP. Before, a string was being retrived and then encoded. This is problematic if the original binary was not utf-8. --- storage_backend_ftp/components/ftp_adapter.py | 13 ++++++------- storage_backend_ftp/readme/CONTRIBUTORS.rst | 1 + 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/storage_backend_ftp/components/ftp_adapter.py b/storage_backend_ftp/components/ftp_adapter.py index c6711a63a2..2c3f7bab05 100644 --- a/storage_backend_ftp/components/ftp_adapter.py +++ b/storage_backend_ftp/components/ftp_adapter.py @@ -6,7 +6,7 @@ import os import ssl from contextlib import contextmanager -from io import StringIO +from io import BytesIO from odoo.addons.component.core import Component @@ -99,20 +99,19 @@ def add(self, relative_path, data, **kwargs): def get(self, relative_path, **kwargs): full_path = self._fullpath(relative_path) - with ftp(self.collection) as client, StringIO() as buff: + with ftp(self.collection) as client, BytesIO() as buff: try: - client.retrlines("RETR " + full_path, buff.write) + client.retrbinary("RETR " + full_path, buff.write) + data = buff.getvalue() except ftplib.Error as e: raise FileNotFoundError(repr(e)) - buff.seek(0) - data = buff.read() - return data.encode() + return data def list(self, relative_path): full_path = self._fullpath(relative_path) with ftp(self.collection) as client: try: - return client.retrlines("LIST " + full_path) + return client.nlst(full_path) except IOError as e: if e.errno == errno.ENOENT: # The path do not exist return an empty list diff --git a/storage_backend_ftp/readme/CONTRIBUTORS.rst b/storage_backend_ftp/readme/CONTRIBUTORS.rst index ab1764c1c9..51b8da248c 100644 --- a/storage_backend_ftp/readme/CONTRIBUTORS.rst +++ b/storage_backend_ftp/readme/CONTRIBUTORS.rst @@ -1 +1,2 @@ * François Honoré +* Lois Rilo From 9c8af9e0cbb580fca5ecd7ea9ea59382c36a97c0 Mon Sep 17 00:00:00 2001 From: Lois Rilo Date: Tue, 26 Oct 2021 12:25:38 +0200 Subject: [PATCH 03/32] [IMP] storage_backend_ftp: fix tests and do not support unsecure protocols. --- storage_backend_ftp/components/ftp_adapter.py | 30 +++++++++---------- storage_backend_ftp/tests/test_ftp.py | 12 ++++---- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/storage_backend_ftp/components/ftp_adapter.py b/storage_backend_ftp/components/ftp_adapter.py index 2c3f7bab05..1b01ec9cf7 100644 --- a/storage_backend_ftp/components/ftp_adapter.py +++ b/storage_backend_ftp/components/ftp_adapter.py @@ -8,6 +8,8 @@ from contextlib import contextmanager from io import BytesIO +from odoo.exceptions import UserError + from odoo.addons.component.core import Component _logger = logging.getLogger(__name__) @@ -17,6 +19,16 @@ except ImportError as err: # pragma: no cover _logger.debug(err) +FTP_SECURITY_TO_PROTOCOL = { + "tls": ssl.PROTOCOL_TLS, + "tlsv1": ssl.PROTOCOL_TLSv1, + "tlsv1_1": ssl.PROTOCOL_TLSv1_1, + "tlsv1_2": ssl.PROTOCOL_TLSv1_2, + "sslv2": "sslv2 has been deprecated due to security issues", + "sslv23": ssl.PROTOCOL_SSLv23, + "sslv3": "sslv3 has been deprecated due to security issues", +} + def ftp_mkdirs(client, path): try: @@ -39,21 +51,9 @@ def ftp(backend): ftp = ftplib.FTP_TLS # Due to a bug into between ftplib and ssl, this part (about ssl) might not work! # https://bugs.python.org/issue31727 - security = None - if backend.ftp_security == "tls": - security = ssl.PROTOCOL_TLS - elif backend.ftp_security == "tlsv1": - security = ssl.PROTOCOL_TLSv1 - elif backend.ftp_security == "tlsv1_1": - security = ssl.PROTOCOL_TLSv1_1 - elif backend.ftp_security == "tlsv1_2": - security = ssl.PROTOCOL_TLSv1_2 - elif backend.ftp_security == "sslv2": - security = ssl.PROTOCOL_SSLv2 - elif backend.ftp_security == "sslv23": - security = ssl.PROTOCOL_SSLv23 - elif backend.ftp_security == "sslv3": - security = ssl.PROTOCOL_SSLv3 + security = FTP_SECURITY_TO_PROTOCOL.get(backend.ftp_security, None) + if isinstance(security, str): + raise UserError(security) if security: ctx = ssl._create_stdlib_context(security) params.update({"context": ctx}) diff --git a/storage_backend_ftp/tests/test_ftp.py b/storage_backend_ftp/tests/test_ftp.py index c3bd4a48d7..1b95d52a35 100644 --- a/storage_backend_ftp/tests/test_ftp.py +++ b/storage_backend_ftp/tests/test_ftp.py @@ -70,15 +70,15 @@ def test_get(self, mocked_ftplib): with open("/tmp/fakefile2.txt", "w+b") as fakefile: fakefile.write(content) - def side_effect_retrlines(*args, **kwargs): + def side_effect_retrbinary(*args, **kwargs): """ Mock function to read tmp file. """ cmd, buff_write = args - with open("/tmp/fakefile2.txt", "r") as tmp_file: + with open("/tmp/fakefile2.txt", "rb") as tmp_file: buff_write(tmp_file.read()) - client.retrlines.side_effect = side_effect_retrlines + client.retrbinary.side_effect = side_effect_retrbinary self.assertEqual(self.backend.get("fake/path"), content) @mock.patch(FTP_LIB_PATH) @@ -87,12 +87,12 @@ def test_list(self, mocked_ftplib): # simulate errors exc = IOError() # general - client.retrlines.side_effect = exc + client.nlst.side_effect = exc with self.assertRaises(IOError): self.backend.list_files() # not found exc.errno = errno.ENOENT - client.retrlines.side_effect = exc + client.nlst.side_effect = exc self.assertEqual(self.backend.list_files(), []) def test_find_files(self): @@ -107,7 +107,7 @@ def test_find_files(self): ) # Do not patch the entire ftplib otherwise the error_perm Exception - # become also a mock and then a traceback is genrated on the "except ftplib.error_perm" + # become also a mock and then a traceback is generated on the "except ftplib.error_perm" # because this ftplib.error_perm is not really an Exception (but a mock)! @mock.patch(FTP_LIB_PATH + ".FTP") def test_move_files(self, mocked_ftplib): From 0f38087a4da8378226eee8106c8ca3486719c73f Mon Sep 17 00:00:00 2001 From: oca-travis Date: Wed, 27 Oct 2021 13:32:16 +0000 Subject: [PATCH 04/32] [UPD] Update storage_backend_ftp.pot --- .../i18n/storage_backend_ftp.pot | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 storage_backend_ftp/i18n/storage_backend_ftp.pot diff --git a/storage_backend_ftp/i18n/storage_backend_ftp.pot b/storage_backend_ftp/i18n/storage_backend_ftp.pot new file mode 100644 index 0000000000..f5b1322ebc --- /dev/null +++ b/storage_backend_ftp/i18n/storage_backend_ftp.pot @@ -0,0 +1,111 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * storage_backend_ftp +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 13.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_ftp +#: model:ir.model.fields,field_description:storage_backend_ftp.field_storage_backend__backend_type +msgid "Backend Type" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__backend_type__ftp +#: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__ftp_encryption__ftp +#: model_terms:ir.ui.view,arch_db:storage_backend_ftp.storage_backend_view_form +msgid "FTP" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields,field_description:storage_backend_ftp.field_storage_backend__ftp_encryption +msgid "FTP Encryption method" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields,field_description:storage_backend_ftp.field_storage_backend__ftp_server +msgid "FTP Host" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields,field_description:storage_backend_ftp.field_storage_backend__ftp_login +msgid "FTP Login" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields,field_description:storage_backend_ftp.field_storage_backend__ftp_passive +msgid "FTP Passive" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields,field_description:storage_backend_ftp.field_storage_backend__ftp_password +msgid "FTP Password" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields,field_description:storage_backend_ftp.field_storage_backend__ftp_port +msgid "FTP Port" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__ftp_encryption__tls +msgid "FTP over TLS" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields,field_description:storage_backend_ftp.field_storage_backend__ftp_security +msgid "FTP security option" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields,help:storage_backend_ftp.field_storage_backend__ftp_login +msgid "Login to connect to ftp server" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__ftp_security__none +msgid "None" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__ftp_security__sslv2 +msgid "SSLv2" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__ftp_security__sslv23 +msgid "SSLv23" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__ftp_security__sslv3 +msgid "SSLv3" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model,name:storage_backend_ftp.model_storage_backend +msgid "Storage Backend" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__ftp_security__tlsv1 +msgid "TLS" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__ftp_security__tlsv1_1 +msgid "TLSv1_1" +msgstr "" + +#. module: storage_backend_ftp +#: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__ftp_security__tlsv1_2 +msgid "TLSv1_2" +msgstr "" From 68c4b2ac3ca243f0d02f98784321c91103f72d2e Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Wed, 27 Oct 2021 13:41:36 +0000 Subject: [PATCH 05/32] [UPD] README.rst --- storage_backend_ftp/README.rst | 1 + storage_backend_ftp/static/description/index.html | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/storage_backend_ftp/README.rst b/storage_backend_ftp/README.rst index 5ff3bb30bc..493471fc61 100644 --- a/storage_backend_ftp/README.rst +++ b/storage_backend_ftp/README.rst @@ -54,6 +54,7 @@ Contributors ~~~~~~~~~~~~ * François Honoré +* Lois Rilo Maintainers ~~~~~~~~~~~ diff --git a/storage_backend_ftp/static/description/index.html b/storage_backend_ftp/static/description/index.html index a3df4e58dc..dbdb82062c 100644 --- a/storage_backend_ftp/static/description/index.html +++ b/storage_backend_ftp/static/description/index.html @@ -3,7 +3,7 @@ - + Storage Backend FTP -
-

Storage Backend FTP

+
+ + +Odoo Community Association + +
+

Storage Backend FTP

-

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

+

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

Add FTP as storage backend

Table of contents

@@ -384,39 +389,42 @@

Storage Backend FTP

-

Bug Tracker

+

Bug Tracker

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

+feedback.

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

-

Credits

+

Credits

-

Authors

+

Authors

  • Acsone SA/NV
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

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

-

This module is part of the OCA/storage project on GitHub.

+

This module is part of the OCA/storage project on GitHub.

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

+
From 4ff75b0f48c472a0db0079031164b00c49fd7663 Mon Sep 17 00:00:00 2001 From: Eldhose George Date: Wed, 12 Aug 2026 12:05:47 +0530 Subject: [PATCH 24/32] [FIX] storage_backend_ftp: use unittest.mock instead of removed mock dependency --- storage_backend_ftp/tests/test_ftp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/storage_backend_ftp/tests/test_ftp.py b/storage_backend_ftp/tests/test_ftp.py index 33a8116c79..620511cf31 100644 --- a/storage_backend_ftp/tests/test_ftp.py +++ b/storage_backend_ftp/tests/test_ftp.py @@ -9,8 +9,7 @@ import ftplib import logging import os - -import mock +from unittest import mock from odoo.addons.storage_backend.tests.common import BackendStorageTestMixin, CommonCase From b57e216db9bcb3a7974d2802c20435a6bed1a563 Mon Sep 17 00:00:00 2001 From: Maksym Yankin Date: Mon, 23 Mar 2026 15:40:49 +0200 Subject: [PATCH 25/32] [REF] image_tag: server_environment should not be a required dependency --- image_tag/README.rst | 6 +++- image_tag/__manifest__.py | 2 +- image_tag/models/image_tag.py | 1 - image_tag/static/description/index.html | 38 +++++++++++++++---------- image_tag/views/image_tag.xml | 2 -- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/image_tag/README.rst b/image_tag/README.rst index 81ab69688d..2e029c0243 100644 --- a/image_tag/README.rst +++ b/image_tag/README.rst @@ -1,3 +1,7 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + ========= Image Tag ========= @@ -13,7 +17,7 @@ Image Tag .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status :alt: Beta -.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github diff --git a/image_tag/__manifest__.py b/image_tag/__manifest__.py index 0bbe310d2d..d82ca5191f 100644 --- a/image_tag/__manifest__.py +++ b/image_tag/__manifest__.py @@ -9,7 +9,7 @@ "license": "AGPL-3", "author": "ACSONE SA/NV,Akretion,Odoo Community Association (OCA)", "website": "https://github.com/OCA/storage", - "depends": ["server_environment"], + "depends": ["base"], "data": [ "security/res_groups.xml", "security/image_tag.xml", diff --git a/image_tag/models/image_tag.py b/image_tag/models/image_tag.py index 86f255873d..847d4e1544 100644 --- a/image_tag/models/image_tag.py +++ b/image_tag/models/image_tag.py @@ -8,7 +8,6 @@ class ImageTag(models.Model): _name = "image.tag" - _inherit = ["server.env.techname.mixin"] _description = "Image Tag" @api.model diff --git a/image_tag/static/description/index.html b/image_tag/static/description/index.html index a37630a2ff..608ba12042 100644 --- a/image_tag/static/description/index.html +++ b/image_tag/static/description/index.html @@ -1,18 +1,18 @@ - -Image Tag +README.rst -
-

Image Tag

+
+ + +Odoo Community Association + +
+

Image Tag

-

Beta License: AGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

+

Beta License: AGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

This addon provide only one basic model used to define image’s tags. These tags are used by other addons to enrich the image’s information of an image linked to an other model. The fs_product_multi_image addon use this model.

@@ -387,12 +392,12 @@

Image Tag

-

Usage

+

Usage

To manage the list of available tags, you must have the Image Tag Manager role.

-

Bug Tracker

+

Bug Tracker

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

Bug Tracker

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

-

Credits

+

Credits

-

Authors

+

Authors

  • ACSONE SA/NV
  • Akretion
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

-Odoo Community Association + +Odoo Community Association +

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

@@ -426,5 +433,6 @@

Maintainers

+
diff --git a/image_tag/views/image_tag.xml b/image_tag/views/image_tag.xml index 6ecda60972..18411f7c4b 100644 --- a/image_tag/views/image_tag.xml +++ b/image_tag/views/image_tag.xml @@ -5,7 +5,6 @@ - @@ -15,7 +14,6 @@ - From 79975fcea063adb20d28f7bd57437c218ba348dc Mon Sep 17 00:00:00 2001 From: Maksym Yankin Date: Mon, 23 Mar 2026 15:50:13 +0200 Subject: [PATCH 26/32] [ADD] image_tag_environment: make server_environment an optional dependency --- image_tag/__manifest__.py | 2 +- image_tag/upgrades/16.0.1.0.2/post-update.py | 13 + image_tag_environment/README.rst | 87 ++++ image_tag_environment/__init__.py | 1 + image_tag_environment/__manifest__.py | 16 + image_tag_environment/i18n/es.po | 90 ++++ image_tag_environment/i18n/image_tag.pot | 86 ++++ image_tag_environment/i18n/it.po | 89 ++++ image_tag_environment/models/__init__.py | 1 + image_tag_environment/models/image_tag.py | 11 + image_tag_environment/readme/CONTRIBUTORS.rst | 2 + image_tag_environment/readme/DESCRIPTION.rst | 1 + image_tag_environment/readme/USAGE.rst | 1 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 436 ++++++++++++++++++ image_tag_environment/views/image_tag.xml | 21 + .../odoo/addons/image_tag_environment | 1 + setup/image_tag_environment/setup.py | 6 + 18 files changed, 863 insertions(+), 1 deletion(-) create mode 100644 image_tag/upgrades/16.0.1.0.2/post-update.py create mode 100644 image_tag_environment/README.rst create mode 100644 image_tag_environment/__init__.py create mode 100644 image_tag_environment/__manifest__.py create mode 100644 image_tag_environment/i18n/es.po create mode 100644 image_tag_environment/i18n/image_tag.pot create mode 100644 image_tag_environment/i18n/it.po create mode 100644 image_tag_environment/models/__init__.py create mode 100644 image_tag_environment/models/image_tag.py create mode 100644 image_tag_environment/readme/CONTRIBUTORS.rst create mode 100644 image_tag_environment/readme/DESCRIPTION.rst create mode 100644 image_tag_environment/readme/USAGE.rst create mode 100644 image_tag_environment/static/description/icon.png create mode 100644 image_tag_environment/static/description/index.html create mode 100644 image_tag_environment/views/image_tag.xml create mode 120000 setup/image_tag_environment/odoo/addons/image_tag_environment create mode 100644 setup/image_tag_environment/setup.py diff --git a/image_tag/__manifest__.py b/image_tag/__manifest__.py index d82ca5191f..7d3756cbe0 100644 --- a/image_tag/__manifest__.py +++ b/image_tag/__manifest__.py @@ -5,7 +5,7 @@ "name": "Image Tag", "summary": """ Image tag model""", - "version": "16.0.1.0.1", + "version": "16.0.1.0.2", "license": "AGPL-3", "author": "ACSONE SA/NV,Akretion,Odoo Community Association (OCA)", "website": "https://github.com/OCA/storage", diff --git a/image_tag/upgrades/16.0.1.0.2/post-update.py b/image_tag/upgrades/16.0.1.0.2/post-update.py new file mode 100644 index 0000000000..574c6795b0 --- /dev/null +++ b/image_tag/upgrades/16.0.1.0.2/post-update.py @@ -0,0 +1,13 @@ +# Copyright 2026 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from openupgradelib import openupgrade + + +@openupgrade.migrate() +def migrate(env, version): + module = env["ir.module.module"].search( + [("name", "=", "image_tag_environment"), ("state", "=", "uninstalled")] + ) + if module: + module.button_install() diff --git a/image_tag_environment/README.rst b/image_tag_environment/README.rst new file mode 100644 index 0000000000..7ad8b3ca10 --- /dev/null +++ b/image_tag_environment/README.rst @@ -0,0 +1,87 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +============================== +Image Tag - Server Environment +============================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:05203837238360e0c011f8ed825bbf70e20f56a5157f18585a37353e9a148a86 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fstorage-lightgray.png?logo=github + :target: https://github.com/OCA/storage/tree/16.0/image_tag_environment + :alt: OCA/storage +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/storage-16-0/storage-16-0-image_tag_environment + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/storage&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Glue module to make Server Environment features available for the Image Tag addon. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Specify technical name during the creation of an image tag. + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* ACSONE SA/NV +* Akretion + +Contributors +~~~~~~~~~~~~ + +* Laurent Mignon +* Maksym Yankin + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/storage `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/image_tag_environment/__init__.py b/image_tag_environment/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/image_tag_environment/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/image_tag_environment/__manifest__.py b/image_tag_environment/__manifest__.py new file mode 100644 index 0000000000..4e5cb0b554 --- /dev/null +++ b/image_tag_environment/__manifest__.py @@ -0,0 +1,16 @@ +# Copyright 2023 ACSONE SA/NV +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +{ + "name": "Image Tag - Server Environment", + "summary": "Server environment features for the Image Tag model", + "version": "16.0.1.0.0", + "license": "AGPL-3", + "author": "ACSONE SA/NV,Akretion,Odoo Community Association (OCA)", + "website": "https://github.com/OCA/storage", + "depends": ["image_tag", "server_environment"], + "data": [ + "views/image_tag.xml", + ], + "auto_install": True, +} diff --git a/image_tag_environment/i18n/es.po b/image_tag_environment/i18n/es.po new file mode 100644 index 0000000000..36459bc555 --- /dev/null +++ b/image_tag_environment/i18n/es.po @@ -0,0 +1,90 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * image_tag +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-10-29 00:15+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__apply_on +msgid "Apply On" +msgstr "Aplicar En" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__create_uid +msgid "Created by" +msgstr "Creado por" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__create_date +msgid "Created on" +msgstr "Creado el" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__display_name +msgid "Display Name" +msgstr "Mostrar Nombre" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__id +msgid "ID" +msgstr "ID (identificación)" + +#. module: image_tag +#: model:ir.actions.act_window,name:image_tag.act_open_image_tag_view +#: model:ir.model,name:image_tag.model_image_tag +#: model_terms:ir.ui.view,arch_db:image_tag.image_tag_view_search +msgid "Image Tag" +msgstr "Etiqueta de Imagen" + +#. module: image_tag +#: model:res.groups,name:image_tag.group_image_tag_manager +msgid "Image Tag Manager" +msgstr "Gestor de Etiquetas de Imagen" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag____last_update +msgid "Last Modified on" +msgstr "Última Modifiación el" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__write_uid +msgid "Last Updated by" +msgstr "Actualizado por Última vez por" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__write_date +msgid "Last Updated on" +msgstr "Última Actualización el" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__name +msgid "Name" +msgstr "Nombre" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__server_env_defaults +msgid "Server Env Defaults" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__tech_name +msgid "Tech Name" +msgstr "Nombre Técnico" + +#. module: image_tag +#: model:ir.model.fields,help:image_tag.field_image_tag__tech_name +msgid "Unique name for technical purposes. Eg: server env keys." +msgstr "" +"Nombre único con fines técnicos. Por ejemplo: claves de ent del servidor." diff --git a/image_tag_environment/i18n/image_tag.pot b/image_tag_environment/i18n/image_tag.pot new file mode 100644 index 0000000000..9229bba009 --- /dev/null +++ b/image_tag_environment/i18n/image_tag.pot @@ -0,0 +1,86 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * image_tag +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.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: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__apply_on +msgid "Apply On" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__create_uid +msgid "Created by" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__create_date +msgid "Created on" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__display_name +msgid "Display Name" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__id +msgid "ID" +msgstr "" + +#. module: image_tag +#: model:ir.actions.act_window,name:image_tag.act_open_image_tag_view +#: model:ir.model,name:image_tag.model_image_tag +#: model_terms:ir.ui.view,arch_db:image_tag.image_tag_view_search +msgid "Image Tag" +msgstr "" + +#. module: image_tag +#: model:res.groups,name:image_tag.group_image_tag_manager +msgid "Image Tag Manager" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag____last_update +msgid "Last Modified on" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__write_date +msgid "Last Updated on" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__name +msgid "Name" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__server_env_defaults +msgid "Server Env Defaults" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__tech_name +msgid "Tech Name" +msgstr "" + +#. module: image_tag +#: model:ir.model.fields,help:image_tag.field_image_tag__tech_name +msgid "Unique name for technical purposes. Eg: server env keys." +msgstr "" diff --git a/image_tag_environment/i18n/it.po b/image_tag_environment/i18n/it.po new file mode 100644 index 0000000000..3d4d2f19d0 --- /dev/null +++ b/image_tag_environment/i18n/it.po @@ -0,0 +1,89 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * image_tag +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2025-07-23 11:25+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 5.10.4\n" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__apply_on +msgid "Apply On" +msgstr "Applica a" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__create_uid +msgid "Created by" +msgstr "Creato da" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__create_date +msgid "Created on" +msgstr "Creato il" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__id +msgid "ID" +msgstr "ID" + +#. module: image_tag +#: model:ir.actions.act_window,name:image_tag.act_open_image_tag_view +#: model:ir.model,name:image_tag.model_image_tag +#: model_terms:ir.ui.view,arch_db:image_tag.image_tag_view_search +msgid "Image Tag" +msgstr "Etichetta immagine" + +#. module: image_tag +#: model:res.groups,name:image_tag.group_image_tag_manager +msgid "Image Tag Manager" +msgstr "Gestore etichetta immagine" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__write_uid +msgid "Last Updated by" +msgstr "Ultimo aggiornamento di" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__write_date +msgid "Last Updated on" +msgstr "Ultimo aggiornamento il" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__name +msgid "Name" +msgstr "Nome" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__server_env_defaults +msgid "Server Env Defaults" +msgstr "Predefiniti ambiente server" + +#. module: image_tag +#: model:ir.model.fields,field_description:image_tag.field_image_tag__tech_name +msgid "Tech Name" +msgstr "Nome tecnico" + +#. module: image_tag +#: model:ir.model.fields,help:image_tag.field_image_tag__tech_name +msgid "Unique name for technical purposes. Eg: server env keys." +msgstr "Nome univoco per motivi tecnici. Es: chiavi server ambiente." diff --git a/image_tag_environment/models/__init__.py b/image_tag_environment/models/__init__.py new file mode 100644 index 0000000000..888490ab30 --- /dev/null +++ b/image_tag_environment/models/__init__.py @@ -0,0 +1 @@ +from . import image_tag diff --git a/image_tag_environment/models/image_tag.py b/image_tag_environment/models/image_tag.py new file mode 100644 index 0000000000..2c50349ff8 --- /dev/null +++ b/image_tag_environment/models/image_tag.py @@ -0,0 +1,11 @@ +# Copyright 2023 ACSONE SA/NV +# Copyright 2018 Akretion (http://www.akretion.com). +# @author Raphaël Reverdy +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo import models + + +class ImageTag(models.Model): + _name = "image.tag" + _inherit = ["image.tag", "server.env.techname.mixin"] diff --git a/image_tag_environment/readme/CONTRIBUTORS.rst b/image_tag_environment/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..0f79cbc864 --- /dev/null +++ b/image_tag_environment/readme/CONTRIBUTORS.rst @@ -0,0 +1,2 @@ +* Laurent Mignon +* Maksym Yankin diff --git a/image_tag_environment/readme/DESCRIPTION.rst b/image_tag_environment/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..4ddadc72f6 --- /dev/null +++ b/image_tag_environment/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Glue module to make Server Environment features available for the Image Tag addon. diff --git a/image_tag_environment/readme/USAGE.rst b/image_tag_environment/readme/USAGE.rst new file mode 100644 index 0000000000..b57527eec8 --- /dev/null +++ b/image_tag_environment/readme/USAGE.rst @@ -0,0 +1 @@ +Specify technical name during the creation of an image tag. diff --git a/image_tag_environment/static/description/icon.png b/image_tag_environment/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 diff --git a/image_tag_environment/static/description/index.html b/image_tag_environment/static/description/index.html new file mode 100644 index 0000000000..54e6c3fd51 --- /dev/null +++ b/image_tag_environment/static/description/index.html @@ -0,0 +1,436 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Image Tag - Server Environment

+ +

Beta License: AGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

+

Glue module to make Server Environment features available for the Image Tag addon.

+

Table of contents

+ +
+

Usage

+

Specify technical name during the creation of an image tag.

+
+
+

Bug Tracker

+

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

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • ACSONE SA/NV
  • +
  • Akretion
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

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

+

This module is part of the OCA/storage project on GitHub.

+

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

+
+
+
+
+ + diff --git a/image_tag_environment/views/image_tag.xml b/image_tag_environment/views/image_tag.xml new file mode 100644 index 0000000000..b1409ab2b0 --- /dev/null +++ b/image_tag_environment/views/image_tag.xml @@ -0,0 +1,21 @@ + + + + image.tag + + + + + + + + + image.tag + + + + + + + + diff --git a/setup/image_tag_environment/odoo/addons/image_tag_environment b/setup/image_tag_environment/odoo/addons/image_tag_environment new file mode 120000 index 0000000000..fdb0826de9 --- /dev/null +++ b/setup/image_tag_environment/odoo/addons/image_tag_environment @@ -0,0 +1 @@ +../../../../image_tag_environment \ No newline at end of file diff --git a/setup/image_tag_environment/setup.py b/setup/image_tag_environment/setup.py new file mode 100644 index 0000000000..28c57bb640 --- /dev/null +++ b/setup/image_tag_environment/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From dd694921b6ff366a60c7fd15b9953cb95f30a446 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Thu, 20 Aug 2026 11:22:02 +0000 Subject: [PATCH 27/32] [UPD] Update image_tag.pot --- image_tag/i18n/image_tag.pot | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/image_tag/i18n/image_tag.pot b/image_tag/i18n/image_tag.pot index 9229bba009..8d9040591c 100644 --- a/image_tag/i18n/image_tag.pot +++ b/image_tag/i18n/image_tag.pot @@ -69,18 +69,3 @@ msgstr "" #: model:ir.model.fields,field_description:image_tag.field_image_tag__name msgid "Name" msgstr "" - -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__server_env_defaults -msgid "Server Env Defaults" -msgstr "" - -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__tech_name -msgid "Tech Name" -msgstr "" - -#. module: image_tag -#: model:ir.model.fields,help:image_tag.field_image_tag__tech_name -msgid "Unique name for technical purposes. Eg: server env keys." -msgstr "" From 71f601ecf6301de52da74e1e8735338e8c964815 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Thu, 20 Aug 2026 11:22:02 +0000 Subject: [PATCH 28/32] [UPD] Update image_tag_environment.pot --- image_tag_environment/i18n/es.po | 96 +++++++------------ .../i18n/image_tag_environment.pot | 34 +++++++ image_tag_environment/i18n/it.po | 94 +++++++----------- 3 files changed, 107 insertions(+), 117 deletions(-) create mode 100644 image_tag_environment/i18n/image_tag_environment.pot diff --git a/image_tag_environment/i18n/es.po b/image_tag_environment/i18n/es.po index 36459bc555..4c41eb35cd 100644 --- a/image_tag_environment/i18n/es.po +++ b/image_tag_environment/i18n/es.po @@ -16,75 +16,53 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 4.17\n" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__apply_on -msgid "Apply On" -msgstr "Aplicar En" +#. module: image_tag_environment +#: model:ir.model,name:image_tag_environment.model_image_tag +msgid "Image Tag" +msgstr "Etiqueta de Imagen" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__create_uid -msgid "Created by" -msgstr "Creado por" +#. module: image_tag_environment +#: model:ir.model.fields,field_description:image_tag_environment.field_image_tag__server_env_defaults +msgid "Server Env Defaults" +msgstr "" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__create_date -msgid "Created on" -msgstr "Creado el" +#. module: image_tag_environment +#: model:ir.model.fields,field_description:image_tag_environment.field_image_tag__tech_name +msgid "Tech Name" +msgstr "Nombre Técnico" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__display_name -msgid "Display Name" -msgstr "Mostrar Nombre" +#. module: image_tag_environment +#: model:ir.model.fields,help:image_tag_environment.field_image_tag__tech_name +msgid "Unique name for technical purposes. Eg: server env keys." +msgstr "" +"Nombre único con fines técnicos. Por ejemplo: claves de ent del servidor." -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__id -msgid "ID" -msgstr "ID (identificación)" +#~ msgid "Apply On" +#~ msgstr "Aplicar En" -#. module: image_tag -#: model:ir.actions.act_window,name:image_tag.act_open_image_tag_view -#: model:ir.model,name:image_tag.model_image_tag -#: model_terms:ir.ui.view,arch_db:image_tag.image_tag_view_search -msgid "Image Tag" -msgstr "Etiqueta de Imagen" +#~ msgid "Created by" +#~ msgstr "Creado por" -#. module: image_tag -#: model:res.groups,name:image_tag.group_image_tag_manager -msgid "Image Tag Manager" -msgstr "Gestor de Etiquetas de Imagen" +#~ msgid "Created on" +#~ msgstr "Creado el" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag____last_update -msgid "Last Modified on" -msgstr "Última Modifiación el" +#~ msgid "Display Name" +#~ msgstr "Mostrar Nombre" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__write_uid -msgid "Last Updated by" -msgstr "Actualizado por Última vez por" +#~ msgid "ID" +#~ msgstr "ID (identificación)" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__write_date -msgid "Last Updated on" -msgstr "Última Actualización el" +#~ msgid "Image Tag Manager" +#~ msgstr "Gestor de Etiquetas de Imagen" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__name -msgid "Name" -msgstr "Nombre" +#~ msgid "Last Modified on" +#~ msgstr "Última Modifiación el" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__server_env_defaults -msgid "Server Env Defaults" -msgstr "" +#~ msgid "Last Updated by" +#~ msgstr "Actualizado por Última vez por" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__tech_name -msgid "Tech Name" -msgstr "Nombre Técnico" +#~ msgid "Last Updated on" +#~ msgstr "Última Actualización el" -#. module: image_tag -#: model:ir.model.fields,help:image_tag.field_image_tag__tech_name -msgid "Unique name for technical purposes. Eg: server env keys." -msgstr "" -"Nombre único con fines técnicos. Por ejemplo: claves de ent del servidor." +#~ msgid "Name" +#~ msgstr "Nombre" diff --git a/image_tag_environment/i18n/image_tag_environment.pot b/image_tag_environment/i18n/image_tag_environment.pot new file mode 100644 index 0000000000..fad2502af0 --- /dev/null +++ b/image_tag_environment/i18n/image_tag_environment.pot @@ -0,0 +1,34 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * image_tag_environment +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.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: image_tag_environment +#: model:ir.model,name:image_tag_environment.model_image_tag +msgid "Image Tag" +msgstr "" + +#. module: image_tag_environment +#: model:ir.model.fields,field_description:image_tag_environment.field_image_tag__server_env_defaults +msgid "Server Env Defaults" +msgstr "" + +#. module: image_tag_environment +#: model:ir.model.fields,field_description:image_tag_environment.field_image_tag__tech_name +msgid "Tech Name" +msgstr "" + +#. module: image_tag_environment +#: model:ir.model.fields,help:image_tag_environment.field_image_tag__tech_name +msgid "Unique name for technical purposes. Eg: server env keys." +msgstr "" diff --git a/image_tag_environment/i18n/it.po b/image_tag_environment/i18n/it.po index 3d4d2f19d0..76dcaea580 100644 --- a/image_tag_environment/i18n/it.po +++ b/image_tag_environment/i18n/it.po @@ -16,74 +16,52 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Weblate 5.10.4\n" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__apply_on -msgid "Apply On" -msgstr "Applica a" +#. module: image_tag_environment +#: model:ir.model,name:image_tag_environment.model_image_tag +msgid "Image Tag" +msgstr "Etichetta immagine" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__create_uid -msgid "Created by" -msgstr "Creato da" +#. module: image_tag_environment +#: model:ir.model.fields,field_description:image_tag_environment.field_image_tag__server_env_defaults +msgid "Server Env Defaults" +msgstr "Predefiniti ambiente server" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__create_date -msgid "Created on" -msgstr "Creato il" +#. module: image_tag_environment +#: model:ir.model.fields,field_description:image_tag_environment.field_image_tag__tech_name +msgid "Tech Name" +msgstr "Nome tecnico" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__display_name -msgid "Display Name" -msgstr "Nome visualizzato" +#. module: image_tag_environment +#: model:ir.model.fields,help:image_tag_environment.field_image_tag__tech_name +msgid "Unique name for technical purposes. Eg: server env keys." +msgstr "Nome univoco per motivi tecnici. Es: chiavi server ambiente." -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__id -msgid "ID" -msgstr "ID" +#~ msgid "Apply On" +#~ msgstr "Applica a" -#. module: image_tag -#: model:ir.actions.act_window,name:image_tag.act_open_image_tag_view -#: model:ir.model,name:image_tag.model_image_tag -#: model_terms:ir.ui.view,arch_db:image_tag.image_tag_view_search -msgid "Image Tag" -msgstr "Etichetta immagine" +#~ msgid "Created by" +#~ msgstr "Creato da" -#. module: image_tag -#: model:res.groups,name:image_tag.group_image_tag_manager -msgid "Image Tag Manager" -msgstr "Gestore etichetta immagine" +#~ msgid "Created on" +#~ msgstr "Creato il" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag____last_update -msgid "Last Modified on" -msgstr "Ultima modifica il" +#~ msgid "Display Name" +#~ msgstr "Nome visualizzato" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__write_uid -msgid "Last Updated by" -msgstr "Ultimo aggiornamento di" +#~ msgid "ID" +#~ msgstr "ID" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__write_date -msgid "Last Updated on" -msgstr "Ultimo aggiornamento il" +#~ msgid "Image Tag Manager" +#~ msgstr "Gestore etichetta immagine" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__name -msgid "Name" -msgstr "Nome" +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__server_env_defaults -msgid "Server Env Defaults" -msgstr "Predefiniti ambiente server" +#~ msgid "Last Updated by" +#~ msgstr "Ultimo aggiornamento di" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__tech_name -msgid "Tech Name" -msgstr "Nome tecnico" +#~ msgid "Last Updated on" +#~ msgstr "Ultimo aggiornamento il" -#. module: image_tag -#: model:ir.model.fields,help:image_tag.field_image_tag__tech_name -msgid "Unique name for technical purposes. Eg: server env keys." -msgstr "Nome univoco per motivi tecnici. Es: chiavi server ambiente." +#~ msgid "Name" +#~ msgstr "Nome" From d5d6d6de44a3251d0c92c88a2454fc9ca44a7e87 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 20 Aug 2026 11:25:42 +0000 Subject: [PATCH 29/32] [BOT] post-merge updates --- README.md | 3 ++- image_tag/README.rst | 2 +- image_tag/__manifest__.py | 2 +- image_tag/static/description/index.html | 2 +- image_tag_environment/README.rst | 2 +- image_tag_environment/__manifest__.py | 2 +- image_tag_environment/static/description/index.html | 2 +- setup/_metapackage/VERSION.txt | 2 +- setup/_metapackage/setup.py | 1 + 9 files changed, 10 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 5501d11f6a..ee67bf4c02 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,8 @@ addon | version | maintainers | summary [fs_storage_backup](fs_storage_backup/) | 16.0.2.0.0 | | Filesystem Storage Backup [fs_storage_backup_environment](fs_storage_backup_environment/) | 16.0.1.0.0 | | Allows to use server environment with fs storage attachment [fs_storage_environment](fs_storage_environment/) | 16.0.1.0.0 | | Allows to use server environment with fs storage -[image_tag](image_tag/) | 16.0.1.0.1 | | Image tag model +[image_tag](image_tag/) | 16.0.2.0.0 | | Image tag model +[image_tag_environment](image_tag_environment/) | 16.0.2.0.0 | | Server environment features for the Image Tag model [storage_backend](storage_backend/) | 16.0.1.1.0 | | Implement the concept of Storage with amazon S3, sftp... [storage_backend_sftp](storage_backend_sftp/) | 16.0.1.0.2 | | Implement SFTP Storage [storage_file](storage_file/) | 16.0.1.0.1 | | Storage file in storage backend diff --git a/image_tag/README.rst b/image_tag/README.rst index 2e029c0243..3be438dc6d 100644 --- a/image_tag/README.rst +++ b/image_tag/README.rst @@ -11,7 +11,7 @@ Image Tag !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:05203837238360e0c011f8ed825bbf70e20f56a5157f18585a37353e9a148a86 + !! source digest: sha256:9a9aa1210e00d5861a492c284df7dd7c5b975689b83cdaef8f98a15768340cf1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/image_tag/__manifest__.py b/image_tag/__manifest__.py index 7d3756cbe0..e71666e992 100644 --- a/image_tag/__manifest__.py +++ b/image_tag/__manifest__.py @@ -5,7 +5,7 @@ "name": "Image Tag", "summary": """ Image tag model""", - "version": "16.0.1.0.2", + "version": "16.0.2.0.0", "license": "AGPL-3", "author": "ACSONE SA/NV,Akretion,Odoo Community Association (OCA)", "website": "https://github.com/OCA/storage", diff --git a/image_tag/static/description/index.html b/image_tag/static/description/index.html index 608ba12042..3003169efd 100644 --- a/image_tag/static/description/index.html +++ b/image_tag/static/description/index.html @@ -372,7 +372,7 @@

Image Tag

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:05203837238360e0c011f8ed825bbf70e20f56a5157f18585a37353e9a148a86 +!! source digest: sha256:9a9aa1210e00d5861a492c284df7dd7c5b975689b83cdaef8f98a15768340cf1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

This addon provide only one basic model used to define image’s tags. These diff --git a/image_tag_environment/README.rst b/image_tag_environment/README.rst index 7ad8b3ca10..fc8b7541df 100644 --- a/image_tag_environment/README.rst +++ b/image_tag_environment/README.rst @@ -11,7 +11,7 @@ Image Tag - Server Environment !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:05203837238360e0c011f8ed825bbf70e20f56a5157f18585a37353e9a148a86 + !! source digest: sha256:20e304c07b50e37319543a302422d4bae8d9b6e234f6c8138b12e938a68c2ab9 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/image_tag_environment/__manifest__.py b/image_tag_environment/__manifest__.py index 4e5cb0b554..1ed162d063 100644 --- a/image_tag_environment/__manifest__.py +++ b/image_tag_environment/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Image Tag - Server Environment", "summary": "Server environment features for the Image Tag model", - "version": "16.0.1.0.0", + "version": "16.0.2.0.0", "license": "AGPL-3", "author": "ACSONE SA/NV,Akretion,Odoo Community Association (OCA)", "website": "https://github.com/OCA/storage", diff --git a/image_tag_environment/static/description/index.html b/image_tag_environment/static/description/index.html index 54e6c3fd51..5b9b78aaaa 100644 --- a/image_tag_environment/static/description/index.html +++ b/image_tag_environment/static/description/index.html @@ -372,7 +372,7 @@

Image Tag - Server Environment

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:05203837238360e0c011f8ed825bbf70e20f56a5157f18585a37353e9a148a86 +!! source digest: sha256:20e304c07b50e37319543a302422d4bae8d9b6e234f6c8138b12e938a68c2ab9 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: AGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

Glue module to make Server Environment features available for the Image Tag addon.

diff --git a/setup/_metapackage/VERSION.txt b/setup/_metapackage/VERSION.txt index f2eb63f0a9..95cfd381bc 100644 --- a/setup/_metapackage/VERSION.txt +++ b/setup/_metapackage/VERSION.txt @@ -1 +1 @@ -16.0.20260608.0 \ No newline at end of file +16.0.20260820.0 \ No newline at end of file diff --git a/setup/_metapackage/setup.py b/setup/_metapackage/setup.py index e7a0f2cba5..f86f2f8335 100644 --- a/setup/_metapackage/setup.py +++ b/setup/_metapackage/setup.py @@ -27,6 +27,7 @@ 'odoo-addon-fs_storage_backup_environment>=16.0dev,<16.1dev', 'odoo-addon-fs_storage_environment>=16.0dev,<16.1dev', 'odoo-addon-image_tag>=16.0dev,<16.1dev', + 'odoo-addon-image_tag_environment>=16.0dev,<16.1dev', 'odoo-addon-storage_backend>=16.0dev,<16.1dev', 'odoo-addon-storage_backend_sftp>=16.0dev,<16.1dev', 'odoo-addon-storage_file>=16.0dev,<16.1dev', From 550f5035492b89c2d8840596f27351e481ef522c Mon Sep 17 00:00:00 2001 From: Weblate Date: Thu, 20 Aug 2026 11:25:53 +0000 Subject: [PATCH 30/32] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: storage-16.0/storage-16.0-image_tag Translate-URL: https://translation.odoo-community.org/projects/storage-16-0/storage-16-0-image_tag/ --- image_tag/i18n/es.po | 19 +++++-------------- image_tag/i18n/it.po | 18 ++++++------------ 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/image_tag/i18n/es.po b/image_tag/i18n/es.po index 36459bc555..026a3c19bd 100644 --- a/image_tag/i18n/es.po +++ b/image_tag/i18n/es.po @@ -73,18 +73,9 @@ msgstr "Última Actualización el" msgid "Name" msgstr "Nombre" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__server_env_defaults -msgid "Server Env Defaults" -msgstr "" - -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__tech_name -msgid "Tech Name" -msgstr "Nombre Técnico" +#~ msgid "Tech Name" +#~ msgstr "Nombre Técnico" -#. module: image_tag -#: model:ir.model.fields,help:image_tag.field_image_tag__tech_name -msgid "Unique name for technical purposes. Eg: server env keys." -msgstr "" -"Nombre único con fines técnicos. Por ejemplo: claves de ent del servidor." +#~ msgid "Unique name for technical purposes. Eg: server env keys." +#~ msgstr "" +#~ "Nombre único con fines técnicos. Por ejemplo: claves de ent del servidor." diff --git a/image_tag/i18n/it.po b/image_tag/i18n/it.po index 3d4d2f19d0..b61b9cf738 100644 --- a/image_tag/i18n/it.po +++ b/image_tag/i18n/it.po @@ -73,17 +73,11 @@ msgstr "Ultimo aggiornamento il" msgid "Name" msgstr "Nome" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__server_env_defaults -msgid "Server Env Defaults" -msgstr "Predefiniti ambiente server" +#~ msgid "Server Env Defaults" +#~ msgstr "Predefiniti ambiente server" -#. module: image_tag -#: model:ir.model.fields,field_description:image_tag.field_image_tag__tech_name -msgid "Tech Name" -msgstr "Nome tecnico" +#~ msgid "Tech Name" +#~ msgstr "Nome tecnico" -#. module: image_tag -#: model:ir.model.fields,help:image_tag.field_image_tag__tech_name -msgid "Unique name for technical purposes. Eg: server env keys." -msgstr "Nome univoco per motivi tecnici. Es: chiavi server ambiente." +#~ msgid "Unique name for technical purposes. Eg: server env keys." +#~ msgstr "Nome univoco per motivi tecnici. Es: chiavi server ambiente." From 01b4e7ab7d8ee4b49b1281b4d0563544a7db9a47 Mon Sep 17 00:00:00 2001 From: oca-ci Date: Thu, 20 Aug 2026 11:30:01 +0000 Subject: [PATCH 31/32] [UPD] Update storage_backend_ftp.pot --- storage_backend_ftp/i18n/storage_backend_ftp.pot | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/storage_backend_ftp/i18n/storage_backend_ftp.pot b/storage_backend_ftp/i18n/storage_backend_ftp.pot index 580c5a9256..2f780a8c0b 100644 --- a/storage_backend_ftp/i18n/storage_backend_ftp.pot +++ b/storage_backend_ftp/i18n/storage_backend_ftp.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" @@ -18,6 +18,11 @@ msgstr "" msgid "Backend Type" msgstr "" +#. module: storage_backend_ftp +#: model:ir.model.fields,field_description:storage_backend_ftp.field_storage_backend__backend_type_env_default +msgid "Backend Type Env Default" +msgstr "" + #. module: storage_backend_ftp #: model:ir.model.fields.selection,name:storage_backend_ftp.selection__storage_backend__ftp_encryption__tls_explicit msgid "Explicit FTP over TLS" From 7738d7997b8ec9a5a7bb48fc7a6cf4aa0864aefa Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Thu, 20 Aug 2026 11:33:32 +0000 Subject: [PATCH 32/32] [BOT] post-merge updates --- README.md | 1 + setup/_metapackage/VERSION.txt | 2 +- setup/_metapackage/setup.py | 1 + storage_backend_ftp/README.rst | 2 +- storage_backend_ftp/static/description/index.html | 2 +- 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ee67bf4c02..adf7845074 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ addon | version | maintainers | summary [image_tag](image_tag/) | 16.0.2.0.0 | | Image tag model [image_tag_environment](image_tag_environment/) | 16.0.2.0.0 | | Server environment features for the Image Tag model [storage_backend](storage_backend/) | 16.0.1.1.0 | | Implement the concept of Storage with amazon S3, sftp... +[storage_backend_ftp](storage_backend_ftp/) | 16.0.1.0.0 | | Implement FTP Storage [storage_backend_sftp](storage_backend_sftp/) | 16.0.1.0.2 | | Implement SFTP Storage [storage_file](storage_file/) | 16.0.1.0.1 | | Storage file in storage backend diff --git a/setup/_metapackage/VERSION.txt b/setup/_metapackage/VERSION.txt index 95cfd381bc..e3e99b0c1a 100644 --- a/setup/_metapackage/VERSION.txt +++ b/setup/_metapackage/VERSION.txt @@ -1 +1 @@ -16.0.20260820.0 \ No newline at end of file +16.0.20260820.1 \ No newline at end of file diff --git a/setup/_metapackage/setup.py b/setup/_metapackage/setup.py index f86f2f8335..312f6ce903 100644 --- a/setup/_metapackage/setup.py +++ b/setup/_metapackage/setup.py @@ -29,6 +29,7 @@ 'odoo-addon-image_tag>=16.0dev,<16.1dev', 'odoo-addon-image_tag_environment>=16.0dev,<16.1dev', 'odoo-addon-storage_backend>=16.0dev,<16.1dev', + 'odoo-addon-storage_backend_ftp>=16.0dev,<16.1dev', 'odoo-addon-storage_backend_sftp>=16.0dev,<16.1dev', 'odoo-addon-storage_file>=16.0dev,<16.1dev', ], diff --git a/storage_backend_ftp/README.rst b/storage_backend_ftp/README.rst index 5a2d748230..6e53cdb747 100644 --- a/storage_backend_ftp/README.rst +++ b/storage_backend_ftp/README.rst @@ -11,7 +11,7 @@ Storage Backend FTP !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - !! source digest: sha256:caf4f1efb3f07f4b77cec7afe2c53bec2e64cb061f93ecad19fb1bae279121e2 + !! source digest: sha256:56d23d879b05c109e87056403e4153adf478bf0ac3270e865cf1d248cfc6f3c5 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png diff --git a/storage_backend_ftp/static/description/index.html b/storage_backend_ftp/static/description/index.html index 6636472f6b..5c6201754a 100644 --- a/storage_backend_ftp/static/description/index.html +++ b/storage_backend_ftp/static/description/index.html @@ -372,7 +372,7 @@

Storage Backend FTP

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -!! source digest: sha256:caf4f1efb3f07f4b77cec7afe2c53bec2e64cb061f93ecad19fb1bae279121e2 +!! source digest: sha256:56d23d879b05c109e87056403e4153adf478bf0ac3270e865cf1d248cfc6f3c5 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->

Beta License: LGPL-3 OCA/storage Translate me on Weblate Try me on Runboat

Add FTP as storage backend