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