diff --git a/fs_attachment/__manifest__.py b/fs_attachment/__manifest__.py index 4d2be130b3..ff2667e4c3 100644 --- a/fs_attachment/__manifest__.py +++ b/fs_attachment/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Base Attachment Object Store", "summary": "Store attachments on external object store", - "version": "19.0.1.1.2", + "version": "19.0.1.1.3", "author": "Camptocamp, ACSONE SA/NV, Odoo Community Association (OCA)", "license": "AGPL-3", "development_status": "Beta", diff --git a/fs_attachment/models/fs_storage.py b/fs_attachment/models/fs_storage.py index 80155739ff..fdffe76e15 100644 --- a/fs_attachment/models/fs_storage.py +++ b/fs_attachment/models/fs_storage.py @@ -89,23 +89,6 @@ def _check_use_as_default_for_attachments(self): self.env._("Only one storage can be used as default for attachments") ) - @property - def _server_env_fields(self): - env_fields = super()._server_env_fields - env_fields.update( - { - "optimizes_directory_path": {}, - "autovacuum_gc": {}, - "base_url": {}, - "is_directory_path_in_url": {}, - "use_x_sendfile_to_serve_internal_url": {}, - "use_as_default_for_attachments": {}, - "force_db_for_default_attachment_rules": {}, - "use_filename_obfuscation": {}, - } - ) - return env_fields - @property def _default_force_db_for_default_attachment_rules(self) -> str: return '{"image/": 51200, "application/javascript": 0, "text/css": 0}' diff --git a/fs_attachment/tests/test_fs_storage.py b/fs_attachment/tests/test_fs_storage.py index 3947b1b647..43a5c4d679 100644 --- a/fs_attachment/tests/test_fs_storage.py +++ b/fs_attachment/tests/test_fs_storage.py @@ -300,6 +300,7 @@ def test_url_for_image_dir_optimized_and_not_obfuscated(self): "name": "FS Product Image Backend", "code": "file", "base_url": "https://localhost/images", + "protocol": "odoofs", "optimizes_directory_path": True, "use_filename_obfuscation": False, } diff --git a/fs_attachment/upgrades/19.0.1.1.3/post-migration.py b/fs_attachment/upgrades/19.0.1.1.3/post-migration.py new file mode 100644 index 0000000000..d8aa7045c4 --- /dev/null +++ b/fs_attachment/upgrades/19.0.1.1.3/post-migration.py @@ -0,0 +1,21 @@ +from openupgradelib import openupgrade + +from odoo import exceptions + + +@openupgrade.migrate() +def migrate(env, version): + module = env["ir.module.module"].search( + [("name", "=", "fs_attachment_environment")] + ) + if not module: + raise exceptions.UserError( + env._( + "The 'fs_attachment_environment' module is not available. " + "It is required to preserve the server environment managed " + "fields of 'fs.storage'. Make it available on the " + "addons path before upgrading 'fs_attachment'." + ) + ) + if module.state == "uninstalled": + module.button_install() diff --git a/fs_attachment_environment/README.rst b/fs_attachment_environment/README.rst new file mode 100644 index 0000000000..a9846b8f93 --- /dev/null +++ b/fs_attachment_environment/README.rst @@ -0,0 +1,83 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +============================= +Filesystem Attachment Backend +============================= + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:bbd1be658bbe5cda3a0ca2391c1de17eafb45624ac49610b3b2503c65d2610af + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/19.0/fs_attachment_environment + :alt: OCA/storage +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/storage-19-0/storage-19-0-fs_attachment_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=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Glue module for fs_attachment to use fs_storage_environment + +**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 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 +* Dixmit + +Contributors +------------ + +- Laurent Mignon +- Sébastien BEAU +- Enric Tobella + +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/fs_attachment_environment/__init__.py b/fs_attachment_environment/__init__.py new file mode 100644 index 0000000000..1a9a001cf7 --- /dev/null +++ b/fs_attachment_environment/__init__.py @@ -0,0 +1,2 @@ +from . import models +from .hooks import post_init_hook, uninstall_hook diff --git a/fs_attachment_environment/__manifest__.py b/fs_attachment_environment/__manifest__.py new file mode 100644 index 0000000000..9dd790a6db --- /dev/null +++ b/fs_attachment_environment/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2026 Dixmit +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Filesystem Attachment Backend", + "summary": "Allows to use server environment with fs storage attachment", + "version": "19.0.1.0.0", + "category": "FS Storage", + "website": "https://github.com/OCA/storage", + "author": " ACSONE SA/NV, Dixmit, Odoo Community Association (OCA)", + "license": "AGPL-3", + "development_status": "Beta", + "installable": True, + "depends": ["fs_storage_environment", "fs_attachment"], + "post_init_hook": "post_init_hook", + "uninstall_hook": "uninstall_hook", +} diff --git a/fs_attachment_environment/hooks.py b/fs_attachment_environment/hooks.py new file mode 100644 index 0000000000..f2fad32319 --- /dev/null +++ b/fs_attachment_environment/hooks.py @@ -0,0 +1,46 @@ +# Copyright 2026 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tools import SQL + +from odoo.addons.server_environment.uninstall import restore_env_managed_columns + +ENV_MANAGED_FIELDS = [ + "optimizes_directory_path", + "autovacuum_gc", + "base_url", + "is_directory_path_in_url", + "use_x_sendfile_to_serve_internal_url", + "use_as_default_for_attachments", + "force_db_for_default_attachment_rules", + "use_filename_obfuscation", +] + + +def post_init_hook(env): + """Preserve fallback values without violating the attachment rule constraint. + + On a fresh install, Odoo initializes the new force database rules column on + existing storages with its non-empty default, even when the storage is not + the default attachment storage. The preservation helper writes fields back + through the ORM one at a time, so this temporary inconsistent state would + trigger the constraint. Normalize the stored fallback with SQL first. + """ + env.cr.execute( + SQL( + "UPDATE %s SET %s = NULL WHERE NOT COALESCE(%s, FALSE)", + SQL.identifier(env["fs.storage"]._table), + SQL.identifier("force_db_for_default_attachment_rules"), + SQL.identifier("use_as_default_for_attachments"), + ) + ) + env["fs.storage"]._preserve_not_env_managed_data(ENV_MANAGED_FIELDS) + + +def uninstall_hook(env): + """Restore database columns dropped by server.env.mixin.""" + restore_env_managed_columns( + env, + "fs.storage", + ENV_MANAGED_FIELDS, + ) diff --git a/fs_attachment_environment/models/__init__.py b/fs_attachment_environment/models/__init__.py new file mode 100644 index 0000000000..349bb0495a --- /dev/null +++ b/fs_attachment_environment/models/__init__.py @@ -0,0 +1 @@ +from . import fs_storage diff --git a/fs_attachment_environment/models/fs_storage.py b/fs_attachment_environment/models/fs_storage.py new file mode 100644 index 0000000000..6d520a3494 --- /dev/null +++ b/fs_attachment_environment/models/fs_storage.py @@ -0,0 +1,30 @@ +# Copyright 2023 ACSONE SA/NV (https://www.acsone.eu). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +from __future__ import annotations + +import logging + +from odoo import models + +_logger = logging.getLogger(__name__) + + +class FSStorage(models.Model): + _inherit = "fs.storage" + + @property + def _server_env_fields(self): + env_fields = super()._server_env_fields + env_fields.update( + { + "optimizes_directory_path": {}, + "autovacuum_gc": {}, + "base_url": {}, + "is_directory_path_in_url": {}, + "use_x_sendfile_to_serve_internal_url": {}, + "use_as_default_for_attachments": {}, + "force_db_for_default_attachment_rules": {}, + "use_filename_obfuscation": {}, + } + ) + return env_fields diff --git a/fs_attachment_environment/pyproject.toml b/fs_attachment_environment/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/fs_attachment_environment/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/fs_attachment_environment/readme/CONTRIBUTORS.md b/fs_attachment_environment/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..b4896734fa --- /dev/null +++ b/fs_attachment_environment/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- Laurent Mignon \ +- Sébastien BEAU \ +- Enric Tobella diff --git a/fs_attachment_environment/readme/DESCRIPTION.md b/fs_attachment_environment/readme/DESCRIPTION.md new file mode 100644 index 0000000000..9411ff1785 --- /dev/null +++ b/fs_attachment_environment/readme/DESCRIPTION.md @@ -0,0 +1 @@ +Glue module for fs_attachment to use fs_storage_environment diff --git a/fs_attachment_environment/static/description/icon.png b/fs_attachment_environment/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/fs_attachment_environment/static/description/icon.png differ diff --git a/fs_attachment_environment/static/description/index.html b/fs_attachment_environment/static/description/index.html new file mode 100644 index 0000000000..bc7b3b472c --- /dev/null +++ b/fs_attachment_environment/static/description/index.html @@ -0,0 +1,432 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Filesystem Attachment Backend

