diff options
author | Thomas Steur <tsteur@users.noreply.github.com> | 2018-07-18 07:47:13 +0300 |
---|---|---|
committer | diosmosis <diosmosis@users.noreply.github.com> | 2018-07-18 07:47:13 +0300 |
commit | 105e007721b5c0ea12ff2596d8d82c721021fb4e (patch) | |
tree | 558162844ba663781fdf0ec691642f0dc453e94e /tests | |
parent | 74334d8d0908910ed3cc4a9a918436d9f9ccc3f6 (diff) |
Introducing a new role "write" and possibility to define capabilities (#13163)
* started working on some ACL concept
* acl implementation
* add category
* small tweaks
* more tweaks
* more api methods and fixes
* cache capabilities
* various enhancements, fixes, tweaks
* more tweaks
* added more tests and fixed some bugs
* fix parameter
* make sure to be BC
* make sure to be BC
* fix some tests
* more apis, translations, changelog entry, ...
* update db
* correct error message
* fix capabilities were not detected in tests
* directly access provider
* fix and add test
* JS api to check capabilities, better structure for capabilities in tests
* add ability to inject permissions
* apply review changes
* fix test
Diffstat (limited to 'tests')
-rw-r--r-- | tests/PHPUnit/Framework/Mock/FakeAccess.php | 108 | ||||
-rw-r--r-- | tests/PHPUnit/Integration/AccessTest.php | 130 | ||||
-rw-r--r-- | tests/PHPUnit/Integration/DbTest.php | 2 | ||||
-rw-r--r-- | tests/PHPUnit/Integration/Tracker/RequestTest.php | 24 | ||||
-rw-r--r-- | tests/PHPUnit/Integration/Updater/Migration/Db/MigrationsTest.php | 14 | ||||
-rw-r--r-- | tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png | 4 |
6 files changed, 230 insertions, 52 deletions
diff --git a/tests/PHPUnit/Framework/Mock/FakeAccess.php b/tests/PHPUnit/Framework/Mock/FakeAccess.php index e23ceb2148..be86704305 100644 --- a/tests/PHPUnit/Framework/Mock/FakeAccess.php +++ b/tests/PHPUnit/Framework/Mock/FakeAccess.php @@ -9,10 +9,11 @@ namespace Piwik\Tests\Framework\Mock; use Piwik\Access; use Piwik\Auth; +use Piwik\Container\StaticContainer; use Piwik\NoAccessException; +use Piwik\Piwik; use Piwik\Plugins\SitesManager\API; use Piwik\Site as PiwikSite; -use Exception; /** * FakeAccess for UnitTests @@ -22,16 +23,20 @@ class FakeAccess extends Access { public static $superUser = false; public static $idSitesAdmin = array(); + public static $idSitesWrite = array(); public static $idSitesView = array(); + public static $idSitesCapabilities = array(); public static $identity = 'superUserLogin'; public static $superUserLogin = 'superUserLogin'; - public static function clearAccess($superUser = false, $idSitesAdmin = array(), $idSitesView = array(), $identity = 'superUserLogin') + public static function clearAccess($superUser = false, $idSitesAdmin = array(), $idSitesView = array(), $identity = 'superUserLogin', $idSitesWrite = array(), $idSitesCapabilities = array()) { self::$superUser = $superUser; self::$idSitesAdmin = $idSitesAdmin; + self::$idSitesWrite = $idSitesWrite; self::$idSitesView = $idSitesView; self::$identity = $identity; + self::$idSitesCapabilities = $idSitesCapabilities; } public function getTokenAuth() @@ -39,11 +44,15 @@ class FakeAccess extends Access return false; } - public function __construct($superUser = false, $idSitesAdmin = array(), $idSitesView = array(), $identity = 'superUserLogin') + public function __construct($superUser = false, $idSitesAdmin = array(), $idSitesView = array(), $identity = 'superUserLogin', $idSitesWrite = array()) { - parent::__construct(); + // couldn't use DI here as tests seem to fail cause at this time when it is called eg in + // plugins/Live/tests/System/ApiCounterTest.php the environment is not set up yet + $role = new Access\RolesProvider(); + $capabilities = new Access\CapabilitiesProvider(); + parent::__construct($role, $capabilities); - self::clearAccess($superUser, $idSitesAdmin, $idSitesView, $identity); + self::clearAccess($superUser, $idSitesAdmin, $idSitesView, $identity, $idSitesWrite); } public static function setIdSitesAdmin($ids) @@ -58,6 +67,12 @@ class FakeAccess extends Access self::$idSitesView = $ids; } + public static function setIdSitesWrite($ids) + { + self::$superUser = false; + self::$idSitesWrite = $ids; + } + public function hasSuperUserAccess() { return self::$superUser; @@ -97,6 +112,50 @@ class FakeAccess extends Access } } + public function checkUserHasWriteAccess($idSites) + { + if (!self::$superUser) { + $websitesAccess = array_merge(self::$idSitesWrite, self::$idSitesAdmin); + } else { + $websitesAccess = API::getInstance()->getAllSitesId(); + } + + $idSites = PiwikSite::getIdSitesFromIdSitesString($idSites); + + foreach ($idSites as $idsite) { + if (!in_array($idsite, $websitesAccess)) { + throw new NoAccessException("checkUserHasWriteAccess Fake exception // string not to be tested"); + } + } + } + + public function checkUserHasCapability($idSites, $capability) + { + $cap = $this->capabilityProvider->getCapability($capability); + + if ($cap && Piwik::isUserHasAdminAccess($idSites) && $cap->hasRoleCapability(Access\Role\Admin::ID)) { + return; + } elseif ($cap && Piwik::isUserHasWriteAccess($idSites) && $cap->hasRoleCapability(Access\Role\Write::ID)) { + return; + } elseif ($cap && Piwik::isUserHasViewAccess($idSites) && $cap->hasRoleCapability(Access\Role\View::ID)) { + return; + } + + if (isset(self::$idSitesCapabilities[$capability]) && is_array(self::$idSitesCapabilities[$capability])) { + if (!is_array($idSites)) { + $idSites = array($idSites); + } + $idSites = array_map('intval', $idSites); + $idSitesCap = array_map('intval', self::$idSitesCapabilities[$capability]); + $missingSites = array_diff($idSites, $idSitesCap); + if (empty($missingSites)) { + return; + } + } + + throw new NoAccessException("checkUserHasCapability " . $capability ." Fake exception // string not to be tested"); + } + //means at least view access public function checkUserHasViewAccess($idSites) { @@ -104,7 +163,7 @@ class FakeAccess extends Access return; } - $websitesAccess = array_merge(self::$idSitesView, self::$idSitesAdmin); + $websitesAccess = array_merge(self::$idSitesView, self::$idSitesWrite, self::$idSitesAdmin); if (!is_array($idSites)) { if ($idSites == 'all') { @@ -128,7 +187,7 @@ class FakeAccess extends Access public function checkUserHasSomeViewAccess() { if (!self::$superUser) { - if (count(array_merge(self::$idSitesView, self::$idSitesAdmin)) == 0) { + if (count(array_merge(self::$idSitesView, self::$idSitesWrite, self::$idSitesAdmin)) == 0) { throw new NoAccessException("checkUserHasSomeViewAccess Fake exception // string not to be tested"); } } else { @@ -136,7 +195,7 @@ class FakeAccess extends Access } } - //means at least view access + //means at least admin access public function isUserHasSomeAdminAccess() { if (self::$superUser) { @@ -146,7 +205,17 @@ class FakeAccess extends Access return count(self::$idSitesAdmin) > 0; } - //means at least view access + //means at least write access + public function isUserHasSomeWriteAccess() + { + if (self::$superUser) { + return true; + } + + return count(self::$idSitesAdmin) > 0 || count(self::$idSitesWrite) > 0; + } + + //means at least admin access public function checkUserHasSomeAdminAccess() { if (!$this->isUserHasSomeAdminAccess()) { @@ -154,6 +223,14 @@ class FakeAccess extends Access } } + //means at least write access + public function checkUserHasSomeWriteAccess() + { + if (!$this->isUserHasSomeWriteAccess()) { + throw new NoAccessException("checkUserHasSomeWriteAccess Fake exception // string not to be tested"); + } + } + public function getLogin() { return self::$identity; @@ -177,20 +254,29 @@ class FakeAccess extends Access return self::$idSitesView; } + public function getSitesIdWithWriteAccess() + { + if (self::$superUser) { + return API::getInstance()->getAllSitesId(); + } + + return self::$idSitesWrite; + } + public function getSitesIdWithAtLeastViewAccess() { if (self::$superUser) { return API::getInstance()->getAllSitesId(); } - return array_merge(self::$idSitesView, self::$idSitesAdmin); + return array_merge(self::$idSitesView, self::$idSitesWrite, self::$idSitesAdmin); } public function getRawSitesWithSomeViewAccess($login) { $result = array(); - foreach (array_merge(self::$idSitesView, self::$idSitesAdmin) as $idSite) { + foreach (array_merge(self::$idSitesView, self::$idSitesWrite, self::$idSitesAdmin) as $idSite) { $result[] = array('idsite' => $idSite); } diff --git a/tests/PHPUnit/Integration/AccessTest.php b/tests/PHPUnit/Integration/AccessTest.php index 9616bec782..755d075b0e 100644 --- a/tests/PHPUnit/Integration/AccessTest.php +++ b/tests/PHPUnit/Integration/AccessTest.php @@ -22,39 +22,45 @@ class AccessTest extends IntegrationTestCase { public function testGetListAccess() { - $accessList = Access::getListAccess(); - $shouldBe = array('noaccess', 'view', 'admin', 'superuser'); + $roleProvider = new Access\RolesProvider(); + $accessList = $roleProvider->getAllRoleIds(); + $shouldBe = array('view', 'write', 'admin'); $this->assertEquals($shouldBe, $accessList); } + + private function getAccess() + { + return new Access(new Access\RolesProvider(), new Access\CapabilitiesProvider()); + } public function testGetTokenAuthWithEmptyAccess() { - $access = new Access(); + $access = $this->getAccess(); $this->assertNull($access->getTokenAuth()); } public function testGetLoginWithEmptyAccess() { - $access = new Access(); + $access = $this->getAccess(); $this->assertNull($access->getLogin()); } public function testHasSuperUserAccessWithEmptyAccess() { - $access = new Access(); + $access = $this->getAccess(); $this->assertFalse($access->hasSuperUserAccess()); } public function testHasSuperUserAccessWithSuperUserAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->setSuperUserAccess(true); $this->assertTrue($access->hasSuperUserAccess()); } public function test_GetLogin_UserIsNotAnonymous_WhenSuperUserAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->setSuperUserAccess(true); $this->assertNotEmpty($access->getLogin()); $this->assertNotSame('anonymous', $access->getLogin()); @@ -62,26 +68,32 @@ class AccessTest extends IntegrationTestCase public function testHasSuperUserAccessWithNoSuperUserAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->setSuperUserAccess(false); $this->assertFalse($access->hasSuperUserAccess()); } public function testGetSitesIdWithAtLeastViewAccessWithEmptyAccess() { - $access = new Access(); + $access = $this->getAccess(); $this->assertEmpty($access->getSitesIdWithAtLeastViewAccess()); } public function testGetSitesIdWithAdminAccessWithEmptyAccess() { - $access = new Access(); + $access = $this->getAccess(); $this->assertEmpty($access->getSitesIdWithAdminAccess()); } + public function testGetSitesIdWithWriteAccessWithEmptyAccess() + { + $access = $this->getAccess(); + $this->assertEmpty($access->getSitesIdWithWriteAccess()); + } + public function testGetSitesIdWithViewAccessWithEmptyAccess() { - $access = new Access(); + $access = $this->getAccess(); $this->assertEmpty($access->getSitesIdWithViewAccess()); } @@ -90,13 +102,13 @@ class AccessTest extends IntegrationTestCase */ public function testCheckUserHasSuperUserAccessWithEmptyAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->checkUserHasSuperUserAccess(); } public function testCheckUserHasSuperUserAccessWithSuperUserAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->setSuperUserAccess(true); $access->checkUserHasSuperUserAccess(); } @@ -106,27 +118,27 @@ class AccessTest extends IntegrationTestCase */ public function testCheckUserHasSomeAdminAccessWithEmptyAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->checkUserHasSomeAdminAccess(); } public function testCheckUserHasSomeAdminAccessWithSuperUserAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->setSuperUserAccess(true); $access->checkUserHasSomeAdminAccess(); } public function test_isUserHasSomeAdminAccess_WithSuperUserAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->setSuperUserAccess(true); $this->assertTrue($access->isUserHasSomeAdminAccess()); } public function test_isUserHasSomeAdminAccess_WithOnlyViewAccess() { - $access = new Access(); + $access = $this->getAccess(); $this->assertFalse($access->isUserHasSomeAdminAccess()); } @@ -182,13 +194,13 @@ class AccessTest extends IntegrationTestCase */ public function testCheckUserHasSomeViewAccessWithEmptyAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->checkUserHasSomeViewAccess(); } public function testCheckUserHasSomeViewAccessWithSuperUserAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->setSuperUserAccess(true); $access->checkUserHasSomeViewAccess(); } @@ -204,12 +216,37 @@ class AccessTest extends IntegrationTestCase $mock->checkUserHasSomeViewAccess(); } + public function testCheckUserHasSomeWriteAccessWithSomeAccess() + { + $mock = $this->createAccessMockWithAuthenticatedUser(array('getRawSitesWithSomeViewAccess')); + + $mock->expects($this->once()) + ->method('getRawSitesWithSomeViewAccess') + ->will($this->returnValue($this->buildWriteAccessForSiteIds(array(1, 2, 3, 4)))); + + $mock->checkUserHasSomeWriteAccess(); + } + + /** + * @expectedException \Piwik\NoAccessException + */ + public function testCheckUserHasSomeWriteAccessWithSomeAccessDoesNotHaveAccess() + { + $mock = $this->createAccessMockWithAuthenticatedUser(array('getRawSitesWithSomeViewAccess')); + + $mock->expects($this->once()) + ->method('getRawSitesWithSomeViewAccess') + ->will($this->returnValue($this->buildWriteAccessForSiteIds(array()))); + + $mock->checkUserHasSomeWriteAccess(); + } + /** * @expectedException \Piwik\NoAccessException */ public function testCheckUserHasViewAccessWithEmptyAccessNoSiteIdsGiven() { - $access = new Access(); + $access = $this->getAccess(); $access->checkUserHasViewAccess(array()); } @@ -258,9 +295,39 @@ class AccessTest extends IntegrationTestCase $mock->checkUserHasViewAccess(array(1, 5)); } + /** + * @expectedException \Piwik\NoAccessException + */ + public function testCheckUserHasWriteAccessWithEmptyAccessNoSiteIdsGiven() + { + $access = $this->getAccess(); + $access->checkUserHasWriteAccess(array()); + } + + public function testCheckUserHasWriteAccessWithSuperUserAccess() + { + $access = Access::getInstance(); + $access->setSuperUserAccess(true); + $access->checkUserHasWriteAccess(array()); + } + + /** + * @expectedException \Piwik\NoAccessException + */ + public function testCheckUserHasWriteAccessWithSomeAccessFailure() + { + $mock = $this->getMockBuilder('Piwik\Access')->setMethods(array('getSitesIdWithAtLeastWriteAccess'))->getMock(); + + $mock->expects($this->once()) + ->method('getSitesIdWithAtLeastWriteAccess') + ->will($this->returnValue(array(1, 2, 3, 4))); + + $mock->checkUserHasWriteAccess(array(1, 5)); + } + public function testCheckUserHasAdminAccessWithSuperUserAccess() { - $access = new Access(); + $access = $this->getAccess(); $access->setSuperUserAccess(true); $access->checkUserHasAdminAccess(array()); } @@ -270,7 +337,7 @@ class AccessTest extends IntegrationTestCase */ public function testCheckUserHasAdminAccessWithEmptyAccessNoSiteIdsGiven() { - $access = new Access(); + $access = $this->getAccess(); $access->checkUserHasViewAccess(array()); } @@ -325,13 +392,13 @@ class AccessTest extends IntegrationTestCase public function testReloadAccessWithEmptyAuth() { - $access = new Access(); + $access = $this->getAccess(); $this->assertFalse($access->reloadAccess(null)); } public function testReloadAccessWithEmptyAuthSuperUser() { - $access = new Access(); + $access = $this->getAccess(); $access->setSuperUserAccess(true); $this->assertTrue($access->reloadAccess(null)); } @@ -339,7 +406,7 @@ class AccessTest extends IntegrationTestCase public function testReloadAccess_ShouldResetTokenAuthAndLogin_IfAuthIsNotValid() { $mock = $this->createAuthMockWithAuthResult(AuthResult::SUCCESS); - $access = new Access(); + $access = $this->getAccess(); $this->assertTrue($access->reloadAccess($mock)); $this->assertSame('login', $access->getLogin()); @@ -361,7 +428,7 @@ class AccessTest extends IntegrationTestCase $mock->expects($this->any())->method('getName')->will($this->returnValue("test name")); - $access = new Access(); + $access = $this->getAccess(); $this->assertTrue($access->reloadAccess($mock)); $this->assertFalse($access->hasSuperUserAccess()); } @@ -468,6 +535,17 @@ class AccessTest extends IntegrationTestCase return $access; } + private function buildWriteAccessForSiteIds($siteIds) + { + $access = array(); + + foreach ($siteIds as $siteId) { + $access[] = array('access' => 'write', 'idsite' => $siteId); + } + + return $access; + } + private function buildViewAccessForSiteIds($siteIds) { $access = array(); diff --git a/tests/PHPUnit/Integration/DbTest.php b/tests/PHPUnit/Integration/DbTest.php index 0ca35122b5..0f3ab4bd9d 100644 --- a/tests/PHPUnit/Integration/DbTest.php +++ b/tests/PHPUnit/Integration/DbTest.php @@ -20,7 +20,7 @@ class DbTest extends IntegrationTestCase { public function test_getColumnNamesFromTable() { - $this->assertColumnNames('access', array('login', 'idsite', 'access')); + $this->assertColumnNames('access', array('idaccess', 'login', 'idsite', 'access')); $this->assertColumnNames('option', array('option_name', 'option_value', 'autoload')); } diff --git a/tests/PHPUnit/Integration/Tracker/RequestTest.php b/tests/PHPUnit/Integration/Tracker/RequestTest.php index 05eee7ea30..647acf1100 100644 --- a/tests/PHPUnit/Integration/Tracker/RequestTest.php +++ b/tests/PHPUnit/Integration/Tracker/RequestTest.php @@ -227,10 +227,10 @@ class RequestTest extends IntegrationTestCase public function test_authenticateSuperUserOrAdmin_ShouldFailIfTokenIsEmpty() { - $isAuthenticated = Request::authenticateSuperUserOrAdmin('', 2); + $isAuthenticated = Request::authenticateSuperUserOrAdminOrWrite('', 2); $this->assertFalse($isAuthenticated); - $isAuthenticated = Request::authenticateSuperUserOrAdmin(null, 2); + $isAuthenticated = Request::authenticateSuperUserOrAdminOrWrite(null, 2); $this->assertFalse($isAuthenticated); } @@ -241,16 +241,16 @@ class RequestTest extends IntegrationTestCase $called++; }); - Request::authenticateSuperUserOrAdmin('', 2); + Request::authenticateSuperUserOrAdminOrWrite('', 2); $this->assertSame(0, $called); - Request::authenticateSuperUserOrAdmin('atoken', 2); + Request::authenticateSuperUserOrAdminOrWrite('atoken', 2); $this->assertSame(1, $called); - Request::authenticateSuperUserOrAdmin('anothertoken', 2); + Request::authenticateSuperUserOrAdminOrWrite('anothertoken', 2); $this->assertSame(2, $called); - Request::authenticateSuperUserOrAdmin(null, 2); + Request::authenticateSuperUserOrAdminOrWrite(null, 2); $this->assertSame(2, $called); } @@ -258,10 +258,10 @@ class RequestTest extends IntegrationTestCase { $token = $this->createAdminUserForSite(2); - $isAuthenticated = Request::authenticateSuperUserOrAdmin($token, -2); + $isAuthenticated = Request::authenticateSuperUserOrAdminOrWrite($token, -2); $this->assertFalse($isAuthenticated); - $isAuthenticated = Request::authenticateSuperUserOrAdmin($token, 0); + $isAuthenticated = Request::authenticateSuperUserOrAdminOrWrite($token, 0); $this->assertFalse($isAuthenticated); } @@ -269,10 +269,10 @@ class RequestTest extends IntegrationTestCase { $token = $this->createAdminUserForSite(2); - $isAuthenticated = Request::authenticateSuperUserOrAdmin($token, 1); + $isAuthenticated = Request::authenticateSuperUserOrAdminOrWrite($token, 1); $this->assertFalse($isAuthenticated); - $isAuthenticated = Request::authenticateSuperUserOrAdmin($token, 2); + $isAuthenticated = Request::authenticateSuperUserOrAdminOrWrite($token, 2); $this->assertTrue($isAuthenticated); } @@ -281,10 +281,10 @@ class RequestTest extends IntegrationTestCase Fixture::createSuperUser(false); $token = Fixture::getTokenAuth(); - $isAuthenticated = Request::authenticateSuperUserOrAdmin($token, 1); + $isAuthenticated = Request::authenticateSuperUserOrAdminOrWrite($token, 1); $this->assertTrue($isAuthenticated); - $isAuthenticated = Request::authenticateSuperUserOrAdmin($token, 2); + $isAuthenticated = Request::authenticateSuperUserOrAdminOrWrite($token, 2); $this->assertTrue($isAuthenticated); } diff --git a/tests/PHPUnit/Integration/Updater/Migration/Db/MigrationsTest.php b/tests/PHPUnit/Integration/Updater/Migration/Db/MigrationsTest.php index 2b91587251..9a630a2d08 100644 --- a/tests/PHPUnit/Integration/Updater/Migration/Db/MigrationsTest.php +++ b/tests/PHPUnit/Integration/Updater/Migration/Db/MigrationsTest.php @@ -139,6 +139,20 @@ class MigrationsTest extends IntegrationTestCase /** * @depends test_addPrimaryIndex */ + public function test_dropPrimaryKey() + { + $index = Db::fetchAll("SHOW INDEX FROM {$this->testTablePrefixed} WHERE Key_name = 'PRIMARY'"); + $this->assertCount(1, $index); + + $this->factory->dropPrimaryKey($this->testTable)->exec(); + + $index = Db::fetchAll("SHOW INDEX FROM {$this->testTablePrefixed} WHERE Key_name = 'PRIMARY'"); + $this->assertCount(0, $index); + } + + /** + * @depends test_addPrimaryIndex + */ public function test_changeColumnType() { $this->factory->changeColumnType($this->testTable, 'column2', 'SMALLINT(4) NOT NULL')->exec(); diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png index 0a86593dda..f1020f0afc 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:462b39b9f971b3c5be5abbeec00244867b6de68ed0a35b363d82025decb74c87 -size 4479480 +oid sha256:da072fcbaf8fb5a143984e6b37bd6191e5acf0633f487dedca7588cf56211b8b +size 4517064 |