[FIX] payment: prevent access error for manual payments

Rev. cf1df16aea introduced new callback
fields with restricted access. The lazy hash generation in create() was
however causing access errors for manual transactions created by users
who are not administrators (e.g. Accountants).

Those manual transactions do not typically need a callback, but checking
the presence of the callback requires a limited sudo() context.

Similarly, the execute_callback() method may be called for a manual,
non-admin transaction, and should not do anything if there is no
callback, instead of crashing with an AccessError.

The generation of the hash and execution of the callback should be done
with a normal environment, though, as these must only be used for
transactions run by the system.

opw-747536
This commit is contained in:
Christophe Matthieu
2017-06-26 15:09:13 +02:00
committed by Olivier Dony
parent e1c74e374c
commit 4d79a1ff58
+11 -3
View File
@@ -507,7 +507,9 @@ class PaymentTransaction(models.Model):
tx.write({'reference': str(tx.id)})
# Generate callback hash if it is configured on the tx; avoid generating unnecessary stuff
if tx.callback_model_id and tx.callback_res_id and tx.sudo().callback_method:
# (limited sudo env for checking callback presence, must work for manual transactions too)
tx_sudo = tx.sudo()
if tx_sudo.callback_model_id and tx_sudo.callback_res_id and tx_sudo.callback_method:
tx.write({'callback_hash': tx._generate_callback_hash()})
return tx
@@ -637,7 +639,13 @@ class PaymentTransaction(models.Model):
@api.multi
def execute_callback(self):
res = None
for transaction in self.filtered(lambda tx: tx.callback_model_id and tx.callback_res_id and tx.sudo().callback_method):
for transaction in self:
# limited sudo env, only for checking callback presence, not for running it!
# manual transactions have no callback, and can pass without being run by admin user
tx_sudo = transaction.sudo()
if not (tx_sudo.callback_model_id and tx_sudo.callback_res_id and tx_sudo.callback_method):
continue
valid_token = transaction._generate_callback_hash()
if not consteq(ustr(valid_token), transaction.callback_hash):
_logger.warning("Invalid callback signature for transaction %d" % (transaction.id))
@@ -645,7 +653,7 @@ class PaymentTransaction(models.Model):
record = self.env[transaction.callback_model_id.model].browse(transaction.callback_res_id).exists()
if record:
res = getattr(record, transaction.sudo().callback_method)(transaction)
res = getattr(record, transaction.callback_method)(transaction)
else:
_logger.warning("Did not found record %s.%s for callback of transaction %d" % (transaction.callback_model_id.model, transaction.callback_res_id, transaction.id))
return res