diff --git a/report_qweb_signer/__manifest__.py b/report_qweb_signer/__manifest__.py index 407de830c..d5896497d 100644 --- a/report_qweb_signer/__manifest__.py +++ b/report_qweb_signer/__manifest__.py @@ -6,7 +6,7 @@ { "name": "Qweb PDF reports signer", "summary": "Sign Qweb PDFs usign a PKCS#12 certificate", - "version": "13.0.2.0.0", + "version": "14.0.1.0.0", "category": "Reporting", "website": "https://github.com/OCA/reporting-engine", "author": "Tecnativa, " "Odoo Community Association (OCA)", diff --git a/report_qweb_signer/data/defaults.xml b/report_qweb_signer/data/defaults.xml index d08649a1b..3783897d3 100644 --- a/report_qweb_signer/data/defaults.xml +++ b/report_qweb_signer/data/defaults.xml @@ -2,6 +2,10 @@ report_qweb_signer.java_parameters - -Xms4M -Xmx4M -XX:CompressedClassSpaceSize=256m + -Xms16M -Xmx16M -XX:CompressedClassSpaceSize=256m + + + report_qweb_signer.java_position_parameters + -llx 400 -lly 820 -urx 600 -ury 100 -fs 8 diff --git a/report_qweb_signer/demo/report_partner_demo.xml b/report_qweb_signer/demo/report_partner_demo.xml index 84bdc71a0..dea7a775d 100644 --- a/report_qweb_signer/demo/report_partner_demo.xml +++ b/report_qweb_signer/demo/report_partner_demo.xml @@ -33,14 +33,16 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). - + + Test PDF certificate + res.partner + qweb-pdf + report_qweb_signer.report_partner_demo + 'test_' + (object.name or '').replace(' ', '_').lower() + '.pdf' + True + + report + diff --git a/report_qweb_signer/models/ir_actions_report.py b/report_qweb_signer/models/ir_actions_report.py index 4db4237c7..ea9108fda 100644 --- a/report_qweb_signer/models/ir_actions_report.py +++ b/report_qweb_signer/models/ir_actions_report.py @@ -8,7 +8,6 @@ import logging import os import subprocess import tempfile -import time from contextlib import closing from cryptography.hazmat import backends @@ -17,7 +16,7 @@ from endesive import pdf from odoo import _, models from odoo.exceptions import AccessError, UserError -from odoo.tools.safe_eval import safe_eval +from odoo.tools.safe_eval import safe_eval, time _logger = logging.getLogger(__name__) @@ -122,8 +121,13 @@ class IrActionsReport(models.Model): irc_param = self.env["ir.config_parameter"].sudo() java_bin = "java -jar" java_param = irc_param.get_param("report_qweb_signer.java_parameters") - jar = "{}/../static/jar/jPdfSign.jar".format(me) - return "{} {} {} {}".format(java_bin, java_param, jar, opts) + java_position_param = irc_param.get_param( + "report_qweb_signer.java_position_parameters" + ) + jar = "{}/../static/jar/JSignPdf.jar".format(me) + return "{} {} {} {} {}".format( + java_bin, java_param, jar, opts, java_position_param + ) def _get_endesive_params(self, certificate): date = datetime.datetime.utcnow() - datetime.timedelta(hours=12) @@ -160,7 +164,7 @@ class IrActionsReport(models.Model): return pdfsigned def pdf_sign(self, pdf, certificate): - pdfsigned = pdf + ".signed.pdf" + pdfsigned = pdf[:-4] + "_signed.pdf" p12 = _normalize_filepath(certificate.path) passwd = _normalize_filepath(certificate.password_file) method_used = certificate.signing_method @@ -169,7 +173,12 @@ class IrActionsReport(models.Model): _("Signing report (PDF): " "Certificate or password file not found") ) if method_used == "java": - signer_opts = '"{}" "{}" "{}" "{}"'.format(p12, pdf, pdfsigned, passwd) + passwd_f = open(passwd, "tr") + passwd = passwd_f.read().strip() + passwd_f.close() + signer_opts = ' "{}" -ksf "{}" -ksp "{}" -V -d "/tmp"'.format( + pdf, p12, passwd + ) signer = self._signer_bin(signer_opts) process = subprocess.Popen( signer, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True @@ -188,7 +197,7 @@ class IrActionsReport(models.Model): self._signer_endesive(params, p12, pdf, pdfsigned, passwd) return pdfsigned - def render_qweb_pdf(self, res_ids=None, data=None): + def _render_qweb_pdf(self, res_ids=None, data=None): certificate = self._certificate_get(res_ids) if certificate and certificate.attachment: signed_content = self._attach_signed_read(res_ids, certificate) @@ -199,7 +208,7 @@ class IrActionsReport(models.Model): res_ids, ) return signed_content, "pdf" - content, ext = super(IrActionsReport, self).render_qweb_pdf(res_ids, data) + content, ext = super(IrActionsReport, self)._render_qweb_pdf(res_ids, data) if certificate: # Creating temporary origin PDF pdf_fd, pdf = tempfile.mkstemp(suffix=".pdf", prefix="report.tmp.") @@ -220,7 +229,7 @@ class IrActionsReport(models.Model): for fname in (pdf, signed): try: os.unlink(fname) - except (OSError, IOError): + except OSError: _logger.error("Error when trying to remove file %s", fname) if certificate.attachment: self._attach_signed_write(res_ids, certificate, content) diff --git a/report_qweb_signer/models/report_certificate.py b/report_qweb_signer/models/report_certificate.py index 6159fa176..95222e542 100644 --- a/report_qweb_signer/models/report_certificate.py +++ b/report_qweb_signer/models/report_certificate.py @@ -31,9 +31,11 @@ class ReportCertificate(models.Model): required=True, comodel_name="ir.model", help="Model where apply this certificate", + ondelete="cascade", ) domain = fields.Char( - string="Domain", help="Domain for filtering if sign or not the document", + string="Domain", + help="Domain for filtering if sign or not the document", ) allow_only_one = fields.Boolean( string="Allow only one document", @@ -67,5 +69,6 @@ class ReportCertificate(models.Model): help="Location to include in digital signature (typically, a city name). ", ) endesive_certificate_reason = fields.Char( - string="Signature reason", help="Reason text to include in digital signature.", + string="Signature reason", + help="Reason text to include in digital signature.", ) diff --git a/report_qweb_signer/readme/CONTRIBUTORS.rst b/report_qweb_signer/readme/CONTRIBUTORS.rst index b8f0c6c7e..9b6a265ad 100644 --- a/report_qweb_signer/readme/CONTRIBUTORS.rst +++ b/report_qweb_signer/readme/CONTRIBUTORS.rst @@ -5,3 +5,5 @@ * Pedro M. Baeza * Jairo Llopis * David Vidal +* Santi Argüeso +* Omar Castiñeira diff --git a/report_qweb_signer/readme/CREDITS.rst b/report_qweb_signer/readme/CREDITS.rst index 14593eb9d..49127c54a 100644 --- a/report_qweb_signer/readme/CREDITS.rst +++ b/report_qweb_signer/readme/CREDITS.rst @@ -1,9 +1,7 @@ External utilities ++++++++++++++++++ -* iText v1.4.8: © 2000-2006, Paulo Soares, Bruno Lowagie and others - License `MPL `__ or `LGPL2 `__ - http://sourceforge.net/projects/itext -* jPdfSign: © 2006 Jan Peter Stotz - License `MPL `__ or `LGPL2 `__ (inherited from iText) - http://private.sit.fraunhofer.de/~stotz/software/jpdfsign -* Modified jPdfSign: © 2015 Antonio Espinosa - License `MPL `__ or `LGPL2 `__ (inherited from iText) - static/src/java/JPdfSign.java +* JSignPdf: © Josef Cacek - License `MPL `__ or `LGPL2 `__ - http://jsignpdf.sourceforge.net/ Icon ++++ diff --git a/report_qweb_signer/readme/ROADMAP.rst b/report_qweb_signer/readme/ROADMAP.rst index db930cb21..f5bc87ca1 100644 --- a/report_qweb_signer/readme/ROADMAP.rst +++ b/report_qweb_signer/readme/ROADMAP.rst @@ -1,5 +1,4 @@ * When signing multiple documents (if 'Allow only one document' is disable) then 'Save as attachment' is not applied and signed result is not saved as attachment. -* To have a visible signature through an image embedded in the resulting PDF. * Add tests. diff --git a/report_qweb_signer/static/jar/JSignPdf.jar b/report_qweb_signer/static/jar/JSignPdf.jar new file mode 100644 index 000000000..27de18c27 Binary files /dev/null and b/report_qweb_signer/static/jar/JSignPdf.jar differ diff --git a/report_qweb_signer/static/jar/itext-1.4.8.jar b/report_qweb_signer/static/jar/itext-1.4.8.jar deleted file mode 100644 index dbbd4280c..000000000 Binary files a/report_qweb_signer/static/jar/itext-1.4.8.jar and /dev/null differ diff --git a/report_qweb_signer/static/jar/jPdfSign.jar b/report_qweb_signer/static/jar/jPdfSign.jar deleted file mode 100644 index 784b11fc6..000000000 Binary files a/report_qweb_signer/static/jar/jPdfSign.jar and /dev/null differ diff --git a/report_qweb_signer/tests/test_report_qweb_signer.py b/report_qweb_signer/tests/test_report_qweb_signer.py index d39341784..a7acc5887 100644 --- a/report_qweb_signer/tests/test_report_qweb_signer.py +++ b/report_qweb_signer/tests/test_report_qweb_signer.py @@ -13,7 +13,7 @@ class TestReportQwebSigner(HttpCase): ).with_context(force_report_rendering=True) def test_report_qweb_signer(self): - self.report.render_qweb_pdf(self.partner.ids) + self.report._render_qweb_pdf(self.partner.ids) # Reprint again for taking the PDF from attachment IrAttachment = self.env["ir.attachment"] domain = [ @@ -21,6 +21,6 @@ class TestReportQwebSigner(HttpCase): ("res_model", "=", self.partner._name), ] num_attachments = IrAttachment.search_count(domain) - self.report.render_qweb_pdf(self.partner.ids) + self.report._render_qweb_pdf(self.partner.ids) num_attachments_after = IrAttachment.search_count(domain) self.assertEqual(num_attachments, num_attachments_after) diff --git a/requirements.txt b/requirements.txt index 9e86e12c0..f7541f661 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,6 @@ # generated from manifests external_dependencies +cryptography +endesive lxml PyPDF2 xlrd diff --git a/setup/report_qweb_signer/odoo/addons/report_qweb_signer b/setup/report_qweb_signer/odoo/addons/report_qweb_signer new file mode 120000 index 000000000..d1c373301 --- /dev/null +++ b/setup/report_qweb_signer/odoo/addons/report_qweb_signer @@ -0,0 +1 @@ +../../../../report_qweb_signer \ No newline at end of file diff --git a/setup/report_qweb_signer/setup.py b/setup/report_qweb_signer/setup.py new file mode 100644 index 000000000..28c57bb64 --- /dev/null +++ b/setup/report_qweb_signer/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +)