Merge "deferred: make DeferredUpdates::attemptUpdate() use callback owners for $fname...
[lhc/web/wiklou.git] / tests / phpunit / includes / Permissions / PermissionManagerTest.php
index 3da73c1..3c5f43b 100644 (file)
@@ -3,7 +3,20 @@
 namespace MediaWiki\Tests\Permissions;
 
 use Action;
+use ContentHandler;
 use FauxRequest;
+use LoggedServiceOptions;
+use MediaWiki\Block\DatabaseBlock;
+use MediaWiki\Block\Restriction\NamespaceRestriction;
+use MediaWiki\Block\Restriction\PageRestriction;
+use MediaWiki\Block\SystemBlock;
+use MediaWiki\Linker\LinkTarget;
+use MediaWiki\MediaWikiServices;
+use MediaWiki\Permissions\PermissionManager;
+use MediaWiki\Revision\MutableRevisionRecord;
+use MediaWiki\Revision\RevisionLookup;
+use TestAllServiceOptionsUsed;
+use Wikimedia\ScopedCallback;
 use MediaWiki\Session\SessionId;
 use MediaWiki\Session\TestUtils;
 use MediaWikiLangTestCase;
@@ -11,12 +24,6 @@ use RequestContext;
 use stdClass;
 use Title;
 use User;
-use MediaWiki\Block\DatabaseBlock;
-use MediaWiki\Block\Restriction\NamespaceRestriction;
-use MediaWiki\Block\Restriction\PageRestriction;
-use MediaWiki\Block\SystemBlock;
-use MediaWiki\MediaWikiServices;
-use MediaWiki\Permissions\PermissionManager;
 use Wikimedia\TestingAccessWrapper;
 
 /**
@@ -25,6 +32,7 @@ use Wikimedia\TestingAccessWrapper;
  * @covers \MediaWiki\Permissions\PermissionManager
  */
 class PermissionManagerTest extends MediaWikiLangTestCase {
+       use TestAllServiceOptionsUsed;
 
        /**
         * @var string
@@ -41,11 +49,6 @@ class PermissionManagerTest extends MediaWikiLangTestCase {
         */
        protected $user, $anonUser, $userUser, $altUser;
 
-       /**
-        * @var PermissionManager
-        */
-       protected $permissionManager;
-
        /** Constant for self::testIsBlockedFrom */
        const USER_TALK_PAGE = '<user talk page>';
 
@@ -702,6 +705,70 @@ class PermissionManagerTest extends MediaWikiLangTestCase {
                );
        }
 