+ +

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

+

Glue module for fs_attachment to use fs_storage_environment

+

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 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
  • +
  • Dixmit
  • +
+
+
+

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/fs_attachment_s3/__manifest__.py b/fs_attachment_s3/__manifest__.py index 75baac25ac..cf2fd61221 100644 --- a/fs_attachment_s3/__manifest__.py +++ b/fs_attachment_s3/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Fs Attachment S3", "summary": """Store attachments into S3 complient filesystem""", - "version": "19.0.1.2.0", + "version": "19.0.1.2.1", "license": "AGPL-3", "author": "ACSONE SA/NV,Odoo Community Association (OCA)", "website": "https://github.com/OCA/storage", diff --git a/fs_attachment_s3/models/fs_storage.py b/fs_attachment_s3/models/fs_storage.py index 1b737c722d..9007b85297 100644 --- a/fs_attachment_s3/models/fs_storage.py +++ b/fs_attachment_s3/models/fs_storage.py @@ -22,18 +22,6 @@ class FsStorage(models.Model): "Default is 30 seconds.", ) - @property - def _server_env_fields(self): - """Override to include S3 specific fields.""" - fields = super()._server_env_fields - fields.update( - { - "s3_uses_signed_url_for_x_sendfile": {}, - "s3_signed_url_expiration": {}, - } - ) - return fields - @property def is_s3_storage(self): """Check if the storage is an S3 storage.""" diff --git a/fs_attachment_s3/upgrades/19.0.1.2.1/post-migration.py b/fs_attachment_s3/upgrades/19.0.1.2.1/post-migration.py new file mode 100644 index 0000000000..a716e623c0 --- /dev/null +++ b/fs_attachment_s3/upgrades/19.0.1.2.1/post-migration.py @@ -0,0 +1,21 @@ +from openupgradelib import openupgrade + +from odoo import exceptions + + +@openupgrade.migrate() +def migrate(env, version): + module = env["ir.module.module"].search( + [("name", "=", "fs_attachment_s3_environment")] + ) + if not module: + raise exceptions.UserError( + env._( + "The 'fs_attachment_s3_environment' module is not available. " + "It is required to preserve the server environment managed " + "fields of 'fs.storage'. Make it available on the " + "addons path before upgrading 'fs_attachment_s3'." + ) + ) + if module.state == "uninstalled": + module.button_install() diff --git a/fs_attachment_s3_environment/README.rst b/fs_attachment_s3_environment/README.rst new file mode 100644 index 0000000000..1c6655ff39 --- /dev/null +++ b/fs_attachment_s3_environment/README.rst @@ -0,0 +1,83 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +================================ +Filesystem Attachment Backend S3 +================================ + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:bbd1be658bbe5cda3a0ca2391c1de17eafb45624ac49610b3b2503c65d2610af + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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/19.0/fs_attachment_s3_environment + :alt: OCA/storage +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/storage-19-0/storage-19-0-fs_attachment_s3_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=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Glue module for fs_attachment to use fs_storage_environment + +**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 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 +* Dixmit + +Contributors +------------ + +- Laurent Mignon +- Sébastien BEAU +- Enric Tobella + +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/fs_attachment_s3_environment/__init__.py b/fs_attachment_s3_environment/__init__.py new file mode 100644 index 0000000000..1a9a001cf7 --- /dev/null +++ b/fs_attachment_s3_environment/__init__.py @@ -0,0 +1,2 @@ +from . import models +from .hooks import post_init_hook, uninstall_hook diff --git a/fs_attachment_s3_environment/__manifest__.py b/fs_attachment_s3_environment/__manifest__.py new file mode 100644 index 0000000000..4c0787b9f6 --- /dev/null +++ b/fs_attachment_s3_environment/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2026 Dixmit +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + "name": "Filesystem Attachment Backend S3", + "summary": "Allows to use server environment with fs storage attachment S3", + "version": "19.0.1.0.0", + "category": "FS Storage", + "website": "https://github.com/OCA/storage", + "author": " ACSONE SA/NV, Dixmit, Odoo Community Association (OCA)", + "license": "AGPL-3", + "development_status": "Beta", + "installable": True, + "depends": ["fs_attachment_environment", "fs_attachment_s3"], + "post_init_hook": "post_init_hook", + "uninstall_hook": "uninstall_hook", +} diff --git a/fs_attachment_s3_environment/hooks.py b/fs_attachment_s3_environment/hooks.py new file mode 100644 index 0000000000..ab948acfd0 --- /dev/null +++ b/fs_attachment_s3_environment/hooks.py @@ -0,0 +1,22 @@ +# Copyright 2026 Camptocamp SA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.addons.server_environment.uninstall import restore_env_managed_columns + +ENV_MANAGED_FIELDS = [ + "s3_uses_signed_url_for_x_sendfile", + "s3_signed_url_expiration", +] + + +def post_init_hook(env): + env["fs.storage"]._preserve_not_env_managed_data(ENV_MANAGED_FIELDS) + + +def uninstall_hook(env): + """Restore database columns dropped by server.env.mixin.""" + restore_env_managed_columns( + env, + "fs.storage", + ENV_MANAGED_FIELDS, + ) diff --git a/fs_attachment_s3_environment/models/__init__.py b/fs_attachment_s3_environment/models/__init__.py new file mode 100644 index 0000000000..349bb0495a --- /dev/null +++ b/fs_attachment_s3_environment/models/__init__.py @@ -0,0 +1 @@ +from . import fs_storage diff --git a/fs_attachment_s3_environment/models/fs_storage.py b/fs_attachment_s3_environment/models/fs_storage.py new file mode 100644 index 0000000000..3057681e7a --- /dev/null +++ b/fs_attachment_s3_environment/models/fs_storage.py @@ -0,0 +1,25 @@ +# Copyright 2023 ACSONE SA/NV (https://www.acsone.eu). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +from __future__ import annotations + +import logging + +from odoo import models + +_logger = logging.getLogger(__name__) + + +class FSStorage(models.Model): + _inherit = "fs.storage" + + @property + def _server_env_fields(self): + """Override to include S3 specific fields.""" + fields = super()._server_env_fields + fields.update( + { + "s3_uses_signed_url_for_x_sendfile": {}, + "s3_signed_url_expiration": {}, + } + ) + return fields diff --git a/fs_attachment_s3_environment/pyproject.toml b/fs_attachment_s3_environment/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/fs_attachment_s3_environment/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/fs_attachment_s3_environment/readme/CONTRIBUTORS.md b/fs_attachment_s3_environment/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..b4896734fa --- /dev/null +++ b/fs_attachment_s3_environment/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- Laurent Mignon \ +- Sébastien BEAU \ +- Enric Tobella diff --git a/fs_attachment_s3_environment/readme/DESCRIPTION.md b/fs_attachment_s3_environment/readme/DESCRIPTION.md new file mode 100644 index 0000000000..9411ff1785 --- /dev/null +++ b/fs_attachment_s3_environment/readme/DESCRIPTION.md @@ -0,0 +1 @@ +Glue module for fs_attachment to use fs_storage_environment diff --git a/fs_attachment_s3_environment/static/description/icon.png b/fs_attachment_s3_environment/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/fs_attachment_s3_environment/static/description/icon.png differ diff --git a/fs_attachment_s3_environment/static/description/index.html b/fs_attachment_s3_environment/static/description/index.html new file mode 100644 index 0000000000..00c3511bbf --- /dev/null +++ b/fs_attachment_s3_environment/static/description/index.html @@ -0,0 +1,432 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Filesystem Attachment Backend S3

+ +

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

+

Glue module for fs_attachment to use fs_storage_environment

+

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 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
  • +
  • Dixmit
  • +
+
+
+

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/fs_storage/__manifest__.py b/fs_storage/__manifest__.py index d9ec89cc10..b6e16ad18e 100644 --- a/fs_storage/__manifest__.py +++ b/fs_storage/__manifest__.py @@ -5,18 +5,18 @@ { "name": "Filesystem Storage Backend", "summary": "Implement the concept of Storage with amazon S3, sftp...", - "version": "19.0.1.1.2", + "version": "19.0.1.1.3", "category": "FS Storage", "website": "https://github.com/OCA/storage", "author": " ACSONE SA/NV, Odoo Community Association (OCA)", "license": "LGPL-3", "development_status": "Beta", - "depends": ["base", "base_sparse_field", "server_environment"], + "installable": True, + "depends": ["base", "base_sparse_field"], "data": [ "views/fs_storage_view.xml", "security/ir.model.access.csv", "wizards/fs_test_connection.xml", ], "external_dependencies": {"python": ["fsspec>=2024.5.0"]}, - "installable": True, } diff --git a/fs_storage/models/fs_storage.py b/fs_storage/models/fs_storage.py index 58ae2c6180..98f422a510 100644 --- a/fs_storage/models/fs_storage.py +++ b/fs_storage/models/fs_storage.py @@ -89,7 +89,6 @@ def wrapper(self, *args, **kwargs): class FSStorage(models.Model): _name = "fs.storage" - _inherit = "server.env.mixin" _description = "FS Storage" __slots__ = ("__fs", "__odoo_storage_path") @@ -229,8 +228,6 @@ def __init__(self, env, ids=(), prefetch_ids=()): "The code must be unique", ) - _server_env_section_name_field = "code" - @api.constrains("model_xmlids") def _check_model_xmlid_storage_unique(self): """ @@ -298,22 +295,12 @@ def _get_check_connection_method_selection(self): ("ls", self.env._("List File")), ] - @property - def _server_env_fields(self): - return { - "protocol": {}, - "options": {}, - "directory_path": {}, - "eval_options_from_env": {}, - "model_xmlids": {}, - "field_xmlids": {}, - "check_connection_method": {}, - } - @api.model_create_multi @prevent_call_from_safe_eval("create") def create(self, vals_list): - return super().create(vals_list) + records = super().create(vals_list) + self.env.registry.clear_cache() + return records @prevent_call_from_safe_eval("create") def _create(self, data_list): diff --git a/fs_storage/readme/newsfragments/627.feature.rst b/fs_storage/readme/newsfragments/627.feature.rst new file mode 100644 index 0000000000..0107afb987 --- /dev/null +++ b/fs_storage/readme/newsfragments/627.feature.rst @@ -0,0 +1 @@ +- Remove the dependancy of server_environment module and make fs_storage_environment a bridge between fs_storage and server_environment modules. \ No newline at end of file diff --git a/fs_storage/upgrades/19.0.1.1.3/post-update.py b/fs_storage/upgrades/19.0.1.1.3/post-update.py new file mode 100644 index 0000000000..420f3bfdb2 --- /dev/null +++ b/fs_storage/upgrades/19.0.1.1.3/post-update.py @@ -0,0 +1,19 @@ +from openupgradelib import openupgrade + +from odoo import exceptions + + +@openupgrade.migrate() +def migrate(env, version): + module = env["ir.module.module"].search([("name", "=", "fs_storage_environment")]) + if not module: + raise exceptions.UserError( + env._( + "The 'fs_storage_environment' module is not available. " + "It is required to preserve the server environment managed " + "fields of 'fs.storage'. Make it available on the " + "addons path before upgrading 'fs_storage'." + ) + ) + if module.state == "uninstalled": + module.button_install() diff --git a/fs_storage_environment/README.rst b/fs_storage_environment/README.rst new file mode 100644 index 0000000000..5085d587ae --- /dev/null +++ b/fs_storage_environment/README.rst @@ -0,0 +1,140 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +========================== +Filesystem Storage Backend +========================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:bbd1be658bbe5cda3a0ca2391c1de17eafb45624ac49610b3b2503c65d2610af + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |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-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/19.0/fs_storage_environment + :alt: OCA/storage +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/storage-19-0/storage-19-0-fs_storage_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=19.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows to use server environment with fs storage. It is a +bridge between fs_storage and server_environment modules. It provides an +implementation of the StorageEnvironment class that uses the filesystem +as a storage backend. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To ease the management of the filesystem storages configuration accross +the different environments, the configuration of the filesystem storages +can be defined in environment files or directly in the main +configuration file. For example, the configuration of a filesystem +storage with the code fsprod can be provided in the main configuration +file as follows: + +.. code:: ini + + [fs_storage.fsprod] + protocol=s3 + options={"endpoint_url": "https://my_s3_server/", "key": "KEY", "secret": "SECRET"} + directory_path=my_bucket + +To work, a storage.backend record must exist with the code fsprod into +the database. In your configuration section, you can specify the value +for the following fields: + +- protocol +- options +- directory_path + +When evaluating directory_path, {db_name} is replaced by the database +name. This is usefull in multi-tenant with a setup completly controlled +by configuration files. + +Migration from storage_backend +------------------------------ + +The fs_storage addon can be used to replace the storage_backend addon. +(It has been designed to be a drop-in replacement for the +storage_backend addon). To ease the migration, the fs.storage model +defines the high-level methods available in the storage_backend model. +These methods are: + +- add +- get +- list_files +- find_files +- move_files +- delete + +These methods are wrappers around the methods of the +fsspec.AbstractFileSystem class (see +https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.spec.AbstractFileSystem). +These methods are marked as deprecated and will be removed in a future +version (V18) of the addon. You should use the methods of the +fsspec.AbstractFileSystem class instead since they are more flexible and +powerful. You can access the instance of the fsspec.AbstractFileSystem +class using the fs property of a fs.storage record. + +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 +* Dixmit + +Contributors +------------ + +- Laurent Mignon +- Sébastien BEAU +- Enric Tobella + +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/fs_storage_environment/__init__.py b/fs_storage_environment/__init__.py new file mode 100644 index 0000000000..1a9a001cf7 --- /dev/null +++ b/fs_storage_environment/__init__.py @@ -0,0 +1,2 @@ +from . import models +from .hooks import post_init_hook, uninstall_hook diff --git a/fs_storage_environment/__manifest__.py b/fs_storage_environment/__manifest__.py new file mode 100644 index 0000000000..ecc55dbaa6 --- /dev/null +++ b/fs_storage_environment/__manifest__.py @@ -0,0 +1,17 @@ +# Copyright 2026 Dixmit +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +{ + "name": "Filesystem Storage Backend", + "summary": "Allows to use server environment with fs storage", + "version": "19.0.1.0.0", + "category": "FS Storage", + "website": "https://github.com/OCA/storage", + "author": " ACSONE SA/NV, Dixmit, Odoo Community Association (OCA)", + "license": "LGPL-3", + "development_status": "Beta", + "installable": True, + "depends": ["fs_storage", "server_environment"], + "post_init_hook": "post_init_hook", + "uninstall_hook": "uninstall_hook", +} diff --git a/fs_storage_environment/hooks.py b/fs_storage_environment/hooks.py new file mode 100644 index 0000000000..ce3e288b6a --- /dev/null +++ b/fs_storage_environment/hooks.py @@ -0,0 +1,28 @@ +# Copyright 2026 Camptocamp SA +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). + +from odoo.addons.server_environment.uninstall import restore_env_managed_columns + +ENV_MANAGED_FIELDS = [ + "protocol", + "options", + "directory_path", + "eval_options_from_env", + "model_xmlids", + "field_xmlids", + "check_connection_method", +] + + +def post_init_hook(env): + env["fs.storage"]._preserve_not_env_managed_data(ENV_MANAGED_FIELDS) + + +def uninstall_hook(env): + """Restore database columns dropped by server.env.mixin.""" + restore_env_managed_columns( + env, + "fs.storage", + ENV_MANAGED_FIELDS, + field_defaults={"protocol": "odoofs"}, + ) diff --git a/fs_storage_environment/models/__init__.py b/fs_storage_environment/models/__init__.py new file mode 100644 index 0000000000..349bb0495a --- /dev/null +++ b/fs_storage_environment/models/__init__.py @@ -0,0 +1 @@ +from . import fs_storage diff --git a/fs_storage_environment/models/fs_storage.py b/fs_storage_environment/models/fs_storage.py new file mode 100644 index 0000000000..57b08ba17d --- /dev/null +++ b/fs_storage_environment/models/fs_storage.py @@ -0,0 +1,28 @@ +# Copyright 2023 ACSONE SA/NV (https://www.acsone.eu). +# License LGPL-3.0 or later (http://www.gnu.org/licenses/lgpl). +from __future__ import annotations + +import logging + +from odoo import models + +_logger = logging.getLogger(__name__) + + +class FSStorage(models.Model): + _name = "fs.storage" + _inherit = ["fs.storage", "server.env.mixin"] + + _server_env_section_name_field = "code" + + @property + def _server_env_fields(self): + return { + "protocol": {}, + "options": {}, + "directory_path": {}, + "eval_options_from_env": {}, + "model_xmlids": {}, + "field_xmlids": {}, + "check_connection_method": {}, + } diff --git a/fs_storage_environment/pyproject.toml b/fs_storage_environment/pyproject.toml new file mode 100644 index 0000000000..4231d0cccb --- /dev/null +++ b/fs_storage_environment/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/fs_storage_environment/readme/CONTRIBUTORS.md b/fs_storage_environment/readme/CONTRIBUTORS.md new file mode 100644 index 0000000000..b4896734fa --- /dev/null +++ b/fs_storage_environment/readme/CONTRIBUTORS.md @@ -0,0 +1,3 @@ +- Laurent Mignon \ +- Sébastien BEAU \ +- Enric Tobella diff --git a/fs_storage_environment/readme/DESCRIPTION.md b/fs_storage_environment/readme/DESCRIPTION.md new file mode 100644 index 0000000000..a01fa9ab8d --- /dev/null +++ b/fs_storage_environment/readme/DESCRIPTION.md @@ -0,0 +1,4 @@ +This module allows to use server environment with fs storage. It is a +bridge between fs_storage and server_environment modules. It provides an +implementation of the StorageEnvironment class that uses the filesystem +as a storage backend. diff --git a/fs_storage_environment/readme/USAGE.md b/fs_storage_environment/readme/USAGE.md new file mode 100644 index 0000000000..fb7d2c073e --- /dev/null +++ b/fs_storage_environment/readme/USAGE.md @@ -0,0 +1,49 @@ +To ease the management of the filesystem storages configuration accross +the different environments, the configuration of the filesystem storages +can be defined in environment files or directly in the main +configuration file. For example, the configuration of a filesystem +storage with the code fsprod can be provided in the main configuration +file as follows: + +``` ini +[fs_storage.fsprod] +protocol=s3 +options={"endpoint_url": "https://my_s3_server/", "key": "KEY", "secret": "SECRET"} +directory_path=my_bucket +``` + +To work, a storage.backend record must exist with the code fsprod into +the database. In your configuration section, you can specify the value +for the following fields: + +- protocol +- options +- directory_path + +When evaluating directory_path, {db_name} is replaced by the database +name. This is usefull in multi-tenant with a setup completly controlled +by configuration files. + +## Migration from storage_backend + +The fs_storage addon can be used to replace the storage_backend addon. +(It has been designed to be a drop-in replacement for the +storage_backend addon). To ease the migration, the fs.storage model +defines the high-level methods available in the storage_backend model. +These methods are: + +- add +- get +- list_files +- find_files +- move_files +- delete + +These methods are wrappers around the methods of the +fsspec.AbstractFileSystem class (see +). +These methods are marked as deprecated and will be removed in a future +version (V18) of the addon. You should use the methods of the +fsspec.AbstractFileSystem class instead since they are more flexible and +powerful. You can access the instance of the fsspec.AbstractFileSystem +class using the fs property of a fs.storage record. diff --git a/fs_storage_environment/readme/newsfragments/.gitignore b/fs_storage_environment/readme/newsfragments/.gitignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/fs_storage_environment/static/description/icon.png b/fs_storage_environment/static/description/icon.png new file mode 100644 index 0000000000..3a0328b516 Binary files /dev/null and b/fs_storage_environment/static/description/icon.png differ diff --git a/fs_storage_environment/static/description/index.html b/fs_storage_environment/static/description/index.html new file mode 100644 index 0000000000..cc4dc3a736 --- /dev/null +++ b/fs_storage_environment/static/description/index.html @@ -0,0 +1,489 @@ + + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

