WMDE-leszek has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/361693 )

Change subject: [WIP] Add WikiPageEntityStorePermissionChecker for consistent 
permission checks
......................................................................

[WIP] Add WikiPageEntityStorePermissionChecker for consistent permission checks

WikiPageEntityStorePermissionChecker is meant a central place to check
permission for editing entity wiki pages.

TODO: follow ups using it EditEntity, dropping permission
checker part of EntityContentFactory etc, removing other
permission checking code from other places.

TODOs:
 - Isn't the new code changing some of the previous behaviour/logic?
 - How to structure tests better? All test cases needed?
 - why PermissionsHelper does not want to work?
 - Anything special needed for foreign entities?

Bug: T166586
Change-Id: Ifb78d909cacb9e63168898ed35fd0f286ad711e1
---
M repo/Wikibase.php
A repo/includes/Store/WikiPageEntityStorePermissionChecker.php
A repo/tests/phpunit/includes/Store/WikiPageEntityStorePermissionCheckerTest.php
3 files changed, 723 insertions(+), 0 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase 
refs/changes/93/361693/1

diff --git a/repo/Wikibase.php b/repo/Wikibase.php
index 977819f..45f5e23 100644
--- a/repo/Wikibase.php
+++ b/repo/Wikibase.php
@@ -121,18 +121,21 @@
        $wgGroupPermissions['*']['property-term'] = true;
        $wgGroupPermissions['*']['item-merge'] = true;
        $wgGroupPermissions['*']['item-redirect'] = true;
+       $wgGroupPermissions['*']['item-create'] = true;
        $wgGroupPermissions['*']['property-create'] = true;
 
        $wgAvailableRights[] = 'item-term';
        $wgAvailableRights[] = 'property-term';
        $wgAvailableRights[] = 'item-merge';
        $wgAvailableRights[] = 'item-redirect';
+       $wgAvailableRights[] = 'item-create';
        $wgAvailableRights[] = 'property-create';
 
        $wgGrantPermissions['editpage']['item-term'] = true;
        $wgGrantPermissions['editpage']['item-redirect'] = true;
        $wgGrantPermissions['editpage']['item-merge'] = true;
        $wgGrantPermissions['editpage']['property-term'] = true;
+       $wgGrantPermissions['createeditmovepage']['item-create'] = true;
        $wgGrantPermissions['createeditmovepage']['property-create'] = true;
 
        // i18n
