Steps to replicate the issue (include links if applicable):
- Attempt to modify userrights on a different wiki using the API, for example:
{ "action": "userrights", "format": "json", "user": "Void@loginwiki", "add": "sysop", "expiry": "1 minute", "reason": "testing API" }
What happens?:
The API request fails with the contents:
{ "error": { "code": "internal_api_error_Wikimedia\\Assert\\PreconditionException", "info": "[c21a9dd7975bac4712ea8f68] Caught exception of type Wikimedia\\Assert\\PreconditionException", "errorclass": "Wikimedia\\Assert\\PreconditionException" }, "servedby": "mw" }
The stack trace from the logs is:
Expected MediaWiki\User\UserIdentityValue to belong to the local wiki, but it belongs to 'loginwiki' from /srv/mediawiki/1.41/includes/dao/WikiAwareEntityTrait.php(59) #0 /srv/mediawiki/1.41/includes/user/UserIdentityValue.php(139): MediaWiki\User\UserIdentityValue->assertWiki(boolean) #1 /srv/mediawiki/1.41/includes/api/ApiUserrights.php(142): MediaWiki\User\UserIdentityValue->getId() #2 /srv/mediawiki/1.41/includes/api/ApiMain.php(1936): ApiUserrights->execute() #3 /srv/mediawiki/1.41/includes/api/ApiMain.php(912): ApiMain->executeAction() #4 /srv/mediawiki/1.41/includes/api/ApiMain.php(883): ApiMain->executeActionWithErrorHandling() #5 /srv/mediawiki/1.41/api.php(95): ApiMain->execute() #6 /srv/mediawiki/1.41/api.php(48): wfApiMain() #7 /srv/mediawiki/config/initialise/entrypoints/api.php(3): require(string) #8 {main}
What should have happened instead?:
The API request should have succeeded and modified the user groups of the user on the remote wiki.
Software version (on Special:Version page; skip for WMF-hosted wikis like Wikipedia):
1.41.0 (5498056)
Comments
Looks like this is related to the replacement of UserRightsProxy in SpecialUserRights::fetchUser with UserIdentityValue. UserRightsProxy::getId takes an optional $wikiId parameter that it simply discards, returning the ID of the remote user. On the other hand, UserIdentityValue::getId takes the same optional parameter, failing if the specified wikiId is different from the wikiId of the user identity. However, the default wikiId is the local wiki, which means that calling getId with no parameters for a remote user will always fail. I'm not sure if the proper handling is to alter ApiUserrights to do $user->getId( $user->getWikiId() ); or to have UserIdentityValue::getId default to the identity's own wikiId.