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