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

Change subject: Consider create permissions when entity is creating with API 
action for editing entity terms
......................................................................

Consider create permissions when entity is creating with API action for editing 
entity terms

Bug: T166586
Change-Id: I6148d0a86197f1ad75bad09937be2fddc4e419e4
---
M repo/includes/Store/WikiPageEntityStorePermissionChecker.php
M repo/tests/phpunit/includes/Api/SetAliasesTest.php
M repo/tests/phpunit/includes/Api/SetDescriptionTest.php
M repo/tests/phpunit/includes/Api/SetLabelTest.php
M repo/tests/phpunit/includes/Api/SetSiteLinkTest.php
M repo/tests/phpunit/includes/Store/WikiPageEntityStorePermissionCheckerTest.php
6 files changed, 350 insertions(+), 22 deletions(-)


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

diff --git a/repo/includes/Store/WikiPageEntityStorePermissionChecker.php 
b/repo/includes/Store/WikiPageEntityStorePermissionChecker.php
index 0831a7f..6cda6b3 100644
--- a/repo/includes/Store/WikiPageEntityStorePermissionChecker.php
+++ b/repo/includes/Store/WikiPageEntityStorePermissionChecker.php
@@ -66,11 +66,6 @@
                if ( $id === null ) {
                        $entityType = $entity->getType();
 
-                       if ( $action === EntityPermissionChecker::ACTION_EDIT ) 
{
-                               // for editing a non-existing page, check the 
create permission
-                               return $this->getPermissionStatusForEntityType( 
$user, EntityPermissionChecker::ACTION_CREATE, $entityType, $quick );
-                       }
-
                        return $this->getPermissionStatusForEntityType( $user, 
$action, $entityType, $quick );
                }
 
@@ -93,15 +88,6 @@
                $title = $this->titleLookup->getTitleForId( $entityId );
 
                if ( $title === null || !$title->exists() ) {
-                       if ( $action === EntityPermissionChecker::ACTION_EDIT ) 
{
-                               return $this->getPermissionStatusForEntityType(
-                                       $user,
-                                       EntityPermissionChecker::ACTION_CREATE,
-                                       $entityId->getEntityType(),
-                                       $quick
-                               );
-                       }
-
                        return $this->getPermissionStatusForEntityType(
                                $user,
                                $action,
@@ -110,7 +96,7 @@
                        );
                }
 