diff --git a/repo/includes/Store/WikiPageEntityStorePermissionChecker.php 
b/repo/includes/Store/WikiPageEntityStorePermissionChecker.php
new file mode 100644
index 0000000..29162b3
--- /dev/null
+++ b/repo/includes/Store/WikiPageEntityStorePermissionChecker.php
@@ -0,0 +1,145 @@
+<?php
+
+namespace Wikibase\Repo\Store;
+
+use Status;
+use Title;
+use User;
+use Wikibase\DataModel\Entity\EntityDocument;
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\Lib\Store\EntityNamespaceLookup;
+use Wikibase\Lib\Store\EntityTitleLookup;
+
+/**
+ * Checks permissions to do actions on the entity based on MediaWiki page 
permissions.
+ *
+ * @license GPL-2.0+
+ */
+class WikiPageEntityStorePermissionChecker implements EntityPermissionChecker {
+
+       /**
+        * @var EntityNamespaceLookup
+        */
+       private $namespaceLookup;
+
+       /**
+        * @var EntityTitleLookup
+        */
+       private $titleLookup;
+
+       public function __construct( EntityNamespaceLookup $namespaceLookup, 
EntityTitleLookup $titleLookup ) {
+               $this->namespaceLookup = $namespaceLookup;
+               $this->titleLookup = $titleLookup;
+       }
+
+       public function getPermissionStatusForEntity( User $user, $permission, 
EntityDocument $entity, $quick = '' ) {
+               $id = $entity->getId();
+               $status = null;
+
+               if ( $id === null ) {
+                       $entityType = $entity->getType();
+
+                       if ( $permission === 'edit' ) {
+                               // for editing a non-existing page, check the 
createpage permission
+                               return $this->getPermissionStatusForEntityType( 
$user, 'createpage', $entityType, $quick );
+                       }
+
+                       return $this->getPermissionStatusForEntityType( $user, 
$permission, $entityType, $quick );
+               }
+
+               return $this->getPermissionStatusForEntityId( $user, 
$permission, $id, $quick );
+       }
+
+       public function getPermissionStatusForEntityId( User $user, 
$permission, EntityId $entityId, $quick = '' ) {
+               $title = $this->titleLookup->getTitleForId( $entityId );
+
+               if ( $title === null ) {
+                       if ( $permission === 'edit' ) {
+                               return $this->getPermissionStatusForEntityType(
+                                       $user,
+                                       'createpage',
+                                       $entityId->getEntityType(),
+                                       $quick
+                               );
+                       }
+
+                       return $this->getPermissionStatusForEntityType(
+                               $user,
+                               $permission,
+                               $entityId->getEntityType(),
+                               $quick
+                       );
+               }
+
+               return $this->checkPermission( $user, $permission, $title, 
$entityId->getEntityType(), $quick );
+       }
+
+       public function getPermissionStatusForEntityType( User $user, 
$permission, $type, $quick = '' ) {
+               $title = $this->getPageTitleInEntityNamespace( $type );
+
+               if ( $permission === 'edit' ) {
+                       // Note: No entity ID given, assuming creating new 
entity, i.e. create permissions will be checked
+                       return $this->checkPermission(
+                               $user,
+                               'createpage',
+                               $title,
+                               $type,
+                               $quick
+                       );
+               }
+
+               return $this->checkPermission( $user, $permission, $title, 
$type, $quick );
+       }
+
+       /**
+        * @param string $entityType
+        *
+        * @return Title
+        */
+       private function getPageTitleInEntityNamespace( $entityType ) {
+               $namespace = $this->namespaceLookup->getEntityNamespace( 
$entityType ); // TODO: can be null!
+
+               return Title::makeTitle( $namespace, '/' );
+       }
+
+       private function checkPermission( User $user, $permission, Title 
$title, $entityType, $quick ='' ) {
+               $status = Status::newGood();
+
+               $permissions = $this->getMediaWikiPermissionsToCheck( 
$permission, $entityType );
+
+               foreach ( $permissions as $permission ) {
+                       $partialStatus = $this->getPermissionStatus( $user, 
$permission, $title, $quick );
+                       $status->merge( $partialStatus );
+               }
+
+               return $status;
+       }
+
+       private function getMediaWikiPermissionsToCheck( $permission, 
$entityType ) {
+               if ( $permission === 'edit' ) {
+                       return [ 'read', 'edit' ]; // TODO: need to check read 
permission?
+               }
+
+               if ( $permission === 'createpage' || $permission === 
$entityType . '-create' ) {
+                       return [ 'read', 'edit', 'createpage', $entityType . 
'-create' ]; // TODO: need to check read permission?
+               }
+
+               return [ $permission ];
+       }
+
+       private function getPermissionStatus( User $user, $permission, Title 
$title, $quick = '' ) {
+               $status = Status::newGood();
+
+               $errors = $title->getUserPermissionsErrors( $permission, $user, 
$quick !== 'quick' );
+
+               if ( $errors ) {
+                       $status->setResult( false );
+                       foreach ( $errors as $error ) {
+                               $status->fatal( $error );
+                       }
+               }
+
+               return $status;
+       }
+
+}
\ No newline at end of file
diff --git 
a/repo/tests/phpunit/includes/Store/WikiPageEntityStorePermissionCheckerTest.php
 