+       public function testJsConfigRedirectEditPermissions() {
+               $revision = null;
+               $user = $this->getTestUser()->getUser();
+               $otherUser = $this->getTestUser( 'sysop' )->getUser();
+               $localJsTitle = Title::newFromText( 'User:' . $user->getName() . '/foo.js' );
+               $otherLocalJsTitle = Title::newFromText( 'User:' . $user->getName() . '/foo2.js' );
+               $nonlocalJsTitle = Title::newFromText( 'User:' . $otherUser->getName() . '/foo.js' );
+
+               $services = MediaWikiServices::getInstance();
+               $revisionLookup = $this->getMockBuilder( RevisionLookup::class )
+                       ->setMethods( [ 'getRevisionByTitle' ] )
+                       ->getMockForAbstractClass();
+               $revisionLookup->method( 'getRevisionByTitle' )
+                       ->willReturnCallback( function ( LinkTarget $page ) use (
+                               $services, &$revision, $localJsTitle
+                       ) {
+                               if ( $localJsTitle->equals( Title::newFromLinkTarget( $page ) ) ) {
+                                       return $revision;
+                               } else {
+                                       return $services->getRevisionLookup()->getRevisionByTitle( $page );
+                               }
+                       } );
+               $permissionManager = new PermissionManager(
+                       new LoggedServiceOptions(
+                               self::$serviceOptionsAccessLog,
+                               PermissionManager::$constructorOptions,
+                               [
+                                       'WhitelistRead' => [],
+                                       'WhitelistReadRegexp' => [],
+                                       'EmailConfirmToEdit' => false,
+                                       'BlockDisablesLogin' => false,
+                                       'GroupPermissions' => [],
+                                       'RevokePermissions' => [],
+                                       'AvailableRights' => []
+                               ]
+                       ),
+                       $services->getSpecialPageFactory(),
+                       $revisionLookup,
+                       MediaWikiServices::getInstance()->getNamespaceInfo()
+               );
+               $this->setService( 'PermissionManager', $permissionManager );
+
+               $permissionManager->overrideUserRightsForTesting( $user, [ 'edit', 'editmyuserjs' ] );
+
+               $revision = $this->getJavascriptRevision( $localJsTitle, $user, '/* script */' );
+               $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
+               $this->assertSame( [], $errors );
+
+               $revision = $this->getJavascriptRedirectRevision( $localJsTitle, $otherLocalJsTitle, $user );
+               $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
+               $this->assertSame( [], $errors );
+
+               $revision = $this->getJavascriptRedirectRevision( $localJsTitle, $nonlocalJsTitle, $user );
+               $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
+               $this->assertSame( [ [ 'mycustomjsredirectprotected', 'edit' ] ], $errors );
+
+               $permissionManager->overrideUserRightsForTesting( $user,
+                       [ 'edit', 'editmyuserjs', 'editmyuserjsredirect' ] );
+
+               $revision = $this->getJavascriptRedirectRevision( $localJsTitle, $nonlocalJsTitle, $user );
+               $errors = $permissionManager->getPermissionErrors( 'edit', $user, $localJsTitle );
+               $this->assertSame( [], $errors );
+       }
+
        /**
         * @todo This test method should be split up into separate test methods and
         * data providers
@@ -1103,7 +1170,7 @@ class PermissionManagerTest extends MediaWikiLangTestCase {
                        'auto' => true,
                        'expiry' => 0
                ] );
-               $this->user->mBlock->mTimestamp = 0;
+               $this->user->mBlock->setTimestamp( 0 );
                $this->assertEquals( [ [ 'autoblockedtext',
                        "[[User:Useruser|\u{202A}Useruser\u{202C}]]", 'no reason given', '127.0.0.1',
                        "\u{202A}Useruser\u{202C}", null, 'infinite', '127.0.8.1',
@@ -1490,7 +1557,8 @@ class PermissionManagerTest extends MediaWikiLangTestCase {
                $user = $this->getTestUser( [ 'unittesters', 'testwriters' ] )->getUser();
                $userWrapper = TestingAccessWrapper::newFromObject( $user );
 
-               $rights = MediaWikiServices::getInstance()->getPermissionManager()
+               $rights = MediaWikiServices::getInstance()
+                       ->getPermissionManager()
                        ->getUserPermissions( $user );
                $this->assertContains( 'test', $rights, 'sanity check' );
                $this->assertContains( 'runtest', $rights, 'sanity check' );
@@ -1498,13 +1566,14 @@ class PermissionManagerTest extends MediaWikiLangTestCase {
                $this->assertNotContains( 'nukeworld', $rights, 'sanity check' );
 
                // Add a hook manipluating the rights
-               $this->mergeMwGlobalArrayValue( 'wgHooks', [ 'UserGetRights' => [ function ( $user, &$rights ) {
+               $this->setTemporaryHook( 'UserGetRights', function ( $user, &$rights ) {
                        $rights[] = 'nukeworld';
                        $rights = array_diff( $rights, [ 'writetest' ] );
-               } ] ] );
+               } );
 
                $this->resetServices();
-               $rights = MediaWikiServices::getInstance()->getPermissionManager()
+               $rights = MediaWikiServices::getInstance()
+                       ->getPermissionManager()
                        ->getUserPermissions( $user );
                $this->assertContains( 'test', $rights );
                $this->assertContains( 'runtest', $rights );
@@ -1527,7 +1596,8 @@ class PermissionManagerTest extends MediaWikiLangTestCase {
                $userWrapper->mRequest = $mockRequest;
 
                $this->resetServices();
-               $rights = MediaWikiServices::getInstance()->getPermissionManager()
+               $rights = MediaWikiServices::getInstance()
+                       ->getPermissionManager()
                        ->getUserPermissions( $user );
                $this->assertContains( 'test', $rights );
                $this->assertNotContains( 'runtest', $rights );
@@ -1653,4 +1723,69 @@ class PermissionManagerTest extends MediaWikiLangTestCase {
                $this->assertFalse( $result );
        }
 
+       /**
+        * @covers \MediaWiki\Permissions\PermissionManager::addTemporaryUserRights
+        */
+       public function testAddTemporaryUserRights() {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               $this->overrideUserPermissions( $this->user, [ 'read', 'edit' ] );
+               // sanity checks
+               $this->assertEquals( [ 'read', 'edit' ], $permissionManager->getUserPermissions( $this->user ) );
+               $this->assertFalse( $permissionManager->userHasRight( $this->user, 'move' ) );
+
+               $scope = $permissionManager->addTemporaryUserRights( $this->user, [ 'move', 'delete' ] );
+               $this->assertEquals( [ 'read', 'edit', 'move', 'delete' ],
+                       $permissionManager->getUserPermissions( $this->user ) );
+               $this->assertTrue( $permissionManager->userHasRight( $this->user, 'move' ) );
+
+               $scope2 = $permissionManager->addTemporaryUserRights( $this->user, [ 'delete', 'upload' ] );
+               $this->assertEquals( [ 'read', 'edit', 'move', 'delete', 'upload' ],
+                       $permissionManager->getUserPermissions( $this->user ) );
+
+               ScopedCallback::consume( $scope );
+               $this->assertEquals( [ 'read', 'edit', 'delete', 'upload' ],
+                       $permissionManager->getUserPermissions( $this->user ) );
+               ScopedCallback::consume( $scope2 );
+               $this->assertEquals( [ 'read', 'edit' ],
+                       $permissionManager->getUserPermissions( $this->user ) );
+               $this->assertFalse( $permissionManager->userHasRight( $this->user, 'move' ) );
+
+               ( function () use ( $permissionManager ) {
+                       $scope = $permissionManager->addTemporaryUserRights( $this->user, 'move' );
+                       $this->assertTrue( $permissionManager->userHasRight( $this->user, 'move' ) );
+               } )();
+               $this->assertFalse( $permissionManager->userHasRight( $this->user, 'move' ) );
+       }
+
+       /**
+        * Create a RevisionRecord with a single Javascript main slot.
+        * @param Title $title
+        * @param User $user
+        * @param string $text
+        * @return MutableRevisionRecord
+        */
+       private function getJavascriptRevision( Title $title, User $user, $text ) {
+               $content = ContentHandler::makeContent( $text, $title, CONTENT_MODEL_JAVASCRIPT );
+               $revision = new MutableRevisionRecord( $title );
+               $revision->setContent( 'main', $content );
+               return $revision;
+       }
+
+       /**
+        * Create a RevisionRecord with a single Javascript redirect main slot.
+        * @param Title $title
+        * @param Title $redirectTargetTitle
+        * @param User $user
+        * @return MutableRevisionRecord
+        */
+       private function getJavascriptRedirectRevision(
+               Title $title, Title $redirectTargetTitle, User $user
+       ) {
+               $content = ContentHandler::getForModelID( CONTENT_MODEL_JAVASCRIPT )
+                       ->makeRedirectContent( $redirectTargetTitle );
+               $revision = new MutableRevisionRecord( $title );
+               $revision->setContent( 'main', $content );
+               return $revision;
+       }
+
 }