-               return $this->checkPermissionsForAction( $user, $action, 
$title, $entityId->getEntityType(), $quick );
+               return $this->checkPermissionsForActions( $user, [ $action ], 
$title, $entityId->getEntityType(), $quick );
        }
 
        /**
@@ -128,18 +114,27 @@
        public function getPermissionStatusForEntityType( User $user, $action, 
$type, $quick = '' ) {
                $title = $this->getPageTitleInEntityNamespace( $type );
 
-               if ( $action === EntityPermissionChecker::ACTION_EDIT ) {
+               if ( $this->isEditAction( $action ) ) {
                        // Note: No entity ID given, assuming creating new 
entity, i.e. create permissions will be checked
-                       return $this->checkPermissionsForAction(
+                       return $this->checkPermissionsForActions(
                                $user,
-                               EntityPermissionChecker::ACTION_CREATE,
+                               [ $action, 
EntityPermissionChecker::ACTION_CREATE ],
                                $title,
                                $type,
                                $quick
                        );
                }
 
-               return $this->checkPermissionsForAction( $user, $action, 
$title, $type, $quick );
+               return $this->checkPermissionsForActions( $user, [ $action ], 
$title, $type, $quick );
+       }
+
+       /**
+        * @param string $action
+        *
+        * @return bool
+        */
+       private function isEditAction( $action ) {
+               return $action === EntityPermissionChecker::ACTION_EDIT || 
$action === EntityPermissionChecker::ACTION_EDIT_TERMS;
        }
 
        /**
@@ -153,10 +148,19 @@
                return Title::makeTitle( $namespace, '/' );
        }
 
-       private function checkPermissionsForAction( User $user, $action, Title 
$title, $entityType, $quick ='' ) {
+       private function checkPermissionsForActions( User $user, array 
$actions, Title $title, $entityType, $quick ='' ) {
                $status = Status::newGood();
 
-               $mediaWikiPermissions = $this->getMediaWikiPermissionsToCheck( 
$action, $entityType );
+               $mediaWikiPermissions = [];
+
+               foreach ( $actions as $action ) {
+                       $mediaWikiPermissions = array_merge(
+                               $mediaWikiPermissions,
+                               $this->getMediaWikiPermissionsToCheck( $action, 
$entityType )
+                       );
+               }
+
+               $mediaWikiPermissions = array_unique( $mediaWikiPermissions );
 
                foreach ( $mediaWikiPermissions as $mwPermission ) {
                        $partialStatus = $this->getPermissionStatus( $user, 
$mwPermission, $title, $quick );
@@ -171,9 +175,11 @@
                        $entityTypeSpecificCreatePermission = $entityType . 
'-create';
 
                        $permissions = [ 'read', 'edit', 'createpage' ];
+
                        if ( $this->mediawikiPermissionExists( 
$entityTypeSpecificCreatePermission ) ) {
                                $permissions[] = 
$entityTypeSpecificCreatePermission;
                        }
+
                        return $permissions;
                }
 
diff --git a/repo/tests/phpunit/includes/Api/SetAliasesTest.php 
b/repo/tests/phpunit/includes/Api/SetAliasesTest.php
index c64df6a..15b2d15 100644
--- a/repo/tests/phpunit/includes/Api/SetAliasesTest.php
+++ b/repo/tests/phpunit/includes/Api/SetAliasesTest.php
@@ -303,6 +303,45 @@
                );
        }
 
+       public function 
testUserCanCreateItemWithAliasWhenTheyHaveSufficientPermissions() {
+               $userWithAllPermissions = $this->createUserWithGroup( 
'all-permission' );
+
+               $this->setMwGlobals( 'wgGroupPermissions', [
+                       'all-permission' => [ 'item-term' => true, 'createpage' 
=> true ],
+                       '*' => [ 'read' => true, 'edit' => true, 'writeapi' => 
true ]
+               ] );
+
+               list ( $result, ) = $this->doApiRequestWithToken(
+                       $this->getCreateItemAndSetAliasRequestParams(),
+                       null,
+                       $userWithAllPermissions
+               );
+
+               $this->assertEquals( 1, $result['success'] );
+               $this->assertSame( 'an alias', 
$result['entity']['aliases']['en'][0]['value'] );
+       }
+
+       public function testUserCannotCreateItemWhenTheyLackPermission() {
+               $userWithInsufficientPermissions = $this->createUserWithGroup( 
'no-permission' );
+
+               $this->setMwGlobals( 'wgGroupPermissions', [
+                       'no-permission' => [ 'createpage' => false ],
+                       '*' => [ 'read' => true, 'edit' => true, 'item-term' => 
true, 'writeapi' => true ]
+               ] );
+
+               // Then the request is denied
+               $expected = [
+                       'type' => ApiUsageException::class,
+                       'code' => 'permissiondenied'
+               ];
+
+               $this->doTestQueryExceptions(
+                       $this->getCreateItemAndSetAliasRequestParams(),
+                       $expected,
+                       $userWithInsufficientPermissions
+               );
+       }
+
        /**
         * @param User $user
         * @return Item
@@ -330,4 +369,13 @@
                ];
        }
 
+       private function getCreateItemAndSetAliasRequestParams() {
+               return [
+                       'action' => 'wbsetaliases',
+                       'new' => 'item',
+                       'language' => 'en',
+                       'add' => 'an alias',
+               ];
+       }
+
 }
diff --git a/repo/tests/phpunit/includes/Api/SetDescriptionTest.php 
b/repo/tests/phpunit/includes/Api/SetDescriptionTest.php
index 99e8998..1dd35dd 100644
--- a/repo/tests/phpunit/includes/Api/SetDescriptionTest.php
+++ b/repo/tests/phpunit/includes/Api/SetDescriptionTest.php
@@ -98,6 +98,45 @@
                );
        }
 
+       public function 
testUserCanCreateItemWithDescriptionWhenTheyHaveSufficientPermissions() {
+               $userWithAllPermissions = $this->createUserWithGroup( 
'all-permission' );
+
+               $this->setMwGlobals( 'wgGroupPermissions', [
+                       'all-permission' => [ 'item-term' => true, 'createpage' 
=> true ],
+                       '*' => [ 'read' => true, 'edit' => true, 'writeapi' => 
true ]
+               ] );
+
+               list ( $result, ) = $this->doApiRequestWithToken(
+                       $this->getCreateItemAndSetDescriptionRequestParams(),
+                       null,
+                       $userWithAllPermissions
+               );
+
+               $this->assertEquals( 1, $result['success'] );
+               $this->assertSame( 'some description', 
$result['entity']['descriptions']['en']['value'] );
+       }
+
+       public function testUserCannotCreateItemWhenTheyLackPermission() {
+               $userWithInsufficientPermissions = $this->createUserWithGroup( 
'no-permission' );
+
+               $this->setMwGlobals( 'wgGroupPermissions', [
+                       'no-permission' => [ 'createpage' => false ],
+                       '*' => [ 'read' => true, 'edit' => true, 'item-term' => 
true, 'writeapi' => true ]
+               ] );
+
+               // Then the request is denied
+               $expected = [
+                       'type' => ApiUsageException::class,
+                       'code' => 'permissiondenied'
+               ];
+
+               $this->doTestQueryExceptions(
+                       $this->getCreateItemAndSetDescriptionRequestParams(),
+                       $expected,
+                       $userWithInsufficientPermissions
+               );
+       }
+
        /**
         * @param User $user
         * @return Item
@@ -125,4 +164,13 @@
                ];
        }
 
+       private function getCreateItemAndSetDescriptionRequestParams() {
+               return [
+                       'action' => 'wbsetdescription',
+                       'new' => 'item',
+                       'language' => 'en',
+                       'value' => 'some description',
+               ];
+       }
+
 }
diff --git a/repo/tests/phpunit/includes/Api/SetLabelTest.php 
b/repo/tests/phpunit/includes/Api/SetLabelTest.php
index 4875845..1dff140 100644
--- a/repo/tests/phpunit/includes/Api/SetLabelTest.php
+++ b/repo/tests/phpunit/includes/Api/SetLabelTest.php
@@ -98,6 +98,45 @@
                );
        }
 
+       public function 
testUserCanCreateItemWithLabelWhenTheyHaveSufficientPermissions() {
+               $userWithAllPermissions = $this->createUserWithGroup( 
'all-permission' );
+
+               $this->setMwGlobals( 'wgGroupPermissions', [
+                       'all-permission' => [ 'item-term' => true, 'createpage' 
=> true ],
+                       '*' => [ 'read' => true, 'edit' => true, 'writeapi' => 
true ]
+               ] );
+
+               list ( $result, ) = $this->doApiRequestWithToken(
+                       $this->getCreateItemAndSetLabelRequestParams(),
+                       null,
+                       $userWithAllPermissions
+               );
+
+               $this->assertEquals( 1, $result['success'] );
+               $this->assertSame( 'a label', 
$result['entity']['labels']['en']['value'] );
+       }
+
+       public function testUserCannotCreateItemWhenTheyLackPermission() {
+               $userWithInsufficientPermissions = $this->createUserWithGroup( 
'no-permission' );
+
+               $this->setMwGlobals( 'wgGroupPermissions', [
+                       'no-permission' => [ 'createpage' => false ],
+                       '*' => [ 'read' => true, 'edit' => true, 'item-term' => 
true, 'writeapi' => true ]
+               ] );
+
+               // Then the request is denied
+               $expected = [
+                       'type' => ApiUsageException::class,
+                       'code' => 'permissiondenied'
+               ];
+
+               $this->doTestQueryExceptions(
+                       $this->getCreateItemAndSetLabelRequestParams(),
+                       $expected,
+                       $userWithInsufficientPermissions
+               );
+       }
+
        /**
         * @param User $user
         * @return Item
@@ -116,6 +155,15 @@
 
        }
 
+       private function getCreateItemAndSetLabelRequestParams() {
+               return [
+                       'action' => 'wbsetlabel',
+                       'new' => 'item',
+                       'language' => 'en',
+                       'value' => 'a label',
+               ];
+       }
+
        private function getSetLabelRequestParams( ItemId $id ) {
                return [
                        'action' => 'wbsetlabel',
diff --git a/repo/tests/phpunit/includes/Api/SetSiteLinkTest.php 
b/repo/tests/phpunit/includes/Api/SetSiteLinkTest.php
index 4ae4ecd..e93990d 100644
--- a/repo/tests/phpunit/includes/Api/SetSiteLinkTest.php
+++ b/repo/tests/phpunit/includes/Api/SetSiteLinkTest.php
@@ -610,6 +610,45 @@
                );
        }
 
+       public function 
testUserCanCreateItemWithSiteLinkWhenTheyHaveSufficientPermissions() {
+               $userWithAllPermissions = $this->createUserWithGroup( 
'all-permission' );
+
+               $this->setMwGlobals( 'wgGroupPermissions', [
+                       'all-permission' => [ 'edit' => true, 'createpage' => 
true ],
+                       '*' => [ 'read' => true, 'writeapi' => true ]
+               ] );
+
+               list ( $result, ) = $this->doApiRequestWithToken(
+                       $this->getCreateItemAndSetSiteLinkRequestParams(),
+                       null,
+                       $userWithAllPermissions
+               );
+
+               $this->assertEquals( 1, $result['success'] );
+               $this->assertSame( 'Another Cool Page', 
$result['entity']['sitelinks']['enwiki']['title'] );
+       }
+
+       public function testUserCannotCreateItemWhenTheyLackPermission() {
+               $userWithInsufficientPermissions = $this->createUserWithGroup( 
'no-permission' );
+
+               $this->setMwGlobals( 'wgGroupPermissions', [
+                       'no-permission' => [ 'createpage' => false ],
+                       '*' => [ 'read' => true, 'edit' => true, 'writeapi' => 
true ]
+               ] );
+
+               // Then the request is denied
+               $expected = [
+                       'type' => ApiUsageException::class,
+                       'code' => 'permissiondenied'
+               ];
+
+               $this->doTestQueryExceptions(
+                       $this->getCreateItemAndSetSiteLinkRequestParams(),
+                       $expected,
+                       $userWithInsufficientPermissions
+               );
+       }
+
        /**
         * @param User $user
         * @return Item
@@ -633,7 +672,16 @@
                        'action' => 'wbsetsitelink',
                        'id' => $id->getSerialization(),
                        'linksite' => 'enwiki',
-                       'linktitle' => 'Come Cool Page',
+                       'linktitle' => 'Some Cool Page',
+               ];
+       }
+
+       private function getCreateItemAndSetSiteLinkRequestParams() {
+               return [
+                       'action' => 'wbsetsitelink',
+                       'new' => 'item',
+                       'linksite' => 'enwiki',
+                       'linktitle' => 'Another Cool Page',
                ];
        }
 
diff --git 
a/repo/tests/phpunit/includes/Store/WikiPageEntityStorePermissionCheckerTest.php
 
b/repo/tests/phpunit/includes/Store/WikiPageEntityStorePermissionCheckerTest.php
index c8cfbc3..a8d3551 100644
--- 
a/repo/tests/phpunit/includes/Store/WikiPageEntityStorePermissionCheckerTest.php
+++ 
b/repo/tests/phpunit/includes/Store/WikiPageEntityStorePermissionCheckerTest.php
@@ -519,6 +519,136 @@
                ];
        }
 
+       /**
+        * @dataProvider 
provideNonExistingEntitiesAndPermissionsThatAllowEditingTerms
+        */
+       public function 
testAllRequiredPermissionsAreNeededToEditTermsOfNonExistingEntity(
+               EntityDocument $nonExistingEntity,
+               array $groupPermissions
+       ) {
+               $this->anyUserHasPermissions( $groupPermissions );
+
+               $this->assertUserIsAllowedTo( 
EntityPermissionChecker::ACTION_EDIT_TERMS, $nonExistingEntity );
+       }
+
+       public function 
provideNonExistingEntitiesAndPermissionsThatAllowEditingTerms() {
+               return [
+                       'non-existing item, createpage permission' => [
+                               $this->getNonExistingItem(),
+                               [ 'createpage' => true ]
+                       ],
+                       'non-existing item (null ID), createpage permission' => 
[
+                               $this->getNonExistingItemWithNullId(),
+                               [ 'createpage' => true ]
+                       ],
+                       'non-existing property, createpage and property-create 
permission' => [
+                               $this->getNonExistingProperty(),
+                               [ 'createpage' => true, 'property-create' => 
true, ]
+                       ],
+                       'non-existing property (null ID), createpage and 
property-create permission' => [
+                               $this->getNonExistingPropertyWithNullId(),
+                               [ 'createpage' => true, 'property-create' => 
true, ]
+                       ],
+               ];
+       }
+
+       /**
+        * @dataProvider 
provideNonExistingEntitiesAndPermissionsThatDisallowEditingTerms
+        */
+       public function 
testAllRequiredPermissionsAreNeededToEditTermsOfNonExistingEntity_failures(
+               EntityDocument $nonExistingEntity,
+               array $groupPermissions
+       ) {
+               $this->anyUserHasPermissions( $groupPermissions );
+
+               $this->assertItIsForbiddenForUserTo( 
EntityPermissionChecker::ACTION_EDIT_TERMS, $nonExistingEntity );
+       }
+
+       public function 
provideNonExistingEntitiesAndPermissionsThatDisallowEditingTerms() {
+               return [
+                       'non-existing item, no createpage permission' => [
+                               $this->getNonExistingItem(),
+                               [ 'createpage' => false ]
+                       ],
+                       'non-existing item, no item-term permission' => [
+                               $this->getNonExistingItem(),
+                               [ 'item-term' => false, 'createpage' => true ]
+                       ],
+                       'non-existing item, no edit permission' => [
+                               $this->getNonExistingItem(),
+                               [ 'edit' => false, 'item-term' => true, 
'createpage' => true ]
+                       ],
+                       'non-existing item, no read permission' => [
+                               $this->getNonExistingItem(),
+                               [ 'read' => false, 'edit' => true, 'item-term' 
=> true, 'createpage' => true ]
+                       ],
+                       'non-existing item (null ID), no createpage permission' 
=> [
+                               $this->getNonExistingItemWithNullId(),
+                               [ 'createpage' => false ]
+                       ],
+                       'non-existing item (null ID), no item-term permission' 
=> [
+                               $this->getNonExistingItemWithNullId(),
+                               [ 'item-term' => false, 'createpage' => true ]
+                       ],
+                       'non-existing item (null ID), no edit permission' => [
+                               $this->getNonExistingItemWithNullId(),
+                               [ 'edit' => false, 'item-term' => true, 
'createpage' => true ]
+                       ],
+                       'non-existing item (null ID), no read permission' => [
+                               $this->getNonExistingItemWithNullId(),
+                               [ 'read' => false, 'edit' => true, 'item-term' 
=> true, 'createpage' => true ]
+                       ],
+                       'non-existing property, no property-create permission' 
=> [
+                               $this->getNonExistingProperty(),
+                               [ 'createpage' => true, 'property-create' => 
false, ]
+                       ],
+                       'non-existing property, no createpage permission' => [
+                               $this->getNonExistingProperty(),
+                               [ 'createpage' => false, 'property-create' => 
true, ]
+                       ],
+                       'non-existing property, no createpage nor 
property-create permission' => [
+                               $this->getNonExistingProperty(),
+                               [ 'createpage' => false, 'property-create' => 
false, ]
+                       ],
+                       'non-existing property, no property-term permission' => 
[
+                               $this->getNonExistingProperty(),
+                               [ 'property-term' => false, 'createpage' => 
true, 'property-create' => true, ]
+                       ],
+                       'non-existing property, no edit permission' => [
+                               $this->getNonExistingProperty(),
+                               [ 'edit' => false, 'property-term' => true, 
'createpage' => true, 'property-create' => true, ]
+                       ],
+                       'non-existing property, no read permission' => [
+                               $this->getNonExistingProperty(),
+                               [ 'read' => false, 'edit' => true, 
'property-term' => true, 'createpage' => true, 'property-create' => true, ]
+                       ],
+                       'non-existing property (null ID), no property-create 
permission' => [
+                               $this->getNonExistingPropertyWithNullId(),
+                               [ 'createpage' => true, 'property-create' => 
false, ]
+                       ],
+                       'non-existing property (null ID), no createpage 
permission' => [
+                               $this->getNonExistingPropertyWithNullId(),
+                               [ 'createpage' => false, 'property-create' => 
true, ]
+                       ],
+                       'non-existing property (null ID), no createpage nor 
property-create permission' => [
+                               $this->getNonExistingPropertyWithNullId(),
+                               [ 'createpage' => false, 'property-create' => 
false, ]
+                       ],
+                       'non-existing property (null ID), no property-term 
permission' => [
+                               $this->getNonExistingPropertyWithNullId(),
+                               [ 'property-term' => false, 'createpage' => 
true, 'property-create' => true, ]
+                       ],
+                       'non-existing property (null ID), no edit permission' 
=> [
+                               $this->getNonExistingPropertyWithNullId(),
+                               [ 'edit' => false, 'property-term' => true, 
'createpage' => true, 'property-create' => true, ]
+                       ],
+                       'non-existing property (null ID), no read permission' 
=> [
+                               $this->getNonExistingPropertyWithNullId(),
+                               [ 'read' => false, 'edit' => true, 
'property-term' => true, 'createpage' => true, 'property-create' => true, ]
+                       ],
+               ];
+       }
+
        public function 
testGivenUnknownPermission_getPermissionStatusForEntityThrowsException() {
                $checker = $this->getPermissionChecker();
 

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6148d0a86197f1ad75bad09937be2fddc4e419e4
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: WMDE-leszek <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to