fix: update journal access rules to support domain ID filtering and improve read operation handling

This commit is contained in:
Suherdy Yacob 2026-06-17 16:01:33 +07:00
parent 2ba3ca12eb
commit 71e6a8d64a

View File

@ -30,13 +30,61 @@ class AccountJournal(models.Model):
self.env.context.get('install_mode')
)
if not bypass:
allowed_ids = user.sudo().allowed_journal_ids.ids
allowed_ids = list(user.sudo().allowed_journal_ids.ids)
# When Odoo's fetch() verifies a record it just loaded, it re-runs
# _search with [('id', 'in', [X])]. The record was already cleared
# by _check_access/check_access_rule, so we must honour the explicit
# IDs present in the domain and add them to the allow-list so they
# survive the sudo search.
for leaf in domain:
if (
isinstance(leaf, (list, tuple))
and len(leaf) == 3
and leaf[0] == 'id'
and leaf[1] in ('=', 'in')
):
value = leaf[2]
if isinstance(value, (list, tuple, set)):
allowed_ids.extend(value)
elif isinstance(value, int):
allowed_ids.append(value)
domain = [('id', 'in', allowed_ids)] + list(domain)
# Run the search as sudo to bypass standard multi-company rules
return self.sudo()._search(domain, offset=offset, limit=limit, order=order, **kwargs)
return super(AccountJournal, self)._search(domain, offset=offset, limit=limit, order=order, **kwargs)
def _check_access(self, operation):
"""
Overridden to bypass multi-company record rules for allowed journals,
and enforce the allowed journals restriction for write, create, and delete operations.
"""
if self.env.su:
return super(AccountJournal, self)._check_access(operation)
user = self.env.user
allowed_journals = user.sudo().allowed_journal_ids
if allowed_journals:
# Enforce restriction for write, create, and delete operations.
if operation in ('write', 'create', 'unlink'):
forbidden = self.filtered(lambda j: j.id not in allowed_journals.ids)
if forbidden:
import functools
return forbidden, functools.partial(AccessError, _("You do not have access to this journal."))
# Read operations are allowed to prevent access errors when loading
# documents (payments/moves) referencing other journals.
if operation == 'read':
return None
# If all records in self are allowed, bypass standard record rules.
if all(j.id in allowed_journals.ids for j in self):
return None
return super(AccountJournal, self)._check_access(operation)
def check_access_rule(self, operation):
"""
Overridden to bypass multi-company record rules for allowed journals,
@ -55,6 +103,9 @@ class AccountJournal(models.Model):
if not all(j.id in allowed_journals.ids for j in self):
raise AccessError(_("You do not have access to this journal."))
if operation == 'read':
return
# If all records in self are allowed, bypass standard record rules.
if all(j.id in allowed_journals.ids for j in self):
return