Skip to content

[FIX] web: filter cached inaccessible x2many records in web_read - #257517

Closed
fw-bot wants to merge 1 commit into
odoo:18.0from
odoo-dev:18.0-17.0-web-read-x2many-filter-cache-records-cro-502639-fw
Closed

[FIX] web: filter cached inaccessible x2many records in web_read#257517
fw-bot wants to merge 1 commit into
odoo:18.0from
odoo-dev:18.0-17.0-web-read-x2many-filter-cache-records-cro-502639-fw

Conversation

@fw-bot

@fw-bot fw-bot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Description of the issue/feature this PR addresses:
web_read on x2many fields can reuse cached ids after write/web_save. Some of these cached ids may be inaccessible with the current record rules/context (cache pollution).

Example:

  • Context:

    • Two companies exist: Company A and Company B.
    • Two users exist: User A and User B.
    • User A can only access Company A (company_ids=[A], company_id=A).
    • User B is linked to both companies (company_ids=[A, B], company_id=A).
    • The "res.company" record rule is the standard one: [('id', 'in', company_ids)] (company_ids comes from allowed_company_ids).
    • User A edits User B and saves the form.
  • Steps:

    • User A performs a web_read to load User B: company_ids contains only Company A.
    • User A performs web_save (write + internal web_read in the same request): cached ids [A, B] are reused and the code attempts to read Company B.

Current behavior before PR (without fix):
After saving a form with an x2many field, web_save calls write and then web_read. In this flow, web_read can include inaccessible x2many ids from cache and raise an AccessError.

Desired behavior after PR is merged:
x2many records are re-filtered with current read rules before formatting, and inaccessible ids are removed from values_list.

Forward-Port-Of: #250904

@robodoo

robodoo commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

Pull request status dashboard

@fw-bot

fw-bot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor Author

This PR targets 18.0 and is part of the forward-port chain. Further PRs will be created up to master.

More info at https://github.com/odoo/odoo/wiki/Mergebot#forward-port

@robodoo robodoo added the forwardport This PR was created by @fw-bot label Apr 3, 2026
@fw-bot

fw-bot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor Author

@cro-odoo @rco-odoo ci/runbot failed on this forward-port PR

Comment thread addons/web/models/models.py Outdated
Comment on lines 143 to 145
co_records = co_records.with_context(active_test=False).search(
[('id', 'in', co_records.ids)], order=field_spec['order'],
[('id', 'in', co_records.ids)], order=field_spec_order,
).with_context(co_records.env.context) # Reapply previous context

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cro-odoo the failing tests may be because this call to search() crashes. I suggest to wrap it into a try/except, so that some AccessError turns co_records into an empty recordset. That's the behavior we now have in master.

@cro-odoo
cro-odoo force-pushed the 18.0-17.0-web-read-x2many-filter-cache-records-cro-502639-fw branch from d06ddc4 to 6f29334 Compare April 9, 2026 21:10
@fw-bot

fw-bot commented Apr 9, 2026

Copy link
Copy Markdown
Contributor Author

@cro-odoo @rco-odoo this PR has become a normal PR because head updated from d06ddc4f9201b0b159d12c137f0e595e96db5334 to 6f2933446e657f42e6df3b5f344542c6003b4f8e. It must be merged to be forward-ported further.

@cro-odoo
cro-odoo requested a review from rco-odoo April 9, 2026 21:13
@C3POdoo
C3POdoo requested review from a team, HydrionBurst, aab-odoo and jpp-odoo and removed request for a team April 9, 2026 21:27
@fw-bot

fw-bot commented Apr 11, 2026

Copy link
Copy Markdown
Contributor Author

@cro-odoo @rco-odoo this forward port of #250904 is awaiting action (not merged or closed).

@cro-odoo
cro-odoo force-pushed the 18.0-17.0-web-read-x2many-filter-cache-records-cro-502639-fw branch from 6f29334 to b760be6 Compare April 13, 2026 10:08
@cro-odoo

Copy link
Copy Markdown
Contributor

hello @rco-odoo
Due to incompatibility of my patch with the model account.code.mapping, I use the idea of @kmagusiak (#250904 (comment)) ==> using _filtered_access(read) and apply your suggestion of "try/except"

@cro-odoo
cro-odoo force-pushed the 18.0-17.0-web-read-x2many-filter-cache-records-cro-502639-fw branch from b760be6 to 05ded3e Compare April 14, 2026 12:01
@cro-odoo

Copy link
Copy Markdown
Contributor

Hello future reviewer,

I adjusted the previous patch "a bit more" after investigating the failed tests.

The original bug is still cache pollution: "web_read" may reuse inaccessible x2many ids and should not expose or crash on them.

Here is the new logic to remove polluted x2many values:

  1. the order case: search(..., order=...) to get an ordered and "filtered" recordset. (could be replaced by .sorted from saas-18.4 ==> [FIX] web: filter cached inaccessible x2many records in web_read #250904 (comment))
  2. the fields info/value case: filtering polluted x2many values, not ordering ==> we can't do a search([('id', 'in', ...)]) because sometimes is not allowed (e.g. account.code.mapping in which search() method raises an UserError).

So to filter, we use _filtered_access('read') (to be changed to clear_access_cache in 19.1 #250904 (comment)) but using it without checking if the user has access to the model introduces a regression in hr_appraisal app (see TestHrAppraisalRequestUi.test_send_appraisal_request_by_email_flow)

  • manager_ids is a x2many field to hr.employee and the UI tour user is a base.group_user user (not hr user) ==> that user does not have a read access on hr.employee model, so _filtered_access('read') removes all managers from values. The field is required, so the form can't be saved and the modal action no longer opens.

So my idea is to only apply _filtered_access('read') in the fields section when the user has general read access on the comodel, otherwise co-records keep the relation ids unchanged.

This is a bigger patch than the first version, so I would like your feedback @rco-odoo or @kmagusiak on this PR: Is still this look ok for you ? Since you have a more global view on the ORM methods / behaviors.

@kmagusiak

Copy link
Copy Markdown
Contributor

Before deciding, let's see future issues.
@robodoo fw=skipci

If that changes the behaviour too much, I would opt to revert the change in 17.0 and abandon that change as too risky.
If all is fine, this should be backported to 17.0.
Maybe some nitpicks about the order of if statements.

@robodoo

robodoo commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Not waiting for CI to create followup forward-ports.

robodoo pushed a commit that referenced this pull request Apr 16, 2026
closes #257517

Signed-off-by: Raphael Collet <rco@odoo.com>
Signed-off-by: Krzysztof Magusiak (krma) <krma@odoo.com>
@robodoo robodoo closed this Apr 16, 2026
@fw-bot
fw-bot deleted the 18.0-17.0-web-read-x2many-filter-cache-records-cro-502639-fw branch April 23, 2026 14:44
sergio-teruel pushed a commit to Tecnativa/odoo that referenced this pull request Jul 8, 2026
closes odoo#257517

Signed-off-by: Raphael Collet <rco@odoo.com>
Signed-off-by: Krzysztof Magusiak (krma) <krma@odoo.com>
gamarino pushed a commit to numaes/numa-public-odoo that referenced this pull request Jul 22, 2026
closes odoo/odoo#257517

Signed-off-by: Raphael Collet <rco@odoo.com>
Signed-off-by: Krzysztof Magusiak (krma) <krma@odoo.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

forwardport This PR was created by @fw-bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants