fix: let whoever may manage files search them - #904
Merged
blaipr merged 1 commit intoSep 3, 2026
Conversation
The Files tab in Items Management is shown when FILE is granted (isMgmFiles), and the grid inside it searches and pages under ACCOUNT_FILE_SEARCH — which had no arm at all in Acl::checkUserAccess() and fell through to the deny. isAdminApp short-circuits at the top, so an application administrator never saw it; everyone else with isMgmFiles saw the tab, saw the list, and was refused by every search inside it. Two ids authorising one feature, disagreeing. AclAnswersEveryActionCheckedTest exists for exactly this failure and passed, because it scans for the literal checkUserAccess(AclActionsInterface::FOO) and SearchGridControllerBase calls checkUserAccess($this->getAclAction()) — the id is returned from a method in the subclass, never within a regex's reach of the call. Six controllers are authorised that way, and the one the guard could not see is the one that was broken. It now scans getAclAction() bodies too. ACCOUNT_FILE_VIEW, _UPLOAD, _DOWNLOAD, _DELETE and _LIST still have no arm, which is correct: nothing passes them to checkUserAccess(). The web enforces object-level access through AccountFileAcl, the grid does not filter its buttons by ACL, and Api::setup() authorises by the calling token's bound action id without consulting this ACL.
blaipr
deleted the
fix/the-files-page-is-reachable-by-those-who-may-manage-files
branch
September 3, 2026 00:59
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.
The Files tab in Items Management is shown when
FILEis granted —isMgmFiles(). The grid insideit searches and pages under a different action id,
ACCOUNT_FILE_SEARCH, and that id had no armat all in
Acl::checkUserAccess(), so it fell through to the deny at the end.isAdminAppshort-circuits at the top of that method, so an application administrator never saw it.Everyone else with
isMgmFiles()saw the Files tab, saw the list of files in it, and got "Youdon't have permission to do this operation" from every search or page inside it. Two action ids
authorising one feature, disagreeing.
The arm joins the
FILE/FILE_SEARCHgroup it belongs with and answersisMgmFiles(), which iswhat showed the tab in the first place.
Why the guard test did not catch it
AclAnswersEveryActionCheckedTestexists for exactly this failure — it was written after threeactions reached the same state at once — and it passed. It scans the controllers for
checkUserAccess(AclActionsInterface::FOO).AccountFile\SearchControllerdoes not contain that call.SearchGridControllerBase::searchAction()calls
checkUserAccess($this->getAclAction()), and the id is returned from a method in thesubclass. Six controllers are authorised that way, and the id was never within a regex's reach of
the call.
Scanning
getAclAction()bodies as well brings all six in. Of those six —ACCOUNTMGR_SEARCH,ACCOUNTMGR_HISTORY_SEARCH,AUTHTOKEN_SEARCH,CATEGORY_SEARCH,CLIENT_SEARCHandACCOUNT_FILE_SEARCH— the one the guard could not see is the one that was broken.Checked and deliberately not changed
ACCOUNT_FILE_VIEW,_UPLOAD,_DOWNLOAD,_DELETEand_LISTstill have no arm, and that iscorrect rather than an oversight: nothing passes them to
checkUserAccess(). The web controllersenforce object-level access through
AccountFileAcl::requireView()/requireEdit(), the grid doesnot filter its buttons by ACL, and the API authorises by the calling token's bound action id —
Api::setup()callsgetTokenByToken($actionId, $token)and never consults this ACL, so no APIendpoint was affected. Adding arms for ids nothing checks would be inventing policy; the guard
test's own docblock makes the same point about ids that exist only so permissions can be named.
Tests
AclTestgains the behavioural case:mgmFilesgrantsACCOUNT_FILE_SEARCH, and a profilewithout it does not.
AclAnswersEveryActionCheckedTestnow covers 88 actions instead of the direct-call subset.Mutation-verified: with the arm removed the guard fails naming
ACCOUNT_FILE_SEARCHand quotingwhat it costs.