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