N°9723 - IsActionAllowed should work with non instantiated users objects#973
N°9723 - IsActionAllowed should work with non instantiated users objects#973bdalsass wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes password-reset recursion by loading profiles from the database when only unrelated user fields have changed.
Changes:
- Detects changes specifically to
profile_list. - Uses in-memory profiles only when that list was modified.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public function ListProfiles($oUser) | ||
| { | ||
| if (count($oUser->ListChanges()) === 0) { // backward compatibility | ||
| if (!array_key_exists('profile_list', $oUser->ListChanges())) { |
|
| Filename | Overview |
|---|---|
| addons/userrights/userrightsprofile.class.inc.php | Fixes infinite loop in ListProfiles by narrowing the condition from 'user has no changes at all' to 'profile_list attribute is not in changes', allowing the safe DB path when only non-profile attributes are modified. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[IsActionAllowed called\nfor modified User object] --> B[GetUserActionGrant]
B --> C[GetProfileList]
C --> D[UserRights::ListProfiles]
subgraph OLD ["BEFORE fix (infinite loop)"]
D1{"count(ListChanges()) === 0?"}
D1 -- "false: user has ANY change" --> E1["oUser->Get('profile_list')\npermission check triggered"]
E1 --> A
end
subgraph NEW ["AFTER fix (resolved)"]
D2{"array_key_exists('profile_list', ListChanges())?"}
D2 -- "false: profile_list not changed" --> E2["DBObjectSearch with AllowAllData\n(no permission check, no recursion)"]
D2 -- "true: profile_list modified" --> E3["oUser->Get('profile_list')\n(use in-memory data)"]
end
D --> D1
D --> D2
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[IsActionAllowed called\nfor modified User object] --> B[GetUserActionGrant]
B --> C[GetProfileList]
C --> D[UserRights::ListProfiles]
subgraph OLD ["BEFORE fix (infinite loop)"]
D1{"count(ListChanges()) === 0?"}
D1 -- "false: user has ANY change" --> E1["oUser->Get('profile_list')\npermission check triggered"]
E1 --> A
end
subgraph NEW ["AFTER fix (resolved)"]
D2{"array_key_exists('profile_list', ListChanges())?"}
D2 -- "false: profile_list not changed" --> E2["DBObjectSearch with AllowAllData\n(no permission check, no recursion)"]
D2 -- "true: profile_list modified" --> E3["oUser->Get('profile_list')\n(use in-memory data)"]
end
D --> D1
D --> D2
Comments Outside Diff (1)
-
addons/userrights/userrightsprofile.class.inc.php, line 912-923 (link)GetProfileList caching still bypassed on any change
GetProfileListuses the same broadcount($oUser->ListChanges()) === 0guard to decide whether to populateaUsersProfilesList. For a user with any non-profile_listchange (e.g. password reset, the exact scenario this PR fixes),GetProfileListwill skip the cache and callUserRights::ListProfileson every invocation. BecauseListProfilesnow correctly takes the DB path in this case, there's no correctness problem — but each call toGetUserActionGrantfor the same user/class/action will re-query the database rather than hittingaUsersProfilesList. Aligning this guard with the samearray_key_exists('profile_list', $oUser->ListChanges())check used inListProfileswould make caching consistent and avoid unnecessary repeated queries during a single request.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Reviews (1): Last reviewed commit: "N°9723 - IsActionAllowed should work wit..." | Re-trigger Greptile
Base information
Symptom (bug) / Objective (enhancement)
Infinite loop when user try to reset his password
Reproduction procedure (bug)
reset password
Checklist before requesting a review