[2.x] fix: allow non-admins to upload a poll image before the poll exists - #136
Merged
Conversation
The composer uploads a poll image before the poll is saved, so there is
no model to authorize against on that path. It asserted 'startPoll',
which is a policy ability on Post: with a null model core's Gate consults
only GLOBAL policies, finds none, and falls back to
hasPermission('startPoll'). No group can hold that — it is not a
registered permission — so the check could only ever pass for admins.
The two asserts were also AND-ed, so a user creating a global poll was
additionally required to hold the discussion-poll ability, and vice
versa.
Both upload controllers now share assertCanStartAnyPoll(), which allows
the upload when the actor can start a global poll OR holds
discussion.polls.start — the grantable permission the canStartPolls forum
attribute already uses. uploadPollImages is still asserted first, so the
upload remains behind both 'may upload images' and 'could actually be
making a poll'.
Fixes #131
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 #131 — reported by @ekumanov, who also diagnosed the cause.
The bug
Adding an image to a poll while creating it returned 403 for every non-admin, no matter which permissions they held. Editing an existing poll's image worked, because that path takes the
if ($pollId)branch and correctly checksassertCan('edit', $poll).The composer uploads the image before the poll is saved, so on that path there is no model to authorize against. It asserted:
startPollis a policy ability onPost(Access\PostPolicy::startPoll). With a null model, core'sGate::allows()only consultsGLOBALpolicies — so the Post policy is never evaluated — and falls through to:startPollis never registered as a grantable permission (the admin extender registersstartGlobalPoll,uploadPollImagesandstartPollGroup), sohasPermission('startPoll')is always false and only theisAdmin()branch could ever pass.The two asserts were also AND-ed, so even where the first check passed, a user creating a discussion poll was required to hold
startGlobalPollas well.The fix
Both controllers now share
assertCanStartAnyPoll(), which permits the upload when the actor can start a global poll or holdsdiscussion.polls.start— the grantable permission thecanStartPollsforum attribute already uses.uploadPollImagesis still asserted first, so the upload stays behind both "may upload poll images" and "could actually be creating a poll".On the design question left open in the issue: I kept the poll-start requirement rather than letting
uploadPollImagesstand alone, since the request writes a file to disk and the second check keeps that tied to a plausible poll.Note that
UploadPollOptionImageControlleroverrideshandle()and carried its own copy of the same broken branch, so option images were affected identically.Tests
New
UploadPollImageAuthorizationTestcovers the pre-save upload path for both poll and option images, the admin case, and a user who may upload but cannot start a poll anywhere (403).Proven red first: the two pre-save cases return 403 against the current controllers and 200 with the fix, while the negative and admin cases hold in both directions. Full suite 122/122, PHPStan clean.