MediaWiki  REL1_31
ApiUserrightsTest.php
Go to the documentation of this file.
1 <?php
2 
19  protected function setPermissions( $add = [], $remove = [] ) {
21 
22  $this->setGroupPermissions( 'bureaucrat', 'userrights', false );
23 
24  if ( $add ) {
25  $this->stashMwGlobals( 'wgAddGroups' );
26  $wgAddGroups['bureaucrat'] = $add;
27  }
28  if ( $remove ) {
29  $this->stashMwGlobals( 'wgRemoveGroups' );
30  $wgRemoveGroups['bureaucrat'] = $remove;
31  }
32  }
33 
48  protected function doSuccessfulRightsChange(
49  $expectedGroups = 'sysop', array $params = [], User $user = null
50  ) {
51  $expectedGroups = (array)$expectedGroups;
52  $params['action'] = 'userrights';
53 
54  if ( !$user ) {
55  $user = $this->getMutableTestUser()->getUser();
56  }
57 
58  $this->assertTrue( TestUserRegistry::isMutable( $user ),
59  'Immutable user passed to doSuccessfulRightsChange!' );
60 
61  if ( !isset( $params['user'] ) && !isset( $params['userid'] ) ) {
62  $params['user'] = $user->getName();
63  }
64  if ( !isset( $params['add'] ) && !isset( $params['remove'] ) ) {
65  $params['add'] = 'sysop';
66  }
67 
69 
70  $user->clearInstanceCache();
71  $this->assertSame( $expectedGroups, $user->getGroups() );
72 
73  $this->assertArrayNotHasKey( 'warnings', $res[0] );
74  }
75 
85  protected function doFailedRightsChange(
86  $expectedException, array $params = [], User $user = null
87  ) {
88  $params['action'] = 'userrights';
89 
90  $this->setExpectedException( ApiUsageException::class, $expectedException );
91 
92  if ( !$user ) {
93  // If 'user' or 'userid' is specified and $user was not specified,
94  // the user we're creating now will have nothing to do with the API
95  // request, but that's okay, since we're just testing that it has
96  // no groups.
97  $user = $this->getMutableTestUser()->getUser();
98  }
99 
100  $this->assertTrue( TestUserRegistry::isMutable( $user ),
101  'Immutable user passed to doFailedRightsChange!' );
102 
103  if ( !isset( $params['user'] ) && !isset( $params['userid'] ) ) {
104  $params['user'] = $user->getName();
105  }
106  if ( !isset( $params['add'] ) && !isset( $params['remove'] ) ) {
107  $params['add'] = 'sysop';
108  }
109  $expectedGroups = $user->getGroups();
110 
111  try {
112  $this->doApiRequestWithToken( $params );
113  } finally {
114  $user->clearInstanceCache();
115  $this->assertSame( $expectedGroups, $user->getGroups() );
116  }
117  }
118 
119  public function testAdd() {
120  $this->doSuccessfulRightsChange();
121  }
122 
123  public function testBlockedWithUserrights() {
124  global $wgUser;
125 
126  $block = new Block( [ 'address' => $wgUser, 'by' => $wgUser->getId(), ] );
127  $block->insert();
128 
129  try {
130  $this->doSuccessfulRightsChange();
131  } finally {
132  $block->delete();
133  $wgUser->clearInstanceCache();
134  }
135  }
136 
137  public function testBlockedWithoutUserrights() {
138  $user = $this->getTestSysop()->getUser();
139 
140  $this->setPermissions( true, true );
141 
142  $block = new Block( [ 'address' => $user, 'by' => $user->getId() ] );
143  $block->insert();
144 
145  try {
146  $this->doFailedRightsChange( 'You have been blocked from editing.' );
147  } finally {
148  $block->delete();
149  $user->clearInstanceCache();
150  }
151  }
152 
153  public function testAddMultiple() {
155  [ 'bureaucrat', 'sysop' ],
156  [ 'add' => 'bureaucrat|sysop' ]
157  );
158  }
159 
160  public function testTooFewExpiries() {
161  $this->doFailedRightsChange(
162  '2 expiry timestamps were provided where 3 were needed.',
163  [ 'add' => 'sysop|bureaucrat|bot', 'expiry' => 'infinity|tomorrow' ]
164  );
165  }
166 
167  public function testTooManyExpiries() {
168  $this->doFailedRightsChange(
169  '3 expiry timestamps were provided where 2 were needed.',
170  [ 'add' => 'sysop|bureaucrat', 'expiry' => 'infinity|tomorrow|never' ]
171  );
172  }
173 
174  public function testInvalidExpiry() {
175  $this->doFailedRightsChange( 'Invalid expiry time', [ 'expiry' => 'yummy lollipops!' ] );
176  }
177 
178  public function testMultipleInvalidExpiries() {
179  $this->doFailedRightsChange(
180  'Invalid expiry time "foo".',
181  [ 'add' => 'sysop|bureaucrat', 'expiry' => 'foo|bar' ]
182  );
183  }
184 
185  public function testWithTag() {
186  ChangeTags::defineTag( 'custom tag' );
187 
188  $user = $this->getMutableTestUser()->getUser();
189 
190  $this->doSuccessfulRightsChange( 'sysop', [ 'tags' => 'custom tag' ], $user );
191 
192  $dbr = wfGetDB( DB_REPLICA );
193  $this->assertSame(
194  'custom tag',
195  $dbr->selectField(
196  [ 'change_tag', 'logging' ],
197  'ct_tag',
198  [
199  'ct_log_id = log_id',
200  'log_namespace' => NS_USER,
201  'log_title' => strtr( $user->getName(), ' ', '_' )
202  ],
203  __METHOD__
204  )
205  );
206  }
207 
208  public function testWithoutTagPermission() {
210 
211  ChangeTags::defineTag( 'custom tag' );
212 
213  $this->stashMwGlobals( 'wgGroupPermissions' );
214  $wgGroupPermissions['user']['applychangetags'] = false;
215 
216  $this->doFailedRightsChange(
217  'You do not have permission to apply change tags along with your changes.',
218  [ 'tags' => 'custom tag' ]
219  );
220  }
221 
222  public function testNonexistentUser() {
223  $this->doFailedRightsChange(
224  'There is no user by the name "Nonexistent user". Check your spelling.',
225  [ 'user' => 'Nonexistent user' ]
226  );
227  }
228 
229  public function testWebToken() {
230  $sysop = $this->getTestSysop()->getUser();
231  $user = $this->getMutableTestUser()->getUser();
232 
233  $token = $sysop->getEditToken( $user->getName() );
234 
235  $res = $this->doApiRequest( [
236  'action' => 'userrights',
237  'user' => $user->getName(),
238  'add' => 'sysop',
239  'token' => $token,
240  ] );
241 
242  $user->clearInstanceCache();
243  $this->assertSame( [ 'sysop' ], $user->getGroups() );
244 
245  $this->assertArrayNotHasKey( 'warnings', $res[0] );
246  }
247 
256  private function getMockForProcessingExpiries( $canProcessExpiries ) {
257  $sysop = $this->getTestSysop()->getUser();
258  $user = $this->getMutableTestUser()->getUser();
259 
260  $token = $sysop->getEditToken( 'userrights' );
261 
262  $main = new ApiMain( new FauxRequest( [
263  'action' => 'userrights',
264  'user' => $user->getName(),
265  'add' => 'sysop',
266  'token' => $token,
267  ] ) );
268 
269  $mockUserRightsPage = $this->getMockBuilder( UserrightsPage::class )
270  ->setMethods( [ 'canProcessExpiries' ] )
271  ->getMock();
272  $mockUserRightsPage->method( 'canProcessExpiries' )->willReturn( $canProcessExpiries );
273 
274  $mockApi = $this->getMockBuilder( ApiUserrights::class )
275  ->setConstructorArgs( [ $main, 'userrights' ] )
276  ->setMethods( [ 'getUserRightsPage' ] )
277  ->getMock();
278  $mockApi->method( 'getUserRightsPage' )->willReturn( $mockUserRightsPage );
279 
280  return $mockApi;
281  }
282 
283  public function testCanProcessExpiries() {
284  $mock1 = $this->getMockForProcessingExpiries( true );
285  $this->assertArrayHasKey( 'expiry', $mock1->getAllowedParams() );
286 
287  $mock2 = $this->getMockForProcessingExpiries( false );
288  $this->assertArrayNotHasKey( 'expiry', $mock2->getAllowedParams() );
289  }
290 
300  public function testAddAndRemoveGroups(
301  array $permissions = null, array $groupsToChange, array $expectedGroups
302  ) {
303  if ( $permissions !== null ) {
304  $this->setPermissions( $permissions[0], $permissions[1] );
305  }
306 
307  $params = [
308  'add' => implode( '|', $groupsToChange[0] ),
309  'remove' => implode( '|', $groupsToChange[1] ),
310  ];
311 
312  // We'll take a bot so we have a group to remove
313  $user = $this->getMutableTestUser( [ 'bot' ] )->getUser();
314 
315  $this->doSuccessfulRightsChange( $expectedGroups, $params, $user );
316  }
317 
318  public function addAndRemoveGroupsProvider() {
319  return [
320  'Simple add' => [
321  [ [ 'sysop' ], [] ],
322  [ [ 'sysop' ], [] ],
323  [ 'bot', 'sysop' ]
324  ], 'Add with only remove permission' => [
325  [ [], [ 'sysop' ] ],
326  [ [ 'sysop' ], [] ],
327  [ 'bot' ],
328  ], 'Add with global remove permission' => [
329  [ [], true ],
330  [ [ 'sysop' ], [] ],
331  [ 'bot' ],
332  ], 'Simple remove' => [
333  [ [], [ 'bot' ] ],
334  [ [], [ 'bot' ] ],
335  [],
336  ], 'Remove with only add permission' => [
337  [ [ 'bot' ], [] ],
338  [ [], [ 'bot' ] ],
339  [ 'bot' ],
340  ], 'Remove with global add permission' => [
341  [ true, [] ],
342  [ [], [ 'bot' ] ],
343  [ 'bot' ],
344  ], 'Add and remove same new group' => [
345  null,
346  [ [ 'sysop' ], [ 'sysop' ] ],
347  // The userrights code does removals before adds, so it doesn't remove the sysop
348  // group here and only adds it.
349  [ 'bot', 'sysop' ],
350  ], 'Add and remove same existing group' => [
351  null,
352  [ [ 'bot' ], [ 'bot' ] ],
353  // But here it first removes the existing group and then re-adds it.
354  [ 'bot' ],
355  ],
356  ];
357  }
358 }
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:247
ApiMain
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:43
$wgUser
$wgUser
Definition: Setup.php:902
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: FauxRequest.php:33
MediaWikiTestCase\stashMwGlobals
stashMwGlobals( $globalKeys)
Stashes the global, will be restored in tearDown()
Definition: MediaWikiTestCase.php:730
ApiUserrightsTest\testAddAndRemoveGroups
testAddAndRemoveGroups(array $permissions=null, array $groupsToChange, array $expectedGroups)
Tests adding and removing various groups with various permissions.
Definition: ApiUserrightsTest.php:300
ApiUserrightsTest\testAdd
testAdd()
Definition: ApiUserrightsTest.php:119
array
the array() calling protocol came about after MediaWiki 1.4rc1.
ApiUserrightsTest\testNonexistentUser
testNonexistentUser()
Definition: ApiUserrightsTest.php:222
ApiUserrightsTest\doSuccessfulRightsChange
doSuccessfulRightsChange( $expectedGroups='sysop', array $params=[], User $user=null)
Perform an API userrights request that's expected to be successful.
Definition: ApiUserrightsTest.php:48
$params
$params
Definition: styleTest.css.php:40
ApiUserrightsTest\testWebToken
testWebToken()
Definition: ApiUserrightsTest.php:229
$res
$res
Definition: database.txt:21
ApiUserrightsTest\testCanProcessExpiries
testCanProcessExpiries()
Definition: ApiUserrightsTest.php:283
true
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return true
Definition: hooks.txt:2006
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:37
ApiUserrightsTest\testTooFewExpiries
testTooFewExpiries()
Definition: ApiUserrightsTest.php:160
$dbr
$dbr
Definition: testCompression.php:50
TestUserRegistry\isMutable
static isMutable(User $user)
Definition: TestUserRegistry.php:117
ApiTestCase\doApiRequest
doApiRequest(array $params, array $session=null, $appendModule=false, User $user=null, $tokenType=null)
Does the API request and returns the result.
Definition: ApiTestCase.php:100
wfGetDB
wfGetDB( $db, $groups=[], $wiki=false)
Get a Database object.
Definition: GlobalFunctions.php:2812
ApiUserrightsTest\testInvalidExpiry
testInvalidExpiry()
Definition: ApiUserrightsTest.php:174
ApiTestCase\doApiRequestWithToken
doApiRequestWithToken(array $params, array $session=null, User $user=null, $tokenType='auto')
Convenience function to access the token parameter of doApiRequest() more succinctly.
Definition: ApiTestCase.php:170
ChangeTags\defineTag
static defineTag( $tag)
Defines a tag in the valid_tag table, without checking that the tag name is valid.
Definition: ChangeTags.php:825
global
when a variable name is used in a it is silently declared as a new masking the global
Definition: design.txt:95
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
$wgRemoveGroups
$wgRemoveGroups
Definition: DefaultSettings.php:5518
ApiUserrightsTest\testTooManyExpiries
testTooManyExpiries()
Definition: ApiUserrightsTest.php:167
ApiUserrightsTest\testMultipleInvalidExpiries
testMultipleInvalidExpiries()
Definition: ApiUserrightsTest.php:178
ApiUserrightsTest\addAndRemoveGroupsProvider
addAndRemoveGroupsProvider()
Definition: ApiUserrightsTest.php:318
ApiUserrightsTest
API Database medium.
Definition: ApiUserrightsTest.php:10
ApiUserrightsTest\testBlockedWithoutUserrights
testBlockedWithoutUserrights()
Definition: ApiUserrightsTest.php:137
ApiTestCase
Definition: ApiTestCase.php:5
MediaWikiTestCase\getMutableTestUser
static getMutableTestUser( $groups=[])
Convenience method for getting a mutable test user.
Definition: MediaWikiTestCase.php:165
MediaWikiTestCase\getTestSysop
static getTestSysop()
Convenience method for getting an immutable admin test user.
Definition: MediaWikiTestCase.php:177
ApiUserrightsTest\setPermissions
setPermissions( $add=[], $remove=[])
Unsets $wgGroupPermissions['bureaucrat']['userrights'], and sets $wgAddGroups['bureaucrat'] and $wgRe...
Definition: ApiUserrightsTest.php:19
$wgAddGroups
$wgAddGroups
$wgAddGroups and $wgRemoveGroups can be used to give finer control over who can assign which groups a...
Definition: DefaultSettings.php:5513
MediaWikiTestCase\setGroupPermissions
setGroupPermissions( $newPerms, $newKey=null, $newValue=null)
Alters $wgGroupPermissions for the duration of the test.
Definition: MediaWikiTestCase.php:920
ApiUserrightsTest\doFailedRightsChange
doFailedRightsChange( $expectedException, array $params=[], User $user=null)
Perform an API userrights request that's expected to fail.
Definition: ApiUserrightsTest.php:85
ApiUserrightsTest\testWithTag
testWithTag()
Definition: ApiUserrightsTest.php:185
$wgGroupPermissions
$wgGroupPermissions
Permission keys given to users in each group.
Definition: DefaultSettings.php:5123
Block
Definition: Block.php:27
NS_USER
const NS_USER
Definition: Defines.php:76
class
you have access to all of the normal MediaWiki so you can get a DB use the etc For full docs on the Maintenance class
Definition: maintenance.txt:56
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:53
ApiUserrightsTest\testBlockedWithUserrights
testBlockedWithUserrights()
Definition: ApiUserrightsTest.php:123
ApiUserrightsTest\testWithoutTagPermission
testWithoutTagPermission()
Definition: ApiUserrightsTest.php:208
ApiUserrightsTest\getMockForProcessingExpiries
getMockForProcessingExpiries( $canProcessExpiries)
Helper for testCanProcessExpiries that returns a mock ApiUserrights that either can or cannot process...
Definition: ApiUserrightsTest.php:256
ApiUserrightsTest\testAddMultiple
testAddMultiple()
Definition: ApiUserrightsTest.php:153