[2.x] fix: Avoid loading target user's groups in editCredentials check - #4729
Merged
Conversation
UserPolicy::editCredentials evaluated $user->isAdmin() (which reads $user->groups) before checking whether the actor can edit credentials at all. On render paths that serialize many users — post authors, and likers via flarum-likes' default `likes` include — UserResource's email-field visibility runs this check per serialized user, lazy-loading each one's groups: an N+1 that #4696 did not cover. Check the actor's `user.editCredentials` permission first and return no opinion when absent (guests and normal users — the common case), so the target user's groups are never touched. $user->isAdmin() is only consulted when the actor can actually edit credentials, where it is needed to protect admins. The visibility outcome is unchanged in every case. Adds a flarum-likes regression test asserting likers' groups are not loaded one query per liker. Fixes #4724.
imorland
marked this pull request as ready for review
June 13, 2026 18:58
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #4724.
Problem
UserPolicy::editCredentials()evaluated$user->isAdmin()— which reads$user->groups— before checking whether the actor can edit credentials at all:UserResource's email-field visibility callseditCredentialsfor every serialized user. On render paths that serialize many users,$user->isAdmin()lazy-loads each one'sgroups— onegroup_userquery per user. #4696 fixed this for post authors on the JSON:API posts endpoint by eager-loadinguser.groups, but it does not cover other serialized users — notably the likers included by default via flarum-likes'likesrelationship, whose groups are not eager-loaded for post-stream posts.Fix
Check the actor's
user.editCredentialspermission first and return no opinion when they lack it. Guests and normal users — the vast majority of serialized actors — never reach$user->isAdmin(), so the target user'sgroupsare never loaded.$user->isAdmin()is only consulted when the actor can actually edit credentials, where it is needed to stop a non-admin from editing an admin's credentials.This eliminates the work for the common case rather than batching it, and the visibility outcome is unchanged in every case:
editCredentialsTests
ListPostsTest::likers_groups_are_not_loaded_individually): asserts likers' groups are batch-loaded, not one query per liker. Fails without this change (loads them individually), passes with it.