[FIX] account: prevent reading fake binary fields over rpc

Since Odoo 16 [1] account module uses some non-storable computed Binary fields
to compute and access structured data. Those data is not transformed into binary
data and is not supposed to be used outside of server environment. There are
still use cases when ORM tries to process such fields as normal Binary fields.
For example, on using export wizard [2].

This commit fixes similar problem on reading `account.move{.line}` records via
rpc.

STEPS: create `account.move` record and read it via an RPC call [3]

```
account_move_id = 666
models.execute_kw(db, uid, password, 'account.move', 'read', [account_move_id])
```

SOLUTION

1. Add missing `exportable=False` to the fake Binary fields
2. Block access to such fields via method `check_field_access_rights`

[1]:
https://github.com/odoo/odoo/commit/d8d47f9ff8554f4b39487fd2f13c153c7d6f958d
[2]: https://github.com/odoo/odoo/commit/c925ecb2a22750524020f0d111888fd76eedb0cb
[3]: https://www.odoo.com/documentation/16.0/developer/api/external_api.html

opw-3099975

closes odoo/odoo#134164

X-original-commit: 5193d145b96e34ef1e754b8421cccd8c9dab99e7
Signed-off-by: William André (wan) <wan@odoo.com>
This commit is contained in:
Ivan Yelizariev
2023-09-04 17:10:12 +00:00
committed by william-andre
parent 38d0124a93
commit 602b3f3d39
2 changed files with 22 additions and 8 deletions
+10 -3
View File
@@ -292,7 +292,7 @@ class AccountMove(models.Model):
compute='_compute_invoice_payment_term_id', store=True, readonly=False, precompute=True,
check_company=True,
)
needed_terms = fields.Binary(compute='_compute_needed_terms')
needed_terms = fields.Binary(compute='_compute_needed_terms', exportable=False)
needed_terms_dirty = fields.Boolean(compute='_compute_needed_terms')
tax_calculation_rounding_method = fields.Selection(
related='company_id.tax_calculation_rounding_method',
@@ -488,7 +488,7 @@ class AccountMove(models.Model):
help='Use this field to encode the total amount of the invoice.\n'
'Odoo will automatically create one invoice line with default values to match it.',
)
quick_encoding_vals = fields.Binary(compute='_compute_quick_encoding_vals')
quick_encoding_vals = fields.Binary(compute='_compute_quick_encoding_vals', exportable=False)
# === Misc Information === #
narration = fields.Html(
@@ -580,7 +580,7 @@ class AccountMove(models.Model):
need_cancel_request = fields.Boolean(compute='_compute_need_cancel_request')
# used to display the various dates and amount dues on the invoice's PDF
payment_term_details = fields.Binary(compute="_compute_payment_term_details")
payment_term_details = fields.Binary(compute="_compute_payment_term_details", exportable=False)
show_payment_term_details = fields.Boolean(compute="_compute_show_payment_term_details")
show_discount_details = fields.Boolean(compute="_compute_show_payment_term_details")
@@ -2340,6 +2340,13 @@ class AccountMove(models.Model):
# LOW-LEVEL METHODS
# -------------------------------------------------------------------------
def check_field_access_rights(self, operation, field_names):
result = super().check_field_access_rights(operation, field_names)
if not field_names:
weirdos = ['needed_terms', 'quick_encoding_vals', 'payment_term_details']
result = [fname for fname in result if fname not in weirdos]
return result
def copy_data(self, default=None):
data_list = super().copy_data(default)
for move, data in zip(self, data_list):
+12 -5
View File
@@ -354,12 +354,12 @@ class AccountMoveLine(models.Model):
related='company_id.tax_calculation_rounding_method',
string='Tax calculation rounding method', readonly=True)
# === Invoice sync fields === #
term_key = fields.Binary(compute='_compute_term_key')
tax_key = fields.Binary(compute='_compute_tax_key')
compute_all_tax = fields.Binary(compute='_compute_all_tax')
term_key = fields.Binary(compute='_compute_term_key', exportable=False)
tax_key = fields.Binary(compute='_compute_tax_key', exportable=False)
compute_all_tax = fields.Binary(compute='_compute_all_tax', exportable=False)
compute_all_tax_dirty = fields.Boolean(compute='_compute_all_tax')
epd_key = fields.Binary(compute='_compute_epd_key')
epd_needed = fields.Binary(compute='_compute_epd_needed')
epd_key = fields.Binary(compute='_compute_epd_key', exportable=False)
epd_needed = fields.Binary(compute='_compute_epd_needed', exportable=False)
epd_dirty = fields.Boolean(compute='_compute_epd_needed')
# === Analytic fields === #
@@ -1262,6 +1262,13 @@ class AccountMoveLine(models.Model):
# -------------------------------------------------------------------------
# CRUD/ORM
# -------------------------------------------------------------------------
def check_field_access_rights(self, operation, field_names):
result = super().check_field_access_rights(operation, field_names)
if not fields:
weirdos = ['term_key', 'tax_key', 'compute_all_tax', 'epd_key', 'epd_needed']
result = [fname for fname in result if fname not in weirdos]
return result
def invalidate_model(self, fnames=None, flush=True):
# Invalidate cache of related moves
if fnames is None or 'move_id' in fnames: