3 use MediaWiki\MainConfigNames
;
4 use MediaWiki\Request\FauxRequest
;
5 use MediaWiki\Specials\SpecialUserRights
;
6 use MediaWiki\Tests\User\TempUser\TempUserTestTrait
;
7 use MediaWiki\User\UserIdentityValue
;
8 use MediaWiki\WikiMap\WikiMap
;
12 * @covers \MediaWiki\Specials\SpecialUserRights
14 class SpecialUserRightsTest
extends SpecialPageTestBase
{
16 use TempUserTestTrait
;
21 protected function newSpecialPage() {
22 $services = $this->getServiceContainer();
23 return new SpecialUserRights(
24 $services->getUserGroupManagerFactory(),
25 $services->getUserNameUtils(),
26 $services->getUserNamePrefixSearch(),
27 $services->getUserFactory(),
28 $services->getActorStoreFactory(),
29 $services->getWatchlistManager(),
30 $services->getTempUserConfig()
34 /** @dataProvider provideUserCanChangeRights */
35 public function testUserCanChangeRights( $targetUser, $checkIfSelf, $expectedReturnValue ) {
36 $objectUnderTest = $this->newSpecialPage();
37 $this->assertSame( $expectedReturnValue, $objectUnderTest->userCanChangeRights( $targetUser, $checkIfSelf ) );
40 public static function provideUserCanChangeRights() {
42 'Target user not registered' => [ UserIdentityValue
::newAnonymous( 'Test' ), true, false ],
46 public function testUserCanChangeRightsForTemporaryAccount() {
47 $temporaryAccount = $this->getServiceContainer()->getTempUserCreator()
48 ->create( null, new FauxRequest() )->getUser();
49 $this->testUserCanChangeRights( $temporaryAccount, false, false );
52 public function testSaveUserGroups() {
53 $target = $this->getTestUser()->getUser();
54 $performer = $this->getTestSysop()->getUser();
55 $request = new FauxRequest(
57 'saveusergroups' => true,
58 'conflictcheck-originalgroups' => '',
59 'wpGroup-bot' => true,
60 'wpExpiry-bot' => 'existing',
61 'wpEditToken' => $performer->getEditToken( $target->getName() ),
66 $this->executeSpecialPage(
73 $this->assertSame( 1, $request->getSession()->get( 'specialUserrightsSaveSuccess' ) );
76 $this->getServiceContainer()->getUserGroupManager()->getUserGroups( $target )
80 public function testSaveUserGroupsForTemporaryAccount() {
81 $target = $this->getServiceContainer()->getTempUserCreator()->create( null, new FauxRequest() )->getUser();
82 $performer = $this->getTestSysop()->getUser();
83 $request = new FauxRequest(
85 'saveusergroups' => true,
86 'conflictcheck-originalgroups' => '',
87 'wpGroup-bot' => true,
88 'wpExpiry-bot' => 'existing',
89 'wpEditToken' => $performer->getEditToken( $target->getName() ),
94 [ $html ] = $this->executeSpecialPage( $target->getName(), $request, 'qqx', $performer );
96 $this->assertNull( $request->getSession()->get( 'specialUserrightsSaveSuccess' ) );
97 $this->assertCount( 0, $this->getServiceContainer()->getUserGroupManager()->getUserGroups( $target ) );
98 $this->assertStringContainsString( 'userrights-no-group', $html );
101 public function testSaveUserGroups_change() {
102 $target = $this->getTestUser( [ 'sysop' ] )->getUser();
103 $performer = $this->getTestSysop()->getUser();
104 $request = new FauxRequest(
106 'saveusergroups' => true,
107 'conflictcheck-originalgroups' => 'sysop',
108 'wpGroup-sysop' => true,
109 'wpExpiry-sysop' => 'existing',
110 'wpGroup-bot' => true,
111 'wpExpiry-bot' => 'existing',
112 'wpEditToken' => $performer->getEditToken( $target->getName() ),
117 $this->executeSpecialPage(
124 $this->assertSame( 1, $request->getSession()->get( 'specialUserrightsSaveSuccess' ) );
125 $result = $this->getServiceContainer()->getUserGroupManager()->getUserGroups( $target );
133 public function testSaveUserGroups_change_expiry() {
134 $expiry = wfTimestamp( TS_MW
, (int)wfTimestamp( TS_UNIX
) +
100 );
135 $target = $this->getTestUser( [ 'bot' ] )->getUser();
136 $performer = $this->getTestSysop()->getUser();
137 $request = new FauxRequest(
139 'saveusergroups' => true,
140 'conflictcheck-originalgroups' => 'bot',
141 'wpGroup-bot' => true,
142 'wpExpiry-bot' => $expiry,
143 'wpEditToken' => $performer->getEditToken( $target->getName() ),
148 $this->executeSpecialPage(
155 $this->assertSame( 1, $request->getSession()->get( 'specialUserrightsSaveSuccess' ) );
156 $userGroups = $this->getServiceContainer()->getUserGroupManager()->getUserGroupMemberships( $target );
157 $this->assertCount( 1, $userGroups );
158 foreach ( $userGroups as $ugm ) {
159 $this->assertSame( 'bot', $ugm->getGroup() );
160 $this->assertSame( $expiry, $ugm->getExpiry() );
164 private function getExternalDBname(): ?
string {
165 $availableDatabases = array_diff(
166 $this->getConfVar( MainConfigNames
::LocalDatabases
),
167 [ WikiMap
::getCurrentWikiDbDomain()->getDatabase() ]
170 if ( $availableDatabases === [] ) {
174 // sort to ensure results are deterministic
175 sort( $availableDatabases );
176 return $availableDatabases[0];
179 public function testInterwikiRightsChange() {
180 $externalDBname = $this->getExternalDBname();
181 if ( $externalDBname === null ) {
182 $this->markTestSkipped( 'No external database is available' );
185 // FIXME: This should not depend on WikiAdmin user existence
186 // NOTE: This is here, as in WMF's CI setup, WikiAdmin is the only user
187 // guaranteed to exist on the other wiki.
188 $localUser = $this->getServiceContainer()->getUserFactory()->newFromName( 'WikiAdmin' );
190 $externalUsername = $localUser->getName() . '@' . $externalDBname;
192 // FIXME: This should benefit from $tablesUsed; until this is possible, purge user_groups on
194 $externalDbw = $this->getServiceContainer()
195 ->getConnectionProvider()
196 ->getPrimaryDatabase( $externalDBname );
197 $externalDbw->truncateTable( 'user_groups', __METHOD__
);
199 // ensure using SpecialUserRights with external usernames doesn't throw (T342747, T342322)
200 $performer = $this->getTestUser( [ 'bureaucrat' ] );
201 $request = new FauxRequest( [
202 'saveusergroups' => true,
203 'conflictcheck-originalgroups' => '',
204 'wpGroup-sysop' => true,
205 'wpExpiry-sysop' => 'existing',
206 'wpEditToken' => $performer->getUser()->getEditToken( $externalUsername ),
208 [ $html, ] = $this->executeSpecialPage(
212 $performer->getAuthority()
214 $this->assertSame( 1, $request->getSession()->get( 'specialUserrightsSaveSuccess' ) );
215 // ensure logging is done with the right username (T344391)
218 (int)$this->getDb()->newSelectQueryBuilder()
219 ->select( [ 'cnt' => 'COUNT(*)' ] )
222 'log_type' => 'rights',
223 'log_action' => 'rights',
224 'log_namespace' => NS_USER
,
225 'log_title' => $externalUsername,
227 ->caller( __METHOD__
)