[FIX] payment,sale: fix access error when using the capture or void buttons

Before this commit, users may saw the capture and void buttons but
couldn't use them.

As capture or void actions need to access acquirer-related fields,
these actions are now sudoed to allow any users that see the button
to use it.

The access rules and rights are also checked before executing the action
to avoid abusive RPC calls.

task-2785144

closes odoo/odoo#91923

X-original-commit: 2e351d6ff9b7f72b486e83c827ff6e15a05c3331
Signed-off-by: Valentin Chevalier <vcr@odoo.com>
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
Valentin Chevalier
2022-05-20 15:25:46 +02:00
parent ccf8ca3c04
commit 7f6f6a545c
4 changed files with 39 additions and 6 deletions
+10 -2
View File
@@ -2,6 +2,8 @@
from odoo import api, fields, models
from odoo.addons.payment import utils as payment_utils
class AccountMove(models.Model):
_inherit = 'account.move'
@@ -26,10 +28,16 @@ class AccountMove(models.Model):
return self.with_context(active_test=False).transaction_ids._get_last()
def payment_action_capture(self):
self.authorized_transaction_ids.action_capture()
""" Capture all transactions linked to this invoice. """
payment_utils.check_rights_on_recordset(self)
# In sudo mode because we need to be able to read on acquirer fields.
self.authorized_transaction_ids.sudo().action_capture()
def payment_action_void(self):
self.authorized_transaction_ids.action_void()
""" Void all transactions linked to this invoice. """
payment_utils.check_rights_on_recordset(self)
# In sudo mode because we need to be able to read on acquirer fields.
self.authorized_transaction_ids.sudo().action_void()
def action_view_payment_transactions(self):
action = self.env['ir.actions.act_window']._for_xml_id('payment.action_payment_transaction')
+6 -2
View File
@@ -298,16 +298,20 @@ class PaymentTransaction(models.Model):
if any(tx.state != 'authorized' for tx in self):
raise ValidationError(_("Only authorized transactions can be captured."))
payment_utils.check_rights_on_recordset(self)
for tx in self:
tx._send_capture_request()
# In sudo mode because we need to be able to read on acquirer fields.
tx.sudo()._send_capture_request()
def action_void(self):
""" Check the state of the transaction and request to have them voided. """
if any(tx.state != 'authorized' for tx in self):
raise ValidationError(_("Only authorized transactions can be voided."))
payment_utils.check_rights_on_recordset(self)
for tx in self:
tx._send_void_request()
# In sudo mode because we need to be able to read on acquirer fields.
tx.sudo()._send_void_request()
def action_refund(self, amount_to_refund=None):
""" Check the state of the transactions and request their refund.
+13
View File
@@ -156,3 +156,16 @@ def split_partner_name(partner_name):
def get_customer_ip_address():
return request and request.httprequest.remote_addr or ''
def check_rights_on_recordset(recordset):
""" Ensure that the user has the rights to write on the record.
Call this method to check the access rules and rights before doing any operation that is
callable by RPC and that requires to be executed in sudo mode.
:param recordset: The recordset for which the rights should be checked.
:return: None
"""
recordset.check_access_rights('write')
recordset.check_access_rule('write')
+10 -2
View File
@@ -12,6 +12,8 @@ from odoo.exceptions import AccessError, UserError, ValidationError
from odoo.osv import expression
from odoo.tools import float_is_zero, format_amount, format_date, html_keep_url, is_html_empty
from odoo.addons.payment import utils as payment_utils
READONLY_FIELD_STATES = {
state: [('readonly', True)]
for state in {'sale', 'done', 'cancel'}
@@ -1200,10 +1202,16 @@ class SaleOrder(models.Model):
line.qty_to_invoice = 0
def payment_action_capture(self):
self.authorized_transaction_ids.action_capture()
""" Capture all transactions linked to this sale order. """
payment_utils.check_rights_on_recordset(self)
# In sudo mode because we need to be able to read on acquirer fields.
self.authorized_transaction_ids.sudo().action_capture()
def payment_action_void(self):
self.authorized_transaction_ids.action_void()
""" Void all transactions linked to this sale order. """
payment_utils.check_rights_on_recordset(self)
# In sudo mode because we need to be able to read on acquirer fields.
self.authorized_transaction_ids.sudo().action_void()
def get_portal_last_transaction(self):
self.ensure_one()