2023-05-26 22:57:37 +00:00
|
|
|
<?php
|
|
|
|
|
|
2023-08-17 19:05:57 +00:00
|
|
|
use MediaWiki\MainConfigNames;
|
2023-05-26 22:57:37 +00:00
|
|
|
use MediaWiki\Request\FauxRequest;
|
|
|
|
|
use MediaWiki\Specials\SpecialUserRights;
|
2024-09-04 14:51:22 +00:00
|
|
|
use MediaWiki\Tests\User\TempUser\TempUserTestTrait;
|
|
|
|
|
use MediaWiki\User\UserIdentityValue;
|
2023-12-11 14:59:55 +00:00
|
|
|
use MediaWiki\WikiMap\WikiMap;
|
2023-05-26 22:57:37 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @group Database
|
|
|
|
|
* @covers \MediaWiki\Specials\SpecialUserRights
|
|
|
|
|
*/
|
|
|
|
|
class SpecialUserRightsTest extends SpecialPageTestBase {
|
|
|
|
|
|
2024-09-04 14:51:22 +00:00
|
|
|
use TempUserTestTrait;
|
|
|
|
|
|
2023-05-26 22:57:37 +00:00
|
|
|
/**
|
|
|
|
|
* @inheritDoc
|
|
|
|
|
*/
|
|
|
|
|
protected function newSpecialPage() {
|
|
|
|
|
$services = $this->getServiceContainer();
|
|
|
|
|
return new SpecialUserRights(
|
|
|
|
|
$services->getUserGroupManagerFactory(),
|
|
|
|
|
$services->getUserNameUtils(),
|
|
|
|
|
$services->getUserNamePrefixSearch(),
|
|
|
|
|
$services->getUserFactory(),
|
2023-03-20 21:14:32 +00:00
|
|
|
$services->getActorStoreFactory(),
|
2024-09-04 11:21:22 +00:00
|
|
|
$services->getWatchlistManager(),
|
|
|
|
|
$services->getTempUserConfig()
|
2023-05-26 22:57:37 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-04 14:51:22 +00:00
|
|
|
/** @dataProvider provideUserCanChangeRights */
|
|
|
|
|
public function testUserCanChangeRights( $targetUser, $checkIfSelf, $expectedReturnValue ) {
|
|
|
|
|
$objectUnderTest = $this->newSpecialPage();
|
|
|
|
|
$this->assertSame( $expectedReturnValue, $objectUnderTest->userCanChangeRights( $targetUser, $checkIfSelf ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static function provideUserCanChangeRights() {
|
|
|
|
|
return [
|
|
|
|
|
'Target user not registered' => [ UserIdentityValue::newAnonymous( 'Test' ), true, false ],
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testUserCanChangeRightsForTemporaryAccount() {
|
|
|
|
|
$temporaryAccount = $this->getServiceContainer()->getTempUserCreator()
|
|
|
|
|
->create( null, new FauxRequest() )->getUser();
|
|
|
|
|
$this->testUserCanChangeRights( $temporaryAccount, false, false );
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-26 22:57:37 +00:00
|
|
|
public function testSaveUserGroups() {
|
|
|
|
|
$target = $this->getTestUser()->getUser();
|
|
|
|
|
$performer = $this->getTestSysop()->getUser();
|
|
|
|
|
$request = new FauxRequest(
|
|
|
|
|
[
|
|
|
|
|
'saveusergroups' => true,
|
|
|
|
|
'conflictcheck-originalgroups' => '',
|
|
|
|
|
'wpGroup-bot' => true,
|
|
|
|
|
'wpExpiry-bot' => 'existing',
|
|
|
|
|
'wpEditToken' => $performer->getEditToken( $target->getName() ),
|
|
|
|
|
],
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->executeSpecialPage(
|
|
|
|
|
$target->getName(),
|
|
|
|
|
$request,
|
|
|
|
|
'qqx',
|
|
|
|
|
$performer
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 1, $request->getSession()->get( 'specialUserrightsSaveSuccess' ) );
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
[ 'bot' ],
|
|
|
|
|
$this->getServiceContainer()->getUserGroupManager()->getUserGroups( $target )
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-04 11:21:22 +00:00
|
|
|
public function testSaveUserGroupsForTemporaryAccount() {
|
|
|
|
|
$target = $this->getServiceContainer()->getTempUserCreator()->create( null, new FauxRequest() )->getUser();
|
|
|
|
|
$performer = $this->getTestSysop()->getUser();
|
|
|
|
|
$request = new FauxRequest(
|
|
|
|
|
[
|
|
|
|
|
'saveusergroups' => true,
|
|
|
|
|
'conflictcheck-originalgroups' => '',
|
|
|
|
|
'wpGroup-bot' => true,
|
|
|
|
|
'wpExpiry-bot' => 'existing',
|
|
|
|
|
'wpEditToken' => $performer->getEditToken( $target->getName() ),
|
|
|
|
|
],
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
[ $html ] = $this->executeSpecialPage( $target->getName(), $request, 'qqx', $performer );
|
|
|
|
|
|
|
|
|
|
$this->assertNull( $request->getSession()->get( 'specialUserrightsSaveSuccess' ) );
|
|
|
|
|
$this->assertCount( 0, $this->getServiceContainer()->getUserGroupManager()->getUserGroups( $target ) );
|
|
|
|
|
$this->assertStringContainsString( 'userrights-no-group', $html );
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-26 22:57:37 +00:00
|
|
|
public function testSaveUserGroups_change() {
|
|
|
|
|
$target = $this->getTestUser( [ 'sysop' ] )->getUser();
|
|
|
|
|
$performer = $this->getTestSysop()->getUser();
|
|
|
|
|
$request = new FauxRequest(
|
|
|
|
|
[
|
|
|
|
|
'saveusergroups' => true,
|
|
|
|
|
'conflictcheck-originalgroups' => 'sysop',
|
|
|
|
|
'wpGroup-sysop' => true,
|
|
|
|
|
'wpExpiry-sysop' => 'existing',
|
|
|
|
|
'wpGroup-bot' => true,
|
|
|
|
|
'wpExpiry-bot' => 'existing',
|
|
|
|
|
'wpEditToken' => $performer->getEditToken( $target->getName() ),
|
|
|
|
|
],
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->executeSpecialPage(
|
|
|
|
|
$target->getName(),
|
|
|
|
|
$request,
|
|
|
|
|
'qqx',
|
|
|
|
|
$performer
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 1, $request->getSession()->get( 'specialUserrightsSaveSuccess' ) );
|
2023-10-18 03:47:02 +00:00
|
|
|
$result = $this->getServiceContainer()->getUserGroupManager()->getUserGroups( $target );
|
|
|
|
|
sort( $result );
|
2023-05-26 22:57:37 +00:00
|
|
|
$this->assertSame(
|
|
|
|
|
[ 'bot', 'sysop' ],
|
2023-10-18 03:47:02 +00:00
|
|
|
$result
|
2023-05-26 22:57:37 +00:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testSaveUserGroups_change_expiry() {
|
|
|
|
|
$expiry = wfTimestamp( TS_MW, (int)wfTimestamp( TS_UNIX ) + 100 );
|
|
|
|
|
$target = $this->getTestUser( [ 'bot' ] )->getUser();
|
|
|
|
|
$performer = $this->getTestSysop()->getUser();
|
|
|
|
|
$request = new FauxRequest(
|
|
|
|
|
[
|
|
|
|
|
'saveusergroups' => true,
|
|
|
|
|
'conflictcheck-originalgroups' => 'bot',
|
|
|
|
|
'wpGroup-bot' => true,
|
|
|
|
|
'wpExpiry-bot' => $expiry,
|
|
|
|
|
'wpEditToken' => $performer->getEditToken( $target->getName() ),
|
|
|
|
|
],
|
|
|
|
|
true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->executeSpecialPage(
|
|
|
|
|
$target->getName(),
|
|
|
|
|
$request,
|
|
|
|
|
'qqx',
|
|
|
|
|
$performer
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$this->assertSame( 1, $request->getSession()->get( 'specialUserrightsSaveSuccess' ) );
|
|
|
|
|
$userGroups = $this->getServiceContainer()->getUserGroupManager()->getUserGroupMemberships( $target );
|
|
|
|
|
$this->assertCount( 1, $userGroups );
|
|
|
|
|
foreach ( $userGroups as $ugm ) {
|
|
|
|
|
$this->assertSame( 'bot', $ugm->getGroup() );
|
|
|
|
|
$this->assertSame( $expiry, $ugm->getExpiry() );
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-17 19:05:57 +00:00
|
|
|
|
|
|
|
|
private function getExternalDBname(): ?string {
|
|
|
|
|
$availableDatabases = array_diff(
|
|
|
|
|
$this->getConfVar( MainConfigNames::LocalDatabases ),
|
|
|
|
|
[ WikiMap::getCurrentWikiDbDomain()->getDatabase() ]
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if ( $availableDatabases === [] ) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// sort to ensure results are deterministic
|
|
|
|
|
sort( $availableDatabases );
|
|
|
|
|
return $availableDatabases[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function testInterwikiRightsChange() {
|
|
|
|
|
$externalDBname = $this->getExternalDBname();
|
|
|
|
|
if ( $externalDBname === null ) {
|
|
|
|
|
$this->markTestSkipped( 'No external database is available' );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FIXME: This should not depend on WikiAdmin user existence
|
|
|
|
|
// NOTE: This is here, as in WMF's CI setup, WikiAdmin is the only user
|
|
|
|
|
// guaranteed to exist on the other wiki.
|
|
|
|
|
$localUser = $this->getServiceContainer()->getUserFactory()->newFromName( 'WikiAdmin' );
|
|
|
|
|
|
|
|
|
|
$externalUsername = $localUser->getName() . '@' . $externalDBname;
|
|
|
|
|
|
|
|
|
|
// FIXME: This should benefit from $tablesUsed; until this is possible, purge user_groups on
|
|
|
|
|
// the other wiki.
|
|
|
|
|
$externalDbw = $this->getServiceContainer()
|
2024-01-22 21:27:45 +00:00
|
|
|
->getConnectionProvider()
|
2023-08-17 19:05:57 +00:00
|
|
|
->getPrimaryDatabase( $externalDBname );
|
2024-02-03 01:52:33 +00:00
|
|
|
$externalDbw->truncateTable( 'user_groups', __METHOD__ );
|
2023-08-17 19:05:57 +00:00
|
|
|
|
|
|
|
|
// ensure using SpecialUserRights with external usernames doesn't throw (T342747, T342322)
|
|
|
|
|
$performer = $this->getTestUser( [ 'bureaucrat' ] );
|
|
|
|
|
$request = new FauxRequest( [
|
|
|
|
|
'saveusergroups' => true,
|
|
|
|
|
'conflictcheck-originalgroups' => '',
|
|
|
|
|
'wpGroup-sysop' => true,
|
|
|
|
|
'wpExpiry-sysop' => 'existing',
|
|
|
|
|
'wpEditToken' => $performer->getUser()->getEditToken( $externalUsername ),
|
|
|
|
|
], true );
|
|
|
|
|
[ $html, ] = $this->executeSpecialPage(
|
|
|
|
|
$externalUsername,
|
|
|
|
|
$request,
|
|
|
|
|
null,
|
|
|
|
|
$performer->getAuthority()
|
|
|
|
|
);
|
|
|
|
|
$this->assertSame( 1, $request->getSession()->get( 'specialUserrightsSaveSuccess' ) );
|
|
|
|
|
// ensure logging is done with the right username (T344391)
|
|
|
|
|
$this->assertSame(
|
|
|
|
|
1,
|
|
|
|
|
(int)$this->getDb()->newSelectQueryBuilder()
|
|
|
|
|
->select( [ 'cnt' => 'COUNT(*)' ] )
|
|
|
|
|
->from( 'logging' )
|
|
|
|
|
->where( [
|
|
|
|
|
'log_type' => 'rights',
|
|
|
|
|
'log_action' => 'rights',
|
|
|
|
|
'log_namespace' => NS_USER,
|
|
|
|
|
'log_title' => $externalUsername,
|
|
|
|
|
] )
|
|
|
|
|
->caller( __METHOD__ )
|
|
|
|
|
->fetchField()
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-05-26 22:57:37 +00:00
|
|
|
}
|