b/repo/tests/phpunit/includes/Store/WikiPageEntityStorePermissionCheckerTest.php
new file mode 100644
index 0000000..0e4157f
--- /dev/null
+++ 
b/repo/tests/phpunit/includes/Store/WikiPageEntityStorePermissionCheckerTest.php
@@ -0,0 +1,575 @@
+<?php
+
+namespace Wikibase\Repo\Tests\Store;
+
+use Title;
+use TitleValue;
+use User;
+use Wikibase\DataModel\Entity\EntityDocument;
+use Wikibase\DataModel\Entity\EntityId;
+use Wikibase\DataModel\Entity\Item;
+use Wikibase\DataModel\Entity\ItemId;
+use Wikibase\DataModel\Entity\Property;
+use Wikibase\DataModel\Entity\PropertyId;
+use Wikibase\Lib\Store\EntityNamespaceLookup;
+use Wikibase\Lib\Store\EntityTitleLookup;
+use Wikibase\Repo\Store\WikiPageEntityStorePermissionChecker;
+
+/**
+ * @covers Wikibase\Lib\Store\Sql\WikiPageEntityStorePermissionChecker
+ *
+ * @group Database
+ * @group Wikibase
+ * @group medium
+ *
+ * @license GPL-2.0+
+ */
+class WikiPageEntityStorePermissionCheckerTest extends \MediaWikiTestCase {
+
+       const EXISTING_ITEM_ID = 'Q2';
+       const NON_EXISTING_ITEM_ID = 'Q3';
+       const EXISTING_PROPERTY_ID = 'P2';
+       const NON_EXISTING_PROPERTY_ID = 'P3';
+
+       private function getNamespaceLookup() {
+               // TODO: do not use those constants?
+               return new EntityNamespaceLookup( [ 'item' => WB_NS_ITEM, 
'property' => WB_NS_PROPERTY ] );
+       }
+
+       /**
+        * @return EntityTitleLookup
+        */
+       private function getTitleLookup() {
+               $lookup = $this->getMock( EntityTitleLookup::class );
+
+               $lookup->method( 'getTitleForId' )
+                       ->will( $this->returnCallback( function( EntityId $id ) 
{
+                               if ( $id->getSerialization() === 
self::EXISTING_ITEM_ID ) {
+                                       return Title::newFromTitleValue( new 
TitleValue( WB_NS_ITEM, 'Test_Item' ) );
+                               }
+                               if ( $id->getSerialization() === 
self::EXISTING_PROPERTY_ID ) {
+                                       return Title::newFromTitleValue( new 
TitleValue( WB_NS_PROPERTY, 'Test_Property' ) );
+                               }
+                               return null;
+                       } ) );
+
+               return $lookup;
+       }
+
+       private function getPermissionChecker() {
+               return new WikiPageEntityStorePermissionChecker(
+                       $this->getNamespaceLookup(),
+                       $this->getTitleLookup()
+               );
+       }
+
+       private function applyTestPermissions( User $user, array $permissions ) 
{
+               // TODO: Why PermissionsHelper fails when used in these tests?
+               global $wgGroupPermissions;
+               $this->stashMwGlobals( 'wgGroupPermissions' );
+
+               // All allowed by default, have tests specify explicitly what 
permission they rely on
+               // but avoid define obvious right (e.g. "read" when testing 
create page edit permissions)
+               $defaultPermissions = [
+                       'read' => true,
+                       'edit' => true,
+                       'createpage' => true,
+                       'item-create' => true,
+                       'property-create' => true,
+               ];
+
+               $permissions = array_merge( $defaultPermissions, $permissions );
+
+               $oldGroups = $user->getGroups();
+               foreach ( $oldGroups as $group ) {
+                       $user->removeGroup( $group );
+               }
+
+               $group = 'wikibase-permission-checker-unittest';
+
+               $user->addGroup( $group );
+
+               if ( !array_key_exists( $group, $wgGroupPermissions ) ) {
+                       $wgGroupPermissions[$group] = [];
+               }
+
+               $wgGroupPermissions[$group] = array_merge( 
$wgGroupPermissions[$group], $permissions );
+               // Update implicit group permissions too
+               $wgGroupPermissions['*'] = array_merge( 
$wgGroupPermissions['*'], $permissions );
+               $wgGroupPermissions['user'] = array_merge( 
$wgGroupPermissions['user'], $permissions );
+       }
+
+       private function getExistingItem() {
+               return new Item( new ItemId( self::EXISTING_ITEM_ID ) );
+       }
+
+       private function getNonExistingItem() {
+               return new Item( new ItemId( self::NON_EXISTING_ITEM_ID ) );
+       }
+
+       private function getNonExistingItemWithNullId() {
+               return new Item( null );
+       }
+
+       private function getExistingProperty() {
+               return new Property( new PropertyId( self::EXISTING_PROPERTY_ID 
), null, 'test' );
+       }
+
+       private function getNonExistingProperty() {
+               return new Property( new PropertyId( 
self::NON_EXISTING_PROPERTY_ID ), null, 'test' );
+       }
+
+       private function getNonExistingPropertyWithNullId() {
+               return new Property( null, null, 'test' );
+       }
+
+       public function provideExistingEntities() {
+               return [
+                       [ $this->getExistingItem() ],
+                       [ $this->getExistingProperty() ]
+               ];
+       }
+
+       /**
+        * @dataProvider provideExistingEntities
+        */
+       public function testEditPermissionsAreRequiredToEditExistingEntity( 
EntityDocument $entity ) {
+               $groupPermissions = [ 'edit' => true ];
+
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, 'edit', $entity );
+               $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, 'edit', 
$entity->getId() );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, 'edit', 
$entity->getType() );
+
+               $this->assertTrue( $statusForEntity->isOK() );
+               $this->assertTrue( $statusForId->isOK() );
+               $this->assertTrue( $statusForType->isOK() );
+       }
+
+       /**
+        * @dataProvider provideExistingEntities
+        */
+       public function 
testEditPermissionsAreRequiredToEditExistingEntity_failures( EntityDocument 
$entity ) {
+               $groupPermissions = [ 'edit' => false ];
+
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, 'edit', $entity );
+               $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, 'edit', 
$entity->getId() );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, 'edit', 
$entity->getType() );
+
+               $this->assertFalse( $statusForEntity->isOK() );
+               $this->assertFalse( $statusForId->isOK() );
+               $this->assertFalse( $statusForType->isOK() );
+       }
+
+       public function 
provideNonExistingEntitiesAndValidCreateGroupPermissions() {
+               return [
+                       [ $this->getNonExistingItem(), [ 'createpage' => true, 
'item-create' => true, ] ],
+                       [ $this->getNonExistingItemWithNullId(), [ 'createpage' 
=> true, 'item-create' => true, ] ],
+                       [ $this->getNonExistingProperty(), [ 'createpage' => 
true, 'property-create' => true, ] ],
+                       [ $this->getNonExistingPropertyWithNullId(), [ 
'createpage' => true, 'property-create' => true, ] ],
+               ];
+       }
+
+       /**
+        * @dataProvider 
provideNonExistingEntitiesAndValidCreateGroupPermissions
+        */
+       public function 
testCreatePageCreateEntityPermissionsAreRequiredToEditNonExistingEntity(
+               EntityDocument $entity,
+               array $groupPermissions
+       ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, 'edit', $entity );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, 'edit', 
$entity->getType() );
+
+               if ( $entity->getId() !== null ) {
+                       $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, 'edit', 
$entity->getId() );
+                       $this->assertTrue( $statusForId->isOK() );
+               }
+
+               $this->assertTrue( $statusForEntity->isOK() );
+               $this->assertTrue( $statusForType->isOK() );
+       }
+
+       public function 
provideNonExistingEntitiesAndInvalidCreateGroupPermissions() {
+               return [
+                       [ $this->getNonExistingItem(), [ 'createpage' => true, 
'item-create' => false, ] ],
+                       [ $this->getNonExistingItem(), [ 'createpage' => false, 
'item-create' => true, ] ],
+                       [ $this->getNonExistingItem(), [ 'createpage' => false, 
'item-create' => false, ] ],
+                       [ $this->getNonExistingItem(), [ 'edit' => false, 
'createpage' => true, 'item-create' => true, ] ],
+                       [ $this->getNonExistingProperty(), [ 'createpage' => 
true, 'property-create' => false, ] ],
+                       [ $this->getNonExistingProperty(), [ 'createpage' => 
false, 'property-create' => true, ] ],
+                       [ $this->getNonExistingProperty(), [ 'createpage' => 
false, 'property-create' => false, ] ],
+                       [ $this->getNonExistingProperty(), [ 'createpage' => 
true, 'item-create' => true, 'property-create' => false, ] ],
+                       [ $this->getNonExistingProperty(), [ 'edit' => false, 
'createpage' => true, 'property-create' => true, ] ],
+               ];
+       }
+
+       /**
+        * @dataProvider 
provideNonExistingEntitiesAndInvalidCreateGroupPermissions
+        */
+       public function 
testCreatePageCreateEntityPermissionsAreRequiredToEditNonExistingEntity_failures(
+               EntityDocument $entity,
+               array $groupPermissions
+       ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, 'edit', $entity );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, 'edit', 
$entity->getType() );
+
+               if ( $entity->getId() !== null ) {
+                       $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, 'edit', 
$entity->getId() );
+                       $this->assertFalse( $statusForId->isOK() );
+               }
+
+               $this->assertFalse( $statusForEntity->isOK() );
+               $this->assertFalse( $statusForType->isOK() );
+       }
+
+       public function provideAllEntities() {
+               return [
+                       [ $this->getExistingItem() ],
+                       [ $this->getExistingProperty() ],
+                       [ $this->getNonExistingItem() ],
+                       [ $this->getNonExistingItemWithNullId() ],
+                       [ $this->getNonExistingProperty() ],
+                       [ $this->getNonExistingPropertyWithNullId() ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideAllEntities
+        */
+       public function testReadPermissionsAreRequiredToReadEntity( 
EntityDocument $entity ) {
+               $groupPermissions = [ 'read' => true ];
+
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, 'read', $entity );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, 'read', 
$entity->getType() );
+
+               if ( $entity->getId() !== null ) {
+                       $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, 'read', 
$entity->getId() );
+                       $this->assertTrue( $statusForId->isOK() );
+               }
+
+               $this->assertTrue( $statusForEntity->isOK() );
+               $this->assertTrue( $statusForType->isOK() );
+       }
+
+       /**
+        * @dataProvider provideAllEntities
+        */
+       public function testReadPermissionsAreRequiredToReadEntity_failures( 
EntityDocument $entity ) {
+               $groupPermissions = [ 'read' => false ];
+
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, 'read', $entity );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, 'read', 
$entity->getType() );
+
+               if ( $entity->getId() !== null ) {
+                       $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, 'read', 
$entity->getId() );
+                       $this->assertFalse( $statusForId->isOK() );
+               }
+
+               $this->assertFalse( $statusForEntity->isOK() );
+               $this->assertFalse( $statusForType->isOK() );
+       }
+
+       /**
+        * @dataProvider 
provideNonExistingEntitiesAndValidCreateGroupPermissions
+        */
+       public function 
testAllCreatePermissionsAreRequiredForCreatePageOnNonexistingEntity(
+               EntityDocument $entity,
+               array $groupPermissions
+       ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, 'createpage', $entity 
);
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, 'createpage', 
$entity->getType() );
+
+               if ( $entity->getId() !== null ) {
+                       $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, 'createpage', 
$entity->getId() );
+                       $this->assertTrue( $statusForId->isOK() );
+               }
+
+               $this->assertTrue( $statusForEntity->isOK() );
+               $this->assertTrue( $statusForType->isOK() );
+       }
+
+       /**
+        * @dataProvider 
provideNonExistingEntitiesAndInvalidCreateGroupPermissions
+        */
+       public function 
testAllCreatePermissionsAreRequiredForCreatePageOnNonexistingEntity_failures(
+               EntityDocument $entity,
+               array $groupPermissions
+       ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, 'createpage', $entity 
);
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, 'createpage', 
$entity->getType() );
+
+               if ( $entity->getId() !== null ) {
+                       $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, 'createpage', 
$entity->getId() );
+                       $this->assertFalse( $statusForId->isOK() );
+               }
+
+               $this->assertFalse( $statusForEntity->isOK() );
+               $this->assertFalse( $statusForType->isOK() );
+       }
+
+       /**
+        * @dataProvider 
provideNonExistingEntitiesAndValidCreateGroupPermissions
+        */
+       public function 
testAllCreatePermissionsAreRequiredForEntityCreateOnNonexistingEntity(
+               EntityDocument $entity,
+               array $groupPermissions
+       ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $entityType = $entity->getType();
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, $entityType . 
'-create', $entity );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, $entityType . 
'-create', $entity->getType() );
+
+               if ( $entity->getId() !== null ) {
+                       $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, $entityType . 
'-create', $entity->getId() );
+                       $this->assertTrue( $statusForId->isOK() );
+               }
+
+               $this->assertTrue( $statusForEntity->isOK() );
+               $this->assertTrue( $statusForType->isOK() );
+       }
+
+       /**
+        * @dataProvider 
provideNonExistingEntitiesAndInvalidCreateGroupPermissions
+        */
+       public function 
testAllCreatePermissionsAreRequiredForEntityCreateOnNonexistingEntity_failures(
+               EntityDocument $entity,
+               array $groupPermissions
+       ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $entityType = $entity->getType();
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, $entityType . 
'create', $entity );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, $entityType . 
'create', $entity->getType() );
+
+               if ( $entity->getType() ) {
+                       $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, $entityType . 
'create', $entity->getId() );
+                       $this->assertFalse( $statusForId->isOK() );
+               }
+
+               $this->assertFalse( $statusForEntity->isOK() );
+               $this->assertFalse( $statusForType->isOK() );
+       }
+
+       public function provideExistingEntitiesAndValidCreateGroupPermissions() 
{
+               return [
+                       [ $this->getExistingItem(), [ 'createpage' => true, 
'item-create' => true, ] ],
+                       [ $this->getExistingProperty(), [ 'createpage' => true, 
'property-create' => true, ] ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideExistingEntitiesAndValidCreateGroupPermissions
+        */
+       public function 
testAllCreatePermissionsAreRequiredForCreatePageOnExistingEntity(
+               EntityDocument $entity,
+               array $groupPermissions
+       ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, 'createpage', $entity 
);
+               $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, 'createpage', 
$entity->getId() );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, 'createpage', 
$entity->getType() );
+
+               $this->assertTrue( $statusForEntity->isOK() );
+               $this->assertTrue( $statusForId->isOK() );
+               $this->assertTrue( $statusForType->isOK() );
+       }
+
+       public function 
provideExistingEntitiesAndInvalidCreateGroupPermissions() {
+               return [
+                       [ $this->getNonExistingItem(), [ 'createpage' => true, 
'item-create' => false, ] ],
+                       [ $this->getNonExistingItem(), [ 'createpage' => false, 
'item-create' => true, ] ],
+                       [ $this->getNonExistingItem(), [ 'createpage' => false, 
'item-create' => false, ] ],
+                       [ $this->getNonExistingItem(), [ 'edit' => false, 
'createpage' => true, 'item-create' => true, ] ],
+                       [ $this->getNonExistingProperty(), [ 'createpage' => 
true, 'property-create' => false, ] ],
+                       [ $this->getNonExistingProperty(), [ 'createpage' => 
false, 'property-create' => true, ] ],
+                       [ $this->getNonExistingProperty(), [ 'createpage' => 
false, 'property-create' => false, ] ],
+                       [ $this->getNonExistingProperty(), [ 'createpage' => 
true, 'item-create' => true, 'property-create' => false, ] ],
+                       [ $this->getNonExistingProperty(), [ 'edit' => false, 
'createpage' => true, 'property-create' => true, ] ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideExistingEntitiesAndInvalidCreateGroupPermissions
+        */
+       public function 
testAllCreatePermissionsAreRequiredForCreatePageOnExistingEntity_failures(
+               EntityDocument $entity,
+               array $groupPermissions
+       ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, 'createpage', $entity 
);
+               $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, 'createpage', 
$entity->getId() );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, 'createpage', 
$entity->getType() );
+
+               $this->assertFalse( $statusForEntity->isOK() );
+               $this->assertFalse( $statusForId->isOK() );
+               $this->assertFalse( $statusForType->isOK() );
+       }
+
+       /**
+        * @dataProvider provideExistingEntitiesAndValidCreateGroupPermissions
+        */
+       public function 
testAllCreatePermissionsAreRequiredForEntityCreateOnExistingEntity(
+               EntityDocument $entity,
+               array $groupPermissions
+       ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $entityType = $entity->getType();
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, $entityType . 
'-create', $entity );
+               $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, $entityType . 
'-create', $entity->getId() );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, $entityType . 
'-create', $entity->getType() );
+
+               $this->assertTrue( $statusForEntity->isOK() );
+               $this->assertTrue( $statusForId->isOK() );
+               $this->assertTrue( $statusForType->isOK() );
+       }
+
+       /**
+        * @dataProvider provideExistingEntitiesAndInvalidCreateGroupPermissions
+        */
+       public function 
testAllCreatePermissionsAreRequiredForEntityCreateOnExistingEntity_failures(
+               EntityDocument $entity,
+               array $groupPermissions
+       ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, $groupPermissions );
+
+               $entityType = $entity->getType();
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, $entityType . 
'-create', $entity );
+               $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, $entityType . 
'-create', $entity->getId() );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, $entityType . 
'-create', $entity->getType() );
+
+               $this->assertFalse( $statusForEntity->isOK() );
+               $this->assertFalse( $statusForId->isOK() );
+               $this->assertFalse( $statusForType->isOK() );
+       }
+
+       public function provideAllEntitiesAndNonEditPermissions() {
+               return [
+                       [ $this->getExistingItem(), 'delete' ],
+                       [ $this->getExistingProperty(), 'delete' ],
+                       [ $this->getNonExistingItem(), 'delete' ],
+                       [ $this->getNonExistingItemWithNullId(), 'delete' ],
+                       [ $this->getNonExistingProperty(), 'delete' ],
+                       [ $this->getNonExistingPropertyWithNullId(), 'delete' ],
+                       [ $this->getExistingItem(), 'item-merge' ],
+                       [ $this->getNonExistingItem(), 'item-merge' ],
+                       [ $this->getNonExistingItemWithNullId(), 'item-merge' ],
+                       [ $this->getExistingItem(), 'item-redirect' ],
+                       [ $this->getNonExistingItem(), 'item-redirect' ],
+                       [ $this->getNonExistingItemWithNullId(), 
'item-redirect' ],
+                       [ $this->getExistingItem(), 'item-term' ],
+                       [ $this->getNonExistingItem(), 'item-term' ],
+                       [ $this->getNonExistingItemWithNullId(), 'item-term' ],
+                       [ $this->getExistingProperty(), 'property-term' ],
+                       [ $this->getNonExistingProperty(), 'property-term' ],
+                       [ $this->getNonExistingPropertyWithNullId(), 
'property-term' ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideAllEntitiesAndNonEditPermissions
+        */
+       public function testNonEditCreatePermissionsAreSimplyChecked( 
EntityDocument $entity, $permission ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, [ $permission => true ] );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, $permission, $entity );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, $permission, 
$entity->getType() );
+
+               if ( $entity->getId() !== null ) {
+                       $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, $permission, 
$entity->getId() );
+                       $this->assertTrue( $statusForId->isOK() );
+               }
+
+               $this->assertTrue( $statusForEntity->isOK() );
+               $this->assertTrue( $statusForType->isOK() );
+       }
+
+       /**
+        * @dataProvider provideAllEntitiesAndNonEditPermissions
+        */
+       public function testNonEditCreatePermissionsAreSimplyChecked_failures( 
EntityDocument $entity, $permission ) {
+               $user = $this->getTestUser()->getUser();
+               $this->applyTestPermissions( $user, [ $permission => false ] );
+
+               $permissionChecker = $this->getPermissionChecker();
+
+               $statusForEntity = 
$permissionChecker->getPermissionStatusForEntity( $user, $permission, $entity );
+               $statusForType = 
$permissionChecker->getPermissionStatusForEntityType( $user, $permission, 
$entity->getType() );
+
+               if ( $entity->getId() !== null ) {
+                       $statusForId = 
$permissionChecker->getPermissionStatusForEntityId( $user, $permission, 
$entity->getId() );
+                       $this->assertFalse( $statusForId->isOK() );
+               }
+
+               $this->assertFalse( $statusForEntity->isOK() );
+               $this->assertFalse( $statusForType->isOK() );
+       }
+
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/361693
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifb78d909cacb9e63168898ed35fd0f286ad711e1
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: WMDE-leszek <leszek.mani...@wikimedia.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to