From d41ed0b17e7549aa7285e81ad55e65a3d3385796 Mon Sep 17 00:00:00 2001 From: Victor Feyens Date: Thu, 25 Aug 2022 13:17:29 +0000 Subject: [PATCH] [FIX] payment,*: unable to access the documents of your companies Task ID - 2960827 opw-2954181 closes odoo/odoo#99512 X-original-commit: 42ea4244692dc4b6e1f5917a715b1552bd223928 Related: odoo/enterprise#31037 Signed-off-by: Victor Feyens (vfe) Signed-off-by: Antoine Vandevenne (anv) --- addons/account_payment/controllers/portal.py | 20 +++++++++----- addons/payment/controllers/portal.py | 28 +++++++++----------- addons/sale/controllers/portal.py | 13 +++++---- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/addons/account_payment/controllers/portal.py b/addons/account_payment/controllers/portal.py index e0d6876ae04..f665bdadf42 100644 --- a/addons/account_payment/controllers/portal.py +++ b/addons/account_payment/controllers/portal.py @@ -16,18 +16,24 @@ class PortalAccount(portal.PortalAccount): # We set partner_id to the partner id of the current user if logged in, otherwise we set it # to the invoice partner id. We do this to ensure that payment tokens are assigned to the # correct partner and to avoid linking tokens to the public user. - partner = request.env.user.partner_id if logged_in else invoice.partner_id - - # Make sure that the partner's company matches the invoice's company. + partner_sudo = request.env.user.partner_id if logged_in else invoice.partner_id invoice_company = invoice.company_id or request.env.company - PaymentPortal._ensure_matching_companies(partner, invoice_company) providers_sudo = request.env['payment.provider'].sudo()._get_compatible_providers( - invoice_company.id, partner.id, invoice.amount_total, currency_id=invoice.currency_id.id + invoice_company.id, + partner_sudo.id, + invoice.amount_total, + currency_id=invoice.currency_id.id ) # In sudo mode to read the fields of providers and partner (if not logged in) tokens = request.env['payment.token'].search( - [('provider_id', 'in', providers_sudo.ids), ('partner_id', '=', partner.id)] + [('provider_id', 'in', providers_sudo.ids), ('partner_id', '=', partner_sudo.id)] ) # Tokens are cleared at the end if the user is not logged in + + # Make sure that the partner's company matches the invoice's company. + if not PaymentPortal._can_partner_pay_in_company(partner_sudo, invoice_company): + providers_sudo = request.env['payment.provider'].sudo() + tokens = request.env['payment.token'] + fees_by_provider = { pro_sudo: pro_sudo._compute_fees( invoice.amount_total, invoice.currency_id, invoice.partner_id.country_id @@ -42,7 +48,7 @@ class PortalAccount(portal.PortalAccount): ), 'amount': invoice.amount_residual, 'currency': invoice.currency_id, - 'partner_id': partner.id, + 'partner_id': partner_sudo.id, 'access_token': access_token, 'transaction_route': f'/invoice/transaction/{invoice.id}/', 'landing_route': _build_url_w_params(invoice.access_url, {'access_token': access_token}) diff --git a/addons/payment/controllers/portal.py b/addons/payment/controllers/portal.py index dc5cf482033..60bff3b3377 100644 --- a/addons/payment/controllers/portal.py +++ b/addons/payment/controllers/portal.py @@ -102,9 +102,6 @@ class PaymentPortal(portal.CustomerPortal): company = request.env['res.company'].sudo().browse(company_id) currency_id = currency_id or company.currency_id.id - # Make sure that the company passed as parameter matches the partner's company. - PaymentPortal._ensure_matching_companies(partner_sudo, company) - # Make sure that the currency exists and is active currency = request.env['res.currency'].browse(currency_id).exists() if not currency or not currency.active: @@ -120,10 +117,15 @@ class PaymentPortal(portal.CustomerPortal): [('provider_id', 'in', providers_sudo.ids), ('partner_id', '=', partner_sudo.id)] ) if logged_in else request.env['payment.token'] + # Make sure that the partner's company matches the company passed as parameter. + if not PaymentPortal._can_partner_pay_in_company(partner_sudo, company): + providers_sudo = request.env['payment.provider'].sudo() + payment_tokens = request.env['payment.token'] + # Compute the fees taken by providers supporting the feature fees_by_provider = { - pro_sudo: pro_sudo._compute_fees(amount, currency, partner_sudo.country_id) - for pro_sudo in providers_sudo.filtered('fees_active') + provider_sudo: provider_sudo._compute_fees(amount, currency, partner_sudo.country_id) + for provider_sudo in providers_sudo.filtered('fees_active') } # Generate a new access token in case the partner id or the currency id was updated @@ -427,20 +429,16 @@ class PaymentPortal(portal.CustomerPortal): return None @staticmethod - def _ensure_matching_companies(partner, document_company): - """ Check that the partner's company is the same as the document's company. + def _can_partner_pay_in_company(partner, document_company): + """ Return whether the provided partner can pay in the provided company. - If the partner company is not set, the check passes. If the companies don't match, a - `UserError` is raised. + The payment is allowed either if the partner's company is not set or if the companies match. :param recordset partner: The partner on behalf on which the payment is made, as a `res.partner` record. :param recordset document_company: The company of the document being paid, as a `res.company` record. - :return: None - :raise UserError: If the companies don't match. + :return: Whether the payment is allowed. + :rtype: str """ - if partner.company_id and partner.company_id != document_company: - raise UserError( - _("Please switch to company '%s' to make this payment.", document_company.name) - ) + return not partner.company_id or partner.company_id == document_company diff --git a/addons/sale/controllers/portal.py b/addons/sale/controllers/portal.py index 95fee1349e4..e09de174735 100644 --- a/addons/sale/controllers/portal.py +++ b/addons/sale/controllers/portal.py @@ -158,11 +158,6 @@ class CustomerPortal(portal.CustomerPortal): if order_sudo._has_to_be_paid(): logged_in = not request.env.user._is_public() - # Make sure that the partner's company matches the sales order's company. - payment_portal.PaymentPortal._ensure_matching_companies( - order_sudo.partner_id, order_sudo.company_id - ) - providers_sudo = request.env['payment.provider'].sudo()._get_compatible_providers( order_sudo.company_id.id, order_sudo.partner_id.id, @@ -174,6 +169,14 @@ class CustomerPortal(portal.CustomerPortal): ('provider_id', 'in', providers_sudo.ids), ('partner_id', '=', order_sudo.partner_id.id) ]) if logged_in else request.env['payment.token'] + + # Make sure that the partner's company matches the order's company. + if not payment_portal.PaymentPortal._can_partner_pay_in_company( + order_sudo.partner_id, order_sudo.company_id + ): + providers_sudo = request.env['payment.provider'].sudo() + tokens = request.env['payment.token'] + fees_by_provider = { provider: provider._compute_fees( order_sudo.amount_total,