[IMP]hide_portal_module_by_user: fix invoices access in v18

This commit is contained in:
2026-08-10 16:04:48 +02:00
parent 76d0085c2d
commit bb759eb8ca
4 changed files with 67 additions and 9 deletions

View File

@@ -1,16 +1,47 @@
# Copyright 2026 Munin
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from urllib.parse import parse_qsl, urlsplit
from odoo import fields, models
def match_portal_url(portal_url, target):
"""Whether ``target`` is covered by the ``portal_url`` of a portal group.
A group url is the one read from the portal.portal_docs_entry t-call it
was generated from, and it covers:
- the listing itself and its sub-pages, since the portal serves detail
and pager pages below it ('/my/projects/135', '/my/projects/page/2'),
which go through _prepare_portal_layout_values as well;
- the entries narrowing that listing down with query arguments. Odoo 18
splits some listings in several entries this way, eg. account has
'/my/invoices?filterby=invoices' and '/my/invoices?filterby=bills'
where 16.0 had a single '/my/invoices'.
A group url carrying query arguments only matches targets carrying them
all, so a group can be restricted to one such entry; a group url without
any matches every entry of the listing.
"""
if not portal_url or not target:
return False
ref = urlsplit(portal_url)
got = urlsplit(target)
root = ref.path.rstrip('/')
if not (got.path == root or got.path.startswith(root + '/')):
return False
return set(parse_qsl(ref.query)) <= set(parse_qsl(got.query))
class ResUsers(models.Model):
_inherit = "res.users"
portal_url = fields.Char(string='Portal URL')
def validate_portal_url(self, url):
group = self.sudo().env['res.groups'].search([('portal_url', '=', url)])
if self.env.user in group.users:
return True
groups = self.sudo().env['res.groups'].search([('portal_url', '!=', False)])
for group in groups.filtered(lambda g: match_portal_url(g.portal_url, url)):
if self.env.user in group.users:
return True
return False