Svoboda | Graniru | BBC Russia | Golosameriki | Facebook
BBC RussianHomePhabricator
Log In
Maniphest T347633

Allow implicit user groups in the augroup and aurights parameters of the allusers API
Closed, ResolvedPublic

Description

The documentation of the allusers API module says:

aurights: Only include users with the given rights. Does not include rights granted by implicit or auto-promoted groups like *, user, or autoconfirmed.

A similar restriction applies to the augroup parameter, although it's not explicitly documented.

I can't fathom why this restriction exists in the first place, if not for technical limitations in the current code. It would be nice to remove this restriction and accept all groups and rights. So much so because of a counterintuitive behaviour that I will mention below.

I can also provide a use case for this: the Campaigns team would like to have a form with an UsersMultiselect component. Ideally, this component would only suggest users who have a certain user right. UsersMultiselect uses the allusers API to obtain a list of users, and it looks like it would be simple enough to add support for passing the aurights parameter. However, the right in question is assigned to all users by default, and therefore cannot be passed to the allusers API.

And here's the counterintuitive behaviour: say you have a user right assigned to the user group. If you execute the request api.php?action=query&format=json&list=allusers&formatversion=2&aurights=my-user-right, the API responds with an empty set. By reading the documentation one should already expect that they won't get a list of users with that right, but at least they could think they'll get an unfiltered list of users. Instead, for some reason it just returns absolutely nothing (skimming through the code, I suspect it's because it queries the DB directly and certain user group memberships aren't stored in the DB). Note that implicit groups cannot be passed to augroup, but at least if you execute api.php?action=query&format=json&list=allusers&formatversion=2&augroup=user the response contains a warning that the value is invalid, as well as the unfiltered list of users.

Event Timeline

Change 965547 had a related patch set uploaded (by Aaron Schulz; author: Aaron Schulz):

[mediawiki/core@master] Mention implicit group exception in apihelp-query+allusers-param-group

https://gerrit.wikimedia.org/r/965547

If we wanted to support filtering by implicit groups/rights, it would require a JOIN on the user table for stock 'autoconfirmed' conditions. But there are lots of APCOND_* constants for conditions that can be configured, and even extensions (e.g. FlaggedRevs) can define their own, some of which use block table info, *current session* info, or possibly stuff from key/value stores. Filtering for that would be slow, complex. Paging through rows would require a two-level pager where the lower pager iteratively fetches row batchs *and* checks the implicit group/right checks until X (page limit) rows were found to feed to the upper pager. If few users have the implicit right, it would timeout.

I suppose it's possible to give a warning if a right is only assigned to implicit groups. What if it is assigned to both implicit and explicit (db) groups?

Maybe supporting the narrow case of rights given to * and "user" groups could be handled by:

  • Treating augroup=[...,*] and augroup=[...,user] as matching every user
  • Treating auexcludegroup[...,*] and augroup=[...,user] as not matching every user
  • Treating auright=[X] as matching every user as long as it's assigned via $wgGroupPermissions['*'], $wgGroupPermissions['user'], or PermissionManager::getImplicitRights()
  • Likewise for similar APIs like "contributors"

If we wanted to support filtering by implicit groups/rights, it would require a JOIN on the user table for stock 'autoconfirmed' conditions. But there are lots of APCOND_* constants for conditions that can be configured, and even extensions (e.g. FlaggedRevs) can define their own, some of which use block table info, *current session* info, or possibly stuff from key/value stores. Filtering for that would be slow, complex. Paging through rows would require a two-level pager where the lower pager iteratively fetches row batchs *and* checks the implicit group/right checks until X (page limit) rows were found to feed to the upper pager. If few users have the implicit right, it would timeout.

Very good point, I was more focused on the user group and did not consider this aspect for autopromoted groups.

I suppose it's possible to give a warning if a right is only assigned to implicit groups. What if it is assigned to both implicit and explicit (db) groups?

Maybe still give a warning? More information should be better than less, especially if it states this fact clearly.

Maybe supporting the narrow case of rights given to * and "user" groups could be handled by:

  • Treating augroup=[...,*] and augroup=[...,user] as matching every user
  • Treating auexcludegroup[...,*] and augroup=[...,user] as not matching every user
  • Treating auright=[X] as matching every user as long as it's assigned via $wgGroupPermissions['*'], $wgGroupPermissions['user'], or PermissionManager::getImplicitRights()
  • Likewise for similar APIs like "contributors"

Seems reasonable!

Change 965547 merged by jenkins-bot:

[mediawiki/core@master] Mention implicit group exception in apihelp-query+allusers-param-group

https://gerrit.wikimedia.org/r/965547

Since augroup/auexcludegroup already gives warnings for */user, they are not useful to filter on even if they did work, and I don't want to give the impression that other implicit groups work, I worry that changing how those filters work is not worth the tech debt.

aurights is more interesting, since it doesn't warn and has more of a use case (e.g. some wikis might assign X to everyone but others require an explicit group). There is still no complete way to apply this filter for wikis where a right is only given via an implicit group like autoconfirmed.

What kind of rights does Campaigns need to check?

aaron triaged this task as Low priority.Oct 18 2023, 7:56 PM

aurights is more interesting, since it doesn't warn and has more of a use case (e.g. some wikis might assign X to everyone but others require an explicit group). There is still no complete way to apply this filter for wikis where a right is only given via an implicit group like autoconfirmed.

Indeed, and that's the issue we faced:

What kind of rights does Campaigns need to check?

We'd like to use this for the campaignevents-organize-events right, which is assigned to all users by default (and also in beta and prod test wikis), but only to the campaignevents-beta-tester group in metawiki.

I'm noticing that GroupPermissionsLookup is poorly documented.

Also, APIQueryAllUsers doesn't fully handle $wgRevokePermissions (as user in groups A and B will show up for right X if A grants X but B revokes X. This probably to avoid slow, complicated, queries.

It's also odd that if you give augroups and aurights, the two are disjunctive rather than conjunctive, which isn't what I would expect. Worse is that if no groups have the aurights, then it becomes conjunctive by returning empty results without regard for 'augroups'. I hope clients don't rely on that...

Change 967290 had a related patch set uploaded (by Aaron Schulz; author: Aaron Schulz):

[mediawiki/core@master] api: make APIQueryAllUsers handle implicit/*/user rights for aurights

https://gerrit.wikimedia.org/r/967290

Change 967290 merged by jenkins-bot:

[mediawiki/core@master] api: make APIQueryAllUsers handle implicit/*/user rights for aurights

https://gerrit.wikimedia.org/r/967290