Services: Convert PermissionManager's static to a const now HHVM is gone
[lhc/web/wiklou.git] / tests / phpunit / includes / Permissions / PermissionManagerTest.php
1 <?php
2
3 namespace MediaWiki\Tests\Permissions;
4
5 use Action;
6 use ContentHandler;
7 use FauxRequest;
8 use LoggedServiceOptions;
9 use MediaWiki\Block\DatabaseBlock;
10 use MediaWiki\Block\Restriction\NamespaceRestriction;
11 use MediaWiki\Block\Restriction\PageRestriction;
12 use MediaWiki\Block\SystemBlock;
13 use MediaWiki\Linker\LinkTarget;
14 use MediaWiki\MediaWikiServices;
15 use MediaWiki\Permissions\PermissionManager;
16 use MediaWiki\Revision\MutableRevisionRecord;
17 use MediaWiki\Revision\RevisionLookup;
18 use MWException;
19 use TestAllServiceOptionsUsed;
20 use Wikimedia\ScopedCallback;
21 use MediaWiki\Session\SessionId;
22 use MediaWiki\Session\TestUtils;
23 use MediaWikiLangTestCase;
24 use RequestContext;
25 use stdClass;
26 use Title;
27 use User;
28 use Wikimedia\TestingAccessWrapper;
29
30 /**
31 * @group Database
32 *
33 * @covers \MediaWiki\Permissions\PermissionManager
34 */
35 class PermissionManagerTest extends MediaWikiLangTestCase {
36 use TestAllServiceOptionsUsed;
37
38 /**
39 * @var string
40 */
41 protected $userName, $altUserName;
42
43 /**
44 * @var Title
45 */
46 protected $title;
47
48 /**
49 * @var User
50 */
51 protected $user, $anonUser, $userUser, $altUser;
52
53 /** Constant for self::testIsBlockedFrom */
54 const USER_TALK_PAGE = '<user talk page>';
55
56 protected function setUp() {
57 parent::setUp();
58
59 $localZone = 'UTC';
60 $localOffset = date( 'Z' ) / 60;
61
62 $this->setMwGlobals( [
63 'wgLocaltimezone' => $localZone,
64 'wgLocalTZoffset' => $localOffset,
65 'wgNamespaceProtection' => [
66 NS_MEDIAWIKI => 'editinterface',
67 ],
68 'wgRevokePermissions' => [
69 'formertesters' => [
70 'runtest' => true
71 ]
72 ],
73 'wgAvailableRights' => [
74 'test',
75 'runtest',
76 'writetest',
77 'nukeworld',
78 'modifytest',
79 'editmyoptions'
80 ]
81 ] );
82
83 $this->setGroupPermissions( 'unittesters', 'test', true );
84 $this->setGroupPermissions( 'unittesters', 'runtest', true );
85 $this->setGroupPermissions( 'unittesters', 'writetest', false );
86 $this->setGroupPermissions( 'unittesters', 'nukeworld', false );
87
88 $this->setGroupPermissions( 'testwriters', 'test', true );
89 $this->setGroupPermissions( 'testwriters', 'writetest', true );
90 $this->setGroupPermissions( 'testwriters', 'modifytest', true );
91
92 $this->setGroupPermissions( '*', 'editmyoptions', true );
93
94 // Without this testUserBlock will use a non-English context on non-English MediaWiki
95 // installations (because of how Title::checkUserBlock is implemented) and fail.
96 RequestContext::resetMain();
97
98 $this->userName = 'Useruser';
99 $this->altUserName = 'Altuseruser';
100 date_default_timezone_set( $localZone );
101
102 $this->title = Title::makeTitle( NS_MAIN, "Main Page" );
103 if ( !isset( $this->userUser ) || !( $this->userUser instanceof User ) ) {
104 $this->userUser = User::newFromName( $this->userName );
105
106 if ( !$this->userUser->getId() ) {
107 $this->userUser = User::createNew( $this->userName, [
108 "email" => "test@example.com",
109 "real_name" => "Test User" ] );
110 $this->userUser->load();
111 }
112
113 $this->altUser = User::newFromName( $this->altUserName );
114 if ( !$this->altUser->getId() ) {
115 $this->altUser = User::createNew( $this->altUserName, [
116 "email" => "alttest@example.com",
117 "real_name" => "Test User Alt" ] );
118 $this->altUser->load();
119 }
120
121 $this->anonUser = User::newFromId( 0 );
122
123 $this->user = $this->userUser;
124 }
125 }
126
127 public function tearDown() {
128 parent::tearDown();
129 $this->restoreMwServices();
130 }
131
132 protected function setTitle( $ns, $title = "Main_Page" ) {
133 $this->title = Title::makeTitle( $ns, $title );
134 }
135
136 protected function setUser( $userName = null ) {
137 if ( $userName === 'anon' ) {
138 $this->user = $this->anonUser;
139 } elseif ( $userName === null || $userName === $this->userName ) {
140 $this->user = $this->userUser;
141 } else {
142 $this->user = $this->altUser;
143 }
144 }
145
146 /**
147 * @todo This test method should be split up into separate test methods and
148 * data providers
149 *
150 * This test is failing per T201776.
151 *
152 * @group Broken
153 * @covers \MediaWiki\Permissions\PermissionManager::checkQuickPermissions
154 */
155 public function testQuickPermissions() {
156 $prefix = MediaWikiServices::getInstance()->getContentLanguage()->
157 getFormattedNsText( NS_PROJECT );
158
159 $this->setUser( 'anon' );
160 $this->setTitle( NS_TALK );
161 $this->overrideUserPermissions( $this->user, "createtalk" );
162 $res = MediaWikiServices::getInstance()->getPermissionManager()
163 ->getPermissionErrors( 'create', $this->user, $this->title );
164 $this->assertEquals( [], $res );
165
166 $this->setTitle( NS_TALK );
167 $this->overrideUserPermissions( $this->user, "createpage" );
168 $res = MediaWikiServices::getInstance()->getPermissionManager()
169 ->getPermissionErrors( 'create', $this->user, $this->title );
170 $this->assertEquals( [ [ "nocreatetext" ] ], $res );
171
172 $this->setTitle( NS_TALK );
173 $this->overrideUserPermissions( $this->user, "" );
174 $res = MediaWikiServices::getInstance()->getPermissionManager()
175 ->getPermissionErrors( 'create', $this->user, $this->title );
176 $this->assertEquals( [ [ 'nocreatetext' ] ], $res );
177
178 $this->setTitle( NS_MAIN );
179 $this->overrideUserPermissions( $this->user, "createpage" );
180 $res = MediaWikiServices::getInstance()->getPermissionManager()
181 ->getPermissionErrors( 'create', $this->user, $this->title );
182 $this->assertEquals( [], $res );
183
184 $this->setTitle( NS_MAIN );
185 $this->overrideUserPermissions( $this->user, "createtalk" );
186 $res = MediaWikiServices::getInstance()->getPermissionManager()
187 ->getPermissionErrors( 'create', $this->user, $this->title );
188 $this->assertEquals( [ [ 'nocreatetext' ] ], $res );
189
190 $this->setUser( $this->userName );
191 $this->setTitle( NS_TALK );
192 $this->overrideUserPermissions( $this->user, "createtalk" );
193 $res = MediaWikiServices::getInstance()->getPermissionManager()
194 ->getPermissionErrors( 'create', $this->user, $this->title );
195 $this->assertEquals( [], $res );
196
197 $this->setTitle( NS_TALK );
198 $this->overrideUserPermissions( $this->user, "createpage" );
199 $res = MediaWikiServices::getInstance()->getPermissionManager()
200 ->getPermissionErrors( 'create', $this->user, $this->title );
201 $this->assertEquals( [ [ 'nocreate-loggedin' ] ], $res );
202
203 $this->setTitle( NS_TALK );
204 $this->overrideUserPermissions( $this->user, "" );
205 $res = MediaWikiServices::getInstance()->getPermissionManager()
206 ->getPermissionErrors( 'create', $this->user, $this->title );
207 $this->assertEquals( [ [ 'nocreate-loggedin' ] ], $res );
208
209 $this->setTitle( NS_MAIN );
210 $this->overrideUserPermissions( $this->user, "createpage" );
211 $res = MediaWikiServices::getInstance()->getPermissionManager()
212 ->getPermissionErrors( 'create', $this->user, $this->title );
213 $this->assertEquals( [], $res );
214
215 $this->setTitle( NS_MAIN );
216 $this->overrideUserPermissions( $this->user, "createtalk" );
217 $res = MediaWikiServices::getInstance()->getPermissionManager()
218 ->getPermissionErrors( 'create', $this->user, $this->title );
219 $this->assertEquals( [ [ 'nocreate-loggedin' ] ], $res );
220
221 $this->setTitle( NS_MAIN );
222 $this->overrideUserPermissions( $this->user, "" );
223 $res = MediaWikiServices::getInstance()->getPermissionManager()
224 ->getPermissionErrors( 'create', $this->user, $this->title );
225 $this->assertEquals( [ [ 'nocreate-loggedin' ] ], $res );
226
227 $this->setUser( 'anon' );
228 $this->setTitle( NS_USER, $this->userName . '' );
229 $this->overrideUserPermissions( $this->user, "" );
230 $res = MediaWikiServices::getInstance()->getPermissionManager()
231 ->getPermissionErrors( 'move', $this->user, $this->title );
232 $this->assertEquals( [ [ 'cant-move-user-page' ], [ 'movenologintext' ] ], $res );
233
234 $this->setTitle( NS_USER, $this->userName . '/subpage' );
235 $this->overrideUserPermissions( $this->user, "" );
236 $res = MediaWikiServices::getInstance()->getPermissionManager()
237 ->getPermissionErrors( 'move', $this->user, $this->title );
238 $this->assertEquals( [ [ 'movenologintext' ] ], $res );
239
240 $this->setTitle( NS_USER, $this->userName . '' );
241 $this->overrideUserPermissions( $this->user, "move-rootuserpages" );
242 $res = MediaWikiServices::getInstance()->getPermissionManager()
243 ->getPermissionErrors( 'move', $this->user, $this->title );
244 $this->assertEquals( [ [ 'movenologintext' ] ], $res );
245
246 $this->setTitle( NS_USER, $this->userName . '/subpage' );
247 $this->overrideUserPermissions( $this->user, "move-rootuserpages" );
248 $res = MediaWikiServices::getInstance()->getPermissionManager()
249 ->getPermissionErrors( 'move', $this->user, $this->title );
250 $this->assertEquals( [ [ 'movenologintext' ] ], $res );
251
252 $this->setTitle( NS_USER, $this->userName . '' );
253 $this->overrideUserPermissions( $this->user, "" );
254 $res = MediaWikiServices::getInstance()->getPermissionManager()
255 ->getPermissionErrors( 'move', $this->user, $this->title );
256 $this->assertEquals( [ [ 'cant-move-user-page' ], [ 'movenologintext' ] ], $res );
257
258 $this->setTitle( NS_USER, $this->userName . '/subpage' );
259 $this->overrideUserPermissions( $this->user, "" );
260 $res = MediaWikiServices::getInstance()->getPermissionManager()
261 ->getPermissionErrors( 'move', $this->user, $this->title );
262 $this->assertEquals( [ [ 'movenologintext' ] ], $res );
263
264 $this->setTitle( NS_USER, $this->userName . '' );
265 $this->overrideUserPermissions( $this->user, "move-rootuserpages" );
266 $res = MediaWikiServices::getInstance()->getPermissionManager()
267 ->getPermissionErrors( 'move', $this->user, $this->title );
268 $this->assertEquals( [ [ 'movenologintext' ] ], $res );
269
270 $this->setTitle( NS_USER, $this->userName . '/subpage' );
271 $this->overrideUserPermissions( $this->user, "move-rootuserpages" );
272 $res = MediaWikiServices::getInstance()->getPermissionManager()
273 ->getPermissionErrors( 'move', $this->user, $this->title );
274 $this->assertEquals( [ [ 'movenologintext' ] ], $res );
275
276 $this->setUser( $this->userName );
277 $this->setTitle( NS_FILE, "img.png" );
278 $this->overrideUserPermissions( $this->user, "" );
279 $res = MediaWikiServices::getInstance()->getPermissionManager()
280 ->getPermissionErrors( 'move', $this->user, $this->title );
281 $this->assertEquals( [ [ 'movenotallowedfile' ], [ 'movenotallowed' ] ], $res );
282
283 $this->setTitle( NS_FILE, "img.png" );
284 $this->overrideUserPermissions( $this->user, "movefile" );
285 $res = MediaWikiServices::getInstance()->getPermissionManager()
286 ->getPermissionErrors( 'move', $this->user, $this->title );
287 $this->assertEquals( [ [ 'movenotallowed' ] ], $res );
288
289 $this->setUser( 'anon' );
290 $this->setTitle( NS_FILE, "img.png" );
291 $this->overrideUserPermissions( $this->user, "" );
292 $res = MediaWikiServices::getInstance()->getPermissionManager()
293 ->getPermissionErrors( 'move', $this->user, $this->title );
294 $this->assertEquals( [ [ 'movenotallowedfile' ], [ 'movenologintext' ] ], $res );
295
296 $this->setTitle( NS_FILE, "img.png" );
297 $this->overrideUserPermissions( $this->user, "movefile" );
298 $res = MediaWikiServices::getInstance()->getPermissionManager()
299 ->getPermissionErrors( 'move', $this->user, $this->title );
300 $this->assertEquals( [ [ 'movenologintext' ] ], $res );
301
302 $this->setUser( $this->userName );
303 // $this->setUserPerm( "move" );
304 $this->runGroupPermissions( 'move', 'move', [ [ 'movenotallowedfile' ] ] );
305
306 // $this->setUserPerm( "" );
307 $this->runGroupPermissions(
308 '',
309 'move',
310 [ [ 'movenotallowedfile' ], [ 'movenotallowed' ] ]
311 );
312
313 $this->setUser( 'anon' );
314 //$this->setUserPerm( "move" );
315 $this->runGroupPermissions( 'move', 'move', [ [ 'movenotallowedfile' ] ] );
316
317 // $this->setUserPerm( "" );
318 $this->runGroupPermissions(
319 '',
320 'move',
321 [ [ 'movenotallowedfile' ], [ 'movenotallowed' ] ],
322 [ [ 'movenotallowedfile' ], [ 'movenologintext' ] ]
323 );
324
325 if ( $this->isWikitextNS( NS_MAIN ) ) {
326 // NOTE: some content models don't allow moving
327 // @todo find a Wikitext namespace for testing
328
329 $this->setTitle( NS_MAIN );
330 $this->setUser( 'anon' );
331 // $this->setUserPerm( "move" );
332 $this->runGroupPermissions( 'move', 'move', [] );
333
334 // $this->setUserPerm( "" );
335 $this->runGroupPermissions( '', 'move', [ [ 'movenotallowed' ] ],
336 [ [ 'movenologintext' ] ] );
337
338 $this->setUser( $this->userName );
339 // $this->setUserPerm( "" );
340 $this->runGroupPermissions( '', 'move', [ [ 'movenotallowed' ] ] );
341
342 //$this->setUserPerm( "move" );
343 $this->runGroupPermissions( 'move', 'move', [] );
344
345 $this->setUser( 'anon' );
346 $this->overrideUserPermissions( $this->user, 'move' );
347 $res = MediaWikiServices::getInstance()->getPermissionManager()
348 ->getPermissionErrors( 'move-target', $this->user, $this->title );
349 $this->assertEquals( [], $res );
350
351 $this->overrideUserPermissions( $this->user, '' );
352 $res = MediaWikiServices::getInstance()->getPermissionManager()
353 ->getPermissionErrors( 'move-target', $this->user, $this->title );
354 $this->assertEquals( [ [ 'movenotallowed' ] ], $res );
355 }
356
357 $this->setTitle( NS_USER );
358 $this->setUser( $this->userName );
359 $this->overrideUserPermissions( $this->user, [ "move", "move-rootuserpages" ] );
360 $res = MediaWikiServices::getInstance()->getPermissionManager()
361 ->getPermissionErrors( 'move-target', $this->user, $this->title );
362 $this->assertEquals( [], $res );
363
364 $this->overrideUserPermissions( $this->user, "move" );
365 $res = MediaWikiServices::getInstance()->getPermissionManager()
366 ->getPermissionErrors( 'move-target', $this->user, $this->title );
367 $this->assertEquals( [ [ 'cant-move-to-user-page' ] ], $res );
368
369 $this->setUser( 'anon' );
370 $this->overrideUserPermissions( $this->user, [ "move", "move-rootuserpages" ] );
371 $res = MediaWikiServices::getInstance()->getPermissionManager()
372 ->getPermissionErrors( 'move-target', $this->user, $this->title );
373 $this->assertEquals( [], $res );
374
375 $this->setTitle( NS_USER, "User/subpage" );
376 $this->overrideUserPermissions( $this->user, [ "move", "move-rootuserpages" ] );
377 $res = MediaWikiServices::getInstance()->getPermissionManager()
378 ->getPermissionErrors( 'move-target', $this->user, $this->title );
379 $this->assertEquals( [], $res );
380
381 $this->overrideUserPermissions( $this->user, "move" );
382 $res = MediaWikiServices::getInstance()->getPermissionManager()
383 ->getPermissionErrors( 'move-target', $this->user, $this->title );
384 $this->assertEquals( [], $res );
385
386 $this->setUser( 'anon' );
387 $check = [
388 'edit' => [
389 [ [ 'badaccess-groups', "*, [[$prefix:Users|Users]]", 2 ] ],
390 [ [ 'badaccess-group0' ] ],
391 [],
392 true
393 ],
394 'protect' => [
395 [ [
396 'badaccess-groups',
397 "[[$prefix:Administrators|Administrators]]", 1 ],
398 [ 'protect-cantedit'
399 ] ],
400 [ [ 'badaccess-group0' ], [ 'protect-cantedit' ] ],
401 [ [ 'protect-cantedit' ] ],
402 false
403 ],
404 '' => [ [], [], [], true ]
405 ];
406
407 foreach ( [ "edit", "protect", "" ] as $action ) {
408 $this->overrideUserPermissions( $this->user );
409 $this->assertEquals( $check[$action][0],
410 MediaWikiServices::getInstance()->getPermissionManager()
411 ->getPermissionErrors( $action, $this->user, $this->title, true ) );
412 $this->assertEquals( $check[$action][0],
413 MediaWikiServices::getInstance()->getPermissionManager()
414 ->getPermissionErrors( $action, $this->user, $this->title, 'full' ) );
415 $this->assertEquals( $check[$action][0],
416 MediaWikiServices::getInstance()->getPermissionManager()
417 ->getPermissionErrors( $action, $this->user, $this->title, 'secure' ) );
418
419 global $wgGroupPermissions;
420 $old = $wgGroupPermissions;
421 $this->setMwGlobals( 'wgGroupPermissions', [] );
422
423 $this->assertEquals( $check[$action][1],
424 MediaWikiServices::getInstance()->getPermissionManager()
425 ->getPermissionErrors( $action, $this->user, $this->title, true ) );
426 $this->assertEquals( $check[$action][1],
427 MediaWikiServices::getInstance()->getPermissionManager()
428 ->getPermissionErrors( $action, $this->user, $this->title, 'full' ) );
429 $this->assertEquals( $check[$action][1],
430 MediaWikiServices::getInstance()->getPermissionManager()
431 ->getPermissionErrors( $action, $this->user, $this->title, 'secure' ) );
432 $this->setMwGlobals( 'wgGroupPermissions', $old );
433
434 $this->overrideUserPermissions( $this->user, $action );
435 $this->assertEquals( $check[$action][2],
436 MediaWikiServices::getInstance()->getPermissionManager()
437 ->getPermissionErrors( $action, $this->user, $this->title, true ) );
438 $this->assertEquals( $check[$action][2],
439 MediaWikiServices::getInstance()->getPermissionManager()
440 ->getPermissionErrors( $action, $this->user, $this->title, 'full' ) );
441 $this->assertEquals( $check[$action][2],
442 MediaWikiServices::getInstance()->getPermissionManager()
443 ->getPermissionErrors( $action, $this->user, $this->title, 'secure' ) );
444
445 $this->overrideUserPermissions( $this->user, $action );
446 $this->assertEquals( $check[$action][3],
447 MediaWikiServices::getInstance()->getPermissionManager()
448 ->userCan( $action, $this->user, $this->title, true ) );
449 $this->assertEquals( $check[$action][3],
450 MediaWikiServices::getInstance()->getPermissionManager()
451 ->quickUserCan( $action, $this->user, $this->title ) );
452 # count( User::getGroupsWithPermissions( $action ) ) < 1
453 }
454 }
455
456 protected function runGroupPermissions( $perm, $action, $result, $result2 = null ) {
457 if ( $result2 === null ) {
458 $result2 = $result;
459 }
460
461 $this->setGroupPermissions( 'autoconfirmed', 'move', false );
462 $this->setGroupPermissions( 'user', 'move', false );
463 $this->overrideUserPermissions( $this->user, $perm );
464 $res = MediaWikiServices::getInstance()->getPermissionManager()
465 ->getPermissionErrors( $action, $this->user, $this->title );
466 $this->assertEquals( $result, $res );
467
468 $this->setGroupPermissions( 'autoconfirmed', 'move', true );
469 $this->setGroupPermissions( 'user', 'move', false );
470 $this->overrideUserPermissions( $this->user, $perm );
471 $res = MediaWikiServices::getInstance()->getPermissionManager()
472 ->getPermissionErrors( $action, $this->user, $this->title );
473 $this->assertEquals( $result2, $res );
474
475 $this->setGroupPermissions( 'autoconfirmed', 'move', true );
476 $this->setGroupPermissions( 'user', 'move', true );
477 $this->overrideUserPermissions( $this->user, $perm );
478 $res = MediaWikiServices::getInstance()->getPermissionManager()
479 ->getPermissionErrors( $action, $this->user, $this->title );
480 $this->assertEquals( $result2, $res );
481
482 $this->setGroupPermissions( 'autoconfirmed', 'move', false );
483 $this->setGroupPermissions( 'user', 'move', true );
484 $this->overrideUserPermissions( $this->user, $perm );
485 $res = MediaWikiServices::getInstance()->getPermissionManager()
486 ->getPermissionErrors( $action, $this->user, $this->title );
487 $this->assertEquals( $result2, $res );
488 }
489
490 /**
491 * @todo This test method should be split up into separate test methods and
492 * data providers
493 * @covers MediaWiki\Permissions\PermissionManager::checkSpecialsAndNSPermissions
494 */
495 public function testSpecialsAndNSPermissions() {
496 $this->setUser( $this->userName );
497
498 $this->setTitle( NS_SPECIAL );
499
500 $this->assertEquals( [ [ 'badaccess-group0' ], [ 'ns-specialprotected' ] ],
501 MediaWikiServices::getInstance()->getPermissionManager()
502 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
503
504 $this->setTitle( NS_MAIN );
505 $this->overrideUserPermissions( $this->user, 'bogus' );
506 $this->assertEquals( [],
507 MediaWikiServices::getInstance()->getPermissionManager()
508 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
509
510 $this->setTitle( NS_MAIN );
511 $this->overrideUserPermissions( $this->user, '' );
512 $this->assertEquals( [ [ 'badaccess-group0' ] ],
513 MediaWikiServices::getInstance()->getPermissionManager()
514 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
515
516 $this->mergeMwGlobalArrayValue( 'wgNamespaceProtection', [
517 NS_USER => [ 'bogus' ]
518 ] );
519 $this->resetServices();
520 $this->overrideUserPermissions( $this->user, '' );
521
522 $this->setTitle( NS_USER );
523 $this->assertEquals( [ [ 'badaccess-group0' ],
524 [ 'namespaceprotected', 'User', 'bogus' ] ],
525 MediaWikiServices::getInstance()->getPermissionManager()
526 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
527
528 $this->setTitle( NS_MEDIAWIKI );
529 $this->overrideUserPermissions( $this->user, 'bogus' );
530 $this->assertEquals( [ [ 'protectedinterface', 'bogus' ] ],
531 MediaWikiServices::getInstance()->getPermissionManager()
532 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
533
534 $this->setTitle( NS_MEDIAWIKI );
535 $this->overrideUserPermissions( $this->user, 'bogus' );
536 $this->assertEquals( [ [ 'protectedinterface', 'bogus' ] ],
537 MediaWikiServices::getInstance()->getPermissionManager()
538 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
539
540 $this->setMwGlobals( 'wgNamespaceProtection', null );
541 $this->resetServices();
542 $this->overrideUserPermissions( $this->user, 'bogus' );
543
544 $this->assertEquals( [],
545 MediaWikiServices::getInstance()->getPermissionManager()
546 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
547 $this->assertEquals( true,
548 MediaWikiServices::getInstance()->getPermissionManager()
549 ->userCan( 'bogus', $this->user, $this->title ) );
550
551 $this->overrideUserPermissions( $this->user, '' );
552 $this->assertEquals( [ [ 'badaccess-group0' ] ],
553 MediaWikiServices::getInstance()->getPermissionManager()
554 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
555 $this->assertEquals( false,
556 MediaWikiServices::getInstance()->getPermissionManager()
557 ->userCan( 'bogus', $this->user, $this->title ) );
558 }
559
560 /**
561 * @todo This test method should be split up into separate test methods and
562 * data providers
563 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
564 */
565 public function testJsConfigEditPermissions() {
566 $this->setUser( $this->userName );
567
568 $this->setTitle( NS_USER, $this->userName . '/test.js' );
569 $this->runConfigEditPermissions(
570 [ [ 'badaccess-group0' ], [ 'mycustomjsprotected', 'bogus' ] ],
571
572 [ [ 'badaccess-group0' ], [ 'mycustomjsprotected', 'bogus' ] ],
573 [ [ 'badaccess-group0' ], [ 'mycustomjsprotected', 'bogus' ] ],
574 [ [ 'badaccess-group0' ] ],
575
576 [ [ 'badaccess-group0' ], [ 'mycustomjsprotected', 'bogus' ] ],
577 [ [ 'badaccess-group0' ], [ 'mycustomjsprotected', 'bogus' ] ],
578 [ [ 'badaccess-group0' ] ],
579 [ [ 'badaccess-groups' ] ]
580 );
581 }
582
583 /**
584 * @todo This test method should be split up into separate test methods and
585 * data providers
586 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
587 */
588 public function testJsonConfigEditPermissions() {
589 $prefix = MediaWikiServices::getInstance()->getContentLanguage()->
590 getFormattedNsText( NS_PROJECT );
591 $this->setUser( $this->userName );
592
593 $this->setTitle( NS_USER, $this->userName . '/test.json' );
594 $this->runConfigEditPermissions(
595 [ [ 'badaccess-group0' ], [ 'mycustomjsonprotected', 'bogus' ] ],
596
597 [ [ 'badaccess-group0' ], [ 'mycustomjsonprotected', 'bogus' ] ],
598 [ [ 'badaccess-group0' ] ],
599 [ [ 'badaccess-group0' ], [ 'mycustomjsonprotected', 'bogus' ] ],
600
601 [ [ 'badaccess-group0' ], [ 'mycustomjsonprotected', 'bogus' ] ],
602 [ [ 'badaccess-group0' ] ],
603 [ [ 'badaccess-group0' ], [ 'mycustomjsonprotected', 'bogus' ] ],
604 [ [ 'badaccess-groups' ] ]
605 );
606 }
607
608 /**
609 * @todo This test method should be split up into separate test methods and
610 * data providers
611 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
612 */
613 public function testCssConfigEditPermissions() {
614 $this->setUser( $this->userName );
615
616 $this->setTitle( NS_USER, $this->userName . '/test.css' );
617 $this->runConfigEditPermissions(
618 [ [ 'badaccess-group0' ], [ 'mycustomcssprotected', 'bogus' ] ],
619
620 [ [ 'badaccess-group0' ] ],
621 [ [ 'badaccess-group0' ], [ 'mycustomcssprotected', 'bogus' ] ],
622 [ [ 'badaccess-group0' ], [ 'mycustomcssprotected', 'bogus' ] ],
623
624 [ [ 'badaccess-group0' ] ],
625 [ [ 'badaccess-group0' ], [ 'mycustomcssprotected', 'bogus' ] ],
626 [ [ 'badaccess-group0' ], [ 'mycustomcssprotected', 'bogus' ] ],
627 [ [ 'badaccess-groups' ] ]
628 );
629 }
630
631 /**
632 * @todo This test method should be split up into separate test methods and
633 * data providers
634 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
635 */
636 public function testOtherJsConfigEditPermissions() {
637 $this->setUser( $this->userName );
638
639 $this->setTitle( NS_USER, $this->altUserName . '/test.js' );
640 $this->runConfigEditPermissions(
641 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
642
643 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
644 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
645 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
646
647 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
648 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
649 [ [ 'badaccess-group0' ] ],
650 [ [ 'badaccess-groups' ] ]
651 );
652 }
653
654 /**
655 * @todo This test method should be split up into separate test methods and
656 * data providers
657 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
658 */
659 public function testOtherJsonConfigEditPermissions() {
660 $this->setUser( $this->userName );
661
662 $this->setTitle( NS_USER, $this->altUserName . '/test.json' );
663 $this->runConfigEditPermissions(
664 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
665
666 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
667 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
668 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
669
670 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
671 [ [ 'badaccess-group0' ] ],
672 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
673 [ [ 'badaccess-groups' ] ]
674 );
675 }
676
677 /**
678 * @todo This test method should be split up into separate test methods and
679 * data providers
680 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
681 */
682 public function testOtherCssConfigEditPermissions() {
683 $this->setUser( $this->userName );
684
685 $this->setTitle( NS_USER, $this->altUserName . '/test.css' );
686 $this->runConfigEditPermissions(
687 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
688
689 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
690 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
691 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
692
693 [ [ 'badaccess-group0' ] ],
694 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
695 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
696 [ [ 'badaccess-groups' ] ]
697 );
698 }
699
700 public function testJsConfigRedirectEditPermissions() {
701 $revision = null;
702 $user = $this->getTestUser()->getUser();
703 $otherUser = $this->getTestUser( 'sysop' )->getUser();
704 $localJsTitle = Title::newFromText( 'User:' . $user->getName() . '/foo.js' );
705 $otherLocalJsTitle = Title::newFromText( 'User:' . $user->getName() . '/foo2.js' );
706 $nonlocalJsTitle = Title::newFromText( 'User:' . $otherUser->getName() . '/foo.js' );
707
708 $services = MediaWikiServices::getInstance();
709 $revisionLookup = $this->getMockBuilder( RevisionLookup::class )
710 ->setMethods( [ 'getRevisionByTitle' ] )
711 ->getMockForAbstractClass();
712 $revisionLookup->method( 'getRevisionByTitle' )
713 ->willReturnCallback( function ( LinkTarget $page ) use (
714 $services, &$revision, $localJsTitle
715 ) {
716 if ( $localJsTitle->equals( Title::newFromLinkTarget( $page ) ) ) {
717 return $revision;
718 } else {
719 return $services->getRevisionLookup()->getRevisionByTitle( $page );
720 }
721 } );
722 $permissionManager = new PermissionManager(
723 new LoggedServiceOptions(
724 self::$serviceOptionsAccessLog,
725 PermissionManager::CONSTRUCTOR_OPTIONS,
726 [
727 'WhitelistRead' => [],
728 'WhitelistReadRegexp' => [],
729 'EmailConfirmToEdit' => false,
730 'BlockDisablesLogin' => false,
731 'GroupPermissions' => [],
732 'RevokePermissions' => [],
733 'AvailableRights' => [],
734 'NamespaceProtection' => [],
735 'RestrictionLevels' => []
736 ]
737 ),
738 $services->getSpecialPageFactory(),
739 $revisionLookup,
740 MediaWikiServices::getInstance()->getNamespaceInfo()
741 );
742 $this->setService( 'PermissionManager', $permissionManager );
743
744 $permissionManager->overrideUserRightsForTesting( $user, [ 'edit', 'editmyuserjs' ] );
745
746 $revision = $this->getJavascriptRevision( $localJsTitle, $user, '/* script */' );
747 $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
748 $this->assertSame( [], $errors );
749
750 $revision = $this->getJavascriptRedirectRevision( $localJsTitle, $otherLocalJsTitle, $user );
751 $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
752 $this->assertSame( [], $errors );
753
754 $revision = $this->getJavascriptRedirectRevision( $localJsTitle, $nonlocalJsTitle, $user );
755 $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
756 $this->assertSame( [ [ 'mycustomjsredirectprotected', 'edit' ] ], $errors );
757
758 $permissionManager->overrideUserRightsForTesting( $user,
759 [ 'edit', 'editmyuserjs', 'editmyuserjsredirect' ] );
760
761 $revision = $this->getJavascriptRedirectRevision( $localJsTitle, $nonlocalJsTitle, $user );
762 $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
763 $this->assertSame( [], $errors );
764 }
765
766 /**
767 * @todo This test method should be split up into separate test methods and
768 * data providers
769 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
770 */
771 public function testOtherNonConfigEditPermissions() {
772 $this->setUser( $this->userName );
773
774 $this->setTitle( NS_USER, $this->altUserName . '/tempo' );
775 $this->runConfigEditPermissions(
776 [ [ 'badaccess-group0' ] ],
777
778 [ [ 'badaccess-group0' ] ],
779 [ [ 'badaccess-group0' ] ],
780 [ [ 'badaccess-group0' ] ],
781
782 [ [ 'badaccess-group0' ] ],
783 [ [ 'badaccess-group0' ] ],
784 [ [ 'badaccess-group0' ] ],
785 [ [ 'badaccess-groups' ] ]
786 );
787 }
788
789 /**
790 * @todo This should use data providers like the other methods here.
791 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
792 */
793 public function testPatrolActionConfigEditPermissions() {
794 $this->setUser( 'anon' );
795 $this->setTitle( NS_USER, 'ToPatrolOrNotToPatrol' );
796 $this->runConfigEditPermissions(
797 [ [ 'badaccess-group0' ] ],
798
799 [ [ 'badaccess-group0' ] ],
800 [ [ 'badaccess-group0' ] ],
801 [ [ 'badaccess-group0' ] ],
802
803 [ [ 'badaccess-group0' ] ],
804 [ [ 'badaccess-group0' ] ],
805 [ [ 'badaccess-group0' ] ],
806 [ [ 'badaccess-groups' ] ]
807 );
808 }
809
810 protected function runConfigEditPermissions(
811 $resultNone,
812 $resultMyCss,
813 $resultMyJson,
814 $resultMyJs,
815 $resultUserCss,
816 $resultUserJson,
817 $resultUserJs,
818 $resultPatrol
819 ) {
820 $this->overrideUserPermissions( $this->user );
821 $result = MediaWikiServices::getInstance()->getPermissionManager()
822 ->getPermissionErrors( 'bogus', $this->user, $this->title );
823 $this->assertEquals( $resultNone, $result );
824
825 $this->overrideUserPermissions( $this->user, 'editmyusercss' );
826 $result = MediaWikiServices::getInstance()->getPermissionManager()
827 ->getPermissionErrors( 'bogus', $this->user, $this->title );
828 $this->assertEquals( $resultMyCss, $result );
829
830 $this->overrideUserPermissions( $this->user, 'editmyuserjson' );
831 $result = MediaWikiServices::getInstance()->getPermissionManager()
832 ->getPermissionErrors( 'bogus', $this->user, $this->title );
833 $this->assertEquals( $resultMyJson, $result );
834
835 $this->overrideUserPermissions( $this->user, 'editmyuserjs' );
836 $result = MediaWikiServices::getInstance()->getPermissionManager()
837 ->getPermissionErrors( 'bogus', $this->user, $this->title );
838 $this->assertEquals( $resultMyJs, $result );
839
840 $this->overrideUserPermissions( $this->user, 'editusercss' );
841 $result = MediaWikiServices::getInstance()->getPermissionManager()
842 ->getPermissionErrors( 'bogus', $this->user, $this->title );
843 $this->assertEquals( $resultUserCss, $result );
844
845 $this->overrideUserPermissions( $this->user, 'edituserjson' );
846 $result = MediaWikiServices::getInstance()->getPermissionManager()
847 ->getPermissionErrors( 'bogus', $this->user, $this->title );
848 $this->assertEquals( $resultUserJson, $result );
849
850 $this->overrideUserPermissions( $this->user, 'edituserjs' );
851 $result = MediaWikiServices::getInstance()->getPermissionManager()
852 ->getPermissionErrors( 'bogus', $this->user, $this->title );
853 $this->assertEquals( $resultUserJs, $result );
854
855 $this->overrideUserPermissions( $this->user );
856 $result = MediaWikiServices::getInstance()->getPermissionManager()
857 ->getPermissionErrors( 'patrol', $this->user, $this->title );
858 $this->assertEquals( reset( $resultPatrol[0] ), reset( $result[0] ) );
859
860 $this->overrideUserPermissions( $this->user, [ 'edituserjs', 'edituserjson', 'editusercss' ] );
861 $result = MediaWikiServices::getInstance()->getPermissionManager()
862 ->getPermissionErrors( 'bogus', $this->user, $this->title );
863 $this->assertEquals( [ [ 'badaccess-group0' ] ], $result );
864 }
865
866 /**
867 * @todo This test method should be split up into separate test methods and
868 * data providers
869 *
870 * This test is failing per T201776.
871 *
872 * @group Broken
873 * @covers \MediaWiki\Permissions\PermissionManager::checkPageRestrictions
874 */
875 public function testPageRestrictions() {
876 $prefix = MediaWikiServices::getInstance()->getContentLanguage()->
877 getFormattedNsText( NS_PROJECT );
878
879 $this->setTitle( NS_MAIN );
880 $this->title->mRestrictionsLoaded = true;
881 $this->overrideUserPermissions( $this->user, "edit" );
882 $this->title->mRestrictions = [ "bogus" => [ 'bogus', "sysop", "protect", "" ] ];
883
884 $this->assertEquals( [],
885 MediaWikiServices::getInstance()->getPermissionManager()
886 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
887
888 $this->assertEquals( true,
889 MediaWikiServices::getInstance()->getPermissionManager()
890 ->quickUserCan( 'edit', $this->user, $this->title ) );
891
892 $this->title->mRestrictions = [ "edit" => [ 'bogus', "sysop", "protect", "" ],
893 "bogus" => [ 'bogus', "sysop", "protect", "" ] ];
894
895 $this->assertEquals( [ [ 'badaccess-group0' ],
896 [ 'protectedpagetext', 'bogus', 'bogus' ],
897 [ 'protectedpagetext', 'editprotected', 'bogus' ],
898 [ 'protectedpagetext', 'protect', 'bogus' ] ],
899 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
900 'bogus', $this->user, $this->title ) );
901 $this->assertEquals( [ [ 'protectedpagetext', 'bogus', 'edit' ],
902 [ 'protectedpagetext', 'editprotected', 'edit' ],
903 [ 'protectedpagetext', 'protect', 'edit' ] ],
904 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
905 'edit', $this->user, $this->title ) );
906 $this->overrideUserPermissions( $this->user );
907 $this->assertEquals( [ [ 'badaccess-group0' ],
908 [ 'protectedpagetext', 'bogus', 'bogus' ],
909 [ 'protectedpagetext', 'editprotected', 'bogus' ],
910 [ 'protectedpagetext', 'protect', 'bogus' ] ],
911 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
912 'bogus', $this->user, $this->title ) );
913 $this->assertEquals( [ [ 'badaccess-groups', "*, [[$prefix:Users|Users]]", 2 ],
914 [ 'protectedpagetext', 'bogus', 'edit' ],
915 [ 'protectedpagetext', 'editprotected', 'edit' ],
916 [ 'protectedpagetext', 'protect', 'edit' ] ],
917 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
918 'edit', $this->user, $this->title ) );
919 $this->overrideUserPermissions( $this->user, [ "edit", "editprotected" ] );
920 $this->assertEquals( [ [ 'badaccess-group0' ],
921 [ 'protectedpagetext', 'bogus', 'bogus' ],
922 [ 'protectedpagetext', 'protect', 'bogus' ] ],
923 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
924 'bogus', $this->user, $this->title ) );
925 $this->assertEquals( [
926 [ 'protectedpagetext', 'bogus', 'edit' ],
927 [ 'protectedpagetext', 'protect', 'edit' ] ],
928 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
929 'edit', $this->user, $this->title ) );
930
931 $this->title->mCascadeRestriction = true;
932 $this->overrideUserPermissions( $this->user, "edit" );
933
934 $this->assertEquals( false,
935 MediaWikiServices::getInstance()->getPermissionManager()
936 ->quickUserCan( 'bogus', $this->user, $this->title ) );
937
938 $this->assertEquals( false,
939 MediaWikiServices::getInstance()->getPermissionManager()->quickUserCan(
940 'edit', $this->user, $this->title ) );
941
942 $this->assertEquals( [ [ 'badaccess-group0' ],
943 [ 'protectedpagetext', 'bogus', 'bogus' ],
944 [ 'protectedpagetext', 'editprotected', 'bogus' ],
945 [ 'protectedpagetext', 'protect', 'bogus' ] ],
946 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
947 'bogus', $this->user, $this->title ) );
948 $this->assertEquals( [ [ 'protectedpagetext', 'bogus', 'edit' ],
949 [ 'protectedpagetext', 'editprotected', 'edit' ],
950 [ 'protectedpagetext', 'protect', 'edit' ] ],
951 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
952 'edit', $this->user, $this->title ) );
953
954 $this->overrideUserPermissions( $this->user, [ "edit", "editprotected" ] );
955 $this->assertEquals( false,
956 MediaWikiServices::getInstance()->getPermissionManager()->quickUserCan(
957 'bogus', $this->user, $this->title ) );
958
959 $this->assertEquals( false,
960 MediaWikiServices::getInstance()->getPermissionManager()->quickUserCan(
961 'edit', $this->user, $this->title ) );
962
963 $this->assertEquals( [ [ 'badaccess-group0' ],
964 [ 'protectedpagetext', 'bogus', 'bogus' ],
965 [ 'protectedpagetext', 'protect', 'bogus' ],
966 [ 'protectedpagetext', 'protect', 'bogus' ] ],
967 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
968 'bogus', $this->user, $this->title ) );
969 $this->assertEquals( [ [ 'protectedpagetext', 'bogus', 'edit' ],
970 [ 'protectedpagetext', 'protect', 'edit' ],
971 [ 'protectedpagetext', 'protect', 'edit' ] ],
972 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
973 'edit', $this->user, $this->title ) );
974 }
975
976 /**
977 * @covers \MediaWiki\Permissions\PermissionManager::checkCascadingSourcesRestrictions
978 */
979 public function testCascadingSourcesRestrictions() {
980 $this->setTitle( NS_MAIN, "test page" );
981 $this->overrideUserPermissions( $this->user, [ "edit", "bogus" ] );
982
983 $this->title->mCascadeSources = [
984 Title::makeTitle( NS_MAIN, "Bogus" ),
985 Title::makeTitle( NS_MAIN, "UnBogus" )
986 ];
987 $this->title->mCascadingRestrictions = [
988 "bogus" => [ 'bogus', "sysop", "protect", "" ]
989 ];
990
991 $this->assertEquals( false,
992 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
993 'bogus', $this->user, $this->title ) );
994 $this->assertEquals( [
995 [ "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ],
996 [ "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ],
997 [ "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ] ],
998 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
999 'bogus', $this->user, $this->title ) );
1000
1001 $this->assertEquals( true,
1002 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1003 'edit', $this->user, $this->title ) );
1004 $this->assertEquals( [],
1005 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
1006 'edit', $this->user, $this->title ) );
1007 }
1008
1009 /**
1010 * @todo This test method should be split up into separate test methods and
1011 * data providers
1012 * @covers \MediaWiki\Permissions\PermissionManager::checkActionPermissions
1013 */
1014 public function testActionPermissions() {
1015 $this->overrideUserPermissions( $this->user, [ "createpage" ] );
1016 $this->setTitle( NS_MAIN, "test page" );
1017 $this->title->mTitleProtection['permission'] = '';
1018 $this->title->mTitleProtection['user'] = $this->user->getId();
1019 $this->title->mTitleProtection['expiry'] = 'infinity';
1020 $this->title->mTitleProtection['reason'] = 'test';
1021 $this->title->mCascadeRestriction = false;
1022
1023 $this->assertEquals( [ [ 'titleprotected', 'Useruser', 'test' ] ],
1024 MediaWikiServices::getInstance()->getPermissionManager()
1025 ->getPermissionErrors( 'create', $this->user, $this->title ) );
1026 $this->assertEquals( false,
1027 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1028 'create', $this->user, $this->title ) );
1029
1030 $this->title->mTitleProtection['permission'] = 'editprotected';
1031 $this->overrideUserPermissions( $this->user, [ 'createpage', 'protect' ] );
1032 $this->assertEquals( [ [ 'titleprotected', 'Useruser', 'test' ] ],
1033 MediaWikiServices::getInstance()->getPermissionManager()
1034 ->getPermissionErrors( 'create', $this->user, $this->title ) );
1035 $this->assertEquals( false,
1036 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1037 'create', $this->user, $this->title ) );
1038
1039 $this->overrideUserPermissions( $this->user, [ 'createpage', 'editprotected' ] );
1040 $this->assertEquals( [],
1041 MediaWikiServices::getInstance()->getPermissionManager()
1042 ->getPermissionErrors( 'create', $this->user, $this->title ) );
1043 $this->assertEquals( true,
1044 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1045 'create', $this->user, $this->title ) );
1046
1047 $this->overrideUserPermissions( $this->user, [ 'createpage' ] );
1048 $this->assertEquals( [ [ 'titleprotected', 'Useruser', 'test' ] ],
1049 MediaWikiServices::getInstance()->getPermissionManager()
1050 ->getPermissionErrors( 'create', $this->user, $this->title ) );
1051 $this->assertEquals( false,
1052 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1053 'create', $this->user, $this->title ) );
1054
1055 $this->setTitle( NS_MEDIA, "test page" );
1056 $this->overrideUserPermissions( $this->user, [ "move" ] );
1057 $this->assertEquals( false,
1058 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1059 'move', $this->user, $this->title ) );
1060 $this->assertEquals( [ [ 'immobile-source-namespace', 'Media' ] ],
1061 MediaWikiServices::getInstance()->getPermissionManager()
1062 ->getPermissionErrors( 'move', $this->user, $this->title ) );
1063
1064 $this->setTitle( NS_HELP, "test page" );
1065 $this->assertEquals( [],
1066 MediaWikiServices::getInstance()->getPermissionManager()
1067 ->getPermissionErrors( 'move', $this->user, $this->title ) );
1068 $this->assertEquals( true,
1069 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1070 'move', $this->user, $this->title ) );
1071
1072 $this->title->mInterwiki = "no";
1073 $this->assertEquals( [ [ 'immobile-source-page' ] ],
1074 MediaWikiServices::getInstance()->getPermissionManager()
1075 ->getPermissionErrors( 'move', $this->user, $this->title ) );
1076 $this->assertEquals( false,
1077 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1078 'move', $this->user, $this->title ) );
1079
1080 $this->setTitle( NS_MEDIA, "test page" );
1081 $this->assertEquals( false,
1082 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1083 'move-target', $this->user, $this->title ) );
1084 $this->assertEquals( [ [ 'immobile-target-namespace', 'Media' ] ],
1085 MediaWikiServices::getInstance()->getPermissionManager()
1086 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1087
1088 $this->setTitle( NS_HELP, "test page" );
1089 $this->assertEquals( [],
1090 MediaWikiServices::getInstance()->getPermissionManager()
1091 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1092 $this->assertEquals( true,
1093 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1094 'move-target', $this->user, $this->title ) );
1095
1096 $this->title->mInterwiki = "no";
1097 $this->assertEquals( [ [ 'immobile-target-page' ] ],
1098 MediaWikiServices::getInstance()->getPermissionManager()
1099 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1100 $this->assertEquals( false,
1101 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1102 'move-target', $this->user, $this->title ) );
1103 }
1104
1105 /**
1106 * @covers \MediaWiki\Permissions\PermissionManager::checkUserBlock
1107 */
1108 public function testUserBlock() {
1109 $this->setMwGlobals( [
1110 'wgEmailConfirmToEdit' => true,
1111 'wgEmailAuthentication' => true,
1112 'wgBlockDisablesLogin' => false,
1113 ] );
1114
1115 $this->overrideUserPermissions( $this->user, [
1116 'createpage',
1117 'edit',
1118 'move',
1119 'rollback',
1120 'patrol',
1121 'upload',
1122 'purge'
1123 ] );
1124 $this->setTitle( NS_HELP, "test page" );
1125
1126 # $wgEmailConfirmToEdit only applies to 'edit' action
1127 $this->assertEquals( [],
1128 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
1129 'move-target', $this->user, $this->title ) );
1130 $this->assertContains( [ 'confirmedittext' ],
1131 MediaWikiServices::getInstance()->getPermissionManager()
1132 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1133
1134 $this->setMwGlobals( 'wgEmailConfirmToEdit', false );
1135 $this->overrideUserPermissions( $this->user, [
1136 'createpage',
1137 'edit',
1138 'move',
1139 'rollback',
1140 'patrol',
1141 'upload',
1142 'purge'
1143 ] );
1144
1145 $this->assertNotContains( [ 'confirmedittext' ],
1146 MediaWikiServices::getInstance()->getPermissionManager()
1147 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1148
1149 # $wgEmailConfirmToEdit && !$user->isEmailConfirmed() && $action != 'createaccount'
1150 $this->assertEquals( [],
1151 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
1152 'move-target', $this->user, $this->title ) );
1153
1154 global $wgLang;
1155 $prev = time();
1156 $now = time() + 120;
1157 $this->user->mBlockedby = $this->user->getId();
1158 $this->user->mBlock = new DatabaseBlock( [
1159 'address' => '127.0.8.1',
1160 'by' => $this->user->getId(),
1161 'reason' => 'no reason given',
1162 'timestamp' => $prev + 3600,
1163 'auto' => true,
1164 'expiry' => 0
1165 ] );
1166 $this->user->mBlock->setTimestamp( 0 );
1167 $this->assertEquals( [ [ 'autoblockedtext',
1168 "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
1169 "\u{202A}Useruser\u{202C}", null, 'infinite', '127.0.8.1',
1170 $wgLang->timeanddate( wfTimestamp( TS_MW, $prev ), true ) ] ],
1171 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
1172 'move-target', $this->user, $this->title ) );
1173
1174 $this->assertEquals( false, MediaWikiServices::getInstance()->getPermissionManager()
1175 ->userCan( 'move-target', $this->user, $this->title ) );
1176 // quickUserCan should ignore user blocks
1177 $this->assertEquals( true, MediaWikiServices::getInstance()->getPermissionManager()
1178 ->quickUserCan( 'move-target', $this->user, $this->title ) );
1179
1180 global $wgLocalTZoffset;
1181 $wgLocalTZoffset = -60;
1182 $this->user->mBlockedby = $this->user->getName();
1183 $this->user->mBlock = new DatabaseBlock( [
1184 'address' => '127.0.8.1',
1185 'by' => $this->user->getId(),
1186 'reason' => 'no reason given',
1187 'timestamp' => $now,
1188 'auto' => false,
1189 'expiry' => 10,
1190 ] );
1191 $this->assertEquals( [ [ 'blockedtext',
1192 "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
1193 "\u{202A}Useruser\u{202C}", null, '23:00, 31 December 1969', '127.0.8.1',
1194 $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ],
1195 MediaWikiServices::getInstance()->getPermissionManager()
1196 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1197 # $action != 'read' && $action != 'createaccount' && $user->isBlockedFrom( $this )
1198 # $user->blockedFor() == ''
1199 # $user->mBlock->mExpiry == 'infinity'
1200
1201 $this->user->mBlockedby = $this->user->getName();
1202 $this->user->mBlock = new SystemBlock( [
1203 'address' => '127.0.8.1',
1204 'by' => $this->user->getId(),
1205 'reason' => 'no reason given',
1206 'timestamp' => $now,
1207 'auto' => false,
1208 'systemBlock' => 'test',
1209 ] );
1210
1211 $errors = [ [ 'systemblockedtext',
1212 "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
1213 "\u{202A}Useruser\u{202C}", 'test', 'infinite', '127.0.8.1',
1214 $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ];
1215
1216 $this->assertEquals( $errors,
1217 MediaWikiServices::getInstance()->getPermissionManager()
1218 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1219 $this->assertEquals( $errors,
1220 MediaWikiServices::getInstance()->getPermissionManager()
1221 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1222 $this->assertEquals( $errors,
1223 MediaWikiServices::getInstance()->getPermissionManager()
1224 ->getPermissionErrors( 'rollback', $this->user, $this->title ) );
1225 $this->assertEquals( $errors,
1226 MediaWikiServices::getInstance()->getPermissionManager()
1227 ->getPermissionErrors( 'patrol', $this->user, $this->title ) );
1228 $this->assertEquals( $errors,
1229 MediaWikiServices::getInstance()->getPermissionManager()
1230 ->getPermissionErrors( 'upload', $this->user, $this->title ) );
1231 $this->assertEquals( [],
1232 MediaWikiServices::getInstance()->getPermissionManager()
1233 ->getPermissionErrors( 'purge', $this->user, $this->title ) );
1234
1235 // partial block message test
1236 $this->user->mBlockedby = $this->user->getName();
1237 $this->user->mBlock = new DatabaseBlock( [
1238 'address' => '127.0.8.1',
1239 'by' => $this->user->getId(),
1240 'reason' => 'no reason given',
1241 'timestamp' => $now,
1242 'sitewide' => false,
1243 'expiry' => 10,
1244 ] );
1245
1246 $this->assertEquals( [],
1247 MediaWikiServices::getInstance()->getPermissionManager()
1248 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1249 $this->assertEquals( [],
1250 MediaWikiServices::getInstance()->getPermissionManager()
1251 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1252 $this->assertEquals( [],
1253 MediaWikiServices::getInstance()->getPermissionManager()
1254 ->getPermissionErrors( 'rollback', $this->user, $this->title ) );
1255 $this->assertEquals( [],
1256 MediaWikiServices::getInstance()->getPermissionManager()
1257 ->getPermissionErrors( 'patrol', $this->user, $this->title ) );
1258 $this->assertEquals( [],
1259 MediaWikiServices::getInstance()->getPermissionManager()
1260 ->getPermissionErrors( 'upload', $this->user, $this->title ) );
1261 $this->assertEquals( [],
1262 MediaWikiServices::getInstance()->getPermissionManager()
1263 ->getPermissionErrors( 'purge', $this->user, $this->title ) );
1264
1265 $this->user->mBlock->setRestrictions( [
1266 ( new PageRestriction( 0, $this->title->getArticleID() ) )->setTitle( $this->title ),
1267 ] );
1268
1269 $errors = [ [ 'blockedtext-partial',
1270 "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
1271 "\u{202A}Useruser\u{202C}", null, '23:00, 31 December 1969', '127.0.8.1',
1272 $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ];
1273
1274 $this->assertEquals( $errors,
1275 MediaWikiServices::getInstance()->getPermissionManager()
1276 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1277 $this->assertEquals( $errors,
1278 MediaWikiServices::getInstance()->getPermissionManager()
1279 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1280 $this->assertEquals( $errors,
1281 MediaWikiServices::getInstance()->getPermissionManager()
1282 ->getPermissionErrors( 'rollback', $this->user, $this->title ) );
1283 $this->assertEquals( $errors,
1284 MediaWikiServices::getInstance()->getPermissionManager()
1285 ->getPermissionErrors( 'patrol', $this->user, $this->title ) );
1286 $this->assertEquals( [],
1287 MediaWikiServices::getInstance()->getPermissionManager()
1288 ->getPermissionErrors( 'upload', $this->user, $this->title ) );
1289 $this->assertEquals( [],
1290 MediaWikiServices::getInstance()->getPermissionManager()
1291 ->getPermissionErrors( 'purge', $this->user, $this->title ) );
1292
1293 // Test no block.
1294 $this->user->mBlockedby = null;
1295 $this->user->mBlock = null;
1296
1297 $this->assertEquals( [],
1298 MediaWikiServices::getInstance()->getPermissionManager()
1299 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1300 }
1301
1302 /**
1303 * @covers \MediaWiki\Permissions\PermissionManager::checkUserBlock
1304 *
1305 * Tests to determine that the passed in permission does not get mixed up with
1306 * an action of the same name.
1307 */
1308 public function testUserBlockAction() {
1309 global $wgLang;
1310
1311 $tester = $this->getMockBuilder( Action::class )
1312 ->disableOriginalConstructor()
1313 ->getMock();
1314 $tester->method( 'getName' )
1315 ->willReturn( 'tester' );
1316 $tester->method( 'getRestriction' )
1317 ->willReturn( 'test' );
1318 $tester->method( 'requiresUnblock' )
1319 ->willReturn( false );
1320
1321 $this->setMwGlobals( [
1322 'wgActions' => [
1323 'tester' => $tester,
1324 ],
1325 'wgGroupPermissions' => [
1326 '*' => [
1327 'tester' => true,
1328 ],
1329 ],
1330 ] );
1331
1332 $now = time();
1333 $this->user->mBlockedby = $this->user->getName();
1334 $this->user->mBlock = new DatabaseBlock( [
1335 'address' => '127.0.8.1',
1336 'by' => $this->user->getId(),
1337 'reason' => 'no reason given',
1338 'timestamp' => $now,
1339 'auto' => false,
1340 'expiry' => 'infinity',
1341 ] );
1342
1343 $errors = [ [ 'blockedtext',
1344 "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
1345 "\u{202A}Useruser\u{202C}", null, 'infinite', '127.0.8.1',
1346 $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ];
1347
1348 $this->assertEquals( $errors,
1349 MediaWikiServices::getInstance()->getPermissionManager()
1350 ->getPermissionErrors( 'tester', $this->user, $this->title ) );
1351 }
1352
1353 /**
1354 * @covers \MediaWiki\Permissions\PermissionManager::isBlockedFrom
1355 */
1356 public function testBlockInstanceCache() {
1357 // First, check the user isn't blocked
1358 $user = $this->getMutableTestUser()->getUser();
1359 $ut = Title::makeTitle( NS_USER_TALK, $user->getName() );
1360 $this->assertNull( $user->getBlock( false ), 'sanity check' );
1361 //$this->assertSame( '', $user->blockedBy(), 'sanity check' );
1362 //$this->assertSame( '', $user->blockedFor(), 'sanity check' );
1363 //$this->assertFalse( (bool)$user->isHidden(), 'sanity check' );
1364 $this->assertFalse( MediaWikiServices::getInstance()->getPermissionManager()
1365 ->isBlockedFrom( $user, $ut ), 'sanity check' );
1366
1367 // Block the user
1368 $blocker = $this->getTestSysop()->getUser();
1369 $block = new DatabaseBlock( [
1370 'hideName' => true,
1371 'allowUsertalk' => false,
1372 'reason' => 'Because',
1373 ] );
1374 $block->setTarget( $user );
1375 $block->setBlocker( $blocker );
1376 $res = $block->insert();
1377 $this->assertTrue( (bool)$res['id'], 'sanity check: Failed to insert block' );
1378
1379 // Clear cache and confirm it loaded the block properly
1380 $user->clearInstanceCache();
1381 $this->assertInstanceOf( DatabaseBlock::class, $user->getBlock( false ) );
1382 //$this->assertSame( $blocker->getName(), $user->blockedBy() );
1383 //$this->assertSame( 'Because', $user->blockedFor() );
1384 //$this->assertTrue( (bool)$user->isHidden() );
1385 $this->assertTrue( MediaWikiServices::getInstance()->getPermissionManager()
1386 ->isBlockedFrom( $user, $ut ) );
1387
1388 // Unblock
1389 $block->delete();
1390
1391 // Clear cache and confirm it loaded the not-blocked properly
1392 $user->clearInstanceCache();
1393 $this->assertNull( $user->getBlock( false ) );
1394 //$this->assertSame( '', $user->blockedBy() );
1395 //$this->assertSame( '', $user->blockedFor() );
1396 //$this->assertFalse( (bool)$user->isHidden() );
1397 $this->assertFalse( MediaWikiServices::getInstance()->getPermissionManager()
1398 ->isBlockedFrom( $user, $ut ) );
1399 }
1400
1401 /**
1402 * @covers \MediaWiki\Permissions\PermissionManager::isBlockedFrom
1403 * @dataProvider provideIsBlockedFrom
1404 * @param string|null $title Title to test.
1405 * @param bool $expect Expected result from User::isBlockedFrom()
1406 * @param array $options Additional test options:
1407 * - 'blockAllowsUTEdit': (bool, default true) Value for $wgBlockAllowsUTEdit
1408 * - 'allowUsertalk': (bool, default false) Passed to DatabaseBlock::__construct()
1409 * - 'pageRestrictions': (array|null) If non-empty, page restriction titles for the block.
1410 */
1411 public function testIsBlockedFrom( $title, $expect, array $options = [] ) {
1412 $this->setMwGlobals( [
1413 'wgBlockAllowsUTEdit' => $options['blockAllowsUTEdit'] ?? true,
1414 ] );
1415
1416 $user = $this->getTestUser()->getUser();
1417
1418 if ( $title === self::USER_TALK_PAGE ) {
1419 $title = $user->getTalkPage();
1420 } else {
1421 $title = Title::newFromText( $title );
1422 }
1423
1424 $restrictions = [];
1425 foreach ( $options['pageRestrictions'] ?? [] as $pagestr ) {
1426 $page = $this->getExistingTestPage(
1427 $pagestr === self::USER_TALK_PAGE ? $user->getTalkPage() : $pagestr
1428 );
1429 $restrictions[] = new PageRestriction( 0, $page->getId() );
1430 }
1431 foreach ( $options['namespaceRestrictions'] ?? [] as $ns ) {
1432 $restrictions[] = new NamespaceRestriction( 0, $ns );
1433 }
1434
1435 $block = new DatabaseBlock( [
1436 'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
1437 'allowUsertalk' => $options['allowUsertalk'] ?? false,
1438 'sitewide' => !$restrictions,
1439 ] );
1440 $block->setTarget( $user );
1441 $block->setBlocker( $this->getTestSysop()->getUser() );
1442 if ( $restrictions ) {
1443 $block->setRestrictions( $restrictions );
1444 }
1445 $block->insert();
1446
1447 try {
1448 $this->assertSame( $expect, MediaWikiServices::getInstance()->getPermissionManager()
1449 ->isBlockedFrom( $user, $title ) );
1450 } finally {
1451 $block->delete();
1452 }
1453 }
1454
1455 public static function provideIsBlockedFrom() {
1456 return [
1457 'Sitewide block, basic operation' => [ 'Test page', true ],
1458 'Sitewide block, not allowing user talk' => [
1459 self::USER_TALK_PAGE, true, [
1460 'allowUsertalk' => false,
1461 ]
1462 ],
1463 'Sitewide block, allowing user talk' => [
1464 self::USER_TALK_PAGE, false, [
1465 'allowUsertalk' => true,
1466 ]
1467 ],
1468 'Sitewide block, allowing user talk but $wgBlockAllowsUTEdit is false' => [
1469 self::USER_TALK_PAGE, true, [
1470 'allowUsertalk' => true,
1471 'blockAllowsUTEdit' => false,
1472 ]
1473 ],
1474 'Partial block, blocking the page' => [
1475 'Test page', true, [
1476 'pageRestrictions' => [ 'Test page' ],
1477 ]
1478 ],
1479 'Partial block, not blocking the page' => [
1480 'Test page 2', false, [
1481 'pageRestrictions' => [ 'Test page' ],
1482 ]
1483 ],
1484 'Partial block, not allowing user talk but user talk page is not blocked' => [
1485 self::USER_TALK_PAGE, false, [
1486 'allowUsertalk' => false,
1487 'pageRestrictions' => [ 'Test page' ],
1488 ]
1489 ],
1490 'Partial block, allowing user talk but user talk page is blocked' => [
1491 self::USER_TALK_PAGE, true, [
1492 'allowUsertalk' => true,
1493 'pageRestrictions' => [ self::USER_TALK_PAGE ],
1494 ]
1495 ],
1496 'Partial block, user talk page is not blocked but $wgBlockAllowsUTEdit is false' => [
1497 self::USER_TALK_PAGE, false, [
1498 'allowUsertalk' => false,
1499 'pageRestrictions' => [ 'Test page' ],
1500 'blockAllowsUTEdit' => false,
1501 ]
1502 ],
1503 'Partial block, user talk page is blocked and $wgBlockAllowsUTEdit is false' => [
1504 self::USER_TALK_PAGE, true, [
1505 'allowUsertalk' => true,
1506 'pageRestrictions' => [ self::USER_TALK_PAGE ],
1507 'blockAllowsUTEdit' => false,
1508 ]
1509 ],
1510 'Partial user talk namespace block, not allowing user talk' => [
1511 self::USER_TALK_PAGE, true, [
1512 'allowUsertalk' => false,
1513 'namespaceRestrictions' => [ NS_USER_TALK ],
1514 ]
1515 ],
1516 'Partial user talk namespace block, allowing user talk' => [
1517 self::USER_TALK_PAGE, false, [
1518 'allowUsertalk' => true,
1519 'namespaceRestrictions' => [ NS_USER_TALK ],
1520 ]
1521 ],
1522 'Partial user talk namespace block, where $wgBlockAllowsUTEdit is false' => [
1523 self::USER_TALK_PAGE, true, [
1524 'allowUsertalk' => true,
1525 'namespaceRestrictions' => [ NS_USER_TALK ],
1526 'blockAllowsUTEdit' => false,
1527 ]
1528 ],
1529 ];
1530 }
1531
1532 /**
1533 * @covers \MediaWiki\Permissions\PermissionManager::getUserPermissions
1534 */
1535 public function testGetUserPermissions() {
1536 $user = $this->getTestUser( [ 'unittesters' ] )->getUser();
1537 $rights = MediaWikiServices::getInstance()->getPermissionManager()
1538 ->getUserPermissions( $user );
1539 $this->assertContains( 'runtest', $rights );
1540 $this->assertNotContains( 'writetest', $rights );
1541 $this->assertNotContains( 'modifytest', $rights );
1542 $this->assertNotContains( 'nukeworld', $rights );
1543 }
1544
1545 /**
1546 * @covers \MediaWiki\Permissions\PermissionManager::getUserPermissions
1547 */
1548 public function testGetUserPermissionsHooks() {
1549 $user = $this->getTestUser( [ 'unittesters', 'testwriters' ] )->getUser();
1550 $userWrapper = TestingAccessWrapper::newFromObject( $user );
1551
1552 $rights = MediaWikiServices::getInstance()
1553 ->getPermissionManager()
1554 ->getUserPermissions( $user );
1555 $this->assertContains( 'test', $rights, 'sanity check' );
1556 $this->assertContains( 'runtest', $rights, 'sanity check' );
1557 $this->assertContains( 'writetest', $rights, 'sanity check' );
1558 $this->assertNotContains( 'nukeworld', $rights, 'sanity check' );
1559
1560 // Add a hook manipluating the rights
1561 $this->setTemporaryHook( 'UserGetRights', function ( $user, &$rights ) {
1562 $rights[] = 'nukeworld';
1563 $rights = array_diff( $rights, [ 'writetest' ] );
1564 } );
1565
1566 $rights = MediaWikiServices::getInstance()
1567 ->getPermissionManager()
1568 ->getUserPermissions( $user );
1569 $this->assertContains( 'test', $rights );
1570 $this->assertContains( 'runtest', $rights );
1571 $this->assertNotContains( 'writetest', $rights );
1572 $this->assertContains( 'nukeworld', $rights );
1573
1574 // Add a Session that limits rights
1575 $mock = $this->getMockBuilder( stdClass::class )
1576 ->setMethods( [ 'getAllowedUserRights', 'deregisterSession', 'getSessionId' ] )
1577 ->getMock();
1578 $mock->method( 'getAllowedUserRights' )->willReturn( [ 'test', 'writetest' ] );
1579 $mock->method( 'getSessionId' )->willReturn(
1580 new SessionId( str_repeat( 'X', 32 ) )
1581 );
1582 $session = TestUtils::getDummySession( $mock );
1583 $mockRequest = $this->getMockBuilder( FauxRequest::class )
1584 ->setMethods( [ 'getSession' ] )
1585 ->getMock();
1586 $mockRequest->method( 'getSession' )->willReturn( $session );
1587 $userWrapper->mRequest = $mockRequest;
1588
1589 $this->resetServices();
1590 $rights = MediaWikiServices::getInstance()
1591 ->getPermissionManager()
1592 ->getUserPermissions( $user );
1593 $this->assertContains( 'test', $rights );
1594 $this->assertNotContains( 'runtest', $rights );
1595 $this->assertNotContains( 'writetest', $rights );
1596 $this->assertNotContains( 'nukeworld', $rights );
1597 }
1598
1599 /**
1600 * @covers \MediaWiki\Permissions\PermissionManager::getGroupPermissions
1601 */
1602 public function testGroupPermissions() {
1603 $rights = MediaWikiServices::getInstance()->getPermissionManager()
1604 ->getGroupPermissions( [ 'unittesters' ] );
1605 $this->assertContains( 'runtest', $rights );
1606 $this->assertNotContains( 'writetest', $rights );
1607 $this->assertNotContains( 'modifytest', $rights );
1608 $this->assertNotContains( 'nukeworld', $rights );
1609
1610 $rights = MediaWikiServices::getInstance()->getPermissionManager()
1611 ->getGroupPermissions( [ 'unittesters', 'testwriters' ] );
1612 $this->assertContains( 'runtest', $rights );
1613 $this->assertContains( 'writetest', $rights );
1614 $this->assertContains( 'modifytest', $rights );
1615 $this->assertNotContains( 'nukeworld', $rights );
1616 }
1617
1618 /**
1619 * @covers \MediaWiki\Permissions\PermissionManager::getGroupPermissions
1620 */
1621 public function testRevokePermissions() {
1622 $rights = MediaWikiServices::getInstance()->getPermissionManager()
1623 ->getGroupPermissions( [ 'unittesters', 'formertesters' ] );
1624 $this->assertNotContains( 'runtest', $rights );
1625 $this->assertNotContains( 'writetest', $rights );
1626 $this->assertNotContains( 'modifytest', $rights );
1627 $this->assertNotContains( 'nukeworld', $rights );
1628 }
1629
1630 /**
1631 * @dataProvider provideGetGroupsWithPermission
1632 * @covers \MediaWiki\Permissions\PermissionManager::getGroupsWithPermission
1633 */
1634 public function testGetGroupsWithPermission( $expected, $right ) {
1635 $result = MediaWikiServices::getInstance()->getPermissionManager()
1636 ->getGroupsWithPermission( $right );
1637 sort( $result );
1638 sort( $expected );
1639
1640 $this->assertEquals( $expected, $result, "Groups with permission $right" );
1641 }
1642
1643 public static function provideGetGroupsWithPermission() {
1644 return [
1645 [
1646 [ 'unittesters', 'testwriters' ],
1647 'test'
1648 ],
1649 [
1650 [ 'unittesters' ],
1651 'runtest'
1652 ],
1653 [
1654 [ 'testwriters' ],
1655 'writetest'
1656 ],
1657 [
1658 [ 'testwriters' ],
1659 'modifytest'
1660 ],
1661 ];
1662 }
1663
1664 /**
1665 * @covers \MediaWiki\Permissions\PermissionManager::userHasRight
1666 */
1667 public function testUserHasRight() {
1668 $result = MediaWikiServices::getInstance()->getPermissionManager()->userHasRight(
1669 $this->getTestUser( 'unittesters' )->getUser(),
1670 'test'
1671 );
1672 $this->assertTrue( $result );
1673
1674 $result = MediaWikiServices::getInstance()->getPermissionManager()->userHasRight(
1675 $this->getTestUser( 'formertesters' )->getUser(),
1676 'runtest'
1677 );
1678 $this->assertFalse( $result );
1679
1680 $result = MediaWikiServices::getInstance()->getPermissionManager()->userHasRight(
1681 $this->getTestUser( 'formertesters' )->getUser(),
1682 ''
1683 );
1684 $this->assertTrue( $result );
1685 }
1686
1687 /**
1688 * @covers \MediaWiki\Permissions\PermissionManager::groupHasPermission
1689 */
1690 public function testGroupHasPermission() {
1691 $result = MediaWikiServices::getInstance()->getPermissionManager()->groupHasPermission(
1692 'unittesters',
1693 'test'
1694 );
1695 $this->assertTrue( $result );
1696
1697 $result = MediaWikiServices::getInstance()->getPermissionManager()->groupHasPermission(
1698 'formertesters',
1699 'runtest'
1700 );
1701 $this->assertFalse( $result );
1702 }
1703
1704 /**
1705 * @covers \MediaWiki\Permissions\PermissionManager::isEveryoneAllowed
1706 */
1707 public function testIsEveryoneAllowed() {
1708 $result = MediaWikiServices::getInstance()->getPermissionManager()
1709 ->isEveryoneAllowed( 'editmyoptions' );
1710 $this->assertTrue( $result );
1711
1712 $result = MediaWikiServices::getInstance()->getPermissionManager()
1713 ->isEveryoneAllowed( 'test' );
1714 $this->assertFalse( $result );
1715 }
1716
1717 /**
1718 * @covers \MediaWiki\Permissions\PermissionManager::addTemporaryUserRights
1719 */
1720 public function testAddTemporaryUserRights() {
1721 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
1722 $this->overrideUserPermissions( $this->user, [ 'read', 'edit' ] );
1723 // sanity checks
1724 $this->assertEquals( [ 'read', 'edit' ], $permissionManager->getUserPermissions( $this->user ) );
1725 $this->assertFalse( $permissionManager->userHasRight( $this->user, 'move' ) );
1726
1727 $scope = $permissionManager->addTemporaryUserRights( $this->user, [ 'move', 'delete' ] );
1728 $this->assertEquals( [ 'read', 'edit', 'move', 'delete' ],
1729 $permissionManager->getUserPermissions( $this->user ) );
1730 $this->assertTrue( $permissionManager->userHasRight( $this->user, 'move' ) );
1731
1732 $scope2 = $permissionManager->addTemporaryUserRights( $this->user, [ 'delete', 'upload' ] );
1733 $this->assertEquals( [ 'read', 'edit', 'move', 'delete', 'upload' ],
1734 $permissionManager->getUserPermissions( $this->user ) );
1735
1736 ScopedCallback::consume( $scope );
1737 $this->assertEquals( [ 'read', 'edit', 'delete', 'upload' ],
1738 $permissionManager->getUserPermissions( $this->user ) );
1739 ScopedCallback::consume( $scope2 );
1740 $this->assertEquals( [ 'read', 'edit' ],
1741 $permissionManager->getUserPermissions( $this->user ) );
1742 $this->assertFalse( $permissionManager->userHasRight( $this->user, 'move' ) );
1743
1744 ( function () use ( $permissionManager ) {
1745 $scope = $permissionManager->addTemporaryUserRights( $this->user, 'move' );
1746 $this->assertTrue( $permissionManager->userHasRight( $this->user, 'move' ) );
1747 } )();
1748 $this->assertFalse( $permissionManager->userHasRight( $this->user, 'move' ) );
1749 }
1750
1751 /**
1752 * Create a RevisionRecord with a single Javascript main slot.
1753 * @param Title $title
1754 * @param User $user
1755 * @param string $text
1756 * @return MutableRevisionRecord
1757 */
1758 private function getJavascriptRevision( Title $title, User $user, $text ) {
1759 $content = ContentHandler::makeContent( $text, $title, CONTENT_MODEL_JAVASCRIPT );
1760 $revision = new MutableRevisionRecord( $title );
1761 $revision->setContent( 'main', $content );
1762 return $revision;
1763 }
1764
1765 /**
1766 * Create a RevisionRecord with a single Javascript redirect main slot.
1767 * @param Title $title
1768 * @param Title $redirectTargetTitle
1769 * @param User $user
1770 * @return MutableRevisionRecord
1771 */
1772 private function getJavascriptRedirectRevision(
1773 Title $title, Title $redirectTargetTitle, User $user
1774 ) {
1775 $content = ContentHandler::getForModelID( CONTENT_MODEL_JAVASCRIPT )
1776 ->makeRedirectContent( $redirectTargetTitle );
1777 $revision = new MutableRevisionRecord( $title );
1778 $revision->setContent( 'main', $content );
1779 return $revision;
1780 }
1781
1782 public function provideGetRestrictionLevels() {
1783 return [
1784 'No namespace restriction' => [ [ '', 'autoconfirmed', 'sysop' ], NS_TALK ],
1785 'Restricted to autoconfirmed' => [ [ '', 'sysop' ], NS_MAIN ],
1786 'Restricted to sysop' => [ [ '' ], NS_USER ],
1787 'Restricted to someone in two groups' => [ [ '', 'sysop' ], 101 ],
1788 'No special permissions' => [
1789 [ '' ],
1790 NS_TALK,
1791 []
1792 ],
1793 'autoconfirmed' => [
1794 [ '', 'autoconfirmed' ],
1795 NS_TALK,
1796 [ 'autoconfirmed' ]
1797 ],
1798 'autoconfirmed revoked' => [
1799 [ '' ],
1800 NS_TALK,
1801 [ 'autoconfirmed', 'noeditsemiprotected' ]
1802 ],
1803 'sysop' => [
1804 [ '', 'autoconfirmed', 'sysop' ],
1805 NS_TALK,
1806 [ 'sysop' ]
1807 ],
1808 'sysop with autoconfirmed revoked (a bit silly)' => [
1809 [ '', 'sysop' ],
1810 NS_TALK,
1811 [ 'sysop', 'noeditsemiprotected' ]
1812 ],
1813 ];
1814 }
1815
1816 /**
1817 * @dataProvider provideGetRestrictionLevels
1818 * @covers \MediaWiki\Permissions\PermissionManager::getNamespaceRestrictionLevels
1819 *
1820 * @param array $expected
1821 * @param int $ns
1822 * @param array|null $userGroups
1823 * @throws MWException
1824 */
1825 public function testGetRestrictionLevels( array $expected, $ns, array $userGroups = null ) {
1826 $this->setMwGlobals( [
1827 'wgGroupPermissions' => [
1828 '*' => [ 'edit' => true ],
1829 'autoconfirmed' => [ 'editsemiprotected' => true ],
1830 'sysop' => [
1831 'editsemiprotected' => true,
1832 'editprotected' => true,
1833 ],
1834 'privileged' => [ 'privileged' => true ],
1835 ],
1836 'wgRevokePermissions' => [
1837 'noeditsemiprotected' => [ 'editsemiprotected' => true ],
1838 ],
1839 'wgNamespaceProtection' => [
1840 NS_MAIN => 'autoconfirmed',
1841 NS_USER => 'sysop',
1842 101 => [ 'editsemiprotected', 'privileged' ],
1843 ],
1844 'wgRestrictionLevels' => [ '', 'autoconfirmed', 'sysop' ],
1845 'wgAutopromote' => []
1846 ] );
1847 $user = is_null( $userGroups ) ? null : $this->getTestUser( $userGroups )->getUser();
1848 $this->assertSame( $expected, MediaWikiServices::getInstance()
1849 ->getPermissionManager()
1850 ->getNamespaceRestrictionLevels( $ns, $user ) );
1851 }
1852
1853 /**
1854 * @covers \MediaWiki\Permissions\PermissionManager::getAllPermissions
1855 */
1856 public function testGetAllPermissions() {
1857 $this->setMwGlobals( [
1858 'wgAvailableRights' => [ 'test_right' ]
1859 ] );
1860 $this->resetServices();
1861 $this->assertContains(
1862 'test_right',
1863 MediaWikiServices::getInstance()
1864 ->getPermissionManager()
1865 ->getAllPermissions()
1866 );
1867 }
1868
1869 /**
1870 * @covers \MediaWiki\Permissions\PermissionManager::getRightsCacheKey
1871 * @throws \Exception
1872 */
1873 public function testAnonPermissionsNotClash() {
1874 $user1 = User::newFromName( 'User1' );
1875 $user2 = User::newFromName( 'User2' );
1876 $pm = MediaWikiServices::getInstance()->getPermissionManager();
1877 $pm->overrideUserRightsForTesting( $user2, [] );
1878 $this->assertNotSame( $pm->getUserPermissions( $user1 ), $pm->getUserPermissions( $user2 ) );
1879 }
1880
1881 /**
1882 * @covers \MediaWiki\Permissions\PermissionManager::getRightsCacheKey
1883 */
1884 public function testAnonPermissionsNotClashOneRegistered() {
1885 $user1 = User::newFromName( 'User1' );
1886 $user2 = $this->getTestSysop()->getUser();
1887 $pm = MediaWikiServices::getInstance()->getPermissionManager();
1888 $this->assertNotSame( $pm->getUserPermissions( $user1 ), $pm->getUserPermissions( $user2 ) );
1889 }
1890 }