Filesystem Storage Backend

+ +

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

+

This module allows to use server environment with fs storage. It is a +bridge between fs_storage and server_environment modules. It provides an +implementation of the StorageEnvironment class that uses the filesystem +as a storage backend.

+

Table of contents

+ +
+

Usage

+

To ease the management of the filesystem storages configuration accross +the different environments, the configuration of the filesystem storages +can be defined in environment files or directly in the main +configuration file. For example, the configuration of a filesystem +storage with the code fsprod can be provided in the main configuration +file as follows:

+
+[fs_storage.fsprod]
+protocol=s3
+options={"endpoint_url": "https://my_s3_server/", "key": "KEY", "secret": "SECRET"}
+directory_path=my_bucket
+
+

To work, a storage.backend record must exist with the code fsprod into +the database. In your configuration section, you can specify the value +for the following fields:

+
    +
  • protocol
  • +
  • options
  • +
  • directory_path
  • +
+

When evaluating directory_path, {db_name} is replaced by the database +name. This is usefull in multi-tenant with a setup completly controlled +by configuration files.

+
+

Migration from storage_backend

+

The fs_storage addon can be used to replace the storage_backend addon. +(It has been designed to be a drop-in replacement for the +storage_backend addon). To ease the migration, the fs.storage model +defines the high-level methods available in the storage_backend model. +These methods are:

+
    +
  • add
  • +
  • get
  • +
  • list_files
  • +
  • find_files
  • +
  • move_files
  • +
  • delete
  • +
+

These methods are wrappers around the methods of the +fsspec.AbstractFileSystem class (see +https://filesystem-spec.readthedocs.io/en/latest/api.html#fsspec.spec.AbstractFileSystem). +These methods are marked as deprecated and will be removed in a future +version (V18) of the addon. You should use the methods of the +fsspec.AbstractFileSystem class instead since they are more flexible and +powerful. You can access the instance of the fsspec.AbstractFileSystem +class using the fs property of a fs.storage record.

+
+
+
+

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
  • +
  • Dixmit
  • +
+
+
+

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/test-requirements.txt b/test-requirements.txt index e63f876677..6b97ab6755 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -2,3 +2,4 @@ odoo_test_helper requests_mock vcrpy-unittest s3fs>=2025.3.0 +odoo-addon-server_environment @ git+https://github.com/OCA/server-env.git@refs/pull/288/head#subdirectory=server_environment