profiler: Centralise output responsibility from ProfilerOutputText to Profiler
[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 $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 $this->mergeMwGlobalArrayValue( 'wgNamespaceProtection', [
529 NS_USER => [ 'bogus' ]
530 ] );
531 $this->resetServices();
532 $this->overrideUserPermissions( $this->user, '' );
533
534 $this->setTitle( NS_USER );
535 $this->assertEquals( [ [ 'badaccess-group0' ],
536 [ 'namespaceprotected', 'User', 'bogus' ] ],
537 MediaWikiServices::getInstance()->getPermissionManager()
538 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
539
540 $this->setTitle( NS_MEDIAWIKI );
541 $this->overrideUserPermissions( $this->user, 'bogus' );
542 $this->assertEquals( [ [ 'protectedinterface', 'bogus' ] ],
543 MediaWikiServices::getInstance()->getPermissionManager()
544 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
545
546 $this->setTitle( NS_MEDIAWIKI );
547 $this->overrideUserPermissions( $this->user, 'bogus' );
548 $this->assertEquals( [ [ 'protectedinterface', 'bogus' ] ],
549 MediaWikiServices::getInstance()->getPermissionManager()
550 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
551
552 $this->setMwGlobals( 'wgNamespaceProtection', null );
553 $this->resetServices();
554 $this->overrideUserPermissions( $this->user, 'bogus' );
555
556 $this->assertEquals( [],
557 MediaWikiServices::getInstance()->getPermissionManager()
558 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
559 $this->assertEquals( true,
560 MediaWikiServices::getInstance()->getPermissionManager()
561 ->userCan( 'bogus', $this->user, $this->title ) );
562
563 $this->overrideUserPermissions( $this->user, '' );
564 $this->assertEquals( [ [ 'badaccess-group0' ] ],
565 MediaWikiServices::getInstance()->getPermissionManager()
566 ->getPermissionErrors( 'bogus', $this->user, $this->title ) );
567 $this->assertEquals( false,
568 MediaWikiServices::getInstance()->getPermissionManager()
569 ->userCan( 'bogus', $this->user, $this->title ) );
570 }
571
572 /**
573 * @todo This test method should be split up into separate test methods and
574 * data providers
575 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
576 */
577 public function testJsConfigEditPermissions() {
578 $this->setUser( $this->userName );
579
580 $this->setTitle( NS_USER, $this->userName . '/test.js' );
581 $this->runConfigEditPermissions(
582 [ [ 'badaccess-group0' ], [ 'mycustomjsprotected', 'bogus' ] ],
583
584 [ [ 'badaccess-group0' ], [ 'mycustomjsprotected', 'bogus' ] ],
585 [ [ 'badaccess-group0' ], [ 'mycustomjsprotected', 'bogus' ] ],
586 [ [ 'badaccess-group0' ] ],
587
588 [ [ 'badaccess-group0' ], [ 'mycustomjsprotected', 'bogus' ] ],
589 [ [ 'badaccess-group0' ], [ 'mycustomjsprotected', 'bogus' ] ],
590 [ [ 'badaccess-group0' ] ],
591 [ [ 'badaccess-groups' ] ]
592 );
593 }
594
595 /**
596 * @todo This test method should be split up into separate test methods and
597 * data providers
598 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
599 */
600 public function testJsonConfigEditPermissions() {
601 $prefix = MediaWikiServices::getInstance()->getContentLanguage()->
602 getFormattedNsText( NS_PROJECT );
603 $this->setUser( $this->userName );
604
605 $this->setTitle( NS_USER, $this->userName . '/test.json' );
606 $this->runConfigEditPermissions(
607 [ [ 'badaccess-group0' ], [ 'mycustomjsonprotected', 'bogus' ] ],
608
609 [ [ 'badaccess-group0' ], [ 'mycustomjsonprotected', 'bogus' ] ],
610 [ [ 'badaccess-group0' ] ],
611 [ [ 'badaccess-group0' ], [ 'mycustomjsonprotected', 'bogus' ] ],
612
613 [ [ 'badaccess-group0' ], [ 'mycustomjsonprotected', 'bogus' ] ],
614 [ [ 'badaccess-group0' ] ],
615 [ [ 'badaccess-group0' ], [ 'mycustomjsonprotected', 'bogus' ] ],
616 [ [ 'badaccess-groups' ] ]
617 );
618 }
619
620 /**
621 * @todo This test method should be split up into separate test methods and
622 * data providers
623 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
624 */
625 public function testCssConfigEditPermissions() {
626 $this->setUser( $this->userName );
627
628 $this->setTitle( NS_USER, $this->userName . '/test.css' );
629 $this->runConfigEditPermissions(
630 [ [ 'badaccess-group0' ], [ 'mycustomcssprotected', 'bogus' ] ],
631
632 [ [ 'badaccess-group0' ] ],
633 [ [ 'badaccess-group0' ], [ 'mycustomcssprotected', 'bogus' ] ],
634 [ [ 'badaccess-group0' ], [ 'mycustomcssprotected', 'bogus' ] ],
635
636 [ [ 'badaccess-group0' ] ],
637 [ [ 'badaccess-group0' ], [ 'mycustomcssprotected', 'bogus' ] ],
638 [ [ 'badaccess-group0' ], [ 'mycustomcssprotected', 'bogus' ] ],
639 [ [ 'badaccess-groups' ] ]
640 );
641 }
642
643 /**
644 * @todo This test method should be split up into separate test methods and
645 * data providers
646 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
647 */
648 public function testOtherJsConfigEditPermissions() {
649 $this->setUser( $this->userName );
650
651 $this->setTitle( NS_USER, $this->altUserName . '/test.js' );
652 $this->runConfigEditPermissions(
653 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
654
655 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
656 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
657 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
658
659 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
660 [ [ 'badaccess-group0' ], [ 'customjsprotected', 'bogus' ] ],
661 [ [ 'badaccess-group0' ] ],
662 [ [ 'badaccess-groups' ] ]
663 );
664 }
665
666 /**
667 * @todo This test method should be split up into separate test methods and
668 * data providers
669 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
670 */
671 public function testOtherJsonConfigEditPermissions() {
672 $this->setUser( $this->userName );
673
674 $this->setTitle( NS_USER, $this->altUserName . '/test.json' );
675 $this->runConfigEditPermissions(
676 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
677
678 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
679 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
680 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
681
682 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
683 [ [ 'badaccess-group0' ] ],
684 [ [ 'badaccess-group0' ], [ 'customjsonprotected', 'bogus' ] ],
685 [ [ 'badaccess-groups' ] ]
686 );
687 }
688
689 /**
690 * @todo This test method should be split up into separate test methods and
691 * data providers
692 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
693 */
694 public function testOtherCssConfigEditPermissions() {
695 $this->setUser( $this->userName );
696
697 $this->setTitle( NS_USER, $this->altUserName . '/test.css' );
698 $this->runConfigEditPermissions(
699 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
700
701 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
702 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
703 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
704
705 [ [ 'badaccess-group0' ] ],
706 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
707 [ [ 'badaccess-group0' ], [ 'customcssprotected', 'bogus' ] ],
708 [ [ 'badaccess-groups' ] ]
709 );
710 }
711
712 public function testJsConfigRedirectEditPermissions() {
713 $revision = null;
714 $user = $this->getTestUser()->getUser();
715 $otherUser = $this->getTestUser( 'sysop' )->getUser();
716 $localJsTitle = Title::newFromText( 'User:' . $user->getName() . '/foo.js' );
717 $otherLocalJsTitle = Title::newFromText( 'User:' . $user->getName() . '/foo2.js' );
718 $nonlocalJsTitle = Title::newFromText( 'User:' . $otherUser->getName() . '/foo.js' );
719
720 $services = MediaWikiServices::getInstance();
721 $revisionLookup = $this->getMockBuilder( RevisionLookup::class )
722 ->setMethods( [ 'getRevisionByTitle' ] )
723 ->getMockForAbstractClass();
724 $revisionLookup->method( 'getRevisionByTitle' )
725 ->willReturnCallback( function ( LinkTarget $page ) use (
726 $services, &$revision, $localJsTitle
727 ) {
728 if ( $localJsTitle->equals( Title::newFromLinkTarget( $page ) ) ) {
729 return $revision;
730 } else {
731 return $services->getRevisionLookup()->getRevisionByTitle( $page );
732 }
733 } );
734 $permissionManager = new PermissionManager(
735 new LoggedServiceOptions(
736 self::$serviceOptionsAccessLog,
737 PermissionManager::$constructorOptions,
738 [
739 'WhitelistRead' => [],
740 'WhitelistReadRegexp' => [],
741 'EmailConfirmToEdit' => false,
742 'BlockDisablesLogin' => false,
743 'GroupPermissions' => [],
744 'RevokePermissions' => [],
745 'AvailableRights' => [],
746 'NamespaceProtection' => [],
747 'RestrictionLevels' => []
748 ]
749 ),
750 $services->getSpecialPageFactory(),
751 $revisionLookup,
752 MediaWikiServices::getInstance()->getNamespaceInfo()
753 );
754 $this->setService( 'PermissionManager', $permissionManager );
755
756 $permissionManager->overrideUserRightsForTesting( $user, [ 'edit', 'editmyuserjs' ] );
757
758 $revision = $this->getJavascriptRevision( $localJsTitle, $user, '/* script */' );
759 $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
760 $this->assertSame( [], $errors );
761
762 $revision = $this->getJavascriptRedirectRevision( $localJsTitle, $otherLocalJsTitle, $user );
763 $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
764 $this->assertSame( [], $errors );
765
766 $revision = $this->getJavascriptRedirectRevision( $localJsTitle, $nonlocalJsTitle, $user );
767 $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
768 $this->assertSame( [ [ 'mycustomjsredirectprotected', 'edit' ] ], $errors );
769
770 $permissionManager->overrideUserRightsForTesting( $user,
771 [ 'edit', 'editmyuserjs', 'editmyuserjsredirect' ] );
772
773 $revision = $this->getJavascriptRedirectRevision( $localJsTitle, $nonlocalJsTitle, $user );
774 $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
775 $this->assertSame( [], $errors );
776 }
777
778 /**
779 * @todo This test method should be split up into separate test methods and
780 * data providers
781 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
782 */
783 public function testOtherNonConfigEditPermissions() {
784 $this->setUser( $this->userName );
785
786 $this->setTitle( NS_USER, $this->altUserName . '/tempo' );
787 $this->runConfigEditPermissions(
788 [ [ 'badaccess-group0' ] ],
789
790 [ [ 'badaccess-group0' ] ],
791 [ [ 'badaccess-group0' ] ],
792 [ [ 'badaccess-group0' ] ],
793
794 [ [ 'badaccess-group0' ] ],
795 [ [ 'badaccess-group0' ] ],
796 [ [ 'badaccess-group0' ] ],
797 [ [ 'badaccess-groups' ] ]
798 );
799 }
800
801 /**
802 * @todo This should use data providers like the other methods here.
803 * @covers \MediaWiki\Permissions\PermissionManager::checkUserConfigPermissions
804 */
805 public function testPatrolActionConfigEditPermissions() {
806 $this->setUser( 'anon' );
807 $this->setTitle( NS_USER, 'ToPatrolOrNotToPatrol' );
808 $this->runConfigEditPermissions(
809 [ [ 'badaccess-group0' ] ],
810
811 [ [ 'badaccess-group0' ] ],
812 [ [ 'badaccess-group0' ] ],
813 [ [ 'badaccess-group0' ] ],
814
815 [ [ 'badaccess-group0' ] ],
816 [ [ 'badaccess-group0' ] ],
817 [ [ 'badaccess-group0' ] ],
818 [ [ 'badaccess-groups' ] ]
819 );
820 }
821
822 protected function runConfigEditPermissions(
823 $resultNone,
824 $resultMyCss,
825 $resultMyJson,
826 $resultMyJs,
827 $resultUserCss,
828 $resultUserJson,
829 $resultUserJs,
830 $resultPatrol
831 ) {
832 $this->overrideUserPermissions( $this->user );
833 $result = MediaWikiServices::getInstance()->getPermissionManager()
834 ->getPermissionErrors( 'bogus', $this->user, $this->title );
835 $this->assertEquals( $resultNone, $result );
836
837 $this->overrideUserPermissions( $this->user, 'editmyusercss' );
838 $result = MediaWikiServices::getInstance()->getPermissionManager()
839 ->getPermissionErrors( 'bogus', $this->user, $this->title );
840 $this->assertEquals( $resultMyCss, $result );
841
842 $this->overrideUserPermissions( $this->user, 'editmyuserjson' );
843 $result = MediaWikiServices::getInstance()->getPermissionManager()
844 ->getPermissionErrors( 'bogus', $this->user, $this->title );
845 $this->assertEquals( $resultMyJson, $result );
846
847 $this->overrideUserPermissions( $this->user, 'editmyuserjs' );
848 $result = MediaWikiServices::getInstance()->getPermissionManager()
849 ->getPermissionErrors( 'bogus', $this->user, $this->title );
850 $this->assertEquals( $resultMyJs, $result );
851
852 $this->overrideUserPermissions( $this->user, 'editusercss' );
853 $result = MediaWikiServices::getInstance()->getPermissionManager()
854 ->getPermissionErrors( 'bogus', $this->user, $this->title );
855 $this->assertEquals( $resultUserCss, $result );
856
857 $this->overrideUserPermissions( $this->user, 'edituserjson' );
858 $result = MediaWikiServices::getInstance()->getPermissionManager()
859 ->getPermissionErrors( 'bogus', $this->user, $this->title );
860 $this->assertEquals( $resultUserJson, $result );
861
862 $this->overrideUserPermissions( $this->user, 'edituserjs' );
863 $result = MediaWikiServices::getInstance()->getPermissionManager()
864 ->getPermissionErrors( 'bogus', $this->user, $this->title );
865 $this->assertEquals( $resultUserJs, $result );
866
867 $this->overrideUserPermissions( $this->user );
868 $result = MediaWikiServices::getInstance()->getPermissionManager()
869 ->getPermissionErrors( 'patrol', $this->user, $this->title );
870 $this->assertEquals( reset( $resultPatrol[0] ), reset( $result[0] ) );
871
872 $this->overrideUserPermissions( $this->user, [ 'edituserjs', 'edituserjson', 'editusercss' ] );
873 $result = MediaWikiServices::getInstance()->getPermissionManager()
874 ->getPermissionErrors( 'bogus', $this->user, $this->title );
875 $this->assertEquals( [ [ 'badaccess-group0' ] ], $result );
876 }
877
878 /**
879 * @todo This test method should be split up into separate test methods and
880 * data providers
881 *
882 * This test is failing per T201776.
883 *
884 * @group Broken
885 * @covers \MediaWiki\Permissions\PermissionManager::checkPageRestrictions
886 */
887 public function testPageRestrictions() {
888 $prefix = MediaWikiServices::getInstance()->getContentLanguage()->
889 getFormattedNsText( NS_PROJECT );
890
891 $this->setTitle( NS_MAIN );
892 $this->title->mRestrictionsLoaded = true;
893 $this->overrideUserPermissions( $this->user, "edit" );
894 $this->title->mRestrictions = [ "bogus" => [ 'bogus', "sysop", "protect", "" ] ];
895
896 $this->assertEquals( [],
897 MediaWikiServices::getInstance()->getPermissionManager()
898 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
899
900 $this->assertEquals( true,
901 MediaWikiServices::getInstance()->getPermissionManager()
902 ->userCan( 'edit', $this->user, $this->title, PermissionManager::RIGOR_QUICK ) );
903
904 $this->title->mRestrictions = [ "edit" => [ 'bogus', "sysop", "protect", "" ],
905 "bogus" => [ 'bogus', "sysop", "protect", "" ] ];
906
907 $this->assertEquals( [ [ 'badaccess-group0' ],
908 [ 'protectedpagetext', 'bogus', 'bogus' ],
909 [ 'protectedpagetext', 'editprotected', 'bogus' ],
910 [ 'protectedpagetext', 'protect', 'bogus' ] ],
911 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
912 'bogus', $this->user, $this->title ) );
913 $this->assertEquals( [ [ 'protectedpagetext', 'bogus', 'edit' ],
914 [ 'protectedpagetext', 'editprotected', 'edit' ],
915 [ 'protectedpagetext', 'protect', 'edit' ] ],
916 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
917 'edit', $this->user, $this->title ) );
918 $this->overrideUserPermissions( $this->user );
919 $this->assertEquals( [ [ 'badaccess-group0' ],
920 [ 'protectedpagetext', 'bogus', 'bogus' ],
921 [ 'protectedpagetext', 'editprotected', 'bogus' ],
922 [ 'protectedpagetext', 'protect', 'bogus' ] ],
923 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
924 'bogus', $this->user, $this->title ) );
925 $this->assertEquals( [ [ 'badaccess-groups', "*, [[$prefix:Users|Users]]", 2 ],
926 [ 'protectedpagetext', 'bogus', 'edit' ],
927 [ 'protectedpagetext', 'editprotected', 'edit' ],
928 [ 'protectedpagetext', 'protect', 'edit' ] ],
929 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
930 'edit', $this->user, $this->title ) );
931 $this->overrideUserPermissions( $this->user, [ "edit", "editprotected" ] );
932 $this->assertEquals( [ [ 'badaccess-group0' ],
933 [ 'protectedpagetext', 'bogus', 'bogus' ],
934 [ 'protectedpagetext', 'protect', 'bogus' ] ],
935 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
936 'bogus', $this->user, $this->title ) );
937 $this->assertEquals( [
938 [ 'protectedpagetext', 'bogus', 'edit' ],
939 [ 'protectedpagetext', 'protect', 'edit' ] ],
940 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
941 'edit', $this->user, $this->title ) );
942
943 $this->title->mCascadeRestriction = true;
944 $this->overrideUserPermissions( $this->user, "edit" );
945
946 $this->assertEquals( false,
947 MediaWikiServices::getInstance()->getPermissionManager()
948 ->userCan( 'bogus', $this->user, $this->title, PermissionManager::RIGOR_QUICK ) );
949
950 $this->assertEquals( false,
951 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
952 'edit', $this->user, $this->title, PermissionManager::RIGOR_QUICK ) );
953
954 $this->assertEquals( [ [ 'badaccess-group0' ],
955 [ 'protectedpagetext', 'bogus', 'bogus' ],
956 [ 'protectedpagetext', 'editprotected', 'bogus' ],
957 [ 'protectedpagetext', 'protect', 'bogus' ] ],
958 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
959 'bogus', $this->user, $this->title ) );
960 $this->assertEquals( [ [ 'protectedpagetext', 'bogus', 'edit' ],
961 [ 'protectedpagetext', 'editprotected', 'edit' ],
962 [ 'protectedpagetext', 'protect', 'edit' ] ],
963 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
964 'edit', $this->user, $this->title ) );
965
966 $this->overrideUserPermissions( $this->user, [ "edit", "editprotected" ] );
967 $this->assertEquals( false,
968 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
969 'bogus', $this->user, $this->title, PermissionManager::RIGOR_QUICK ) );
970
971 $this->assertEquals( false,
972 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
973 'edit', $this->user, $this->title, PermissionManager::RIGOR_QUICK ) );
974
975 $this->assertEquals( [ [ 'badaccess-group0' ],
976 [ 'protectedpagetext', 'bogus', 'bogus' ],
977 [ 'protectedpagetext', 'protect', 'bogus' ],
978 [ 'protectedpagetext', 'protect', 'bogus' ] ],
979 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
980 'bogus', $this->user, $this->title ) );
981 $this->assertEquals( [ [ 'protectedpagetext', 'bogus', 'edit' ],
982 [ 'protectedpagetext', 'protect', 'edit' ],
983 [ 'protectedpagetext', 'protect', 'edit' ] ],
984 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
985 'edit', $this->user, $this->title ) );
986 }
987
988 /**
989 * @covers \MediaWiki\Permissions\PermissionManager::checkCascadingSourcesRestrictions
990 */
991 public function testCascadingSourcesRestrictions() {
992 $this->setTitle( NS_MAIN, "test page" );
993 $this->overrideUserPermissions( $this->user, [ "edit", "bogus" ] );
994
995 $this->title->mCascadeSources = [
996 Title::makeTitle( NS_MAIN, "Bogus" ),
997 Title::makeTitle( NS_MAIN, "UnBogus" )
998 ];
999 $this->title->mCascadingRestrictions = [
1000 "bogus" => [ 'bogus', "sysop", "protect", "" ]
1001 ];
1002
1003 $this->assertEquals( false,
1004 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1005 'bogus', $this->user, $this->title ) );
1006 $this->assertEquals( [
1007 [ "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ],
1008 [ "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ],
1009 [ "cascadeprotected", 2, "* [[:Bogus]]\n* [[:UnBogus]]\n", 'bogus' ] ],
1010 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
1011 'bogus', $this->user, $this->title ) );
1012
1013 $this->assertEquals( true,
1014 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1015 'edit', $this->user, $this->title ) );
1016 $this->assertEquals( [],
1017 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
1018 'edit', $this->user, $this->title ) );
1019 }
1020
1021 /**
1022 * @todo This test method should be split up into separate test methods and
1023 * data providers
1024 * @covers \MediaWiki\Permissions\PermissionManager::checkActionPermissions
1025 */
1026 public function testActionPermissions() {
1027 $this->overrideUserPermissions( $this->user, [ "createpage" ] );
1028 $this->setTitle( NS_MAIN, "test page" );
1029 $this->title->mTitleProtection['permission'] = '';
1030 $this->title->mTitleProtection['user'] = $this->user->getId();
1031 $this->title->mTitleProtection['expiry'] = 'infinity';
1032 $this->title->mTitleProtection['reason'] = 'test';
1033 $this->title->mCascadeRestriction = false;
1034
1035 $this->assertEquals( [ [ 'titleprotected', 'Useruser', 'test' ] ],
1036 MediaWikiServices::getInstance()->getPermissionManager()
1037 ->getPermissionErrors( 'create', $this->user, $this->title ) );
1038 $this->assertEquals( false,
1039 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1040 'create', $this->user, $this->title ) );
1041
1042 $this->title->mTitleProtection['permission'] = 'editprotected';
1043 $this->overrideUserPermissions( $this->user, [ 'createpage', 'protect' ] );
1044 $this->assertEquals( [ [ 'titleprotected', 'Useruser', 'test' ] ],
1045 MediaWikiServices::getInstance()->getPermissionManager()
1046 ->getPermissionErrors( 'create', $this->user, $this->title ) );
1047 $this->assertEquals( false,
1048 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1049 'create', $this->user, $this->title ) );
1050
1051 $this->overrideUserPermissions( $this->user, [ 'createpage', 'editprotected' ] );
1052 $this->assertEquals( [],
1053 MediaWikiServices::getInstance()->getPermissionManager()
1054 ->getPermissionErrors( 'create', $this->user, $this->title ) );
1055 $this->assertEquals( true,
1056 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1057 'create', $this->user, $this->title ) );
1058
1059 $this->overrideUserPermissions( $this->user, [ 'createpage' ] );
1060 $this->assertEquals( [ [ 'titleprotected', 'Useruser', 'test' ] ],
1061 MediaWikiServices::getInstance()->getPermissionManager()
1062 ->getPermissionErrors( 'create', $this->user, $this->title ) );
1063 $this->assertEquals( false,
1064 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1065 'create', $this->user, $this->title ) );
1066
1067 $this->setTitle( NS_MEDIA, "test page" );
1068 $this->overrideUserPermissions( $this->user, [ "move" ] );
1069 $this->assertEquals( false,
1070 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1071 'move', $this->user, $this->title ) );
1072 $this->assertEquals( [ [ 'immobile-source-namespace', 'Media' ] ],
1073 MediaWikiServices::getInstance()->getPermissionManager()
1074 ->getPermissionErrors( 'move', $this->user, $this->title ) );
1075
1076 $this->setTitle( NS_HELP, "test page" );
1077 $this->assertEquals( [],
1078 MediaWikiServices::getInstance()->getPermissionManager()
1079 ->getPermissionErrors( 'move', $this->user, $this->title ) );
1080 $this->assertEquals( true,
1081 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1082 'move', $this->user, $this->title ) );
1083
1084 $this->title->mInterwiki = "no";
1085 $this->assertEquals( [ [ 'immobile-source-page' ] ],
1086 MediaWikiServices::getInstance()->getPermissionManager()
1087 ->getPermissionErrors( 'move', $this->user, $this->title ) );
1088 $this->assertEquals( false,
1089 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1090 'move', $this->user, $this->title ) );
1091
1092 $this->setTitle( NS_MEDIA, "test page" );
1093 $this->assertEquals( false,
1094 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1095 'move-target', $this->user, $this->title ) );
1096 $this->assertEquals( [ [ 'immobile-target-namespace', 'Media' ] ],
1097 MediaWikiServices::getInstance()->getPermissionManager()
1098 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1099
1100 $this->setTitle( NS_HELP, "test page" );
1101 $this->assertEquals( [],
1102 MediaWikiServices::getInstance()->getPermissionManager()
1103 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1104 $this->assertEquals( true,
1105 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1106 'move-target', $this->user, $this->title ) );
1107
1108 $this->title->mInterwiki = "no";
1109 $this->assertEquals( [ [ 'immobile-target-page' ] ],
1110 MediaWikiServices::getInstance()->getPermissionManager()
1111 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1112 $this->assertEquals( false,
1113 MediaWikiServices::getInstance()->getPermissionManager()->userCan(
1114 'move-target', $this->user, $this->title ) );
1115 }
1116
1117 /**
1118 * @covers \MediaWiki\Permissions\PermissionManager::checkUserBlock
1119 */
1120 public function testUserBlock() {
1121 $this->setMwGlobals( [
1122 'wgEmailConfirmToEdit' => true,
1123 'wgEmailAuthentication' => true,
1124 'wgBlockDisablesLogin' => false,
1125 ] );
1126
1127 $this->overrideUserPermissions( $this->user, [
1128 'createpage',
1129 'edit',
1130 'move',
1131 'rollback',
1132 'patrol',
1133 'upload',
1134 'purge'
1135 ] );
1136 $this->setTitle( NS_HELP, "test page" );
1137
1138 # $wgEmailConfirmToEdit only applies to 'edit' action
1139 $this->assertEquals( [],
1140 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
1141 'move-target', $this->user, $this->title ) );
1142 $this->assertContains( [ 'confirmedittext' ],
1143 MediaWikiServices::getInstance()->getPermissionManager()
1144 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1145
1146 $this->setMwGlobals( 'wgEmailConfirmToEdit', false );
1147 $this->resetServices();
1148 $this->overrideUserPermissions( $this->user, [
1149 'createpage',
1150 'edit',
1151 'move',
1152 'rollback',
1153 'patrol',
1154 'upload',
1155 'purge'
1156 ] );
1157
1158 $this->assertNotContains( [ 'confirmedittext' ],
1159 MediaWikiServices::getInstance()->getPermissionManager()
1160 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1161
1162 # $wgEmailConfirmToEdit && !$user->isEmailConfirmed() && $action != 'createaccount'
1163 $this->assertEquals( [],
1164 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
1165 'move-target', $this->user, $this->title ) );
1166
1167 global $wgLang;
1168 $prev = time();
1169 $now = time() + 120;
1170 $this->user->mBlockedby = $this->user->getId();
1171 $this->user->mBlock = new DatabaseBlock( [
1172 'address' => '127.0.8.1',
1173 'by' => $this->user->getId(),
1174 'reason' => 'no reason given',
1175 'timestamp' => $prev + 3600,
1176 'auto' => true,
1177 'expiry' => 0
1178 ] );
1179 $this->user->mBlock->setTimestamp( 0 );
1180 $this->assertEquals( [ [ 'autoblockedtext',
1181 "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
1182 "\u{202A}Useruser\u{202C}", null, 'infinite', '127.0.8.1',
1183 $wgLang->timeanddate( wfTimestamp( TS_MW, $prev ), true ) ] ],
1184 MediaWikiServices::getInstance()->getPermissionManager()->getPermissionErrors(
1185 'move-target', $this->user, $this->title ) );
1186
1187 $this->assertEquals( false, MediaWikiServices::getInstance()->getPermissionManager()
1188 ->userCan( 'move-target', $this->user, $this->title ) );
1189 // quickUserCan should ignore user blocks
1190 $this->assertEquals( true, MediaWikiServices::getInstance()->getPermissionManager()
1191 ->userCan( 'move-target', $this->user, $this->title,
1192 PermissionManager::RIGOR_QUICK ) );
1193
1194 global $wgLocalTZoffset;
1195 $wgLocalTZoffset = -60;
1196 $this->user->mBlockedby = $this->user->getName();
1197 $this->user->mBlock = new DatabaseBlock( [
1198 'address' => '127.0.8.1',
1199 'by' => $this->user->getId(),
1200 'reason' => 'no reason given',
1201 'timestamp' => $now,
1202 'auto' => false,
1203 'expiry' => 10,
1204 ] );
1205 $this->assertEquals( [ [ 'blockedtext',
1206 "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
1207 "\u{202A}Useruser\u{202C}", null, '23:00, 31 December 1969', '127.0.8.1',
1208 $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ],
1209 MediaWikiServices::getInstance()->getPermissionManager()
1210 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1211 # $action != 'read' && $action != 'createaccount' && $user->isBlockedFrom( $this )
1212 # $user->blockedFor() == ''
1213 # $user->mBlock->mExpiry == 'infinity'
1214
1215 $this->user->mBlockedby = $this->user->getName();
1216 $this->user->mBlock = new SystemBlock( [
1217 'address' => '127.0.8.1',
1218 'by' => $this->user->getId(),
1219 'reason' => 'no reason given',
1220 'timestamp' => $now,
1221 'auto' => false,
1222 'systemBlock' => 'test',
1223 ] );
1224
1225 $errors = [ [ 'systemblockedtext',
1226 "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
1227 "\u{202A}Useruser\u{202C}", 'test', 'infinite', '127.0.8.1',
1228 $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ];
1229
1230 $this->assertEquals( $errors,
1231 MediaWikiServices::getInstance()->getPermissionManager()
1232 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1233 $this->assertEquals( $errors,
1234 MediaWikiServices::getInstance()->getPermissionManager()
1235 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1236 $this->assertEquals( $errors,
1237 MediaWikiServices::getInstance()->getPermissionManager()
1238 ->getPermissionErrors( 'rollback', $this->user, $this->title ) );
1239 $this->assertEquals( $errors,
1240 MediaWikiServices::getInstance()->getPermissionManager()
1241 ->getPermissionErrors( 'patrol', $this->user, $this->title ) );
1242 $this->assertEquals( $errors,
1243 MediaWikiServices::getInstance()->getPermissionManager()
1244 ->getPermissionErrors( 'upload', $this->user, $this->title ) );
1245 $this->assertEquals( [],
1246 MediaWikiServices::getInstance()->getPermissionManager()
1247 ->getPermissionErrors( 'purge', $this->user, $this->title ) );
1248
1249 // partial block message test
1250 $this->user->mBlockedby = $this->user->getName();
1251 $this->user->mBlock = new DatabaseBlock( [
1252 'address' => '127.0.8.1',
1253 'by' => $this->user->getId(),
1254 'reason' => 'no reason given',
1255 'timestamp' => $now,
1256 'sitewide' => false,
1257 'expiry' => 10,
1258 ] );
1259
1260 $this->assertEquals( [],
1261 MediaWikiServices::getInstance()->getPermissionManager()
1262 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1263 $this->assertEquals( [],
1264 MediaWikiServices::getInstance()->getPermissionManager()
1265 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1266 $this->assertEquals( [],
1267 MediaWikiServices::getInstance()->getPermissionManager()
1268 ->getPermissionErrors( 'rollback', $this->user, $this->title ) );
1269 $this->assertEquals( [],
1270 MediaWikiServices::getInstance()->getPermissionManager()
1271 ->getPermissionErrors( 'patrol', $this->user, $this->title ) );
1272 $this->assertEquals( [],
1273 MediaWikiServices::getInstance()->getPermissionManager()
1274 ->getPermissionErrors( 'upload', $this->user, $this->title ) );
1275 $this->assertEquals( [],
1276 MediaWikiServices::getInstance()->getPermissionManager()
1277 ->getPermissionErrors( 'purge', $this->user, $this->title ) );
1278
1279 $this->user->mBlock->setRestrictions( [
1280 ( new PageRestriction( 0, $this->title->getArticleID() ) )->setTitle( $this->title ),
1281 ] );
1282
1283 $errors = [ [ 'blockedtext-partial',
1284 "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
1285 "\u{202A}Useruser\u{202C}", null, '23:00, 31 December 1969', '127.0.8.1',
1286 $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ];
1287
1288 $this->assertEquals( $errors,
1289 MediaWikiServices::getInstance()->getPermissionManager()
1290 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1291 $this->assertEquals( $errors,
1292 MediaWikiServices::getInstance()->getPermissionManager()
1293 ->getPermissionErrors( 'move-target', $this->user, $this->title ) );
1294 $this->assertEquals( $errors,
1295 MediaWikiServices::getInstance()->getPermissionManager()
1296 ->getPermissionErrors( 'rollback', $this->user, $this->title ) );
1297 $this->assertEquals( $errors,
1298 MediaWikiServices::getInstance()->getPermissionManager()
1299 ->getPermissionErrors( 'patrol', $this->user, $this->title ) );
1300 $this->assertEquals( [],
1301 MediaWikiServices::getInstance()->getPermissionManager()
1302 ->getPermissionErrors( 'upload', $this->user, $this->title ) );
1303 $this->assertEquals( [],
1304 MediaWikiServices::getInstance()->getPermissionManager()
1305 ->getPermissionErrors( 'purge', $this->user, $this->title ) );
1306
1307 // Test no block.
1308 $this->user->mBlockedby = null;
1309 $this->user->mBlock = null;
1310
1311 $this->assertEquals( [],
1312 MediaWikiServices::getInstance()->getPermissionManager()
1313 ->getPermissionErrors( 'edit', $this->user, $this->title ) );
1314 }
1315
1316 /**
1317 * @covers \MediaWiki\Permissions\PermissionManager::checkUserBlock
1318 *
1319 * Tests to determine that the passed in permission does not get mixed up with
1320 * an action of the same name.
1321 */
1322 public function testUserBlockAction() {
1323 global $wgLang;
1324
1325 $tester = $this->getMockBuilder( Action::class )
1326 ->disableOriginalConstructor()
1327 ->getMock();
1328 $tester->method( 'getName' )
1329 ->willReturn( 'tester' );
1330 $tester->method( 'getRestriction' )
1331 ->willReturn( 'test' );
1332 $tester->method( 'requiresUnblock' )
1333 ->willReturn( false );
1334
1335 $this->setMwGlobals( [
1336 'wgActions' => [
1337 'tester' => $tester,
1338 ],
1339 'wgGroupPermissions' => [
1340 '*' => [
1341 'tester' => true,
1342 ],
1343 ],
1344 ] );
1345
1346 $now = time();
1347 $this->user->mBlockedby = $this->user->getName();
1348 $this->user->mBlock = new DatabaseBlock( [
1349 'address' => '127.0.8.1',
1350 'by' => $this->user->getId(),
1351 'reason' => 'no reason given',
1352 'timestamp' => $now,
1353 'auto' => false,
1354 'expiry' => 'infinity',
1355 ] );
1356
1357 $errors = [ [ 'blockedtext',
1358 "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
1359 "\u{202A}Useruser\u{202C}", null, 'infinite', '127.0.8.1',
1360 $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ];
1361
1362 $this->assertEquals( $errors,
1363 MediaWikiServices::getInstance()->getPermissionManager()
1364 ->getPermissionErrors( 'tester', $this->user, $this->title ) );
1365 }
1366
1367 /**
1368 * @covers \MediaWiki\Permissions\PermissionManager::isBlockedFrom
1369 */
1370 public function testBlockInstanceCache() {
1371 // First, check the user isn't blocked
1372 $user = $this->getMutableTestUser()->getUser();
1373 $ut = Title::makeTitle( NS_USER_TALK, $user->getName() );
1374 $this->assertNull( $user->getBlock( false ), 'sanity check' );
1375 //$this->assertSame( '', $user->blockedBy(), 'sanity check' );
1376 //$this->assertSame( '', $user->blockedFor(), 'sanity check' );
1377 //$this->assertFalse( (bool)$user->isHidden(), 'sanity check' );
1378 $this->assertFalse( MediaWikiServices::getInstance()->getPermissionManager()
1379 ->isBlockedFrom( $user, $ut ), 'sanity check' );
1380
1381 // Block the user
1382 $blocker = $this->getTestSysop()->getUser();
1383 $block = new DatabaseBlock( [
1384 'hideName' => true,
1385 'allowUsertalk' => false,
1386 'reason' => 'Because',
1387 ] );
1388 $block->setTarget( $user );
1389 $block->setBlocker( $blocker );
1390 $res = $block->insert();
1391 $this->assertTrue( (bool)$res['id'], 'sanity check: Failed to insert block' );
1392
1393 // Clear cache and confirm it loaded the block properly
1394 $user->clearInstanceCache();
1395 $this->assertInstanceOf( DatabaseBlock::class, $user->getBlock( false ) );
1396 //$this->assertSame( $blocker->getName(), $user->blockedBy() );
1397 //$this->assertSame( 'Because', $user->blockedFor() );
1398 //$this->assertTrue( (bool)$user->isHidden() );
1399 $this->assertTrue( MediaWikiServices::getInstance()->getPermissionManager()
1400 ->isBlockedFrom( $user, $ut ) );
1401
1402 // Unblock
1403 $block->delete();
1404
1405 // Clear cache and confirm it loaded the not-blocked properly
1406 $user->clearInstanceCache();
1407 $this->assertNull( $user->getBlock( false ) );
1408 //$this->assertSame( '', $user->blockedBy() );
1409 //$this->assertSame( '', $user->blockedFor() );
1410 //$this->assertFalse( (bool)$user->isHidden() );
1411 $this->assertFalse( MediaWikiServices::getInstance()->getPermissionManager()
1412 ->isBlockedFrom( $user, $ut ) );
1413 }
1414
1415 /**
1416 * @covers \MediaWiki\Permissions\PermissionManager::isBlockedFrom
1417 * @dataProvider provideIsBlockedFrom
1418 * @param string|null $title Title to test.
1419 * @param bool $expect Expected result from User::isBlockedFrom()
1420 * @param array $options Additional test options:
1421 * - 'blockAllowsUTEdit': (bool, default true) Value for $wgBlockAllowsUTEdit
1422 * - 'allowUsertalk': (bool, default false) Passed to DatabaseBlock::__construct()
1423 * - 'pageRestrictions': (array|null) If non-empty, page restriction titles for the block.
1424 */
1425 public function testIsBlockedFrom( $title, $expect, array $options = [] ) {
1426 $this->setMwGlobals( [
1427 'wgBlockAllowsUTEdit' => $options['blockAllowsUTEdit'] ?? true,
1428 ] );
1429
1430 $user = $this->getTestUser()->getUser();
1431
1432 if ( $title === self::USER_TALK_PAGE ) {
1433 $title = $user->getTalkPage();
1434 } else {
1435 $title = Title::newFromText( $title );
1436 }
1437
1438 $restrictions = [];
1439 foreach ( $options['pageRestrictions'] ?? [] as $pagestr ) {
1440 $page = $this->getExistingTestPage(
1441 $pagestr === self::USER_TALK_PAGE ? $user->getTalkPage() : $pagestr
1442 );
1443 $restrictions[] = new PageRestriction( 0, $page->getId() );
1444 }
1445 foreach ( $options['namespaceRestrictions'] ?? [] as $ns ) {
1446 $restrictions[] = new NamespaceRestriction( 0, $ns );
1447 }
1448
1449 $block = new DatabaseBlock( [
1450 'expiry' => wfTimestamp( TS_MW, wfTimestamp() + ( 40 * 60 * 60 ) ),
1451 'allowUsertalk' => $options['allowUsertalk'] ?? false,
1452 'sitewide' => !$restrictions,
1453 ] );
1454 $block->setTarget( $user );
1455 $block->setBlocker( $this->getTestSysop()->getUser() );
1456 if ( $restrictions ) {
1457 $block->setRestrictions( $restrictions );
1458 }
1459 $block->insert();
1460
1461 try {
1462 $this->assertSame( $expect, MediaWikiServices::getInstance()->getPermissionManager()
1463 ->isBlockedFrom( $user, $title ) );
1464 } finally {
1465 $block->delete();
1466 }
1467 }
1468
1469 public static function provideIsBlockedFrom() {
1470 return [
1471 'Sitewide block, basic operation' => [ 'Test page', true ],
1472 'Sitewide block, not allowing user talk' => [
1473 self::USER_TALK_PAGE, true, [
1474 'allowUsertalk' => false,
1475 ]
1476 ],
1477 'Sitewide block, allowing user talk' => [
1478 self::USER_TALK_PAGE, false, [
1479 'allowUsertalk' => true,
1480 ]
1481 ],
1482 'Sitewide block, allowing user talk but $wgBlockAllowsUTEdit is false' => [
1483 self::USER_TALK_PAGE, true, [
1484 'allowUsertalk' => true,
1485 'blockAllowsUTEdit' => false,
1486 ]
1487 ],
1488 'Partial block, blocking the page' => [
1489 'Test page', true, [
1490 'pageRestrictions' => [ 'Test page' ],
1491 ]
1492 ],
1493 'Partial block, not blocking the page' => [
1494 'Test page 2', false, [
1495 'pageRestrictions' => [ 'Test page' ],
1496 ]
1497 ],
1498 'Partial block, not allowing user talk but user talk page is not blocked' => [
1499 self::USER_TALK_PAGE, false, [
1500 'allowUsertalk' => false,
1501 'pageRestrictions' => [ 'Test page' ],
1502 ]
1503 ],
1504 'Partial block, allowing user talk but user talk page is blocked' => [
1505 self::USER_TALK_PAGE, true, [
1506 'allowUsertalk' => true,
1507 'pageRestrictions' => [ self::USER_TALK_PAGE ],
1508 ]
1509 ],
1510 'Partial block, user talk page is not blocked but $wgBlockAllowsUTEdit is false' => [
1511 self::USER_TALK_PAGE, false, [
1512 'allowUsertalk' => false,
1513 'pageRestrictions' => [ 'Test page' ],
1514 'blockAllowsUTEdit' => false,
1515 ]
1516 ],
1517 'Partial block, user talk page is blocked and $wgBlockAllowsUTEdit is false' => [
1518 self::USER_TALK_PAGE, true, [
1519 'allowUsertalk' => true,
1520 'pageRestrictions' => [ self::USER_TALK_PAGE ],
1521 'blockAllowsUTEdit' => false,
1522 ]
1523 ],
1524 'Partial user talk namespace block, not allowing user talk' => [
1525 self::USER_TALK_PAGE, true, [
1526 'allowUsertalk' => false,
1527 'namespaceRestrictions' => [ NS_USER_TALK ],
1528 ]
1529 ],
1530 'Partial user talk namespace block, allowing user talk' => [
1531 self::USER_TALK_PAGE, false, [
1532 'allowUsertalk' => true,
1533 'namespaceRestrictions' => [ NS_USER_TALK ],
1534 ]
1535 ],
1536 'Partial user talk namespace block, where $wgBlockAllowsUTEdit is false' => [
1537 self::USER_TALK_PAGE, true, [
1538 'allowUsertalk' => true,
1539 'namespaceRestrictions' => [ NS_USER_TALK ],
1540 'blockAllowsUTEdit' => false,
1541 ]
1542 ],
1543 ];
1544 }
1545
1546 /**
1547 * @covers \MediaWiki\Permissions\PermissionManager::getUserPermissions
1548 */
1549 public function testGetUserPermissions() {
1550 $user = $this->getTestUser( [ 'unittesters' ] )->getUser();
1551 $rights = MediaWikiServices::getInstance()->getPermissionManager()
1552 ->getUserPermissions( $user );
1553 $this->assertContains( 'runtest', $rights );
1554 $this->assertNotContains( 'writetest', $rights );
1555 $this->assertNotContains( 'modifytest', $rights );
1556 $this->assertNotContains( 'nukeworld', $rights );
1557 }
1558
1559 /**
1560 * @covers \MediaWiki\Permissions\PermissionManager::getUserPermissions
1561 */
1562 public function testGetUserPermissionsHooks() {
1563 $user = $this->getTestUser( [ 'unittesters', 'testwriters' ] )->getUser();
1564 $userWrapper = TestingAccessWrapper::newFromObject( $user );
1565
1566 $rights = MediaWikiServices::getInstance()
1567 ->getPermissionManager()
1568 ->getUserPermissions( $user );
1569 $this->assertContains( 'test', $rights, 'sanity check' );
1570 $this->assertContains( 'runtest', $rights, 'sanity check' );
1571 $this->assertContains( 'writetest', $rights, 'sanity check' );
1572 $this->assertNotContains( 'nukeworld', $rights, 'sanity check' );
1573
1574 // Add a hook manipluating the rights
1575 $this->setTemporaryHook( 'UserGetRights', function ( $user, &$rights ) {
1576 $rights[] = 'nukeworld';
1577 $rights = array_diff( $rights, [ 'writetest' ] );
1578 } );
1579
1580 $this->resetServices();
1581 $rights = MediaWikiServices::getInstance()
1582 ->getPermissionManager()
1583 ->getUserPermissions( $user );
1584 $this->assertContains( 'test', $rights );
1585 $this->assertContains( 'runtest', $rights );
1586 $this->assertNotContains( 'writetest', $rights );
1587 $this->assertContains( 'nukeworld', $rights );
1588
1589 // Add a Session that limits rights
1590 $mock = $this->getMockBuilder( stdClass::class )
1591 ->setMethods( [ 'getAllowedUserRights', 'deregisterSession', 'getSessionId' ] )
1592 ->getMock();
1593 $mock->method( 'getAllowedUserRights' )->willReturn( [ 'test', 'writetest' ] );
1594 $mock->method( 'getSessionId' )->willReturn(
1595 new SessionId( str_repeat( 'X', 32 ) )
1596 );
1597 $session = TestUtils::getDummySession( $mock );
1598 $mockRequest = $this->getMockBuilder( FauxRequest::class )
1599 ->setMethods( [ 'getSession' ] )
1600 ->getMock();
1601 $mockRequest->method( 'getSession' )->willReturn( $session );
1602 $userWrapper->mRequest = $mockRequest;
1603
1604 $this->resetServices();
1605 $rights = MediaWikiServices::getInstance()
1606 ->getPermissionManager()
1607 ->getUserPermissions( $user );
1608 $this->assertContains( 'test', $rights );
1609 $this->assertNotContains( 'runtest', $rights );
1610 $this->assertNotContains( 'writetest', $rights );
1611 $this->assertNotContains( 'nukeworld', $rights );
1612 }
1613
1614 /**
1615 * @covers \MediaWiki\Permissions\PermissionManager::getGroupPermissions
1616 */
1617 public function testGroupPermissions() {
1618 $rights = MediaWikiServices::getInstance()->getPermissionManager()
1619 ->getGroupPermissions( [ 'unittesters' ] );
1620 $this->assertContains( 'runtest', $rights );
1621 $this->assertNotContains( 'writetest', $rights );
1622 $this->assertNotContains( 'modifytest', $rights );
1623 $this->assertNotContains( 'nukeworld', $rights );
1624
1625 $rights = MediaWikiServices::getInstance()->getPermissionManager()
1626 ->getGroupPermissions( [ 'unittesters', 'testwriters' ] );
1627 $this->assertContains( 'runtest', $rights );
1628 $this->assertContains( 'writetest', $rights );
1629 $this->assertContains( 'modifytest', $rights );
1630 $this->assertNotContains( 'nukeworld', $rights );
1631 }
1632
1633 /**
1634 * @covers \MediaWiki\Permissions\PermissionManager::getGroupPermissions
1635 */
1636 public function testRevokePermissions() {
1637 $rights = MediaWikiServices::getInstance()->getPermissionManager()
1638 ->getGroupPermissions( [ 'unittesters', 'formertesters' ] );
1639 $this->assertNotContains( 'runtest', $rights );
1640 $this->assertNotContains( 'writetest', $rights );
1641 $this->assertNotContains( 'modifytest', $rights );
1642 $this->assertNotContains( 'nukeworld', $rights );
1643 }
1644
1645 /**
1646 * @dataProvider provideGetGroupsWithPermission
1647 * @covers \MediaWiki\Permissions\PermissionManager::getGroupsWithPermission
1648 */
1649 public function testGetGroupsWithPermission( $expected, $right ) {
1650 $result = MediaWikiServices::getInstance()->getPermissionManager()
1651 ->getGroupsWithPermission( $right );
1652 sort( $result );
1653 sort( $expected );
1654
1655 $this->assertEquals( $expected, $result, "Groups with permission $right" );
1656 }
1657
1658 public static function provideGetGroupsWithPermission() {
1659 return [
1660 [
1661 [ 'unittesters', 'testwriters' ],
1662 'test'
1663 ],
1664 [
1665 [ 'unittesters' ],
1666 'runtest'
1667 ],
1668 [
1669 [ 'testwriters' ],
1670 'writetest'
1671 ],
1672 [
1673 [ 'testwriters' ],
1674 'modifytest'
1675 ],
1676 ];
1677 }
1678
1679 /**
1680 * @covers \MediaWiki\Permissions\PermissionManager::userHasRight
1681 */
1682 public function testUserHasRight() {
1683 $result = MediaWikiServices::getInstance()->getPermissionManager()->userHasRight(
1684 $this->getTestUser( 'unittesters' )->getUser(),
1685 'test'
1686 );
1687 $this->assertTrue( $result );
1688
1689 $result = MediaWikiServices::getInstance()->getPermissionManager()->userHasRight(
1690 $this->getTestUser( 'formertesters' )->getUser(),
1691 'runtest'
1692 );
1693 $this->assertFalse( $result );
1694
1695 $result = MediaWikiServices::getInstance()->getPermissionManager()->userHasRight(
1696 $this->getTestUser( 'formertesters' )->getUser(),
1697 ''
1698 );
1699 $this->assertTrue( $result );
1700 }
1701
1702 /**
1703 * @covers \MediaWiki\Permissions\PermissionManager::groupHasPermission
1704 */
1705 public function testGroupHasPermission() {
1706 $result = MediaWikiServices::getInstance()->getPermissionManager()->groupHasPermission(
1707 'unittesters',
1708 'test'
1709 );
1710 $this->assertTrue( $result );
1711
1712 $result = MediaWikiServices::getInstance()->getPermissionManager()->groupHasPermission(
1713 'formertesters',
1714 'runtest'
1715 );
1716 $this->assertFalse( $result );
1717 }
1718
1719 /**
1720 * @covers \MediaWiki\Permissions\PermissionManager::isEveryoneAllowed
1721 */
1722 public function testIsEveryoneAllowed() {
1723 $result = MediaWikiServices::getInstance()->getPermissionManager()
1724 ->isEveryoneAllowed( 'editmyoptions' );
1725 $this->assertTrue( $result );
1726
1727 $result = MediaWikiServices::getInstance()->getPermissionManager()
1728 ->isEveryoneAllowed( 'test' );
1729 $this->assertFalse( $result );
1730 }
1731
1732 /**
1733 * @covers \MediaWiki\Permissions\PermissionManager::addTemporaryUserRights
1734 */
1735 public function testAddTemporaryUserRights() {
1736 $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
1737 $this->overrideUserPermissions( $this->user, [ 'read', 'edit' ] );
1738 // sanity checks
1739 $this->assertEquals( [ 'read', 'edit' ], $permissionManager->getUserPermissions( $this->user ) );
1740 $this->assertFalse( $permissionManager->userHasRight( $this->user, 'move' ) );
1741
1742 $scope = $permissionManager->addTemporaryUserRights( $this->user, [ 'move', 'delete' ] );
1743 $this->assertEquals( [ 'read', 'edit', 'move', 'delete' ],
1744 $permissionManager->getUserPermissions( $this->user ) );
1745 $this->assertTrue( $permissionManager->userHasRight( $this->user, 'move' ) );
1746
1747 $scope2 = $permissionManager->addTemporaryUserRights( $this->user, [ 'delete', 'upload' ] );
1748 $this->assertEquals( [ 'read', 'edit', 'move', 'delete', 'upload' ],
1749 $permissionManager->getUserPermissions( $this->user ) );
1750
1751 ScopedCallback::consume( $scope );
1752 $this->assertEquals( [ 'read', 'edit', 'delete', 'upload' ],
1753 $permissionManager->getUserPermissions( $this->user ) );
1754 ScopedCallback::consume( $scope2 );
1755 $this->assertEquals( [ 'read', 'edit' ],
1756 $permissionManager->getUserPermissions( $this->user ) );
1757 $this->assertFalse( $permissionManager->userHasRight( $this->user, 'move' ) );
1758
1759 ( function () use ( $permissionManager ) {
1760 $scope = $permissionManager->addTemporaryUserRights( $this->user, 'move' );
1761 $this->assertTrue( $permissionManager->userHasRight( $this->user, 'move' ) );
1762 } )();
1763 $this->assertFalse( $permissionManager->userHasRight( $this->user, 'move' ) );
1764 }
1765
1766 /**
1767 * Create a RevisionRecord with a single Javascript main slot.
1768 * @param Title $title
1769 * @param User $user
1770 * @param string $text
1771 * @return MutableRevisionRecord
1772 */
1773 private function getJavascriptRevision( Title $title, User $user, $text ) {
1774 $content = ContentHandler::makeContent( $text, $title, CONTENT_MODEL_JAVASCRIPT );
1775 $revision = new MutableRevisionRecord( $title );
1776 $revision->setContent( 'main', $content );
1777 return $revision;
1778 }
1779
1780 /**
1781 * Create a RevisionRecord with a single Javascript redirect main slot.
1782 * @param Title $title
1783 * @param Title $redirectTargetTitle
1784 * @param User $user
1785 * @return MutableRevisionRecord
1786 */
1787 private function getJavascriptRedirectRevision(
1788 Title $title, Title $redirectTargetTitle, User $user
1789 ) {
1790 $content = ContentHandler::getForModelID( CONTENT_MODEL_JAVASCRIPT )
1791 ->makeRedirectContent( $redirectTargetTitle );
1792 $revision = new MutableRevisionRecord( $title );
1793 $revision->setContent( 'main', $content );
1794 return $revision;
1795 }
1796
1797 public function provideGetRestrictionLevels() {
1798 return [
1799 'No namespace restriction' => [ [ '', 'autoconfirmed', 'sysop' ], NS_TALK ],
1800 'Restricted to autoconfirmed' => [ [ '', 'sysop' ], NS_MAIN ],
1801 'Restricted to sysop' => [ [ '' ], NS_USER ],
1802 'Restricted to someone in two groups' => [ [ '', 'sysop' ], 101 ],
1803 'No special permissions' => [
1804 [ '' ],
1805 NS_TALK,
1806 []
1807 ],
1808 'autoconfirmed' => [
1809 [ '', 'autoconfirmed' ],
1810 NS_TALK,
1811 [ 'autoconfirmed' ]
1812 ],
1813 'autoconfirmed revoked' => [
1814 [ '' ],
1815 NS_TALK,
1816 [ 'autoconfirmed', 'noeditsemiprotected' ]
1817 ],
1818 'sysop' => [
1819 [ '', 'autoconfirmed', 'sysop' ],
1820 NS_TALK,
1821 [ 'sysop' ]
1822 ],
1823 'sysop with autoconfirmed revoked (a bit silly)' => [
1824 [ '', 'sysop' ],
1825 NS_TALK,
1826 [ 'sysop', 'noeditsemiprotected' ]
1827 ],
1828 ];
1829 }
1830
1831 /**
1832 * @dataProvider provideGetRestrictionLevels
1833 * @covers \MediaWiki\Permissions\PermissionManager::getNamespaceRestrictionLevels
1834 *
1835 * @param array $expected
1836 * @param int $ns
1837 * @param array|null $userGroups
1838 * @throws MWException
1839 */
1840 public function testGetRestrictionLevels( array $expected, $ns, array $userGroups = null ) {
1841 $this->setMwGlobals( [
1842 'wgGroupPermissions' => [
1843 '*' => [ 'edit' => true ],
1844 'autoconfirmed' => [ 'editsemiprotected' => true ],
1845 'sysop' => [
1846 'editsemiprotected' => true,
1847 'editprotected' => true,
1848 ],
1849 'privileged' => [ 'privileged' => true ],
1850 ],
1851 'wgRevokePermissions' => [
1852 'noeditsemiprotected' => [ 'editsemiprotected' => true ],
1853 ],
1854 'wgNamespaceProtection' => [
1855 NS_MAIN => 'autoconfirmed',
1856 NS_USER => 'sysop',
1857 101 => [ 'editsemiprotected', 'privileged' ],
1858 ],
1859 'wgRestrictionLevels' => [ '', 'autoconfirmed', 'sysop' ],
1860 'wgAutopromote' => []
1861 ] );
1862 $this->resetServices();
1863 $user = is_null( $userGroups ) ? null : $this->getTestUser( $userGroups )->getUser();
1864 $this->assertSame( $expected, MediaWikiServices::getInstance()
1865 ->getPermissionManager()
1866 ->getNamespaceRestrictionLevels( $ns, $user ) );
1867 }
1868 }