From d395c0ce15234844e7a943aa47485ab307e9c014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Tue, 15 Mar 2022 15:06:13 +0100 Subject: [PATCH 1/8] [ADD] attachment_zipped_download: New addon. TT33403 [UPD] Update attachment_zipped_download.pot [UPD] README.rst --- attachment_zipped_download/README.rst | 84 ++++ attachment_zipped_download/__init__.py | 2 + attachment_zipped_download/__manifest__.py | 15 + .../controllers/__init__.py | 1 + .../controllers/main.py | 21 + .../i18n/attachment_zipped_download.pot | 51 +++ attachment_zipped_download/i18n/es.po | 55 +++ attachment_zipped_download/models/__init__.py | 1 + .../models/ir_attachment.py | 36 ++ .../readme/CONTRIBUTORS.rst | 6 + .../readme/DESCRIPTION.rst | 1 + attachment_zipped_download/readme/USAGE.rst | 2 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 432 ++++++++++++++++++ attachment_zipped_download/tests/__init__.py | 3 + .../tests/test_attachment_zipped_download.py | 35 ++ .../views/ir_attachment_view.xml | 13 + 17 files changed, 758 insertions(+) create mode 100644 attachment_zipped_download/README.rst create mode 100644 attachment_zipped_download/__init__.py create mode 100644 attachment_zipped_download/__manifest__.py create mode 100644 attachment_zipped_download/controllers/__init__.py create mode 100644 attachment_zipped_download/controllers/main.py create mode 100644 attachment_zipped_download/i18n/attachment_zipped_download.pot create mode 100644 attachment_zipped_download/i18n/es.po create mode 100644 attachment_zipped_download/models/__init__.py create mode 100644 attachment_zipped_download/models/ir_attachment.py create mode 100644 attachment_zipped_download/readme/CONTRIBUTORS.rst create mode 100644 attachment_zipped_download/readme/DESCRIPTION.rst create mode 100644 attachment_zipped_download/readme/USAGE.rst create mode 100644 attachment_zipped_download/static/description/icon.png create mode 100644 attachment_zipped_download/static/description/index.html create mode 100644 attachment_zipped_download/tests/__init__.py create mode 100644 attachment_zipped_download/tests/test_attachment_zipped_download.py create mode 100644 attachment_zipped_download/views/ir_attachment_view.xml diff --git a/attachment_zipped_download/README.rst b/attachment_zipped_download/README.rst new file mode 100644 index 00000000..58bb48c4 --- /dev/null +++ b/attachment_zipped_download/README.rst @@ -0,0 +1,84 @@ +========================== +Attachment Zipped Download +========================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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-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%2Fknowledge-lightgray.png?logo=github + :target: https://github.com/OCA/knowledge/tree/14.0/attachment_zipped_download + :alt: OCA/knowledge +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/knowledge-14-0/knowledge-14-0-attachment_zipped_download + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/118/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allows downloading multiple attachments as a zip file. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +#. Go to *Settings > Technical > Database Structure > Attachments* and select some files. +#. Go to *Actions > Download* and a zip file containing the selected files will be downloaded. + +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 +~~~~~~~ + +* Tecnativa + +Contributors +~~~~~~~~~~~~ + +* César Fernández Domínguez + +* `Tecnativa `_: + + * Víctor Martínez + * Pedro M. Baeza + +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/knowledge `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/attachment_zipped_download/__init__.py b/attachment_zipped_download/__init__.py new file mode 100644 index 00000000..91c5580f --- /dev/null +++ b/attachment_zipped_download/__init__.py @@ -0,0 +1,2 @@ +from . import controllers +from . import models diff --git a/attachment_zipped_download/__manifest__.py b/attachment_zipped_download/__manifest__.py new file mode 100644 index 00000000..97b5f90f --- /dev/null +++ b/attachment_zipped_download/__manifest__.py @@ -0,0 +1,15 @@ +# Copyright 2022 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Attachment Zipped Download", + "version": "14.0.1.0.0", + "category": "Tools", + "website": "https://github.com/OCA/knowledge", + "author": "Tecnativa, Odoo Community Association (OCA)", + "license": "AGPL-3", + "depends": ["base"], + "data": [ + "views/ir_attachment_view.xml", + ], + "installable": True, +} diff --git a/attachment_zipped_download/controllers/__init__.py b/attachment_zipped_download/controllers/__init__.py new file mode 100644 index 00000000..12a7e529 --- /dev/null +++ b/attachment_zipped_download/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/attachment_zipped_download/controllers/main.py b/attachment_zipped_download/controllers/main.py new file mode 100644 index 00000000..f4b5f973 --- /dev/null +++ b/attachment_zipped_download/controllers/main.py @@ -0,0 +1,21 @@ +# Copyright 2019 César Fernández Domínguez +# Copyright 2022 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +from odoo import _, http +from odoo.http import request + + +class AttachmentZippedDownloadController(http.Controller): + @http.route("/web/attachment/download_zip", type="http", auth="user") + def download_zip(self, ids=None, debug=0): + ids = [] if not ids else ids + if len(ids) == 0: + return + list_ids = map(int, ids.split(",")) + out_file = request.env["ir.attachment"].browse(list_ids)._create_temp_zip() + return http.send_file( + filepath_or_fp=out_file, + mimetype="application/zip", + as_attachment=True, + filename=_("attachments.zip"), + ) diff --git a/attachment_zipped_download/i18n/attachment_zipped_download.pot b/attachment_zipped_download/i18n/attachment_zipped_download.pot new file mode 100644 index 00000000..89025db4 --- /dev/null +++ b/attachment_zipped_download/i18n/attachment_zipped_download.pot @@ -0,0 +1,51 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attachment_zipped_download +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: attachment_zipped_download +#: model:ir.model,name:attachment_zipped_download.model_ir_attachment +msgid "Attachment" +msgstr "" + +#. module: attachment_zipped_download +#: model:ir.model.fields,field_description:attachment_zipped_download.field_ir_attachment__display_name +msgid "Display Name" +msgstr "" + +#. module: attachment_zipped_download +#: model:ir.actions.server,name:attachment_zipped_download.action_attachments_download +msgid "Download" +msgstr "" + +#. module: attachment_zipped_download +#: model:ir.model.fields,field_description:attachment_zipped_download.field_ir_attachment__id +msgid "ID" +msgstr "" + +#. module: attachment_zipped_download +#: model:ir.model.fields,field_description:attachment_zipped_download.field_ir_attachment____last_update +msgid "Last Modified on" +msgstr "" + +#. module: attachment_zipped_download +#: code:addons/attachment_zipped_download/models/ir_attachment.py:0 +#, python-format +msgid "None attachment selected. Only binary attachments allowed." +msgstr "" + +#. module: attachment_zipped_download +#: code:addons/attachment_zipped_download/controllers/main.py:0 +#, python-format +msgid "attachments.zip" +msgstr "" diff --git a/attachment_zipped_download/i18n/es.po b/attachment_zipped_download/i18n/es.po new file mode 100644 index 00000000..bd6ee4c0 --- /dev/null +++ b/attachment_zipped_download/i18n/es.po @@ -0,0 +1,55 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attachment_zipped_download +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2022-03-15 14:04+0000\n" +"PO-Revision-Date: 2022-03-15 15:05+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: \n" +"X-Generator: Poedit 2.3\n" + +#. module: attachment_zipped_download +#: model:ir.model,name:attachment_zipped_download.model_ir_attachment +msgid "Attachment" +msgstr "Adjunto" + +#. module: attachment_zipped_download +#: model:ir.model.fields,field_description:attachment_zipped_download.field_ir_attachment__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: attachment_zipped_download +#: model:ir.actions.server,name:attachment_zipped_download.action_attachments_download +msgid "Download" +msgstr "Descargar" + +#. module: attachment_zipped_download +#: model:ir.model.fields,field_description:attachment_zipped_download.field_ir_attachment__id +msgid "ID" +msgstr "ID" + +#. module: attachment_zipped_download +#: model:ir.model.fields,field_description:attachment_zipped_download.field_ir_attachment____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: attachment_zipped_download +#: code:addons/attachment_zipped_download/models/ir_attachment.py:0 +#, python-format +msgid "None attachment selected. Only binary attachments allowed." +msgstr "No se seleccionó ningún archivo adjunto. Solo se permiten archivos adjuntos binarios." + +#. module: attachment_zipped_download +#: code:addons/attachment_zipped_download/controllers/main.py:0 +#, python-format +msgid "attachments.zip" +msgstr "adjuntos.zip" diff --git a/attachment_zipped_download/models/__init__.py b/attachment_zipped_download/models/__init__.py new file mode 100644 index 00000000..aaf38a16 --- /dev/null +++ b/attachment_zipped_download/models/__init__.py @@ -0,0 +1 @@ +from . import ir_attachment diff --git a/attachment_zipped_download/models/ir_attachment.py b/attachment_zipped_download/models/ir_attachment.py new file mode 100644 index 00000000..1f58adad --- /dev/null +++ b/attachment_zipped_download/models/ir_attachment.py @@ -0,0 +1,36 @@ +# Copyright 2019 César Fernández Domínguez +# Copyright 2022 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) +import zipfile +from io import BytesIO + +from odoo import _, models +from odoo.exceptions import UserError + + +class IrAttachment(models.Model): + _inherit = "ir.attachment" + + def action_attachments_download(self): + items = self.filtered(lambda x: x.type == "binary") + if not items: + raise UserError( + _("None attachment selected. Only binary attachments allowed.") + ) + ids = ",".join(map(str, items.ids)) + return { + "type": "ir.actions.act_url", + "url": "/web/attachment/download_zip?ids=%s" % (ids), + "target": "self", + } + + def _create_temp_zip(self): + zip_buffer = BytesIO() + with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file: + for attachment in self: + zip_file.write( + attachment._full_path(attachment.store_fname), attachment.name + ) + zip_buffer.seek(0) + zip_file.close() + return zip_buffer diff --git a/attachment_zipped_download/readme/CONTRIBUTORS.rst b/attachment_zipped_download/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..536c5890 --- /dev/null +++ b/attachment_zipped_download/readme/CONTRIBUTORS.rst @@ -0,0 +1,6 @@ +* César Fernández Domínguez + +* `Tecnativa `_: + + * Víctor Martínez + * Pedro M. Baeza diff --git a/attachment_zipped_download/readme/DESCRIPTION.rst b/attachment_zipped_download/readme/DESCRIPTION.rst new file mode 100644 index 00000000..15f07dbb --- /dev/null +++ b/attachment_zipped_download/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +This module allows downloading multiple attachments as a zip file. diff --git a/attachment_zipped_download/readme/USAGE.rst b/attachment_zipped_download/readme/USAGE.rst new file mode 100644 index 00000000..0acc4217 --- /dev/null +++ b/attachment_zipped_download/readme/USAGE.rst @@ -0,0 +1,2 @@ +#. Go to *Settings > Technical > Database Structure > Attachments* and select some files. +#. Go to *Actions > Download* and a zip file containing the selected files will be downloaded. diff --git a/attachment_zipped_download/static/description/icon.png b/attachment_zipped_download/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/attachment_zipped_download/static/description/index.html b/attachment_zipped_download/static/description/index.html new file mode 100644 index 00000000..b302dc2a --- /dev/null +++ b/attachment_zipped_download/static/description/index.html @@ -0,0 +1,432 @@ + + + + + + +Attachment Zipped Download + + + +
+

Attachment Zipped Download

+ + +

Beta License: AGPL-3 OCA/knowledge Translate me on Weblate Try me on Runbot

+

This module allows downloading multiple attachments as a zip file.

+

Table of contents

+ +
+

Usage

+
    +
  1. Go to Settings > Technical > Database Structure > Attachments and select some files.
  2. +
  3. Go to Actions > Download and a zip file containing the selected files will be downloaded.
  4. +
+
+
+

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

+
    +
  • Tecnativa
  • +
+
+
+

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/knowledge project on GitHub.

+

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

+
+
+
+ + diff --git a/attachment_zipped_download/tests/__init__.py b/attachment_zipped_download/tests/__init__.py new file mode 100644 index 00000000..2654e07a --- /dev/null +++ b/attachment_zipped_download/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) + +from . import test_attachment_zipped_download diff --git a/attachment_zipped_download/tests/test_attachment_zipped_download.py b/attachment_zipped_download/tests/test_attachment_zipped_download.py new file mode 100644 index 00000000..63799c8f --- /dev/null +++ b/attachment_zipped_download/tests/test_attachment_zipped_download.py @@ -0,0 +1,35 @@ +# Copyright 2022 Tecnativa - Víctor Martínez +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +import base64 + +import odoo.tests + + +class TestAttachmentZippedDownload(odoo.tests.HttpCase): + def setUp(self): + super().setUp() + test_1 = self._create_attachment("test1.txt") + test_2 = self._create_attachment("test2.txt") + self.attachments = test_1 + test_2 + self.user = self.env["res.users"].create( + { + "name": "test-user", + "login": "test-user", + "password": "test-user", + "groups_id": [(6, 0, [self.env.ref("base.group_user").id])], + } + ) + + def _create_attachment(self, name): + return self.env["ir.attachment"].create( + { + "name": name, + "datas": base64.b64encode(b"\xff data"), + } + ) + + def test_action_attachments_download(self): + self.authenticate("test-user", "test-user") + res = self.attachments.action_attachments_download() + response = self.url_open(res["url"], timeout=20) + self.assertEqual(response.status_code, 200) diff --git a/attachment_zipped_download/views/ir_attachment_view.xml b/attachment_zipped_download/views/ir_attachment_view.xml new file mode 100644 index 00000000..4f4e2b16 --- /dev/null +++ b/attachment_zipped_download/views/ir_attachment_view.xml @@ -0,0 +1,13 @@ + + + + Download + + + code + + if records: + action = records.action_attachments_download() + + + From 1443166fa1545b651bd2ad00d5c0fb58a6f34269 Mon Sep 17 00:00:00 2001 From: mymage Date: Wed, 28 Dec 2022 22:40:10 +0000 Subject: [PATCH 2/8] Added translation using Weblate (Italian) Translated using Weblate (Italian) Currently translated at 100.0% (7 of 7 strings) Translation: knowledge-14.0/knowledge-14.0-attachment_zipped_download Translate-URL: https://translation.odoo-community.org/projects/knowledge-14-0/knowledge-14-0-attachment_zipped_download/it/ --- attachment_zipped_download/i18n/it.po | 54 +++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 attachment_zipped_download/i18n/it.po diff --git a/attachment_zipped_download/i18n/it.po b/attachment_zipped_download/i18n/it.po new file mode 100644 index 00000000..dde33dfb --- /dev/null +++ b/attachment_zipped_download/i18n/it.po @@ -0,0 +1,54 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * attachment_zipped_download +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2022-12-29 02:09+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.14.1\n" + +#. module: attachment_zipped_download +#: model:ir.model,name:attachment_zipped_download.model_ir_attachment +msgid "Attachment" +msgstr "Allegato" + +#. module: attachment_zipped_download +#: model:ir.model.fields,field_description:attachment_zipped_download.field_ir_attachment__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: attachment_zipped_download +#: model:ir.actions.server,name:attachment_zipped_download.action_attachments_download +msgid "Download" +msgstr "Scarica" + +#. module: attachment_zipped_download +#: model:ir.model.fields,field_description:attachment_zipped_download.field_ir_attachment__id +msgid "ID" +msgstr "ID" + +#. module: attachment_zipped_download +#: model:ir.model.fields,field_description:attachment_zipped_download.field_ir_attachment____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. module: attachment_zipped_download +#: code:addons/attachment_zipped_download/models/ir_attachment.py:0 +#, python-format +msgid "None attachment selected. Only binary attachments allowed." +msgstr "Nessun allegato selezionato. Consentiti solo allegati binari." + +#. module: attachment_zipped_download +#: code:addons/attachment_zipped_download/controllers/main.py:0 +#, python-format +msgid "attachments.zip" +msgstr "attachments.zip" From 85d1c6bc86e996801cfacf991e6d2d6698687114 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Tue, 24 Jan 2023 13:28:59 +0100 Subject: [PATCH 3/8] [FIX] attachment_zipped_download: Fix tests attachment_zipped_download 14.0.1.0.1 --- attachment_zipped_download/__manifest__.py | 2 +- .../tests/test_attachment_zipped_download.py | 43 +++++++++++-------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/attachment_zipped_download/__manifest__.py b/attachment_zipped_download/__manifest__.py index 97b5f90f..932e2889 100644 --- a/attachment_zipped_download/__manifest__.py +++ b/attachment_zipped_download/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Attachment Zipped Download", - "version": "14.0.1.0.0", + "version": "14.0.1.0.1", "category": "Tools", "website": "https://github.com/OCA/knowledge", "author": "Tecnativa, Odoo Community Association (OCA)", diff --git a/attachment_zipped_download/tests/test_attachment_zipped_download.py b/attachment_zipped_download/tests/test_attachment_zipped_download.py index 63799c8f..1fe0c709 100644 --- a/attachment_zipped_download/tests/test_attachment_zipped_download.py +++ b/attachment_zipped_download/tests/test_attachment_zipped_download.py @@ -1,31 +1,40 @@ -# Copyright 2022 Tecnativa - Víctor Martínez +# Copyright 2022-2023 Tecnativa - Víctor Martínez # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import base64 import odoo.tests +from odoo.tests import new_test_user class TestAttachmentZippedDownload(odoo.tests.HttpCase): def setUp(self): super().setUp() - test_1 = self._create_attachment("test1.txt") - test_2 = self._create_attachment("test2.txt") - self.attachments = test_1 + test_2 - self.user = self.env["res.users"].create( - { - "name": "test-user", - "login": "test-user", - "password": "test-user", - "groups_id": [(6, 0, [self.env.ref("base.group_user").id])], - } + ctx = { + "mail_create_nolog": True, + "mail_create_nosubscribe": True, + "mail_notrack": True, + "no_reset_password": True, + } + self.user = new_test_user( + self.env, + login="test-user", + password="test-user", + context=ctx, ) + test_1 = self._create_attachment(self.user, "test1.txt") + test_2 = self._create_attachment(self.user, "test2.txt") + self.attachments = test_1 + test_2 - def _create_attachment(self, name): - return self.env["ir.attachment"].create( - { - "name": name, - "datas": base64.b64encode(b"\xff data"), - } + def _create_attachment(self, user, name): + return ( + self.env["ir.attachment"] + .with_user(user) + .create( + { + "name": name, + "datas": base64.b64encode(b"\xff data"), + } + ) ) def test_action_attachments_download(self): From b24ac7ba318d9833c146aee7780b38384847da2b Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 28 Apr 2023 13:51:35 +0200 Subject: [PATCH 4/8] [FIX] attachment_zipped_download: zip allowed document only The previous code allowed any authenticated to retreive any attachment present on odoo filesystem. So a WMS user could technically spoken download a zip with accounting documents. This implementation is calling attachemnt.check("read") to ensure access right and use attachemnt.raw attribute to retreive file to archive which (not test) should works with attachment saved somewhere else than the local filesystem (s3 storage, pgsql large object storage...). attachment_zipped_download 14.0.1.0.2 --- attachment_zipped_download/__manifest__.py | 2 +- .../models/ir_attachment.py | 11 ++- .../tests/test_attachment_zipped_download.py | 84 +++++++++++++++---- 3 files changed, 77 insertions(+), 20 deletions(-) diff --git a/attachment_zipped_download/__manifest__.py b/attachment_zipped_download/__manifest__.py index 932e2889..b9329f5c 100644 --- a/attachment_zipped_download/__manifest__.py +++ b/attachment_zipped_download/__manifest__.py @@ -2,7 +2,7 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Attachment Zipped Download", - "version": "14.0.1.0.1", + "version": "14.0.1.0.2", "category": "Tools", "website": "https://github.com/OCA/knowledge", "author": "Tecnativa, Odoo Community Association (OCA)", diff --git a/attachment_zipped_download/models/ir_attachment.py b/attachment_zipped_download/models/ir_attachment.py index 1f58adad..f91d8588 100644 --- a/attachment_zipped_download/models/ir_attachment.py +++ b/attachment_zipped_download/models/ir_attachment.py @@ -28,9 +28,16 @@ class IrAttachment(models.Model): zip_buffer = BytesIO() with zipfile.ZipFile(zip_buffer, "a", zipfile.ZIP_DEFLATED, False) as zip_file: for attachment in self: - zip_file.write( - attachment._full_path(attachment.store_fname), attachment.name + attachment.check("read") + zip_file.writestr( + attachment._compute_zip_file_name(), + attachment.raw, ) zip_buffer.seek(0) zip_file.close() return zip_buffer + + def _compute_zip_file_name(self): + """Give a chance of easily changing the name of the file inside the ZIP.""" + self.ensure_one() + return self.name diff --git a/attachment_zipped_download/tests/test_attachment_zipped_download.py b/attachment_zipped_download/tests/test_attachment_zipped_download.py index 1fe0c709..e4e1281a 100644 --- a/attachment_zipped_download/tests/test_attachment_zipped_download.py +++ b/attachment_zipped_download/tests/test_attachment_zipped_download.py @@ -1,12 +1,30 @@ # Copyright 2022-2023 Tecnativa - Víctor Martínez # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). import base64 +from unittest import TestCase -import odoo.tests -from odoo.tests import new_test_user +from odoo.exceptions import AccessError +from odoo.tests import HttpCase, SavepointCase, new_test_user -class TestAttachmentZippedDownload(odoo.tests.HttpCase): +class TestAttachmentZippedDownloadBase(TestCase): + @classmethod + def _create_attachment(cls, env, user, name, model=False, res_id=False): + return ( + env["ir.attachment"] + .with_user(user) + .create( + { + "name": name, + "datas": base64.b64encode(b"\xff data"), + "res_model": model, + "res_id": res_id, + } + ) + ) + + +class TestAttachmentZippedDownload(HttpCase, TestAttachmentZippedDownloadBase): def setUp(self): super().setUp() ctx = { @@ -21,24 +39,56 @@ class TestAttachmentZippedDownload(odoo.tests.HttpCase): password="test-user", context=ctx, ) - test_1 = self._create_attachment(self.user, "test1.txt") - test_2 = self._create_attachment(self.user, "test2.txt") + test_1 = self._create_attachment(self.env, self.user, "test1.txt") + test_2 = self._create_attachment(self.env, self.user, "test2.txt") self.attachments = test_1 + test_2 - def _create_attachment(self, user, name): - return ( - self.env["ir.attachment"] - .with_user(user) - .create( - { - "name": name, - "datas": base64.b64encode(b"\xff data"), - } - ) - ) - def test_action_attachments_download(self): self.authenticate("test-user", "test-user") res = self.attachments.action_attachments_download() response = self.url_open(res["url"], timeout=20) self.assertEqual(response.status_code, 200) + + +class TestAttachmentZipped(SavepointCase, TestAttachmentZippedDownloadBase): + @classmethod + def setUpClass(cls): + super().setUpClass() + ctx = { + "mail_create_nolog": True, + "mail_create_nosubscribe": True, + "mail_notrack": True, + "no_reset_password": True, + } + cls.user = new_test_user( + cls.env, + login="test-user", + password="test-user", + groups="base.group_user,base.group_partner_manager", + context=ctx, + ) + test_1 = cls._create_attachment(cls.env, cls.user, "test1.txt") + test_2 = cls._create_attachment(cls.env, cls.user, "test2.txt") + test_3 = cls._create_attachment( + cls.env, + cls.user, + "test3.txt", + model="res.partner", + res_id=cls.user.partner_id.id, + ) + cls.attachments = test_1 + test_2 + test_3 + + def test_create_temp_zip(self): + res = self.attachments._create_temp_zip() + self.assertTrue(res) + + def test_create_temp_zip_access_denined(self): + attachments = self.attachments | self._create_attachment( + self.env, + self.uid, + "test4.txt", + model="ir.ui.view", + res_id=self.env.ref("base.view_view_form").id, + ) + with self.assertRaises(AccessError): + attachments._create_temp_zip() From 9cfafbb23966e5eecddc56707a1af3b0b326c10d Mon Sep 17 00:00:00 2001 From: Pierre Verkest Date: Fri, 28 Apr 2023 16:13:20 +0200 Subject: [PATCH 5/8] [IMP] attachment_zipped_download: provide ir.attachment.action_download mixin This helps to download multiple attachments from any models. [UPD] Update attachment_zipped_download.pot [UPD] README.rst attachment_zipped_download 14.0.2.0.0 [UPD] README.rst Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: knowledge-14.0/knowledge-14.0-attachment_zipped_download Translate-URL: https://translation.odoo-community.org/projects/knowledge-14-0/knowledge-14-0-attachment_zipped_download/ --- attachment_zipped_download/README.rst | 96 ++++++++++++++- attachment_zipped_download/__manifest__.py | 2 +- .../i18n/attachment_zipped_download.pot | 23 ++++ attachment_zipped_download/i18n/es.po | 27 +++- attachment_zipped_download/i18n/fr.po | 78 ++++++++++++ attachment_zipped_download/i18n/it.po | 23 ++++ attachment_zipped_download/models/__init__.py | 1 + .../models/ir_attachment_action_download.py | 55 +++++++++ .../readme/CONTRIBUTORS.rst | 2 + .../readme/DESCRIPTION.rst | 3 + attachment_zipped_download/readme/USAGE.rst | 76 ++++++++++++ .../static/description/index.html | 115 +++++++++++++++--- attachment_zipped_download/tests/__init__.py | 1 + .../tests/models/__init__.py | 0 .../tests/models/res_partner.py | 9 ++ .../test_ir_attachment_action_download.py | 81 ++++++++++++ 16 files changed, 566 insertions(+), 26 deletions(-) create mode 100644 attachment_zipped_download/i18n/fr.po create mode 100644 attachment_zipped_download/models/ir_attachment_action_download.py create mode 100644 attachment_zipped_download/tests/models/__init__.py create mode 100644 attachment_zipped_download/tests/models/res_partner.py create mode 100644 attachment_zipped_download/tests/test_ir_attachment_action_download.py diff --git a/attachment_zipped_download/README.rst b/attachment_zipped_download/README.rst index 58bb48c4..b60fce52 100644 --- a/attachment_zipped_download/README.rst +++ b/attachment_zipped_download/README.rst @@ -2,10 +2,13 @@ Attachment Zipped Download ========================== -.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:f01e61d6df5d9f4d83daca5a9e41a5224a22debafe05c1e3ea55572df7587a51 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status @@ -19,14 +22,17 @@ Attachment Zipped Download .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png :target: https://translation.odoo-community.org/projects/knowledge-14-0/knowledge-14-0-attachment_zipped_download :alt: Translate me on Weblate -.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/118/14.0 - :alt: Try me on Runbot +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/knowledge&target_branch=14.0 + :alt: Try me on Runboat -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| This module allows downloading multiple attachments as a zip file. +This also provide a helper class `IrAttachmentActionDownloadMixin` +to be used by developer to add action method on models. + **Table of contents** .. contents:: @@ -38,12 +44,88 @@ Usage #. Go to *Settings > Technical > Database Structure > Attachments* and select some files. #. Go to *Actions > Download* and a zip file containing the selected files will be downloaded. +## For developer + +You can reuse the `IrAttachmentActionDownloadMixin` on your +favorite models:: + + from odoo import models + + + class StockPicking(models.Model): + _name = "stock.picking" + _inherit = ["stock.picking", "ir.attachment.action_download"] + + +Then you can add an action button on list view line or on the action button +(when multiple lines are selected) to download all files:: + + + + + + stock.picking.tree download attachments + stock.picking + + +