From 6f3f825aa7a593e20d8818f55f37062ee90973cf Mon Sep 17 00:00:00 2001 From: Luc De Meyer Date: Sun, 5 Mar 2023 16:52:28 +0100 Subject: [PATCH] [IMP] add support for non-stored passphrase --- account_ebics/__manifest__.py | 2 +- account_ebics/models/ebics_userid.py | 17 +++++- account_ebics/views/ebics_userid_views.xml | 19 ++++--- account_ebics/wizards/ebics_xfer.py | 57 ++++++++++--------- account_ebics/wizards/ebics_xfer.xml | 14 +++++ account_ebics_batch/models/ebics_batch_log.py | 17 +++++- 6 files changed, 87 insertions(+), 39 deletions(-) diff --git a/account_ebics/__manifest__.py b/account_ebics/__manifest__.py index a146884..fedda9f 100644 --- a/account_ebics/__manifest__.py +++ b/account_ebics/__manifest__.py @@ -3,7 +3,7 @@ { "name": "EBICS banking protocol", - "version": "16.0.1.0.0", + "version": "16.0.1.1.0", "license": "LGPL-3", "author": "Noviat", "website": "https://www.noviat.com", diff --git a/account_ebics/models/ebics_userid.py b/account_ebics/models/ebics_userid.py index 9d541e5..08a8e04 100644 --- a/account_ebics/models/ebics_userid.py +++ b/account_ebics/models/ebics_userid.py @@ -87,6 +87,16 @@ class EbicsUserID(models.Model): ebics_keys_fn = fields.Char(compute="_compute_ebics_keys_fn") ebics_keys_found = fields.Boolean(compute="_compute_ebics_keys_found") ebics_passphrase = fields.Char(string="EBICS Passphrase") + ebics_passphrase_store = fields.Boolean( + string="Store EBICS Passphrase", + default=True, + help="When you uncheck this option the passphrase to unlock " + "your private key will not be stored in the database. " + "We recommend to use this if you want to upload signed " + "payment orders via EBICS.\nYou will be prompted to enter the " + "passphrase for every EBICS transaction, hence do not uncheck this " + "option on a userid for automated EBICS downloads.", + ) ebics_ini_letter = fields.Binary( string="EBICS INI Letter", readonly=True, @@ -195,7 +205,7 @@ class EbicsUserID(models.Model): @api.constrains("ebics_passphrase") def _check_ebics_passphrase(self): for rec in self: - if not rec.ebics_passphrase or len(rec.ebics_passphrase) < 8: + if rec.ebics_passphrase and len(rec.ebics_passphrase) < 8: raise UserError(_("The passphrase must be at least 8 characters long")) @api.onchange("ebics_version") @@ -208,6 +218,11 @@ class EbicsUserID(models.Model): if self.signature_class == "T": self.swift_3skey = False + @api.onchange("ebics_passphrase_store") + def _onchange_ebics_passphrase_store(self): + if not self.ebics_passphrase_store: + self.ebics_passphrase = False + @api.onchange("swift_3skey") def _onchange_swift_3skey(self): if self.swift_3skey: diff --git a/account_ebics/views/ebics_userid_views.xml b/account_ebics/views/ebics_userid_views.xml index 11bb02e..d2da395 100644 --- a/account_ebics/views/ebics_userid_views.xml +++ b/account_ebics/views/ebics_userid_views.xml @@ -93,6 +93,16 @@ password="True" attrs="{'required': [('state', '=', 'draft')]}" /> + + + + + + - - - - - diff --git a/account_ebics/wizards/ebics_xfer.py b/account_ebics/wizards/ebics_xfer.py index 506ec48..55bc2fc 100644 --- a/account_ebics/wizards/ebics_xfer.py +++ b/account_ebics/wizards/ebics_xfer.py @@ -62,6 +62,9 @@ class EbicsXfer(models.TransientModel): comodel_name="ebics.userid", string="EBICS UserID" ) ebics_passphrase = fields.Char(string="EBICS Passphrase") + ebics_passphrase_stored = fields.Char( + string="EBICS Stored Passphrase", related="ebics_userid_id.ebics_passphrase" + ) date_from = fields.Date() date_to = fields.Date() upload_data = fields.Binary(string="File to Upload") @@ -108,7 +111,7 @@ class EbicsXfer(models.TransientModel): @api.onchange("ebics_config_id") def _onchange_ebics_config_id(self): ebics_userids = self.ebics_config_id.ebics_userid_ids - if self._context.get("ebics_download"): + if self.env.context.get("ebics_download"): download_formats = self.ebics_config_id.ebics_file_format_ids.filtered( lambda r: r.type == "down" ) @@ -425,9 +428,15 @@ class EbicsXfer(models.TransientModel): def _setup_client(self): self.ebics_config_id._check_ebics_keys() passphrase = self._get_passphrase() - keyring = EbicsKeyRing( - keys=self.ebics_userid_id.ebics_keys_fn, passphrase=passphrase - ) + try: + keyring = EbicsKeyRing( + keys=self.ebics_userid_id.ebics_keys_fn, passphrase=passphrase + ) + except (RuntimeError, ValueError) as err: + error = _("Error while accessing the EBICS Keys:") + error += "\n" + error += err.args[0] + raise UserError(error) from err bank = EbicsBank( keyring=keyring, @@ -437,11 +446,22 @@ class EbicsXfer(models.TransientModel): if self.ebics_config_id.ebics_version == "H003": bank._order_number = self.ebics_config_id._get_order_number() - user = EbicsUser( - keyring=keyring, - partnerid=self.ebics_config_id.ebics_partner, - userid=self.ebics_userid_id.name, - ) + try: + user = EbicsUser( + keyring=keyring, + partnerid=self.ebics_config_id.ebics_partner, + userid=self.ebics_userid_id.name, + ) + except ValueError as err: + error = _("Error while accessing the EBICS UserID:") + error += "\n" + err_str = err.args[0] + error += err.args[0] + if err_str == "unknown key format": + error += "\n" + error += _("Doublecheck your EBICS Passphrase and UserID settings.") + raise UserError(error) from err + signature_class = ( self.format_id.signature_class or self.ebics_userid_id.signature_class ) @@ -460,24 +480,7 @@ class EbicsXfer(models.TransientModel): return client def _get_passphrase(self): - passphrase = self.ebics_userid_id.ebics_passphrase - - if passphrase: - return passphrase - - module = __name__.split("addons.")[1].split(".")[0] - passphrase_view = self.env.ref("%s.ebics_xfer_view_form_passphrase" % module) - return { - "name": _("EBICS file transfer"), - "res_id": self.id, - "view_type": "form", - "view_mode": "form", - "res_model": "ebics.xfer", - "view_id": passphrase_view.id, - "target": "new", - "context": self._context, - "type": "ir.actions.act_window", - } + return self.ebics_passphrase or self.ebics_userid_id.ebics_passphrase def _file_format_methods(self): """ diff --git a/account_ebics/wizards/ebics_xfer.xml b/account_ebics/wizards/ebics_xfer.xml index 0d28980..3d61d8d 100644 --- a/account_ebics/wizards/ebics_xfer.xml +++ b/account_ebics/wizards/ebics_xfer.xml @@ -20,6 +20,13 @@ required="1" options="{'no_create': True, 'no_open': True}" /> + + + + diff --git a/account_ebics_batch/models/ebics_batch_log.py b/account_ebics_batch/models/ebics_batch_log.py index 74d8b25..82a6970 100644 --- a/account_ebics_batch/models/ebics_batch_log.py +++ b/account_ebics_batch/models/ebics_batch_log.py @@ -105,6 +105,15 @@ class EbicsBatchLog(models.Model): ) ) continue + if not any(config.mapped("ebics_userid_ids.ebics_passphrase_store")): + import_dict["errors"].append( + err_msg + + _( + "No EBICS UserID with stored passphrase found.\n" + "You should configure such a UserID for automated downloads." + ) + ) + continue try: with self.env.cr.savepoint(): ebics_file_ids += self._ebics_import( @@ -146,6 +155,11 @@ class EbicsBatchLog(models.Model): self.state = state def _ebics_import(self, config, date_from, date_to, import_dict): + ebics_userids = config.ebics_userid_ids.filtered( + lambda r: r.ebics_passphrase_store + ) + t_userids = ebics_userids.filtered(lambda r: r.signature_class == "T") + ebics_userid = t_userids and t_userids[0] or ebics_userids[0] xfer_wiz = ( self.env["ebics.xfer"] .with_context(ebics_download=True) @@ -158,8 +172,9 @@ class EbicsBatchLog(models.Model): ) ) xfer_wiz._onchange_ebics_config_id() + xfer_wiz.ebics_userid_id = ebics_userid res = xfer_wiz.ebics_download() - file_ids = res["context"].get("ebics_file_ids") + file_ids = res["context"].get("ebics_file_ids", []) if res["context"]["err_cnt"]: import_dict["errors"].append(xfer_wiz.note) return file_ids