From 58b3e973c94d438de4341759da30d7db8fefb232 Mon Sep 17 00:00:00 2001
From: Enric Tobella
Date: Wed, 16 Sep 2020 18:13:45 +0200
Subject: [PATCH 01/22] [ADD] report_qweb_encrypt
---
report_qweb_encrypt/README.rst | 80 ++++++++++++++++++
report_qweb_encrypt/__init__.py | 2 +
report_qweb_encrypt/__manifest__.py | 21 +++++
report_qweb_encrypt/controllers/__init__.py | 1 +
report_qweb_encrypt/controllers/main.py | 42 +++++++++
report_qweb_encrypt/models/__init__.py | 1 +
.../models/ir_actions_report.py | 33 ++++++++
report_qweb_encrypt/readme/CONTRIBUTORS.rst | 2 +
report_qweb_encrypt/readme/DESCRIPTION.rst | 2 +
report_qweb_encrypt/readme/USAGE.rst | 1 +
.../static/description/icon.png | Bin 0 -> 9455 bytes
.../src/js/report/action_manager_report.js | 80 ++++++++++++++++++
report_qweb_encrypt/templates/assets.xml | 13 +++
.../views/ir_actions_report.xml | 20 +++++
14 files changed, 298 insertions(+)
create mode 100644 report_qweb_encrypt/README.rst
create mode 100644 report_qweb_encrypt/__init__.py
create mode 100644 report_qweb_encrypt/__manifest__.py
create mode 100644 report_qweb_encrypt/controllers/__init__.py
create mode 100644 report_qweb_encrypt/controllers/main.py
create mode 100644 report_qweb_encrypt/models/__init__.py
create mode 100644 report_qweb_encrypt/models/ir_actions_report.py
create mode 100644 report_qweb_encrypt/readme/CONTRIBUTORS.rst
create mode 100644 report_qweb_encrypt/readme/DESCRIPTION.rst
create mode 100644 report_qweb_encrypt/readme/USAGE.rst
create mode 100644 report_qweb_encrypt/static/description/icon.png
create mode 100644 report_qweb_encrypt/static/src/js/report/action_manager_report.js
create mode 100644 report_qweb_encrypt/templates/assets.xml
create mode 100644 report_qweb_encrypt/views/ir_actions_report.xml
diff --git a/report_qweb_encrypt/README.rst b/report_qweb_encrypt/README.rst
new file mode 100644
index 0000000000..967084e652
--- /dev/null
+++ b/report_qweb_encrypt/README.rst
@@ -0,0 +1,80 @@
+===================
+Report Qweb Encrypt
+===================
+
+.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! 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%2Freporting--engine-lightgray.png?logo=github
+ :target: https://github.com/OCA/reporting-engine/tree/12.0/report_qweb_encrypt
+ :alt: OCA/reporting-engine
+.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
+ :target: https://translation.odoo-community.org/projects/reporting-engine-12-0/reporting-engine-12-0-report_qweb_encrypt
+ :alt: Translate me on Weblate
+.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
+ :target: https://runbot.odoo-community.org/runbot/143/12.0
+ :alt: Try me on Runbot
+
+|badge1| |badge2| |badge3| |badge4| |badge5|
+
+This module allows you to encrypt pdf files with a password when
+downloading them.
+
+**Table of contents**
+
+.. contents::
+ :local:
+
+Usage
+=====
+
+To make a report encryptable mark the field `Encryptable` in the report 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 smashing it by providing a detailed and welcomed
+`feedback `_.
+
+Do not contact contributors directly about support or help with technical issues.
+
+Credits
+=======
+
+Authors
+~~~~~~~
+
+* Creu Blanca
+
+Contributors
+~~~~~~~~~~~~
+
+* Enric Tobella
+* Jaime Arroyo
+
+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/reporting-engine `_ project on GitHub.
+
+You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/report_qweb_encrypt/__init__.py b/report_qweb_encrypt/__init__.py
new file mode 100644
index 0000000000..91c5580fed
--- /dev/null
+++ b/report_qweb_encrypt/__init__.py
@@ -0,0 +1,2 @@
+from . import controllers
+from . import models
diff --git a/report_qweb_encrypt/__manifest__.py b/report_qweb_encrypt/__manifest__.py
new file mode 100644
index 0000000000..13eb72697b
--- /dev/null
+++ b/report_qweb_encrypt/__manifest__.py
@@ -0,0 +1,21 @@
+# Copyright 2020 Creu Blanca
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+{
+ 'name': 'Report Qweb Encrypt',
+ 'summary': """
+ Allow to encrypt qweb pdfs""",
+ 'version': '12.0.1.0.0',
+ 'license': 'AGPL-3',
+ 'author': 'Creu Blanca,Odoo Community Association (OCA)',
+ 'website': 'https://github.com/OCA/reporting-engine',
+ 'depends': [
+ 'web',
+ ],
+ 'data': [
+ 'views/ir_actions_report.xml',
+ 'templates/assets.xml'
+ ],
+ 'demo': [
+ ],
+}
diff --git a/report_qweb_encrypt/controllers/__init__.py b/report_qweb_encrypt/controllers/__init__.py
new file mode 100644
index 0000000000..12a7e529b6
--- /dev/null
+++ b/report_qweb_encrypt/controllers/__init__.py
@@ -0,0 +1 @@
+from . import main
diff --git a/report_qweb_encrypt/controllers/main.py b/report_qweb_encrypt/controllers/main.py
new file mode 100644
index 0000000000..0d1c8c5697
--- /dev/null
+++ b/report_qweb_encrypt/controllers/main.py
@@ -0,0 +1,42 @@
+from odoo.addons.web.controllers import main as report
+from odoo.http import route
+from werkzeug.urls import url_decode
+import json
+import logging
+from io import BytesIO
+
+_logger = logging.getLogger(__name__)
+try:
+ from PyPDF2 import PdfFileReader, PdfFileWriter
+except ImportError as err:
+ _logger.debug(err)
+
+
+class ReportController(report.ReportController):
+ @route()
+ def report_download(self, data, token):
+ result = super().report_download(data, token)
+ requestcontent = json.loads(data)
+ url, type = requestcontent[0], requestcontent[1]
+ if (
+ type in ['qweb-pdf'] and
+ result.headers['Content-Type'] == "application/pdf" and
+ '?' in url
+ ):
+ url_data = dict(url_decode(url.split('?')[1]).items())
+ if 'context' in url_data:
+ context_data = json.loads(url_data['context'])
+ if 'encrypt_password' in context_data:
+ # We need to encrypt here because this function is not
+ # passing context, so we need to implement this again
+
+ data = result.get_data()
+ output_pdf = PdfFileWriter()
+ in_buff = BytesIO(data)
+ pdf = PdfFileReader(in_buff)
+ output_pdf.appendPagesFromReader(pdf)
+ output_pdf.encrypt(context_data['encrypt_password'])
+ buff = BytesIO()
+ output_pdf.write(buff)
+ result.set_data(buff.getvalue())
+ return result
diff --git a/report_qweb_encrypt/models/__init__.py b/report_qweb_encrypt/models/__init__.py
new file mode 100644
index 0000000000..a248cf2162
--- /dev/null
+++ b/report_qweb_encrypt/models/__init__.py
@@ -0,0 +1 @@
+from . import ir_actions_report
diff --git a/report_qweb_encrypt/models/ir_actions_report.py b/report_qweb_encrypt/models/ir_actions_report.py
new file mode 100644
index 0000000000..93c2aaa39c
--- /dev/null
+++ b/report_qweb_encrypt/models/ir_actions_report.py
@@ -0,0 +1,33 @@
+# Copyright 2020 Creu Blanca
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+
+from odoo import fields, models
+import logging
+from io import BytesIO
+
+_logger = logging.getLogger(__name__)
+try:
+ from PyPDF2 import PdfFileReader, PdfFileWriter
+except ImportError as err:
+ _logger.debug(err)
+
+
+class IrActionsReport(models.Model):
+
+ _inherit = 'ir.actions.report'
+
+ encrypt = fields.Boolean()
+
+ def render_qweb_pdf(self, res_ids=None, data=None):
+ document, type = super(IrActionsReport, self).render_qweb_pdf(
+ res_ids=res_ids, data=data)
+ if self.encrypt and self.env.context.get('encrypt_password', False):
+ output_pdf = PdfFileWriter()
+ in_buff = BytesIO(document)
+ pdf = PdfFileReader(in_buff)
+ output_pdf.appendPagesFromReader(pdf)
+ output_pdf.encrypt(self.env.context.get('encrypt_password'))
+ buff = BytesIO()
+ output_pdf.write(buff)
+ document = buff.getvalue()
+ return document, type
diff --git a/report_qweb_encrypt/readme/CONTRIBUTORS.rst b/report_qweb_encrypt/readme/CONTRIBUTORS.rst
new file mode 100644
index 0000000000..94e7b0a403
--- /dev/null
+++ b/report_qweb_encrypt/readme/CONTRIBUTORS.rst
@@ -0,0 +1,2 @@
+* Enric Tobella
+* Jaime Arroyo
diff --git a/report_qweb_encrypt/readme/DESCRIPTION.rst b/report_qweb_encrypt/readme/DESCRIPTION.rst
new file mode 100644
index 0000000000..f111d795a2
--- /dev/null
+++ b/report_qweb_encrypt/readme/DESCRIPTION.rst
@@ -0,0 +1,2 @@
+This module allows you to encrypt pdf files with a password when
+downloading them.
diff --git a/report_qweb_encrypt/readme/USAGE.rst b/report_qweb_encrypt/readme/USAGE.rst
new file mode 100644
index 0000000000..aed8cb93b0
--- /dev/null
+++ b/report_qweb_encrypt/readme/USAGE.rst
@@ -0,0 +1 @@
+To make a report encryptable mark the field `Encryptable` in the report record.
diff --git a/report_qweb_encrypt/static/description/icon.png b/report_qweb_encrypt/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/report_qweb_encrypt/static/src/js/report/action_manager_report.js b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
new file mode 100644
index 0000000000..e70ae09bde
--- /dev/null
+++ b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
@@ -0,0 +1,80 @@
+// © 2017 Creu Blanca
+// License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
+odoo.define("report_qweb_encrypt.Dialog", function (require) {
+ "use strict";
+
+ var ActionManager = require("web.ActionManager");
+ var framework = require("web.framework");
+ var Dialog = require("web.Dialog");
+ var core = require('web.core');
+
+ var _t = core._t;
+
+ var EncryptDialog = Dialog.extend({
+ events: _.extend({} , Dialog.prototype.events, {
+ change: '_onChange',
+ }),
+ _setValue: function () {
+ this.value = this.$el.find('.o_password').val()
+ },
+ _onChange: function (event) {
+ this._setValue();
+ },
+
+ })
+ EncryptDialog.askPassword = function (owner, action, action_options, options) {
+ var buttons = [
+ {
+ text: _t("Ok"),
+ classes: 'btn-primary',
+ close: true,
+ click: function (event) {
+ var password = this.value || false;
+ owner._executeReportAction(action, action_options, password)
+ },
+ },
+ {
+ text: _t("Cancel"),
+ close: true,
+ click: false,
+ }
+ ];
+ return new EncryptDialog(owner, _.extend({
+ size: 'small',
+ buttons: buttons,
+ $content: $('
'),
+ title: _t("Encrypt"),
+ }, options)).open();
+ };
+
+ ActionManager.include({
+ _executeReportAction: function (action, options, password) {
+ if (action.encrypt && password === undefined) {
+ EncryptDialog.askPassword(this, action, options);
+ return $.Deferred()
+ }
+ else if (action.encrypt) {
+ action.context = _.extend({}, action.context, {
+ encrypt_password: password,
+ })
+ }
+ return this._super(action, options, password)
+ },
+ _makeReportUrls: function (action) {
+ var reportUrls = this._super.apply(this, arguments);
+ if (action.encrypt && action.context.encrypt_password) {
+ if (_.isUndefined(action.data) || _.isNull(action.data) ||
+ (_.isObject(action.data) && _.isEmpty(action.data))) {
+ var serializedOptionsPath = '?context=' + encodeURIComponent(JSON.stringify({
+ encrypt_password: action.context.encrypt_password,
+ }));
+ reportUrls = _.mapObject(reportUrls, function (value) {
+ return value += serializedOptionsPath;
+ });
+ }
+ }
+ return reportUrls;
+ }
+ });
+
+});
diff --git a/report_qweb_encrypt/templates/assets.xml b/report_qweb_encrypt/templates/assets.xml
new file mode 100644
index 0000000000..f3200b1825
--- /dev/null
+++ b/report_qweb_encrypt/templates/assets.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/report_qweb_encrypt/views/ir_actions_report.xml b/report_qweb_encrypt/views/ir_actions_report.xml
new file mode 100644
index 0000000000..a596e04c20
--- /dev/null
+++ b/report_qweb_encrypt/views/ir_actions_report.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+ ir.actions.report.form (in report_qweb_encrypt)
+ ir.actions.report
+
+
+
+
+
+
+
+
+
+
+
From 1e12ece8ab1b4365c1b23148ebd0c7ebef9c11fe Mon Sep 17 00:00:00 2001
From: Kitti U
Date: Sat, 26 Dec 2020 15:06:58 +0700
Subject: [PATCH 02/22] [ENH] Add option to auto encrypt password based on
python syntax
---
report_qweb_encrypt/README.rst | 18 +-
report_qweb_encrypt/__manifest__.py | 28 +-
report_qweb_encrypt/controllers/main.py | 47 +-
.../i18n/report_qweb_encrypt.pot | 84 ++++
.../models/ir_actions_report.py | 71 ++-
report_qweb_encrypt/readme/CONTRIBUTORS.rst | 1 +
report_qweb_encrypt/readme/DESCRIPTION.rst | 6 +-
report_qweb_encrypt/readme/USAGE.rst | 2 +-
.../static/description/index.html | 433 ++++++++++++++++++
.../src/js/report/action_manager_report.js | 12 +-
report_qweb_encrypt/tests/__init__.py | 1 +
.../tests/test_report_qweb_encrypt.py | 33 ++
.../views/ir_actions_report.xml | 11 +-
13 files changed, 675 insertions(+), 72 deletions(-)
create mode 100644 report_qweb_encrypt/i18n/report_qweb_encrypt.pot
create mode 100644 report_qweb_encrypt/static/description/index.html
create mode 100644 report_qweb_encrypt/tests/__init__.py
create mode 100644 report_qweb_encrypt/tests/test_report_qweb_encrypt.py
diff --git a/report_qweb_encrypt/README.rst b/report_qweb_encrypt/README.rst
index 967084e652..66c5a83569 100644
--- a/report_qweb_encrypt/README.rst
+++ b/report_qweb_encrypt/README.rst
@@ -25,8 +25,10 @@ Report Qweb Encrypt
|badge1| |badge2| |badge3| |badge4| |badge5|
-This module allows you to encrypt pdf files with a password when
-downloading them.
+This module allow you to encrypt PDF with a password seting option,
+
+* Manually keyin password (only applicable for record print action)
+* Auto generated password based on object data (python)
**Table of contents**
@@ -36,7 +38,7 @@ downloading them.
Usage
=====
-To make a report encryptable mark the field `Encryptable` in the report record.
+To make a report encryptable mark the field `Encryption` in the report record.
Bug Tracker
===========
@@ -55,12 +57,14 @@ Authors
~~~~~~~
* Creu Blanca
+* Ecosoft
Contributors
~~~~~~~~~~~~
* Enric Tobella
* Jaime Arroyo
+* Kitti U.
Maintainers
~~~~~~~~~~~
@@ -75,6 +79,14 @@ 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.
+.. |maintainer-kittiu| image:: https://github.com/kittiu.png?size=40px
+ :target: https://github.com/kittiu
+ :alt: kittiu
+
+Current `maintainer `__:
+
+|maintainer-kittiu|
+
This module is part of the `OCA/reporting-engine `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/report_qweb_encrypt/__manifest__.py b/report_qweb_encrypt/__manifest__.py
index 13eb72697b..347f201290 100644
--- a/report_qweb_encrypt/__manifest__.py
+++ b/report_qweb_encrypt/__manifest__.py
@@ -1,21 +1,21 @@
# Copyright 2020 Creu Blanca
+# Copyright 2020 Ecosoft Co., Ltd.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
- 'name': 'Report Qweb Encrypt',
- 'summary': """
- Allow to encrypt qweb pdfs""",
- 'version': '12.0.1.0.0',
- 'license': 'AGPL-3',
- 'author': 'Creu Blanca,Odoo Community Association (OCA)',
- 'website': 'https://github.com/OCA/reporting-engine',
- 'depends': [
- 'web',
+ "name": "Report Qweb Encrypt",
+ "summary": "Allow to encrypt qweb pdfs",
+ "version": "12.0.1.0.0",
+ "license": "AGPL-3",
+ "author": "Creu Blanca,Ecosoft,Odoo Community Association (OCA)",
+ "website": "https://github.com/OCA/reporting-engine",
+ "depends": [
+ "web",
],
- 'data': [
- 'views/ir_actions_report.xml',
- 'templates/assets.xml'
- ],
- 'demo': [
+ "data": [
+ "views/ir_actions_report.xml",
+ "templates/assets.xml"
],
+ "installable": True,
+ "maintainers": ["kittiu"],
}
diff --git a/report_qweb_encrypt/controllers/main.py b/report_qweb_encrypt/controllers/main.py
index 0d1c8c5697..4bbdceebab 100644
--- a/report_qweb_encrypt/controllers/main.py
+++ b/report_qweb_encrypt/controllers/main.py
@@ -1,42 +1,33 @@
+# Copyright 2020 Creu Blanca
+# Copyright 2020 Ecosoft Co., Ltd.
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo.addons.web.controllers import main as report
-from odoo.http import route
+from odoo.http import route, request
from werkzeug.urls import url_decode
import json
-import logging
-from io import BytesIO
-
-_logger = logging.getLogger(__name__)
-try:
- from PyPDF2 import PdfFileReader, PdfFileWriter
-except ImportError as err:
- _logger.debug(err)
class ReportController(report.ReportController):
@route()
def report_download(self, data, token):
result = super().report_download(data, token)
+ # When report is downloaded from print action, this function is called,
+ # but this function cannot pass context (manually entered password) to
+ # report.render_qweb_pdf(), encrypton for manual password is done here.
requestcontent = json.loads(data)
- url, type = requestcontent[0], requestcontent[1]
+ url, ttype = requestcontent[0], requestcontent[1]
if (
- type in ['qweb-pdf'] and
- result.headers['Content-Type'] == "application/pdf" and
- '?' in url
+ ttype in ["qweb-pdf"] and
+ result.headers["Content-Type"] == "application/pdf" and
+ "?" in url
):
- url_data = dict(url_decode(url.split('?')[1]).items())
- if 'context' in url_data:
- context_data = json.loads(url_data['context'])
- if 'encrypt_password' in context_data:
- # We need to encrypt here because this function is not
- # passing context, so we need to implement this again
-
+ url_data = dict(url_decode(url.split("?")[1]).items())
+ if "context" in url_data:
+ context = json.loads(url_data["context"])
+ if "encrypt_password" in context:
+ Report = request.env["ir.actions.report"]
data = result.get_data()
- output_pdf = PdfFileWriter()
- in_buff = BytesIO(data)
- pdf = PdfFileReader(in_buff)
- output_pdf.appendPagesFromReader(pdf)
- output_pdf.encrypt(context_data['encrypt_password'])
- buff = BytesIO()
- output_pdf.write(buff)
- result.set_data(buff.getvalue())
+ encrypted_data = Report._encrypt_pdf(
+ data, context["encrypt_password"])
+ result.set_data(encrypted_data)
return result
diff --git a/report_qweb_encrypt/i18n/report_qweb_encrypt.pot b/report_qweb_encrypt/i18n/report_qweb_encrypt.pot
new file mode 100644
index 0000000000..52fed74106
--- /dev/null
+++ b/report_qweb_encrypt/i18n/report_qweb_encrypt.pot
@@ -0,0 +1,84 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * report_qweb_encrypt
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 12.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: <>\n"
+"Language-Team: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: \n"
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,help:report_qweb_encrypt.field_ir_actions_report__encrypt
+msgid "* Manual Input Password: allow user to key in password on the fly. This option available only on document print action.\n"
+"* Auto Generated Password: system will auto encrypt password when PDF created, based on provided python syntax."
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: selection:ir.actions.report,encrypt:0
+msgid "Auto Generated Password"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#. openerp-web
+#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:37
+#, python-format
+msgid "Cancel"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#. openerp-web
+#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:46
+#, python-format
+msgid "Encrypt"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__encrypt_password
+msgid "Encrypt Password"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__encrypt
+msgid "Encryption"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: selection:ir.actions.report,encrypt:0
+msgid "Manual Input Password"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#. openerp-web
+#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:28
+#, python-format
+msgid "Ok"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,help:report_qweb_encrypt.field_ir_actions_report__encrypt_password
+msgid "Python code syntax to gnerate password."
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: code:addons/report_qweb_encrypt/models/ir_actions_report.py:58
+#, python-format
+msgid "Python code used for encryption password is invalid.\n"
+"%s"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model,name:report_qweb_encrypt.model_ir_actions_report
+msgid "Report Action"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model_terms:ir.ui.view,arch_db:report_qweb_encrypt.ir_actions_report_form_view
+msgid "python syntax, i.e., (object.default_code or 'secretcode')"
+msgstr ""
+
diff --git a/report_qweb_encrypt/models/ir_actions_report.py b/report_qweb_encrypt/models/ir_actions_report.py
index 93c2aaa39c..06921845c8 100644
--- a/report_qweb_encrypt/models/ir_actions_report.py
+++ b/report_qweb_encrypt/models/ir_actions_report.py
@@ -1,9 +1,13 @@
# Copyright 2020 Creu Blanca
+# Copyright 2020 Ecosoft Co., Ltd.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-
-from odoo import fields, models
+import time
import logging
+from odoo import fields, models, _
from io import BytesIO
+from odoo.tools.safe_eval import safe_eval
+from odoo.exceptions import ValidationError
+
_logger = logging.getLogger(__name__)
try:
@@ -13,21 +17,56 @@
class IrActionsReport(models.Model):
+ _inherit = "ir.actions.report"
- _inherit = 'ir.actions.report'
-
- encrypt = fields.Boolean()
+ encrypt = fields.Selection(
+ [("manual", "Manual Input Password"),
+ ("auto", "Auto Generated Password")],
+ string="Encryption",
+ help="* Manual Input Password: allow user to key in password on the fly. "
+ "This option available only on document print action.\n"
+ "* Auto Generated Password: system will auto encrypt password when PDF "
+ "created, based on provided python syntax."
+ )
+ encrypt_password = fields.Char(
+ help="Python code syntax to gnerate password.",
+ )
def render_qweb_pdf(self, res_ids=None, data=None):
- document, type = super(IrActionsReport, self).render_qweb_pdf(
+ document, ttype = super(IrActionsReport, self).render_qweb_pdf(
res_ids=res_ids, data=data)
- if self.encrypt and self.env.context.get('encrypt_password', False):
- output_pdf = PdfFileWriter()
- in_buff = BytesIO(document)
- pdf = PdfFileReader(in_buff)
- output_pdf.appendPagesFromReader(pdf)
- output_pdf.encrypt(self.env.context.get('encrypt_password'))
- buff = BytesIO()
- output_pdf.write(buff)
- document = buff.getvalue()
- return document, type
+ password = self._get_pdf_password(res_ids[:1])
+ document = self._encrypt_pdf(document, password)
+ return document, ttype
+
+ def _get_pdf_password(self, res_id):
+ encrypt_password = False
+ if self.encrypt == "manual":
+ # If use document print action, report_download() is called,
+ # but that can't pass context (encrypt_password) here.
+ # As such, file will be encrypted by report_download() again.
+ # --
+ # Following is used just in case when context is passed in.
+ encrypt_password = self._context.get("encrypt_password", False)
+ elif self.encrypt == "auto" and self.encrypt_password:
+ obj = self.env[self.model].browse(res_id)
+ try:
+ encrypt_password = safe_eval(self.encrypt_password,
+ {'object': obj, 'time': time})
+ except:
+ raise ValidationError(
+ _("Python code used for encryption password is invalid.\n%s")
+ % self.encrypt_password)
+ return encrypt_password
+
+ def _encrypt_pdf(self, data, password):
+ if not password:
+ return data
+ output_pdf = PdfFileWriter()
+ in_buff = BytesIO(data)
+ pdf = PdfFileReader(in_buff)
+ output_pdf.appendPagesFromReader(pdf)
+ output_pdf.encrypt(password)
+ buff = BytesIO()
+ output_pdf.write(buff)
+ return buff.getvalue()
diff --git a/report_qweb_encrypt/readme/CONTRIBUTORS.rst b/report_qweb_encrypt/readme/CONTRIBUTORS.rst
index 94e7b0a403..b7e5dfa747 100644
--- a/report_qweb_encrypt/readme/CONTRIBUTORS.rst
+++ b/report_qweb_encrypt/readme/CONTRIBUTORS.rst
@@ -1,2 +1,3 @@
* Enric Tobella
* Jaime Arroyo
+* Kitti U.
diff --git a/report_qweb_encrypt/readme/DESCRIPTION.rst b/report_qweb_encrypt/readme/DESCRIPTION.rst
index f111d795a2..2f31e4e9d0 100644
--- a/report_qweb_encrypt/readme/DESCRIPTION.rst
+++ b/report_qweb_encrypt/readme/DESCRIPTION.rst
@@ -1,2 +1,4 @@
-This module allows you to encrypt pdf files with a password when
-downloading them.
+This module allow you to encrypt PDF with a password seting option,
+
+* Manually keyin password (only applicable for record print action)
+* Auto generated password based on object data (python)
diff --git a/report_qweb_encrypt/readme/USAGE.rst b/report_qweb_encrypt/readme/USAGE.rst
index aed8cb93b0..1704c7968c 100644
--- a/report_qweb_encrypt/readme/USAGE.rst
+++ b/report_qweb_encrypt/readme/USAGE.rst
@@ -1 +1 @@
-To make a report encryptable mark the field `Encryptable` in the report record.
+To make a report encryptable mark the field `Encryption` in the report record.
diff --git a/report_qweb_encrypt/static/description/index.html b/report_qweb_encrypt/static/description/index.html
new file mode 100644
index 0000000000..b6aca0e00d
--- /dev/null
+++ b/report_qweb_encrypt/static/description/index.html
@@ -0,0 +1,433 @@
+
+
+
+
+
+
+Report Qweb Encrypt
+
+
+
+
+
Report Qweb Encrypt
+
+
+
+
This module allow you to encrypt PDF with a password seting option,
+
+Manually keyin password (only applicable for record print action)
+Auto generated password based on object data (python)
+
+
Table of contents
+
+
+
+
To make a report encryptable mark the field Encryption in the report record.
+
+
+
+
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.
+
+
+
+
+
+
+
+
This module is maintained by the OCA.
+
+
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.
+
Current maintainer :
+
+
This module is part of the OCA/reporting-engine project on GitHub.
+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute .
+
+
+
+
+
diff --git a/report_qweb_encrypt/static/src/js/report/action_manager_report.js b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
index e70ae09bde..5e45630ebf 100644
--- a/report_qweb_encrypt/static/src/js/report/action_manager_report.js
+++ b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
@@ -11,7 +11,7 @@ odoo.define("report_qweb_encrypt.Dialog", function (require) {
var _t = core._t;
var EncryptDialog = Dialog.extend({
- events: _.extend({} , Dialog.prototype.events, {
+ events: _.extend({}, Dialog.prototype.events, {
change: '_onChange',
}),
_setValue: function () {
@@ -49,11 +49,13 @@ odoo.define("report_qweb_encrypt.Dialog", function (require) {
ActionManager.include({
_executeReportAction: function (action, options, password) {
- if (action.encrypt && password === undefined) {
+ if (action.encrypt === 'manual'
+ && action.report_type === 'qweb-pdf'
+ && password === undefined) {
EncryptDialog.askPassword(this, action, options);
- return $.Deferred()
+ return $.Deferred();
}
- else if (action.encrypt) {
+ else if (action.encrypt === 'manual') {
action.context = _.extend({}, action.context, {
encrypt_password: password,
})
@@ -62,7 +64,7 @@ odoo.define("report_qweb_encrypt.Dialog", function (require) {
},
_makeReportUrls: function (action) {
var reportUrls = this._super.apply(this, arguments);
- if (action.encrypt && action.context.encrypt_password) {
+ if (action.encrypt === 'manual' && action.context.encrypt_password) {
if (_.isUndefined(action.data) || _.isNull(action.data) ||
(_.isObject(action.data) && _.isEmpty(action.data))) {
var serializedOptionsPath = '?context=' + encodeURIComponent(JSON.stringify({
diff --git a/report_qweb_encrypt/tests/__init__.py b/report_qweb_encrypt/tests/__init__.py
new file mode 100644
index 0000000000..c6a7ce0a3c
--- /dev/null
+++ b/report_qweb_encrypt/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_report_qweb_encrypt
diff --git a/report_qweb_encrypt/tests/test_report_qweb_encrypt.py b/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
new file mode 100644
index 0000000000..8a8a1f2d94
--- /dev/null
+++ b/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
@@ -0,0 +1,33 @@
+# © 2016 Therp BV
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
+from odoo.exceptions import ValidationError
+from odoo.tests.common import HttpCase
+
+
+class TestReportQwebEncrypt(HttpCase):
+
+ def test_report_qweb_no_encrypt(self):
+ ctx = {"force_report_rendering": True}
+ report = self.env.ref("web.action_report_internalpreview")
+ report.encrypt = False
+ pdf, _ = report.with_context(ctx).render_qweb_pdf([1])
+ self.assertFalse(pdf.count(b"/Encrypt"))
+
+ def test_report_qweb_auto_encrypt(self):
+ ctx = {"force_report_rendering": True}
+ report = self.env.ref("web.action_report_internalpreview")
+ report.encrypt = "auto"
+ report.encrypt_password = False
+ # If no encrypt_password, still not encrypted
+ pdf, _ = report.with_context(ctx).render_qweb_pdf([1])
+ self.assertFalse(pdf.count(b"/Encrypt"))
+ # If invalid encrypt_password, show error
+ report.encrypt_password = "invalid python syntax"
+ with self.assertRaises(ValidationError):
+ pdf, _ = report.with_context(ctx).render_qweb_pdf([1])
+ # Valid python string for password
+ report.encrypt_password = "'secretcode'"
+ pdf, _ = report.with_context(ctx).render_qweb_pdf([1])
+ self.assertTrue(pdf.count(b"/Encrypt"))
+
+ # TODO: test_report_qweb_manual_encrypt, require JS test?
diff --git a/report_qweb_encrypt/views/ir_actions_report.xml b/report_qweb_encrypt/views/ir_actions_report.xml
index a596e04c20..fdff60b6b9 100644
--- a/report_qweb_encrypt/views/ir_actions_report.xml
+++ b/report_qweb_encrypt/views/ir_actions_report.xml
@@ -1,5 +1,6 @@
@@ -10,11 +11,15 @@
-
+
+
+
+
+
-
-
From e4884e05bd3b509fbd7b33eaba97fbc417422392 Mon Sep 17 00:00:00 2001
From: Kitti U
Date: Wed, 10 Feb 2021 00:11:01 +0700
Subject: [PATCH 03/22] [IMP] : black, isort, prettier
---
report_qweb_encrypt/__manifest__.py | 5 +-
report_qweb_encrypt/controllers/main.py | 18 +++--
.../models/ir_actions_report.py | 24 +++---
.../src/js/report/action_manager_report.js | 78 +++++++++++--------
report_qweb_encrypt/templates/assets.xml | 5 +-
.../tests/test_report_qweb_encrypt.py | 1 -
.../views/ir_actions_report.xml | 23 ++++--
7 files changed, 90 insertions(+), 64 deletions(-)
diff --git a/report_qweb_encrypt/__manifest__.py b/report_qweb_encrypt/__manifest__.py
index 347f201290..afc2fc6852 100644
--- a/report_qweb_encrypt/__manifest__.py
+++ b/report_qweb_encrypt/__manifest__.py
@@ -12,10 +12,7 @@
"depends": [
"web",
],
- "data": [
- "views/ir_actions_report.xml",
- "templates/assets.xml"
- ],
+ "data": ["views/ir_actions_report.xml", "templates/assets.xml"],
"installable": True,
"maintainers": ["kittiu"],
}
diff --git a/report_qweb_encrypt/controllers/main.py b/report_qweb_encrypt/controllers/main.py
index 4bbdceebab..015468354e 100644
--- a/report_qweb_encrypt/controllers/main.py
+++ b/report_qweb_encrypt/controllers/main.py
@@ -1,11 +1,14 @@
# Copyright 2020 Creu Blanca
# Copyright 2020 Ecosoft Co., Ltd.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-from odoo.addons.web.controllers import main as report
-from odoo.http import route, request
-from werkzeug.urls import url_decode
import json
+from werkzeug.urls import url_decode
+
+from odoo.http import request, route
+
+from odoo.addons.web.controllers import main as report
+
class ReportController(report.ReportController):
@route()
@@ -17,9 +20,9 @@ def report_download(self, data, token):
requestcontent = json.loads(data)
url, ttype = requestcontent[0], requestcontent[1]
if (
- ttype in ["qweb-pdf"] and
- result.headers["Content-Type"] == "application/pdf" and
- "?" in url
+ ttype in ["qweb-pdf"]
+ and result.headers["Content-Type"] == "application/pdf"
+ and "?" in url
):
url_data = dict(url_decode(url.split("?")[1]).items())
if "context" in url_data:
@@ -28,6 +31,7 @@ def report_download(self, data, token):
Report = request.env["ir.actions.report"]
data = result.get_data()
encrypted_data = Report._encrypt_pdf(
- data, context["encrypt_password"])
+ data, context["encrypt_password"]
+ )
result.set_data(encrypted_data)
return result
diff --git a/report_qweb_encrypt/models/ir_actions_report.py b/report_qweb_encrypt/models/ir_actions_report.py
index 06921845c8..df8dec378b 100644
--- a/report_qweb_encrypt/models/ir_actions_report.py
+++ b/report_qweb_encrypt/models/ir_actions_report.py
@@ -1,13 +1,13 @@
# Copyright 2020 Creu Blanca
# Copyright 2020 Ecosoft Co., Ltd.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-import time
import logging
-from odoo import fields, models, _
+import time
from io import BytesIO
-from odoo.tools.safe_eval import safe_eval
-from odoo.exceptions import ValidationError
+from odoo import _, fields, models
+from odoo.exceptions import ValidationError
+from odoo.tools.safe_eval import safe_eval
_logger = logging.getLogger(__name__)
try:
@@ -20,13 +20,12 @@ class IrActionsReport(models.Model):
_inherit = "ir.actions.report"
encrypt = fields.Selection(
- [("manual", "Manual Input Password"),
- ("auto", "Auto Generated Password")],
+ [("manual", "Manual Input Password"), ("auto", "Auto Generated Password")],
string="Encryption",
help="* Manual Input Password: allow user to key in password on the fly. "
"This option available only on document print action.\n"
"* Auto Generated Password: system will auto encrypt password when PDF "
- "created, based on provided python syntax."
+ "created, based on provided python syntax.",
)
encrypt_password = fields.Char(
help="Python code syntax to gnerate password.",
@@ -34,7 +33,8 @@ class IrActionsReport(models.Model):
def render_qweb_pdf(self, res_ids=None, data=None):
document, ttype = super(IrActionsReport, self).render_qweb_pdf(
- res_ids=res_ids, data=data)
+ res_ids=res_ids, data=data
+ )
password = self._get_pdf_password(res_ids[:1])
document = self._encrypt_pdf(document, password)
return document, ttype
@@ -51,12 +51,14 @@ def _get_pdf_password(self, res_id):
elif self.encrypt == "auto" and self.encrypt_password:
obj = self.env[self.model].browse(res_id)
try:
- encrypt_password = safe_eval(self.encrypt_password,
- {'object': obj, 'time': time})
+ encrypt_password = safe_eval(
+ self.encrypt_password, {"object": obj, "time": time}
+ )
except:
raise ValidationError(
_("Python code used for encryption password is invalid.\n%s")
- % self.encrypt_password)
+ % self.encrypt_password
+ )
return encrypt_password
def _encrypt_pdf(self, data, password):
diff --git a/report_qweb_encrypt/static/src/js/report/action_manager_report.js b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
index 5e45630ebf..0c6b9c640d 100644
--- a/report_qweb_encrypt/static/src/js/report/action_manager_report.js
+++ b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
@@ -6,77 +6,91 @@ odoo.define("report_qweb_encrypt.Dialog", function (require) {
var ActionManager = require("web.ActionManager");
var framework = require("web.framework");
var Dialog = require("web.Dialog");
- var core = require('web.core');
+ var core = require("web.core");
var _t = core._t;
var EncryptDialog = Dialog.extend({
events: _.extend({}, Dialog.prototype.events, {
- change: '_onChange',
+ change: "_onChange",
}),
_setValue: function () {
- this.value = this.$el.find('.o_password').val()
+ this.value = this.$el.find(".o_password").val();
},
_onChange: function (event) {
this._setValue();
},
-
- })
+ });
EncryptDialog.askPassword = function (owner, action, action_options, options) {
var buttons = [
{
text: _t("Ok"),
- classes: 'btn-primary',
+ classes: "btn-primary",
close: true,
click: function (event) {
var password = this.value || false;
- owner._executeReportAction(action, action_options, password)
+ owner._executeReportAction(action, action_options, password);
},
},
{
text: _t("Cancel"),
close: true,
click: false,
- }
+ },
];
- return new EncryptDialog(owner, _.extend({
- size: 'small',
- buttons: buttons,
- $content: $('
'),
- title: _t("Encrypt"),
- }, options)).open();
+ return new EncryptDialog(
+ owner,
+ _.extend(
+ {
+ size: "small",
+ buttons: buttons,
+ $content: $(
+ '
'
+ ),
+ title: _t("Encrypt"),
+ },
+ options
+ )
+ ).open();
};
ActionManager.include({
_executeReportAction: function (action, options, password) {
- if (action.encrypt === 'manual'
- && action.report_type === 'qweb-pdf'
- && password === undefined) {
+ if (
+ action.encrypt === "manual" &&
+ action.report_type === "qweb-pdf" &&
+ password === undefined
+ ) {
EncryptDialog.askPassword(this, action, options);
return $.Deferred();
- }
- else if (action.encrypt === 'manual') {
+ } else if (action.encrypt === "manual") {
action.context = _.extend({}, action.context, {
encrypt_password: password,
- })
+ });
}
- return this._super(action, options, password)
+ return this._super(action, options, password);
},
_makeReportUrls: function (action) {
var reportUrls = this._super.apply(this, arguments);
- if (action.encrypt === 'manual' && action.context.encrypt_password) {
- if (_.isUndefined(action.data) || _.isNull(action.data) ||
- (_.isObject(action.data) && _.isEmpty(action.data))) {
- var serializedOptionsPath = '?context=' + encodeURIComponent(JSON.stringify({
- encrypt_password: action.context.encrypt_password,
- }));
- reportUrls = _.mapObject(reportUrls, function (value) {
- return value += serializedOptionsPath;
- });
+ if (action.encrypt === "manual" && action.context.encrypt_password) {
+ if (
+ _.isUndefined(action.data) ||
+ _.isNull(action.data) ||
+ (_.isObject(action.data) && _.isEmpty(action.data))
+ ) {
+ var serializedOptionsPath =
+ "?context=" +
+ encodeURIComponent(
+ JSON.stringify({
+ encrypt_password: action.context.encrypt_password,
+ })
+ );
+ reportUrls = _.mapObject(reportUrls, function (value) {
+ return (value += serializedOptionsPath);
+ });
}
}
return reportUrls;
- }
+ },
});
-
});
diff --git a/report_qweb_encrypt/templates/assets.xml b/report_qweb_encrypt/templates/assets.xml
index f3200b1825..e313587f35 100644
--- a/report_qweb_encrypt/templates/assets.xml
+++ b/report_qweb_encrypt/templates/assets.xml
@@ -6,7 +6,10 @@
-->
-
+
diff --git a/report_qweb_encrypt/tests/test_report_qweb_encrypt.py b/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
index 8a8a1f2d94..02e69665f0 100644
--- a/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
+++ b/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
@@ -5,7 +5,6 @@
class TestReportQwebEncrypt(HttpCase):
-
def test_report_qweb_no_encrypt(self):
ctx = {"force_report_rendering": True}
report = self.env.ref("web.action_report_internalpreview")
diff --git a/report_qweb_encrypt/views/ir_actions_report.xml b/report_qweb_encrypt/views/ir_actions_report.xml
index fdff60b6b9..b59b52635c 100644
--- a/report_qweb_encrypt/views/ir_actions_report.xml
+++ b/report_qweb_encrypt/views/ir_actions_report.xml
@@ -1,22 +1,29 @@
-
+
-
ir.actions.report.form (in report_qweb_encrypt)
ir.actions.report
-
+
-
-
-
-
+
+
+
+ placeholder="python syntax, i.e., (object.default_code or 'secretcode')"
+ />
From e799fc0993b67a60451acca60cd20672fd5a9d9f Mon Sep 17 00:00:00 2001
From: Kitti U
Date: Wed, 10 Feb 2021 00:12:38 +0700
Subject: [PATCH 04/22] [14.0][MIG] report_qweb_encrypt
---
report_qweb_encrypt/README.rst | 10 ++---
report_qweb_encrypt/__manifest__.py | 2 +-
.../i18n/report_qweb_encrypt.pot | 40 +++++++++++++------
.../models/ir_actions_report.py | 14 +++----
.../static/description/index.html | 6 +--
.../src/js/report/action_manager_report.js | 8 ++--
.../tests/test_report_qweb_encrypt.py | 8 ++--
7 files changed, 52 insertions(+), 36 deletions(-)
diff --git a/report_qweb_encrypt/README.rst b/report_qweb_encrypt/README.rst
index 66c5a83569..ab406389f6 100644
--- a/report_qweb_encrypt/README.rst
+++ b/report_qweb_encrypt/README.rst
@@ -14,13 +14,13 @@ Report Qweb Encrypt
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
- :target: https://github.com/OCA/reporting-engine/tree/12.0/report_qweb_encrypt
+ :target: https://github.com/OCA/reporting-engine/tree/14.0/report_qweb_encrypt
:alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/reporting-engine-12-0/reporting-engine-12-0-report_qweb_encrypt
+ :target: https://translation.odoo-community.org/projects/reporting-engine-14-0/reporting-engine-14-0-report_qweb_encrypt
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/143/12.0
+ :target: https://runbot.odoo-community.org/runbot/143/14.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -46,7 +46,7 @@ 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 `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -87,6 +87,6 @@ Current `maintainer `__:
|maintainer-kittiu|
-This module is part of the `OCA/reporting-engine `_ project on GitHub.
+This module is part of the `OCA/reporting-engine `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/report_qweb_encrypt/__manifest__.py b/report_qweb_encrypt/__manifest__.py
index afc2fc6852..299b595b1e 100644
--- a/report_qweb_encrypt/__manifest__.py
+++ b/report_qweb_encrypt/__manifest__.py
@@ -5,7 +5,7 @@
{
"name": "Report Qweb Encrypt",
"summary": "Allow to encrypt qweb pdfs",
- "version": "12.0.1.0.0",
+ "version": "14.0.1.0.0",
"license": "AGPL-3",
"author": "Creu Blanca,Ecosoft,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/reporting-engine",
diff --git a/report_qweb_encrypt/i18n/report_qweb_encrypt.pot b/report_qweb_encrypt/i18n/report_qweb_encrypt.pot
index 52fed74106..89605ef63b 100644
--- a/report_qweb_encrypt/i18n/report_qweb_encrypt.pot
+++ b/report_qweb_encrypt/i18n/report_qweb_encrypt.pot
@@ -1,12 +1,12 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
-# * report_qweb_encrypt
+# * report_qweb_encrypt
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 12.0\n"
+"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: <>\n"
+"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -15,25 +15,31 @@ msgstr ""
#. module: report_qweb_encrypt
#: model:ir.model.fields,help:report_qweb_encrypt.field_ir_actions_report__encrypt
-msgid "* Manual Input Password: allow user to key in password on the fly. This option available only on document print action.\n"
+msgid ""
+"* Manual Input Password: allow user to key in password on the fly. This option available only on document print action.\n"
"* Auto Generated Password: system will auto encrypt password when PDF created, based on provided python syntax."
msgstr ""
#. module: report_qweb_encrypt
-#: selection:ir.actions.report,encrypt:0
+#: model:ir.model.fields.selection,name:report_qweb_encrypt.selection__ir_actions_report__encrypt__auto
msgid "Auto Generated Password"
msgstr ""
#. module: report_qweb_encrypt
#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:37
+#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
#, python-format
msgid "Cancel"
msgstr ""
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__display_name
+msgid "Display Name"
+msgstr ""
+
#. module: report_qweb_encrypt
#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:46
+#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
#, python-format
msgid "Encrypt"
msgstr ""
@@ -49,13 +55,23 @@ msgid "Encryption"
msgstr ""
#. module: report_qweb_encrypt
-#: selection:ir.actions.report,encrypt:0
+#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__id
+msgid "ID"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields.selection,name:report_qweb_encrypt.selection__ir_actions_report__encrypt__manual
msgid "Manual Input Password"
msgstr ""
#. module: report_qweb_encrypt
#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:28
+#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
#, python-format
msgid "Ok"
msgstr ""
@@ -66,9 +82,10 @@ msgid "Python code syntax to gnerate password."
msgstr ""
#. module: report_qweb_encrypt
-#: code:addons/report_qweb_encrypt/models/ir_actions_report.py:58
+#: code:addons/report_qweb_encrypt/models/ir_actions_report.py:0
#, python-format
-msgid "Python code used for encryption password is invalid.\n"
+msgid ""
+"Python code used for encryption password is invalid.\n"
"%s"
msgstr ""
@@ -81,4 +98,3 @@ msgstr ""
#: model_terms:ir.ui.view,arch_db:report_qweb_encrypt.ir_actions_report_form_view
msgid "python syntax, i.e., (object.default_code or 'secretcode')"
msgstr ""
-
diff --git a/report_qweb_encrypt/models/ir_actions_report.py b/report_qweb_encrypt/models/ir_actions_report.py
index df8dec378b..c4a00dd17c 100644
--- a/report_qweb_encrypt/models/ir_actions_report.py
+++ b/report_qweb_encrypt/models/ir_actions_report.py
@@ -2,7 +2,6 @@
# Copyright 2020 Ecosoft Co., Ltd.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
-import time
from io import BytesIO
from odoo import _, fields, models
@@ -31,8 +30,8 @@ class IrActionsReport(models.Model):
help="Python code syntax to gnerate password.",
)
- def render_qweb_pdf(self, res_ids=None, data=None):
- document, ttype = super(IrActionsReport, self).render_qweb_pdf(
+ def _render_qweb_pdf(self, res_ids=None, data=None):
+ document, ttype = super(IrActionsReport, self)._render_qweb_pdf(
res_ids=res_ids, data=data
)
password = self._get_pdf_password(res_ids[:1])
@@ -51,10 +50,8 @@ def _get_pdf_password(self, res_id):
elif self.encrypt == "auto" and self.encrypt_password:
obj = self.env[self.model].browse(res_id)
try:
- encrypt_password = safe_eval(
- self.encrypt_password, {"object": obj, "time": time}
- )
- except:
+ encrypt_password = safe_eval(self.encrypt_password, {"object": obj})
+ except Exception:
raise ValidationError(
_("Python code used for encryption password is invalid.\n%s")
% self.encrypt_password
@@ -72,3 +69,6 @@ def _encrypt_pdf(self, data, password):
buff = BytesIO()
output_pdf.write(buff)
return buff.getvalue()
+
+ def _get_readable_fields(self):
+ return super()._get_readable_fields() | {"encrypt"}
diff --git a/report_qweb_encrypt/static/description/index.html b/report_qweb_encrypt/static/description/index.html
index b6aca0e00d..a20f845113 100644
--- a/report_qweb_encrypt/static/description/index.html
+++ b/report_qweb_encrypt/static/description/index.html
@@ -367,7 +367,7 @@ Report Qweb Encrypt
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-
+
This module allow you to encrypt PDF with a password seting option,
Manually keyin password (only applicable for record print action)
@@ -395,7 +395,7 @@
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 .
+feedback .
Do not contact contributors directly about support or help with technical issues.
diff --git a/report_qweb_encrypt/static/src/js/report/action_manager_report.js b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
index 0c6b9c640d..376954861f 100644
--- a/report_qweb_encrypt/static/src/js/report/action_manager_report.js
+++ b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
@@ -4,7 +4,6 @@ odoo.define("report_qweb_encrypt.Dialog", function (require) {
"use strict";
var ActionManager = require("web.ActionManager");
- var framework = require("web.framework");
var Dialog = require("web.Dialog");
var core = require("web.core");
@@ -17,7 +16,7 @@ odoo.define("report_qweb_encrypt.Dialog", function (require) {
_setValue: function () {
this.value = this.$el.find(".o_password").val();
},
- _onChange: function (event) {
+ _onChange: function () {
this._setValue();
},
});
@@ -27,7 +26,7 @@ odoo.define("report_qweb_encrypt.Dialog", function (require) {
text: _t("Ok"),
classes: "btn-primary",
close: true,
- click: function (event) {
+ click: function () {
var password = this.value || false;
owner._executeReportAction(action, action_options, password);
},
@@ -86,7 +85,8 @@ odoo.define("report_qweb_encrypt.Dialog", function (require) {
})
);
reportUrls = _.mapObject(reportUrls, function (value) {
- return (value += serializedOptionsPath);
+ value += serializedOptionsPath;
+ return value;
});
}
}
diff --git a/report_qweb_encrypt/tests/test_report_qweb_encrypt.py b/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
index 02e69665f0..b13ae93437 100644
--- a/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
+++ b/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
@@ -9,7 +9,7 @@ def test_report_qweb_no_encrypt(self):
ctx = {"force_report_rendering": True}
report = self.env.ref("web.action_report_internalpreview")
report.encrypt = False
- pdf, _ = report.with_context(ctx).render_qweb_pdf([1])
+ pdf, _ = report.with_context(ctx)._render_qweb_pdf([1])
self.assertFalse(pdf.count(b"/Encrypt"))
def test_report_qweb_auto_encrypt(self):
@@ -18,15 +18,15 @@ def test_report_qweb_auto_encrypt(self):
report.encrypt = "auto"
report.encrypt_password = False
# If no encrypt_password, still not encrypted
- pdf, _ = report.with_context(ctx).render_qweb_pdf([1])
+ pdf, _ = report.with_context(ctx)._render_qweb_pdf([1])
self.assertFalse(pdf.count(b"/Encrypt"))
# If invalid encrypt_password, show error
report.encrypt_password = "invalid python syntax"
with self.assertRaises(ValidationError):
- pdf, _ = report.with_context(ctx).render_qweb_pdf([1])
+ pdf, _ = report.with_context(ctx)._render_qweb_pdf([1])
# Valid python string for password
report.encrypt_password = "'secretcode'"
- pdf, _ = report.with_context(ctx).render_qweb_pdf([1])
+ pdf, _ = report.with_context(ctx)._render_qweb_pdf([1])
self.assertTrue(pdf.count(b"/Encrypt"))
# TODO: test_report_qweb_manual_encrypt, require JS test?
From 417b79b75d021682714a284324cc5177e6a196ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ana=20Su=C3=A1rez?=
Date: Tue, 16 Mar 2021 10:12:19 +0000
Subject: [PATCH 05/22] Added translation using Weblate (Spanish)
---
report_qweb_encrypt/i18n/es.po | 101 +++++++++++++++++++++++++++++++++
1 file changed, 101 insertions(+)
create mode 100644 report_qweb_encrypt/i18n/es.po
diff --git a/report_qweb_encrypt/i18n/es.po b/report_qweb_encrypt/i18n/es.po
new file mode 100644
index 0000000000..054179902f
--- /dev/null
+++ b/report_qweb_encrypt/i18n/es.po
@@ -0,0 +1,101 @@
+# Translation of Odoo Server.
+# This file contains the translation of the following modules:
+# * report_qweb_encrypt
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Odoo Server 14.0\n"
+"Report-Msgid-Bugs-To: \n"
+"Last-Translator: Automatically generated\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"
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,help:report_qweb_encrypt.field_ir_actions_report__encrypt
+msgid ""
+"* Manual Input Password: allow user to key in password on the fly. This option available only on document print action.\n"
+"* Auto Generated Password: system will auto encrypt password when PDF created, based on provided python syntax."
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields.selection,name:report_qweb_encrypt.selection__ir_actions_report__encrypt__auto
+msgid "Auto Generated Password"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#. openerp-web
+#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
+#, python-format
+msgid "Cancel"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__display_name
+msgid "Display Name"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#. openerp-web
+#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
+#, python-format
+msgid "Encrypt"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__encrypt_password
+msgid "Encrypt Password"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__encrypt
+msgid "Encryption"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__id
+msgid "ID"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report____last_update
+msgid "Last Modified on"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields.selection,name:report_qweb_encrypt.selection__ir_actions_report__encrypt__manual
+msgid "Manual Input Password"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#. openerp-web
+#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
+#, python-format
+msgid "Ok"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model.fields,help:report_qweb_encrypt.field_ir_actions_report__encrypt_password
+msgid "Python code syntax to gnerate password."
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: code:addons/report_qweb_encrypt/models/ir_actions_report.py:0
+#, python-format
+msgid ""
+"Python code used for encryption password is invalid.\n"
+"%s"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model:ir.model,name:report_qweb_encrypt.model_ir_actions_report
+msgid "Report Action"
+msgstr ""
+
+#. module: report_qweb_encrypt
+#: model_terms:ir.ui.view,arch_db:report_qweb_encrypt.ir_actions_report_form_view
+msgid "python syntax, i.e., (object.default_code or 'secretcode')"
+msgstr ""
From a416460dd9d0bc83d8b2661a78f00745c43f9906 Mon Sep 17 00:00:00 2001
From: ps-tubtim
Date: Fri, 7 Jan 2022 11:25:50 +0700
Subject: [PATCH 06/22] [FIX] report_qweb_encrypt: conflict with bank statement
---
report_qweb_encrypt/__manifest__.py | 2 +-
report_qweb_encrypt/models/ir_actions_report.py | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/report_qweb_encrypt/__manifest__.py b/report_qweb_encrypt/__manifest__.py
index 299b595b1e..e257ba5120 100644
--- a/report_qweb_encrypt/__manifest__.py
+++ b/report_qweb_encrypt/__manifest__.py
@@ -5,7 +5,7 @@
{
"name": "Report Qweb Encrypt",
"summary": "Allow to encrypt qweb pdfs",
- "version": "14.0.1.0.0",
+ "version": "14.0.1.0.1",
"license": "AGPL-3",
"author": "Creu Blanca,Ecosoft,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/reporting-engine",
diff --git a/report_qweb_encrypt/models/ir_actions_report.py b/report_qweb_encrypt/models/ir_actions_report.py
index c4a00dd17c..6f4be9bf6b 100644
--- a/report_qweb_encrypt/models/ir_actions_report.py
+++ b/report_qweb_encrypt/models/ir_actions_report.py
@@ -34,6 +34,8 @@ def _render_qweb_pdf(self, res_ids=None, data=None):
document, ttype = super(IrActionsReport, self)._render_qweb_pdf(
res_ids=res_ids, data=data
)
+ if isinstance(res_ids, int):
+ res_ids = [res_ids]
password = self._get_pdf_password(res_ids[:1])
document = self._encrypt_pdf(document, password)
return document, ttype
From 9b38680a083e347fae6307ca553a71d48a518074 Mon Sep 17 00:00:00 2001
From: Stefan Rijnhart
Date: Wed, 11 May 2022 19:22:40 +0200
Subject: [PATCH 07/22] [FIX] report_qweb_encrypt: the case without res_ids
---
report_qweb_encrypt/models/ir_actions_report.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/report_qweb_encrypt/models/ir_actions_report.py b/report_qweb_encrypt/models/ir_actions_report.py
index 6f4be9bf6b..2a15da2f4c 100644
--- a/report_qweb_encrypt/models/ir_actions_report.py
+++ b/report_qweb_encrypt/models/ir_actions_report.py
@@ -34,10 +34,11 @@ def _render_qweb_pdf(self, res_ids=None, data=None):
document, ttype = super(IrActionsReport, self)._render_qweb_pdf(
res_ids=res_ids, data=data
)
- if isinstance(res_ids, int):
- res_ids = [res_ids]
- password = self._get_pdf_password(res_ids[:1])
- document = self._encrypt_pdf(document, password)
+ if res_ids:
+ if isinstance(res_ids, int):
+ res_ids = [res_ids]
+ password = self._get_pdf_password(res_ids[:1])
+ document = self._encrypt_pdf(document, password)
return document, ttype
def _get_pdf_password(self, res_id):
From 413846cc5eb0cb6b32bde1f1f926791b9892a550 Mon Sep 17 00:00:00 2001
From: Stefan Rijnhart
Date: Wed, 11 May 2022 19:27:48 +0200
Subject: [PATCH 08/22] [FIX] report_download controller method signature in
two modules
---
report_qweb_encrypt/controllers/main.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/report_qweb_encrypt/controllers/main.py b/report_qweb_encrypt/controllers/main.py
index 015468354e..ed8526f185 100644
--- a/report_qweb_encrypt/controllers/main.py
+++ b/report_qweb_encrypt/controllers/main.py
@@ -12,8 +12,8 @@
class ReportController(report.ReportController):
@route()
- def report_download(self, data, token):
- result = super().report_download(data, token)
+ def report_download(self, data, token, context=None):
+ result = super().report_download(data, token, context=context)
# When report is downloaded from print action, this function is called,
# but this function cannot pass context (manually entered password) to
# report.render_qweb_pdf(), encrypton for manual password is done here.
From 056e822be4ef6c96eeda56deddc796f568b16346 Mon Sep 17 00:00:00 2001
From: KKamaa
Date: Fri, 15 Apr 2022 14:05:47 +0300
Subject: [PATCH 09/22] [FIX] readme sample
---
report_qweb_encrypt/__manifest__.py | 2 +-
.../static/src/js/report/action_manager_report.js | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/report_qweb_encrypt/__manifest__.py b/report_qweb_encrypt/__manifest__.py
index e257ba5120..efda67fbdc 100644
--- a/report_qweb_encrypt/__manifest__.py
+++ b/report_qweb_encrypt/__manifest__.py
@@ -5,7 +5,7 @@
{
"name": "Report Qweb Encrypt",
"summary": "Allow to encrypt qweb pdfs",
- "version": "14.0.1.0.1",
+ "version": "14.0.1.1.0",
"license": "AGPL-3",
"author": "Creu Blanca,Ecosoft,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/reporting-engine",
diff --git a/report_qweb_encrypt/static/src/js/report/action_manager_report.js b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
index 376954861f..7e9585f92e 100644
--- a/report_qweb_encrypt/static/src/js/report/action_manager_report.js
+++ b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
@@ -85,8 +85,9 @@ odoo.define("report_qweb_encrypt.Dialog", function (require) {
})
);
reportUrls = _.mapObject(reportUrls, function (value) {
- value += serializedOptionsPath;
- return value;
+ var val = value;
+ val += serializedOptionsPath;
+ return val;
});
}
}
From 8e292547a5eadc3d7385793e57dac28ea1b9b7f9 Mon Sep 17 00:00:00 2001
From: grzana12
Date: Sat, 5 Nov 2022 22:36:34 +0100
Subject: [PATCH 10/22] [MIG] report_qweb_encrypt: Migration to 15.0
---
report_qweb_encrypt/README.rst | 10 +-
report_qweb_encrypt/__manifest__.py | 14 ++-
report_qweb_encrypt/controllers/main.py | 22 +++--
report_qweb_encrypt/i18n/es.po | 32 ++----
.../i18n/report_qweb_encrypt.pot | 28 +-----
.../models/ir_actions_report.py | 30 +++---
.../static/description/index.html | 6 +-
.../js/report/action_manager_report.esm.js | 77 +++++++++++++++
.../src/js/report/action_manager_report.js | 97 -------------------
.../static/src/js/report/encrypt_dialog.xml | 13 +++
report_qweb_encrypt/templates/assets.xml | 16 ---
.../tests/test_report_qweb_encrypt.py | 25 ++++-
12 files changed, 167 insertions(+), 203 deletions(-)
create mode 100644 report_qweb_encrypt/static/src/js/report/action_manager_report.esm.js
delete mode 100644 report_qweb_encrypt/static/src/js/report/action_manager_report.js
create mode 100644 report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml
delete mode 100644 report_qweb_encrypt/templates/assets.xml
diff --git a/report_qweb_encrypt/README.rst b/report_qweb_encrypt/README.rst
index ab406389f6..3cdbc22849 100644
--- a/report_qweb_encrypt/README.rst
+++ b/report_qweb_encrypt/README.rst
@@ -14,13 +14,13 @@ Report Qweb Encrypt
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
- :target: https://github.com/OCA/reporting-engine/tree/14.0/report_qweb_encrypt
+ :target: https://github.com/OCA/reporting-engine/tree/15.0/report_qweb_encrypt
:alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/reporting-engine-14-0/reporting-engine-14-0-report_qweb_encrypt
+ :target: https://translation.odoo-community.org/projects/reporting-engine-15-0/reporting-engine-15-0-report_qweb_encrypt
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/143/14.0
+ :target: https://runbot.odoo-community.org/runbot/143/15.0
:alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5|
@@ -46,7 +46,7 @@ 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 `_.
+`feedback `_.
Do not contact contributors directly about support or help with technical issues.
@@ -87,6 +87,6 @@ Current `maintainer `__:
|maintainer-kittiu|
-This module is part of the `OCA/reporting-engine `_ project on GitHub.
+This module is part of the `OCA/reporting-engine `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/report_qweb_encrypt/__manifest__.py b/report_qweb_encrypt/__manifest__.py
index efda67fbdc..4644b6ffce 100644
--- a/report_qweb_encrypt/__manifest__.py
+++ b/report_qweb_encrypt/__manifest__.py
@@ -5,14 +5,24 @@
{
"name": "Report Qweb Encrypt",
"summary": "Allow to encrypt qweb pdfs",
- "version": "14.0.1.1.0",
+ "version": "15.0.1.0.0",
"license": "AGPL-3",
"author": "Creu Blanca,Ecosoft,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/reporting-engine",
"depends": [
"web",
],
- "data": ["views/ir_actions_report.xml", "templates/assets.xml"],
+ "data": [
+ "views/ir_actions_report.xml",
+ ],
+ "assets": {
+ "web.assets_backend": [
+ "report_qweb_encrypt/static/src/js/report/action_manager_report.esm.js",
+ ],
+ },
+ "external_dependencies": {
+ "python": ["PyPDF2"] # Python third party libraries required for module
+ },
"installable": True,
"maintainers": ["kittiu"],
}
diff --git a/report_qweb_encrypt/controllers/main.py b/report_qweb_encrypt/controllers/main.py
index ed8526f185..f7beea4aa8 100644
--- a/report_qweb_encrypt/controllers/main.py
+++ b/report_qweb_encrypt/controllers/main.py
@@ -12,8 +12,8 @@
class ReportController(report.ReportController):
@route()
- def report_download(self, data, token, context=None):
- result = super().report_download(data, token, context=context)
+ def report_download(self, data, context=None):
+ result = super(ReportController, self).report_download(data, context=context)
# When report is downloaded from print action, this function is called,
# but this function cannot pass context (manually entered password) to
# report.render_qweb_pdf(), encrypton for manual password is done here.
@@ -24,14 +24,16 @@ def report_download(self, data, token, context=None):
and result.headers["Content-Type"] == "application/pdf"
and "?" in url
):
- url_data = dict(url_decode(url.split("?")[1]).items())
- if "context" in url_data:
- context = json.loads(url_data["context"])
- if "encrypt_password" in context:
- Report = request.env["ir.actions.report"]
- data = result.get_data()
- encrypted_data = Report._encrypt_pdf(
- data, context["encrypt_password"]
+ data = dict(
+ url_decode(url.split("?")[1]).items()
+ ) # decoding the args represented in JSON
+ if "context" in data:
+ context, data_context = json.loads(context or "{}"), json.loads(
+ data.pop("context")
+ )
+ if "encrypt_password" in data_context:
+ encrypted_data = request.env["ir.actions.report"]._encrypt_pdf(
+ result.get_data(), data_context["encrypt_password"]
)
result.set_data(encrypted_data)
return result
diff --git a/report_qweb_encrypt/i18n/es.po b/report_qweb_encrypt/i18n/es.po
index 054179902f..e96025548f 100644
--- a/report_qweb_encrypt/i18n/es.po
+++ b/report_qweb_encrypt/i18n/es.po
@@ -17,8 +17,10 @@ msgstr ""
#. module: report_qweb_encrypt
#: model:ir.model.fields,help:report_qweb_encrypt.field_ir_actions_report__encrypt
msgid ""
-"* Manual Input Password: allow user to key in password on the fly. This option available only on document print action.\n"
-"* Auto Generated Password: system will auto encrypt password when PDF created, based on provided python syntax."
+"* Manual Input Password: allow user to key in password on the fly. This "
+"option available only on document print action.\n"
+"* Auto Generated Password: system will auto encrypt password when PDF "
+"created, based on provided python syntax."
msgstr ""
#. module: report_qweb_encrypt
@@ -28,23 +30,11 @@ msgstr ""
#. module: report_qweb_encrypt
#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
+#: code:addons/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml:0
#, python-format
msgid "Cancel"
msgstr ""
-#. module: report_qweb_encrypt
-#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__display_name
-msgid "Display Name"
-msgstr ""
-
-#. module: report_qweb_encrypt
-#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
-#, python-format
-msgid "Encrypt"
-msgstr ""
-
#. module: report_qweb_encrypt
#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__encrypt_password
msgid "Encrypt Password"
@@ -55,16 +45,6 @@ msgstr ""
msgid "Encryption"
msgstr ""
-#. module: report_qweb_encrypt
-#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__id
-msgid "ID"
-msgstr ""
-
-#. module: report_qweb_encrypt
-#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report____last_update
-msgid "Last Modified on"
-msgstr ""
-
#. module: report_qweb_encrypt
#: model:ir.model.fields.selection,name:report_qweb_encrypt.selection__ir_actions_report__encrypt__manual
msgid "Manual Input Password"
@@ -72,7 +52,7 @@ msgstr ""
#. module: report_qweb_encrypt
#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
+#: code:addons/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml:0
#, python-format
msgid "Ok"
msgstr ""
diff --git a/report_qweb_encrypt/i18n/report_qweb_encrypt.pot b/report_qweb_encrypt/i18n/report_qweb_encrypt.pot
index 89605ef63b..bb6febbf10 100644
--- a/report_qweb_encrypt/i18n/report_qweb_encrypt.pot
+++ b/report_qweb_encrypt/i18n/report_qweb_encrypt.pot
@@ -4,7 +4,7 @@
#
msgid ""
msgstr ""
-"Project-Id-Version: Odoo Server 14.0\n"
+"Project-Id-Version: Odoo Server 15.0\n"
"Report-Msgid-Bugs-To: \n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -27,23 +27,11 @@ msgstr ""
#. module: report_qweb_encrypt
#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
+#: code:addons/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml:0
#, python-format
msgid "Cancel"
msgstr ""
-#. module: report_qweb_encrypt
-#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__display_name
-msgid "Display Name"
-msgstr ""
-
-#. module: report_qweb_encrypt
-#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
-#, python-format
-msgid "Encrypt"
-msgstr ""
-
#. module: report_qweb_encrypt
#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__encrypt_password
msgid "Encrypt Password"
@@ -54,16 +42,6 @@ msgstr ""
msgid "Encryption"
msgstr ""
-#. module: report_qweb_encrypt
-#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__id
-msgid "ID"
-msgstr ""
-
-#. module: report_qweb_encrypt
-#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report____last_update
-msgid "Last Modified on"
-msgstr ""
-
#. module: report_qweb_encrypt
#: model:ir.model.fields.selection,name:report_qweb_encrypt.selection__ir_actions_report__encrypt__manual
msgid "Manual Input Password"
@@ -71,7 +49,7 @@ msgstr ""
#. module: report_qweb_encrypt
#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/action_manager_report.js:0
+#: code:addons/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml:0
#, python-format
msgid "Ok"
msgstr ""
diff --git a/report_qweb_encrypt/models/ir_actions_report.py b/report_qweb_encrypt/models/ir_actions_report.py
index 2a15da2f4c..b72c7b9017 100644
--- a/report_qweb_encrypt/models/ir_actions_report.py
+++ b/report_qweb_encrypt/models/ir_actions_report.py
@@ -1,19 +1,14 @@
# Copyright 2020 Creu Blanca
# Copyright 2020 Ecosoft Co., Ltd.
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-import logging
from io import BytesIO
+from PyPDF2 import PdfFileReader, PdfFileWriter
+
from odoo import _, fields, models
from odoo.exceptions import ValidationError
from odoo.tools.safe_eval import safe_eval
-_logger = logging.getLogger(__name__)
-try:
- from PyPDF2 import PdfFileReader, PdfFileWriter
-except ImportError as err:
- _logger.debug(err)
-
class IrActionsReport(models.Model):
_inherit = "ir.actions.report"
@@ -35,13 +30,11 @@ def _render_qweb_pdf(self, res_ids=None, data=None):
res_ids=res_ids, data=data
)
if res_ids:
- if isinstance(res_ids, int):
- res_ids = [res_ids]
password = self._get_pdf_password(res_ids[:1])
document = self._encrypt_pdf(document, password)
return document, ttype
- def _get_pdf_password(self, res_id):
+ def _get_pdf_password(self, res_ids):
encrypt_password = False
if self.encrypt == "manual":
# If use document print action, report_download() is called,
@@ -51,17 +44,24 @@ def _get_pdf_password(self, res_id):
# Following is used just in case when context is passed in.
encrypt_password = self._context.get("encrypt_password", False)
elif self.encrypt == "auto" and self.encrypt_password:
- obj = self.env[self.model].browse(res_id)
+ # access the report details with sudo() but evaluation context as sudo(False)
+ self_sudo = self.sudo()
+
+ Model = self.env[self_sudo.model]
+ record_ids = Model.browse(res_ids)
try:
- encrypt_password = safe_eval(self.encrypt_password, {"object": obj})
- except Exception:
+ encrypt_password = safe_eval(
+ self.encrypt_password, {"object": record_ids}
+ )
+ except Exception as e:
raise ValidationError(
_("Python code used for encryption password is invalid.\n%s")
% self.encrypt_password
- )
+ ) from e
return encrypt_password
- def _encrypt_pdf(self, data, password):
+ @staticmethod
+ def _encrypt_pdf(data, password):
if not password:
return data
output_pdf = PdfFileWriter()
diff --git a/report_qweb_encrypt/static/description/index.html b/report_qweb_encrypt/static/description/index.html
index a20f845113..26106a3880 100644
--- a/report_qweb_encrypt/static/description/index.html
+++ b/report_qweb_encrypt/static/description/index.html
@@ -367,7 +367,7 @@ Report Qweb Encrypt
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-
+
This module allow you to encrypt PDF with a password seting option,
Manually keyin password (only applicable for record print action)
@@ -395,7 +395,7 @@
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 .
+feedback .
Do not contact contributors directly about support or help with technical issues.
diff --git a/report_qweb_encrypt/static/src/js/report/action_manager_report.esm.js b/report_qweb_encrypt/static/src/js/report/action_manager_report.esm.js
new file mode 100644
index 0000000000..fcf110a3f4
--- /dev/null
+++ b/report_qweb_encrypt/static/src/js/report/action_manager_report.esm.js
@@ -0,0 +1,77 @@
+/** @odoo-module **/
+
+import {Dialog} from "@web/core/dialog/dialog";
+import {download} from "@web/core/network/download";
+import {registry} from "@web/core/registry";
+
+async function download_function(action, options, env) {
+ const type = action.report_type;
+ let url = `/report/${type}/${action.report_name}`;
+ const actionContext = action.context || {};
+ if (action.data && JSON.stringify(action.data) !== "{}") {
+ // Build a query string with `action.data` (it's the place where reports
+ // using a wizard to customize the output traditionally put their options)
+ const action_options = encodeURIComponent(JSON.stringify(action.data));
+ const context = encodeURIComponent(JSON.stringify(actionContext));
+ url += `?options=${action_options}&context=${context}`;
+ } else {
+ if (actionContext.active_ids) {
+ url += `/${actionContext.active_ids.join(",")}`;
+ }
+ if (type === "html") {
+ const context = encodeURIComponent(
+ JSON.stringify(env.services.user.context)
+ );
+ url += `?context=${context}`;
+ }
+ }
+ env.services.ui.block();
+ try {
+ await download({
+ url: "/report/download",
+ data: {
+ data: JSON.stringify([url, action.report_type]),
+ context: JSON.stringify(env.services.user.context),
+ },
+ });
+ } finally {
+ env.services.ui.unblock();
+ }
+ const onClose = options.onClose;
+ if (action.close_on_report_download) {
+ return env.services.action.doAction(
+ {type: "ir.actions.act_window_close"},
+ {onClose}
+ );
+ } else if (onClose) {
+ onClose();
+ }
+ return Promise.resolve(true);
+}
+
+class EncryptDialog extends Dialog {
+ onClick() {
+ const action = this.props.action;
+ action.context = _.extend({}, action.context, {
+ encrypt_password: this.el.find(".o_password").val() || false,
+ });
+ return download_function(action, this.props.options, this.props.env);
+ }
+}
+EncryptDialog.size = "small";
+EncryptDialog.title = "Encrypt";
+EncryptDialog.bodyTemplate = "report_qweb_encrypt.EncryptDialogBody";
+EncryptDialog.footerTemplate = "report_qweb_encrypt.EncryptDialogFooter";
+
+registry
+ .category("ir.actions.report handlers")
+ .add("qweb-pdf-password", async function (action, options, env) {
+ if (action.encrypt === "manual" && action.report_type === "qweb-pdf") {
+ return env.services.dialog.add(EncryptDialog, {
+ action: action,
+ options: options,
+ env: env,
+ });
+ }
+ return Promise.resolve(false);
+ });
diff --git a/report_qweb_encrypt/static/src/js/report/action_manager_report.js b/report_qweb_encrypt/static/src/js/report/action_manager_report.js
deleted file mode 100644
index 7e9585f92e..0000000000
--- a/report_qweb_encrypt/static/src/js/report/action_manager_report.js
+++ /dev/null
@@ -1,97 +0,0 @@
-// © 2017 Creu Blanca
-// License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
-odoo.define("report_qweb_encrypt.Dialog", function (require) {
- "use strict";
-
- var ActionManager = require("web.ActionManager");
- var Dialog = require("web.Dialog");
- var core = require("web.core");
-
- var _t = core._t;
-
- var EncryptDialog = Dialog.extend({
- events: _.extend({}, Dialog.prototype.events, {
- change: "_onChange",
- }),
- _setValue: function () {
- this.value = this.$el.find(".o_password").val();
- },
- _onChange: function () {
- this._setValue();
- },
- });
- EncryptDialog.askPassword = function (owner, action, action_options, options) {
- var buttons = [
- {
- text: _t("Ok"),
- classes: "btn-primary",
- close: true,
- click: function () {
- var password = this.value || false;
- owner._executeReportAction(action, action_options, password);
- },
- },
- {
- text: _t("Cancel"),
- close: true,
- click: false,
- },
- ];
- return new EncryptDialog(
- owner,
- _.extend(
- {
- size: "small",
- buttons: buttons,
- $content: $(
- '
'
- ),
- title: _t("Encrypt"),
- },
- options
- )
- ).open();
- };
-
- ActionManager.include({
- _executeReportAction: function (action, options, password) {
- if (
- action.encrypt === "manual" &&
- action.report_type === "qweb-pdf" &&
- password === undefined
- ) {
- EncryptDialog.askPassword(this, action, options);
- return $.Deferred();
- } else if (action.encrypt === "manual") {
- action.context = _.extend({}, action.context, {
- encrypt_password: password,
- });
- }
- return this._super(action, options, password);
- },
- _makeReportUrls: function (action) {
- var reportUrls = this._super.apply(this, arguments);
- if (action.encrypt === "manual" && action.context.encrypt_password) {
- if (
- _.isUndefined(action.data) ||
- _.isNull(action.data) ||
- (_.isObject(action.data) && _.isEmpty(action.data))
- ) {
- var serializedOptionsPath =
- "?context=" +
- encodeURIComponent(
- JSON.stringify({
- encrypt_password: action.context.encrypt_password,
- })
- );
- reportUrls = _.mapObject(reportUrls, function (value) {
- var val = value;
- val += serializedOptionsPath;
- return val;
- });
- }
- }
- return reportUrls;
- },
- });
-});
diff --git a/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml b/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml
new file mode 100644
index 0000000000..45c359fc96
--- /dev/null
+++ b/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml
@@ -0,0 +1,13 @@
+
+
+
+
+ Ok
+ Cancel
+
+
+
+
+
+
+
diff --git a/report_qweb_encrypt/templates/assets.xml b/report_qweb_encrypt/templates/assets.xml
deleted file mode 100644
index e313587f35..0000000000
--- a/report_qweb_encrypt/templates/assets.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/report_qweb_encrypt/tests/test_report_qweb_encrypt.py b/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
index b13ae93437..0de5e0cb0b 100644
--- a/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
+++ b/report_qweb_encrypt/tests/test_report_qweb_encrypt.py
@@ -9,7 +9,7 @@ def test_report_qweb_no_encrypt(self):
ctx = {"force_report_rendering": True}
report = self.env.ref("web.action_report_internalpreview")
report.encrypt = False
- pdf, _ = report.with_context(ctx)._render_qweb_pdf([1])
+ pdf, _ = report.with_context(**ctx)._render_qweb_pdf([1])
self.assertFalse(pdf.count(b"/Encrypt"))
def test_report_qweb_auto_encrypt(self):
@@ -17,16 +17,33 @@ def test_report_qweb_auto_encrypt(self):
report = self.env.ref("web.action_report_internalpreview")
report.encrypt = "auto"
report.encrypt_password = False
+
# If no encrypt_password, still not encrypted
- pdf, _ = report.with_context(ctx)._render_qweb_pdf([1])
+ pdf, _ = report.with_context(**ctx)._render_qweb_pdf([1])
self.assertFalse(pdf.count(b"/Encrypt"))
+
# If invalid encrypt_password, show error
report.encrypt_password = "invalid python syntax"
with self.assertRaises(ValidationError):
- pdf, _ = report.with_context(ctx)._render_qweb_pdf([1])
+ pdf, _ = report.with_context(**ctx)._render_qweb_pdf([1])
+
# Valid python string for password
report.encrypt_password = "'secretcode'"
- pdf, _ = report.with_context(ctx)._render_qweb_pdf([1])
+ pdf, _ = report.with_context(**ctx)._render_qweb_pdf([1])
+ self.assertTrue(pdf.count(b"/Encrypt"))
+
+ def test_report_qweb_manual_encrypt(self):
+ ctx = {"force_report_rendering": True}
+ report = self.env.ref("web.action_report_internalpreview")
+ report.encrypt = "manual"
+
+ # If no encrypt_password, still not encrypted
+ pdf, _ = report.with_context(**ctx)._render_qweb_pdf([1])
+ self.assertFalse(pdf.count(b"/Encrypt"))
+
+ # Valid python string for password
+ ctx.update({"encrypt_password": "secretcode"})
+ pdf, _ = report.with_context(**ctx)._render_qweb_pdf([1])
self.assertTrue(pdf.count(b"/Encrypt"))
# TODO: test_report_qweb_manual_encrypt, require JS test?
From b9c3a2cfa5535aa647657ad823ff2198b43f3aaf Mon Sep 17 00:00:00 2001
From: Ivorra78
Date: Thu, 13 Jul 2023 18:15:21 +0000
Subject: [PATCH 11/22] Translated using Weblate (Spanish)
Currently translated at 100.0% (11 of 11 strings)
Translation: reporting-engine-15.0/reporting-engine-15.0-report_qweb_encrypt
Translate-URL: https://translation.odoo-community.org/projects/reporting-engine-15-0/reporting-engine-15-0-report_qweb_encrypt/es/
---
report_qweb_encrypt/i18n/es.po | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/report_qweb_encrypt/i18n/es.po b/report_qweb_encrypt/i18n/es.po
index e96025548f..b4233eabc9 100644
--- a/report_qweb_encrypt/i18n/es.po
+++ b/report_qweb_encrypt/i18n/es.po
@@ -6,13 +6,15 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
-"Last-Translator: Automatically generated\n"
+"PO-Revision-Date: 2023-07-13 20:08+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: report_qweb_encrypt
#: model:ir.model.fields,help:report_qweb_encrypt.field_ir_actions_report__encrypt
@@ -22,45 +24,51 @@ msgid ""
"* Auto Generated Password: system will auto encrypt password when PDF "
"created, based on provided python syntax."
msgstr ""
+"* Contraseña de entrada manual: permite al usuario introducir la contraseña "
+"sobre la marcha. Esta opción sólo está disponible en la acción de impresión "
+"de documentos.\n"
+"* Contraseña generada automáticamente: el sistema cifrará automáticamente la "
+"contraseña cuando se cree el PDF, basándose en la sintaxis python "
+"proporcionada."
#. module: report_qweb_encrypt
#: model:ir.model.fields.selection,name:report_qweb_encrypt.selection__ir_actions_report__encrypt__auto
msgid "Auto Generated Password"
-msgstr ""
+msgstr "Contraseña generada automáticamente"
#. module: report_qweb_encrypt
#. openerp-web
#: code:addons/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml:0
#, python-format
msgid "Cancel"
-msgstr ""
+msgstr "Cancelar"
#. module: report_qweb_encrypt
#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__encrypt_password
msgid "Encrypt Password"
-msgstr ""
+msgstr "Encriptar contraseña"
#. module: report_qweb_encrypt
#: model:ir.model.fields,field_description:report_qweb_encrypt.field_ir_actions_report__encrypt
msgid "Encryption"
-msgstr ""
+msgstr "Encriptación"
#. module: report_qweb_encrypt
#: model:ir.model.fields.selection,name:report_qweb_encrypt.selection__ir_actions_report__encrypt__manual
msgid "Manual Input Password"
-msgstr ""
+msgstr "Contraseña de entrada manual"
#. module: report_qweb_encrypt
#. openerp-web
#: code:addons/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml:0
#, python-format
msgid "Ok"
-msgstr ""
+msgstr "Aceptar"
#. module: report_qweb_encrypt
#: model:ir.model.fields,help:report_qweb_encrypt.field_ir_actions_report__encrypt_password
msgid "Python code syntax to gnerate password."
-msgstr ""
+msgstr "Sintaxis del código Python para generar la contraseña."
#. module: report_qweb_encrypt
#: code:addons/report_qweb_encrypt/models/ir_actions_report.py:0
@@ -69,13 +77,15 @@ msgid ""
"Python code used for encryption password is invalid.\n"
"%s"
msgstr ""
+"El código Python utilizado para cifrar la contraseña no es válido.\n"
+"%s"
#. module: report_qweb_encrypt
#: model:ir.model,name:report_qweb_encrypt.model_ir_actions_report
msgid "Report Action"
-msgstr ""
+msgstr "Informar Acción"
#. module: report_qweb_encrypt
#: model_terms:ir.ui.view,arch_db:report_qweb_encrypt.ir_actions_report_form_view
msgid "python syntax, i.e., (object.default_code or 'secretcode')"
-msgstr ""
+msgstr "sintaxis python, es decir, (object.default_code o 'secretcode')"
From 12cedfb09ec7c1f8f75eaa6fe917aabe40f2a83f Mon Sep 17 00:00:00 2001
From: payen000
Date: Thu, 3 Aug 2023 09:00:52 -0700
Subject: [PATCH 12/22] [MIG] report_qweb_encrypt: Migration to 16.0
---
report_qweb_encrypt/README.rst | 23 +++++-----
report_qweb_encrypt/__manifest__.py | 8 ++--
report_qweb_encrypt/controllers/main.py | 6 +--
report_qweb_encrypt/i18n/es.po | 9 ++--
.../i18n/report_qweb_encrypt.pot | 11 ++---
.../models/ir_actions_report.py | 18 +++++---
.../static/description/index.html | 44 ++++++++++---------
.../static/src/js/report/encrypt_dialog.xml | 13 ------
.../report/action_manager_report.esm.js | 24 +++++-----
.../static/src/report/encrypt_dialog.xml | 16 +++++++
.../tests/test_report_qweb_encrypt.py | 14 +++---
11 files changed, 102 insertions(+), 84 deletions(-)
delete mode 100644 report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml
rename report_qweb_encrypt/static/src/{js => }/report/action_manager_report.esm.js (77%)
create mode 100644 report_qweb_encrypt/static/src/report/encrypt_dialog.xml
diff --git a/report_qweb_encrypt/README.rst b/report_qweb_encrypt/README.rst
index 3cdbc22849..0357dd7422 100644
--- a/report_qweb_encrypt/README.rst
+++ b/report_qweb_encrypt/README.rst
@@ -2,10 +2,13 @@
Report Qweb Encrypt
===================
-.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+..
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ !! source digest: sha256:39f6dde3334280de72202685d7a2ff860af9a58611285e8c80da3c2ee12d491c
+ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
@@ -14,16 +17,16 @@ Report Qweb Encrypt
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
- :target: https://github.com/OCA/reporting-engine/tree/15.0/report_qweb_encrypt
+ :target: https://github.com/OCA/reporting-engine/tree/16.0/report_qweb_encrypt
:alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/reporting-engine-15-0/reporting-engine-15-0-report_qweb_encrypt
+ :target: https://translation.odoo-community.org/projects/reporting-engine-16-0/reporting-engine-16-0-report_qweb_encrypt
:alt: Translate me on Weblate
-.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
- :target: https://runbot.odoo-community.org/runbot/143/15.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/reporting-engine&target_branch=16.0
+ :alt: Try me on Runboat
-|badge1| |badge2| |badge3| |badge4| |badge5|
+|badge1| |badge2| |badge3| |badge4| |badge5|
This module allow you to encrypt PDF with a password seting option,
@@ -45,8 +48,8 @@ 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 `_.
+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.
@@ -87,6 +90,6 @@ Current `maintainer `__:
|maintainer-kittiu|
-This module is part of the `OCA/reporting-engine `_ project on GitHub.
+This module is part of the `OCA/reporting-engine `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/report_qweb_encrypt/__manifest__.py b/report_qweb_encrypt/__manifest__.py
index 4644b6ffce..8442ddbd1b 100644
--- a/report_qweb_encrypt/__manifest__.py
+++ b/report_qweb_encrypt/__manifest__.py
@@ -5,7 +5,7 @@
{
"name": "Report Qweb Encrypt",
"summary": "Allow to encrypt qweb pdfs",
- "version": "15.0.1.0.0",
+ "version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Creu Blanca,Ecosoft,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/reporting-engine",
@@ -17,12 +17,10 @@
],
"assets": {
"web.assets_backend": [
- "report_qweb_encrypt/static/src/js/report/action_manager_report.esm.js",
+ "report_qweb_encrypt/static/src/report/action_manager_report.esm.js",
+ "report_qweb_encrypt/static/src/report/encrypt_dialog.xml",
],
},
- "external_dependencies": {
- "python": ["PyPDF2"] # Python third party libraries required for module
- },
"installable": True,
"maintainers": ["kittiu"],
}
diff --git a/report_qweb_encrypt/controllers/main.py b/report_qweb_encrypt/controllers/main.py
index f7beea4aa8..f3450ed254 100644
--- a/report_qweb_encrypt/controllers/main.py
+++ b/report_qweb_encrypt/controllers/main.py
@@ -7,13 +7,13 @@
from odoo.http import request, route
-from odoo.addons.web.controllers import main as report
+from odoo.addons.web.controllers.report import ReportController
-class ReportController(report.ReportController):
+class ReportControllerEncrypt(ReportController):
@route()
def report_download(self, data, context=None):
- result = super(ReportController, self).report_download(data, context=context)
+ result = super().report_download(data, context=context)
# When report is downloaded from print action, this function is called,
# but this function cannot pass context (manually entered password) to
# report.render_qweb_pdf(), encrypton for manual password is done here.
diff --git a/report_qweb_encrypt/i18n/es.po b/report_qweb_encrypt/i18n/es.po
index b4233eabc9..8eea09cec1 100644
--- a/report_qweb_encrypt/i18n/es.po
+++ b/report_qweb_encrypt/i18n/es.po
@@ -37,8 +37,8 @@ msgid "Auto Generated Password"
msgstr "Contraseña generada automáticamente"
#. module: report_qweb_encrypt
-#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml:0
+#. odoo-javascript
+#: code:addons/report_qweb_encrypt/static/src/report/encrypt_dialog.xml:0
#, python-format
msgid "Cancel"
msgstr "Cancelar"
@@ -59,8 +59,8 @@ msgid "Manual Input Password"
msgstr "Contraseña de entrada manual"
#. module: report_qweb_encrypt
-#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml:0
+#. odoo-javascript
+#: code:addons/report_qweb_encrypt/static/src/report/encrypt_dialog.xml:0
#, python-format
msgid "Ok"
msgstr "Aceptar"
@@ -71,6 +71,7 @@ msgid "Python code syntax to gnerate password."
msgstr "Sintaxis del código Python para generar la contraseña."
#. module: report_qweb_encrypt
+#. odoo-python
#: code:addons/report_qweb_encrypt/models/ir_actions_report.py:0
#, python-format
msgid ""
diff --git a/report_qweb_encrypt/i18n/report_qweb_encrypt.pot b/report_qweb_encrypt/i18n/report_qweb_encrypt.pot
index bb6febbf10..6890c9c889 100644
--- a/report_qweb_encrypt/i18n/report_qweb_encrypt.pot
+++ b/report_qweb_encrypt/i18n/report_qweb_encrypt.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"
@@ -26,8 +26,8 @@ msgid "Auto Generated Password"
msgstr ""
#. module: report_qweb_encrypt
-#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml:0
+#. odoo-javascript
+#: code:addons/report_qweb_encrypt/static/src/report/encrypt_dialog.xml:0
#, python-format
msgid "Cancel"
msgstr ""
@@ -48,8 +48,8 @@ msgid "Manual Input Password"
msgstr ""
#. module: report_qweb_encrypt
-#. openerp-web
-#: code:addons/report_qweb_encrypt/static/src/js/report/encrypt_dialog.xml:0
+#. odoo-javascript
+#: code:addons/report_qweb_encrypt/static/src/report/encrypt_dialog.xml:0
#, python-format
msgid "Ok"
msgstr ""
@@ -60,6 +60,7 @@ msgid "Python code syntax to gnerate password."
msgstr ""
#. module: report_qweb_encrypt
+#. odoo-python
#: code:addons/report_qweb_encrypt/models/ir_actions_report.py:0
#, python-format
msgid ""
diff --git a/report_qweb_encrypt/models/ir_actions_report.py b/report_qweb_encrypt/models/ir_actions_report.py
index b72c7b9017..6df9a3d04b 100644
--- a/report_qweb_encrypt/models/ir_actions_report.py
+++ b/report_qweb_encrypt/models/ir_actions_report.py
@@ -25,12 +25,16 @@ class IrActionsReport(models.Model):
help="Python code syntax to gnerate password.",
)
- def _render_qweb_pdf(self, res_ids=None, data=None):
- document, ttype = super(IrActionsReport, self)._render_qweb_pdf(
- res_ids=res_ids, data=data
+ def _render_qweb_pdf(self, reportname, res_ids=None, data=None):
+ document, ttype = super()._render_qweb_pdf(
+ reportname, res_ids=res_ids, data=data
)
if res_ids:
- password = self._get_pdf_password(res_ids[:1])
+ encrypt_password = self._context.get("encrypt_password")
+ report = self._get_report_from_name(reportname).with_context(
+ encrypt_password=encrypt_password
+ )
+ password = report._get_pdf_password(res_ids[:1])
document = self._encrypt_pdf(document, password)
return document, ttype
@@ -55,8 +59,10 @@ def _get_pdf_password(self, res_ids):
)
except Exception as e:
raise ValidationError(
- _("Python code used for encryption password is invalid.\n%s")
- % self.encrypt_password
+ _(
+ "Python code used for encryption password is invalid.\n%s",
+ self.encrypt_password,
+ )
) from e
return encrypt_password
diff --git a/report_qweb_encrypt/static/description/index.html b/report_qweb_encrypt/static/description/index.html
index 26106a3880..69e34559b9 100644
--- a/report_qweb_encrypt/static/description/index.html
+++ b/report_qweb_encrypt/static/description/index.html
@@ -1,20 +1,20 @@
-
+
-
+
Report Qweb Encrypt
-
-
Report Qweb Encrypt
+
+
+
+
+
+
-
+
To make a report encryptable mark the field Encryption in the report
record.
-
+
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
@@ -402,16 +407,16 @@
Do not contact contributors directly about support or help with technical issues.
+
diff --git a/report_qweb_encrypt/static/src/report/action_manager_report.esm.js b/report_qweb_encrypt/static/src/report/action_manager_report.esm.js
index 48e5664fa4..f4b5d9550f 100644
--- a/report_qweb_encrypt/static/src/report/action_manager_report.esm.js
+++ b/report_qweb_encrypt/static/src/report/action_manager_report.esm.js
@@ -1,32 +1,37 @@
-/** @odoo-module **/
-
import {Dialog} from "@web/core/dialog/dialog";
import {download} from "@web/core/network/download";
import {registry} from "@web/core/registry";
+import {useRef} from "@odoo/owl";
+import {user} from "@web/core/user";
+
const {Component} = owl;
-async function download_function(action, options, env) {
- const type = action.report_type === "qweb-pdf" ? "pdf" : action.report_type;
+function buildReportUrl(action, type, userContext) {
let url = `/report/${type}/${action.report_name}`;
const actionContext = action.context || {};
- const userContext = Object.assign(env.services.user.context, {
- encrypt_password: action.context.encrypt_password,
- });
- if (action.data && JSON.stringify(action.data) !== "{}") {
+ if (action.data && Object.keys(action.data).length) {
// Build a query string with `action.data` (it's the place where reports
// using a wizard to customize the output traditionally put their options)
- const action_options = encodeURIComponent(JSON.stringify(action.data));
- const context = encodeURIComponent(JSON.stringify(actionContext));
- url += `?options=${action_options}&context=${context}`;
+ url += `?options=${encodeURIComponent(JSON.stringify(action.data))}`;
+ url += `&context=${encodeURIComponent(JSON.stringify(actionContext))}`;
} else {
if (actionContext.active_ids) {
url += `/${actionContext.active_ids.join(",")}`;
}
if (type === "html") {
- const context = encodeURIComponent(JSON.stringify(userContext));
- url += `?context=${context}`;
+ url += `?context=${encodeURIComponent(JSON.stringify(userContext))}`;
}
}
+ return url;
+}
+
+async function download_function(action, options, env) {
+ const type = action.report_type === "qweb-pdf" ? "pdf" : action.report_type;
+ const userContext = {
+ ...user.context,
+ encrypt_password: action.context?.encrypt_password,
+ };
+ const url = buildReportUrl(action, type, userContext);
env.services.ui.block();
try {
await download({
@@ -39,25 +44,29 @@ async function download_function(action, options, env) {
} finally {
env.services.ui.unblock();
}
- const onClose = options.onClose;
if (action.close_on_report_download) {
return env.services.action.doAction(
{type: "ir.actions.act_window_close"},
- {onClose}
+ {onClose: options.onClose}
);
- } else if (onClose) {
- onClose();
}
- return Promise.resolve(true);
+ options.onClose?.();
+ return true;
}
class EncryptDialog extends Component {
+ setup() {
+ this.passwordRef = useRef("password");
+ }
onClick() {
- const action = this.props.action;
- action.context = _.extend({}, action.context, {
- encrypt_password:
- $("#qweb_encrypt_pdf_password > .o_password").val() || false,
- });
+ const password = this.passwordRef.el?.value || false;
+ const action = {
+ ...this.props.action,
+ context: {
+ ...this.props.action.context,
+ encrypt_password: password,
+ },
+ };
return download_function(action, this.props.options, this.props.env);
}
}
@@ -67,13 +76,9 @@ EncryptDialog.template = "report_qweb_encrypt.EncryptDialogBody";
registry
.category("ir.actions.report handlers")
- .add("qweb-pdf-password", async function (action, options, env) {
+ .add("qweb-pdf-password", async (action, options, env) => {
if (action.encrypt === "manual" && action.report_type === "qweb-pdf") {
- return env.services.dialog.add(EncryptDialog, {
- action: action,
- options: options,
- env: env,
- });
+ return env.services.dialog.add(EncryptDialog, {action, options, env});
}
- return Promise.resolve(false);
+ return false;
});
diff --git a/report_qweb_encrypt/static/src/report/encrypt_dialog.xml b/report_qweb_encrypt/static/src/report/encrypt_dialog.xml
index 3027450055..5bc967ea0f 100644
--- a/report_qweb_encrypt/static/src/report/encrypt_dialog.xml
+++ b/report_qweb_encrypt/static/src/report/encrypt_dialog.xml
@@ -4,7 +4,12 @@
-
+
Ok
diff --git a/report_qweb_encrypt/views/ir_actions_report.xml b/report_qweb_encrypt/views/ir_actions_report.xml
index c71bd21490..e320b35081 100644
--- a/report_qweb_encrypt/views/ir_actions_report.xml
+++ b/report_qweb_encrypt/views/ir_actions_report.xml
@@ -1,9 +1,9 @@
-
+
-
+
ir.actions.report.form (in report_qweb_encrypt)
ir.actions.report
@@ -11,16 +11,16 @@
From f809c9294beca59b9decd35ed40818cfd62c4b2b Mon Sep 17 00:00:00 2001
From: mymage
Date: Wed, 17 Dec 2025 08:01:20 +0000
Subject: [PATCH 19/22] Translated using Weblate (Italian)
Currently translated at 100.0% (12 of 12 strings)
Translation: reporting-engine-18.0/reporting-engine-18.0-report_qweb_encrypt
Translate-URL: https://translation.odoo-community.org/projects/reporting-engine-18-0/reporting-engine-18-0-report_qweb_encrypt/it/
---
report_qweb_encrypt/i18n/it.po | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/report_qweb_encrypt/i18n/it.po b/report_qweb_encrypt/i18n/it.po
index efe356b800..651dd924ef 100644
--- a/report_qweb_encrypt/i18n/it.po
+++ b/report_qweb_encrypt/i18n/it.po
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
-"PO-Revision-Date: 2024-01-18 09:34+0000\n"
+"PO-Revision-Date: 2025-12-17 10:42+0000\n"
"Last-Translator: mymage \n"
"Language-Team: none\n"
"Language: it\n"
@@ -14,7 +14,7 @@ msgstr ""
"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"
+"X-Generator: Weblate 5.10.4\n"
#. module: report_qweb_encrypt
#: model:ir.model.fields,help:report_qweb_encrypt.field_ir_actions_report__encrypt
@@ -57,7 +57,7 @@ msgstr "Criptazione"
#. odoo-javascript
#: code:addons/report_qweb_encrypt/static/src/report/encrypt_dialog.xml:0
msgid "Enter password"
-msgstr ""
+msgstr "Inserire password"
#. module: report_qweb_encrypt
#: model:ir.model.fields.selection,name:report_qweb_encrypt.selection__ir_actions_report__encrypt__manual
From ad54c26897adafdf30e31aea2a705d79f7b0a84a Mon Sep 17 00:00:00 2001
From: "Moises Lopez - https://www.vauxoo.com/"
Date: Fri, 14 Aug 2026 15:08:05 -0600
Subject: [PATCH 20/22] [IMP] report_qweb_encrypt: pre-commit auto fixes
---
report_qweb_encrypt/README.rst | 20 +++++++++----------
.../static/description/index.html | 6 +++---
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/report_qweb_encrypt/README.rst b/report_qweb_encrypt/README.rst
index 21532161f8..626cb0723a 100644
--- a/report_qweb_encrypt/README.rst
+++ b/report_qweb_encrypt/README.rst
@@ -21,21 +21,21 @@ Report Qweb Encrypt
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Freporting--engine-lightgray.png?logo=github
- :target: https://github.com/OCA/reporting-engine/tree/18.0/report_qweb_encrypt
+ :target: https://github.com/OCA/reporting-engine/tree/19.0/report_qweb_encrypt
:alt: OCA/reporting-engine
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
- :target: https://translation.odoo-community.org/projects/reporting-engine-18-0/reporting-engine-18-0-report_qweb_encrypt
+ :target: https://translation.odoo-community.org/projects/reporting-engine-19-0/reporting-engine-19-0-report_qweb_encrypt
: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/reporting-engine&target_branch=18.0
+ :target: https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=19.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module allow you to encrypt PDF with a password seting option,
-- Manually keyin password (only applicable for record print action)
-- Auto generated password based on object data (python)
+- Manually keyin password (only applicable for record print action)
+- Auto generated password based on object data (python)
**Table of contents**
@@ -54,7 +54,7 @@ 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.
@@ -70,9 +70,9 @@ Authors
Contributors
------------
-- Enric Tobella
-- Jaime Arroyo
-- Kitti U.
+- Enric Tobella
+- Jaime Arroyo
+- Kitti U.
Maintainers
-----------
@@ -95,6 +95,6 @@ Current `maintainer `__:
|maintainer-kittiu|
-This module is part of the `OCA/reporting-engine `_ project on GitHub.
+This module is part of the `OCA/reporting-engine `_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
diff --git a/report_qweb_encrypt/static/description/index.html b/report_qweb_encrypt/static/description/index.html
index 786f8b939b..fd9c1142bb 100644
--- a/report_qweb_encrypt/static/description/index.html
+++ b/report_qweb_encrypt/static/description/index.html
@@ -374,7 +374,7 @@ Report Qweb Encrypt
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:0b14a10714ea2e18453d7f01d8a6803ea6ebbc0a1cd46892aa0a05e1aeef5fbc
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
-
+
This module allow you to encrypt PDF with a password seting option,
Manually keyin password (only applicable for record print action)
@@ -403,7 +403,7 @@
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.
From 64c44de5633c005abf59772eb65405bec0e611c5 Mon Sep 17 00:00:00 2001
From: Moises Lopez
Date: Fri, 14 Aug 2026 19:51:55 +0000
Subject: [PATCH 21/22] [MIG] report_qweb_encrypt: Migration to 19.0
Import PdfReader/PdfWriter from odoo.tools.pdf instead of PyPDF2.
Odoo 19 pins PyPDF2==2.12.1 only up to python3.12;
from python 3.13 (Debian Trixie) it pins PyPDF==5.4.0,
where the legacy PdfFileReader/PdfFileWriter names no longer exist:
- https://github.com/odoo/odoo/blob/13e9e827dc21103052e8607d16f23c07adeb5634/odoo/tools/pdf/_pypdf.py#L1-L15
Going through odoo.tools.pdf keeps the module working on both backends,
since that wrapper already absorbs the difference for core.
appendPagesFromReader() is kept on purpose: it is the only spelling available on
every backend, the PyPDF2 1.x one does not provide append_pages_from_reader():
- https://github.com/odoo/odoo/blob/13e9e827dc21103052e8607d16f23c07adeb5634/odoo/tools/pdf/_pypdf2_1.py#L28-L33
Replace self._context with self.env.context.
In 19.0 the _context property is decorated with @api.deprecated, so every access emits a
DeprecationWarning; it still returns self.env.context, but the indirection is scheduled for removal:
https://github.com/odoo/odoo/blob/13e9e827dc21103052e8607d16f23c07adeb5634/odoo/orm/models.py#L5921-L5924
---
report_qweb_encrypt/__manifest__.py | 2 +-
report_qweb_encrypt/models/ir_actions_report.py | 11 +++++------
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/report_qweb_encrypt/__manifest__.py b/report_qweb_encrypt/__manifest__.py
index aeb4e8d81b..36e760df33 100644
--- a/report_qweb_encrypt/__manifest__.py
+++ b/report_qweb_encrypt/__manifest__.py
@@ -5,7 +5,7 @@
{
"name": "Report Qweb Encrypt",
"summary": "Allow to encrypt qweb pdfs",
- "version": "18.0.1.0.0",
+ "version": "19.0.1.0.0",
"license": "AGPL-3",
"author": "Creu Blanca,Ecosoft,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/reporting-engine",
diff --git a/report_qweb_encrypt/models/ir_actions_report.py b/report_qweb_encrypt/models/ir_actions_report.py
index 8597d798d8..8114c7f0b8 100644
--- a/report_qweb_encrypt/models/ir_actions_report.py
+++ b/report_qweb_encrypt/models/ir_actions_report.py
@@ -3,10 +3,9 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from io import BytesIO
-from PyPDF2 import PdfFileReader, PdfFileWriter
-
from odoo import fields, models
from odoo.exceptions import ValidationError
+from odoo.tools.pdf import PdfReader, PdfWriter
from odoo.tools.safe_eval import safe_eval
@@ -34,7 +33,7 @@ def _render_qweb_pdf(self, report_ref, res_ids=None, data=None):
)
report_sudo = self._get_report(report_ref)
if res_ids:
- encrypt_password = self._context.get("encrypt_password")
+ encrypt_password = self.env.context.get("encrypt_password")
report = self._get_report_from_name(report_sudo.report_name).with_context(
encrypt_password=encrypt_password
)
@@ -50,7 +49,7 @@ def _get_pdf_password(self, res_ids):
# As such, file will be encrypted by report_download() again.
# --
# Following is used just in case when context is passed in.
- encrypt_password = self._context.get("encrypt_password", False)
+ encrypt_password = self.env.context.get("encrypt_password", False)
elif self.encrypt == "auto" and self.encrypt_password:
# access the report details with sudo() but evaluation context as
# sudo(False)
@@ -70,9 +69,9 @@ def _get_pdf_password(self, res_ids):
def _encrypt_pdf(data, password):
if not password:
return data
- output_pdf = PdfFileWriter()
+ output_pdf = PdfWriter()
in_buff = BytesIO(data)
- pdf = PdfFileReader(in_buff)
+ pdf = PdfReader(in_buff)
output_pdf.appendPagesFromReader(pdf)
output_pdf.encrypt(password)
buff = BytesIO()
From 668b8cd07f6ca6b5b3049a00012632f85fe0329d Mon Sep 17 00:00:00 2001
From: Moises Lopez
Date: Sat, 15 Aug 2026 02:32:50 +0000
Subject: [PATCH 22/22] [IMP] report_qweb_encrypt: cover the /report/download
override
controllers/main.py was at 25% coverage: no test reached report_download(),
so the manual-password branch was only exercised by hand. Core has no test
hitting /report/download either, so these cases are new.
The new class inherits odoo.addons.web.tests.test_reports.TestReports, so the
core report regression tests also run with this module installed.
force_report_rendering is required in the request context: while tests are
running _render_qweb_pdf() falls back to _render_qweb_html(), and an html
body cannot be encrypted, so without it the encryption branch is never
reached:
- https://github.com/odoo/odoo/blob/13e9e827dc21103052e8607d16f23c07adeb5634/odoo/addons/base/models/ir_actions_report.py#L1027-L1028
Covered branches: password in the url context, url without query string,
context without password, and a non-pdf (qweb-text) response. This takes
controllers/main.py from 25.00% to 100.00%, and the module from 70.89% to
97.47%, which is back above the 80% fail-under.
---
report_qweb_encrypt/tests/__init__.py | 1 +
.../tests/test_report_download.py | 90 +++++++++++++++++++
2 files changed, 91 insertions(+)
create mode 100644 report_qweb_encrypt/tests/test_report_download.py
diff --git a/report_qweb_encrypt/tests/__init__.py b/report_qweb_encrypt/tests/__init__.py
index c6a7ce0a3c..a822879c19 100644
--- a/report_qweb_encrypt/tests/__init__.py
+++ b/report_qweb_encrypt/tests/__init__.py
@@ -1 +1,2 @@
from . import test_report_qweb_encrypt
+from . import test_report_download
diff --git a/report_qweb_encrypt/tests/test_report_download.py b/report_qweb_encrypt/tests/test_report_download.py
new file mode 100644
index 0000000000..3664d6526a
--- /dev/null
+++ b/report_qweb_encrypt/tests/test_report_download.py
@@ -0,0 +1,90 @@
+# Copyright 2026 Vauxoo
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+import json
+from urllib.parse import quote, urlencode
+
+from odoo.tests.common import tagged
+
+from odoo.addons.web.tests.test_reports import TestReports
+
+
+@tagged("-at_install", "post_install")
+class TestReportQwebEncryptDownload(TestReports):
+ """Cover the /report/download override.
+
+ It inherits the core TestReports so its report regression tests also run
+ with this module installed. Core has no test hitting /report/download
+ itself, so the cases below are new.
+ """
+
+ @classmethod
+ def setUpClass(cls):
+ super().setUpClass()
+ cls.encrypt_report = cls.env.ref("web.action_report_internalpreview")
+ # The controller encrypts on its own, using the password found in the
+ # url. Keep the model side disabled so each assertion below can only
+ # be explained by the controller.
+ cls.encrypt_report.encrypt = False
+ cls.encrypt_company = cls.env.ref("base.main_company")
+
+ def _report_url(self, context=None):
+ """Url of the report as action_manager_report.esm.js builds it"""
+ url = f"/report/pdf/{self.encrypt_report.report_name}/{self.encrypt_company.id}"
+ if context is not None:
+ url += "?context=" + quote(json.dumps(context))
+ return url
+
+ def _download(self, url):
+ """Call /report/download the way the web client does
+
+ force_report_rendering is required because _render_qweb_pdf() falls
+ back to _render_qweb_html() while tests are running, and an html body
+ cannot be encrypted.
+ """
+ params = {
+ "data": json.dumps([url, "qweb-pdf"]),
+ "context": json.dumps({"force_report_rendering": True}),
+ }
+ response = self.url_open("/report/download?" + urlencode(params))
+ response.raise_for_status()
+ self.assertEqual(response.headers.get("Content-Type"), "application/pdf")
+ return response
+
+ def test_download_encrypts_with_password_in_url(self):
+ """It should encrypt the pdf with the password given in the url"""
+ self.authenticate("admin", "admin")
+ response = self._download(self._report_url({"encrypt_password": "secretcode"}))
+ self.assertIn(b"/Encrypt", response.content)
+
+ def test_download_without_query_string(self):
+ """It should return the pdf untouched when the url has no context"""
+ self.authenticate("admin", "admin")
+ response = self._download(self._report_url())
+ self.assertNotIn(b"/Encrypt", response.content)
+
+ def test_download_without_password_in_context(self):
+ """It should return the pdf untouched when no password is given"""
+ self.authenticate("admin", "admin")
+ response = self._download(self._report_url({"lang": "en_US"}))
+ self.assertNotIn(b"/Encrypt", response.content)
+
+ def test_download_non_pdf_response_untouched(self):
+ """It should not touch a response that is not a pdf
+
+ report_download() also serves qweb-text reports; the override has to
+ let anything that is not application/pdf go through untouched.
+ """
+ self.authenticate("admin", "admin")
+ context = quote(json.dumps({"encrypt_password": "secretcode"}))
+ url = (
+ f"/report/text/{self.encrypt_report.report_name}"
+ f"/{self.encrypt_company.id}?context={context}"
+ )
+ params = {
+ "data": json.dumps([url, "qweb-text"]),
+ "context": json.dumps({"force_report_rendering": True}),
+ }
+ response = self.url_open("/report/download?" + urlencode(params))
+ response.raise_for_status()
+ self.assertNotEqual(response.headers.get("Content-Type"), "application/pdf")
+ self.assertNotIn(b"/Encrypt", response.content)