1
0
قرینه از https://github.com/matomo-org/matomo.git synced 2025-08-22 15:07:44 +00:00
Files
matomo/plugins/UsersManager/tests/Integration/UsersManagerTest.php
Michal Kleiner 7cc8a70b3d Add mechanism to send inactive users notification (#23425)
* Add new setting for enabling inactive user notifications (#23393)
* Migrate 'last seen' from options table to users table (#23388)
* Create scheduled task to send inactive users security notification (#23403)
* Simplify enrich user and remove surplus methods
* Create a language helper to run code using given user's preferred language
* Update UI test screenshots

---------

Co-authored-by: Nathan Gavin <nathangavin987@gmail.com>
2025-08-05 13:54:58 +12:00

1226 خطوط
42 KiB
PHP

<?php
/**
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
namespace Piwik\Plugins\UsersManager\tests\Integration;
use Exception;
use Piwik\Access;
use Piwik\Auth\Password;
use Piwik\Date;
use Piwik\Option;
use Piwik\Plugins\SitesManager\API as APISitesManager;
use Piwik\Plugins\UsersManager\API;
use Piwik\Plugins\UsersManager\Model;
use Piwik\Plugins\UsersManager\NewsletterSignup;
use Piwik\Plugins\UsersManager\UsersManager;
use Piwik\Plugins\UsersManager\UserUpdater;
use Piwik\Tests\Framework\Fixture;
use Piwik\Tests\Framework\Mock\FakeAccess;
use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
/**
* @group UsersManagerTest
* @group UsersManager
* @group Plugins
*/
class UsersManagerTest extends IntegrationTestCase
{
public const DATETIME_REGEX = '/\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}/';
/**
* @var API
*/
private $api;
/**
* @var Model
*/
private $model;
private $backupIdentity;
public function setUp(): void
{
parent::setUp();
\Piwik\Plugin\Manager::getInstance()->loadPlugin('UsersManager');
\Piwik\Plugin\Manager::getInstance()->installLoadedPlugins();
$this->addSites(4);
// setup the access layer
FakeAccess::setIdSitesView(array(1, 2));
FakeAccess::setIdSitesAdmin(array(3, 4));
//finally we set the user as a Super User by default
FakeAccess::$superUser = true;
FakeAccess::$superUserLogin = 'superusertest';
$this->backupIdentity = FakeAccess::$identity;
$this->api = API::getInstance();
$this->model = new Model();
}
public function tearDown(): void
{
FakeAccess::$identity = $this->backupIdentity;
parent::tearDown();
}
private function flatten($sitesAccess)
{
$result = array();
foreach ($sitesAccess as $siteAccess) {
$result[$siteAccess['site']] = $siteAccess['access'];
}
return $result;
}
private function checkUserHasNotChanged($user, $newPassword, $newEmail = null)
{
if (is_null($newEmail)) {
$newEmail = $user['email'];
}
$userAfter = $this->model->getUser($user["login"]);
$this->assertArrayHasKey('date_registered', $userAfter);
$this->assertRegExp(self::DATETIME_REGEX, $userAfter['date_registered']);
$this->assertArrayHasKey('ts_password_modified', $userAfter);
$this->assertRegExp(self::DATETIME_REGEX, $userAfter['date_registered']);
$this->assertArrayHasKey('password', $userAfter);
$this->assertNotEmpty($userAfter['password']);
unset($userAfter['date_registered']);
unset($userAfter['ts_password_modified']);
unset($userAfter['idchange_last_viewed']);
unset($userAfter['ts_changes_shown']);
unset($userAfter['password']);
unset($userAfter['invite_status']);
unset($userAfter['invite_token']);
unset($userAfter['invite_expired_at']);
unset($userAfter['invite_link_token']);
unset($userAfter['invite_accept_at']);
unset($userAfter['invited_by']);
unset($userAfter['ts_last_seen']);
unset($userAfter['ts_inactivity_notified']);
// implicitly checks password!
$user['email'] = $newEmail;
$user['superuser_access'] = 0;
$user['twofactor_secret'] = '';
unset($user['password']);
unset($user['invite_status']);
$this->assertEquals($user, $userAfter);
}
/**
* bad password => exception
*/
public function testUpdateUserBadpasswd()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionInvalidPassword');
$login = "login";
$user = array(
'login' => $login,
'password' => "geqgeagae",
'email' => "test@test.com",
);
$this->api->addUser($user['login'], $user['password'], $user['email']);
try {
$this->api->updateUser($login, "pas");
} catch (Exception $expected) {
$this->checkUserHasNotChanged($user, $user['password']);
throw $expected;
}
}
/**
* Dataprovider
*/
public function getAddUserInvalidLoginData()
{
return array(
array(9, "password", "email@email.com"), // wrong login / integer => exception
array("gegag'ggea'", "password", "email@email.com"), // wrong login / too short => exception
array("gegag11gge&", "password", "email@email.com"), // wrong login / too long => exception
array("geg'ag11gge@", "password", "email@email.com"), // wrong login / bad characters => exception
);
}
/**
* @dataProvider getAddUserInvalidLoginData
*/
public function testAddUserWrongLogin($userLogin, $password, $email)
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionInvalidLogin');
$this->api->addUser($userLogin, $password, $email);
}
public function testAddUserExistingLogin()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionLoginExists');
$this->api->addUser("test", "password", "email@email.com");
$this->api->addUser("test", "password2", "em2ail@email.com");
}
public function testAddUserExistingEmail()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionEmailExists');
$this->api->addUser("test", "password", "email@email.com");
$this->api->addUser("test2", "password2", "email@email.com");
}
public function testAddUserExistingEmailAsUserName()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionEmailExistsAsLogin');
$this->api->addUser("email@email.com", "password", "email2@email.com");
$this->api->addUser("test2", "password2", "email@email.com");
}
/**
* @see https://github.com/piwik/piwik/issues/8548
*/
public function testAddUserExistingLoginCaseInsensitive()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionLoginExists');
$this->api->addUser("test", "password", "email@email.com");
$this->api->addUser("TeSt", "password2", "em2ail@email.com");
}
/**
* Dataprovider for wrong password tests
*/
public function getWrongPasswordTestData()
{
return array(
array("geggeqgeqag", "pas", "email@email.com"), // too short -> exception
array("geggeqgeqag", "", "email@email.com"), // empty -> exception
);
}
/**
* @dataProvider getWrongPasswordTestData
*/
public function testAddUserWrongPassword($userLogin, $password, $email)
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionInvalidPassword');
$this->api->addUser($userLogin, $password, $email);
}
public function testAddUserWrongEmail()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('mail');
$this->api->addUser('geggeqgeqag', 'geqgeagae', "ema il@email.com");
}
/**
* long password => should work
*/
public function testAddUserLongPassword()
{
$login = "geggeqgeqag";
$this->api->addUser(
$login,
"geqgeagaegeqgeagaegeqgeagaegeqgeagaegeqgeagaegeqgeagaegeqgeagaegeqgeagaegeqgeagaegeqgeagaegeqgeagaeg",
"mgeagi@geq.com"
);
$user = $this->api->getUser($login);
$this->assertEquals($login, $user['login']);
}
/**
* normal test case
*/
public function testAddUser()
{
$login = "geggeq55eqag";
$password = "mypassword";
$email = "mgeag4544i@geq.com";
$time = time();
$this->api->addUser($login, $password, $email);
$user = $this->model->getUser($login);
// check that the date registered is correct
$this->assertTrue(
$time <= strtotime($user['date_registered']) && strtotime($user['date_registered']) <= time(),
"the date_registered " . strtotime($user['date_registered']) . " is different from the time() " . time()
);
// check that password and token are properly set
$this->assertEquals(60, strlen($user['password']));
// check that all fields are the same
$this->assertEquals($login, $user['login']);
$this->assertEquals($email, $user['email']);
$passwordHelper = new Password();
$this->assertTrue($passwordHelper->verify(UsersManager::getPasswordHash($password), $user['password']));
}
public function testAddUserShouldAllowAdminUsersToCreateUsers()
{
FakeAccess::$superUser = false;
FakeAccess::$idSitesAdmin = [1];
$login = "geggeq55eqag";
$password = "mypassword";
$email = "mgeag4544i@geq.com";
$this->api->addUser($login, $password, $email, false, 1);
FakeAccess::$superUser = true;
$user = $this->api->getUser($login);
$this->assertEquals($login, $user['login']);
$this->assertEquals($email, $user['email']);
FakeAccess::$superUser = true;
$access = $this->api->getSitesAccessFromUser($login);
$this->assertEquals([
['site' => 1, 'access' => 'view'],
], $access);
}
public function testAddUserShouldNotAllowAdminUsersToCreateUsersWithNoInitialSiteWithAccess()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_AddUserNoInitialAccessError');
FakeAccess::$superUser = false;
FakeAccess::$idSitesAdmin = [1];
$this->api->addUser('userLogin2', 'password', 'userlogin2@email.com');
}
public function testAddUserShouldNotAllowAdminUsersToCreateUsersWithAccessToSiteThatAdminUserDoesNotHaveAccessTo()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('checkUserHasAdminAccess Fake exception');
FakeAccess::$superUser = false;
FakeAccess::$idSitesAdmin = [2];
$this->api->addUser('userLogin2', 'password', 'userlogin2@email.com', false, 1);
}
public function testDeleteUserDoesntExist()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->api->addUser("geggeqgeqag", "geqgeagae", "test@test.com");
$this->api->deleteUser("geggeqggnew");
}
public function testDeleteUserEmptyUser()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->api->deleteUser("");
}
public function testDeleteUserNullUser()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->api->deleteUser(null);
}
public function testDeleteUserShouldFailInCaseTheUserIsTheOnlyRemainingSuperUser()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionDeleteOnlyUserWithSuperUserAccess');
//add user and set some rights
$this->api->addUser("regularuser", "geqgeagae1", "test1@test.com");
$this->api->addUser("superuser", "geqgeagae2", "test2@test.com");
$userUpdater = new UserUpdater();
$userUpdater->setSuperUserAccessWithoutCurrentPassword('superuser', true);
// delete the user
$this->api->deleteUser("superuser");
}
/**
* normal case, user deleted
*/
public function testDeleteUser()
{
Fixture::createSuperUser();
$this->addSites(3);
//add user and set some rights
$this->api->addUser("geggeqgeqag", "geqgeagae", "test@test.com");
$this->api->setUserAccess("geggeqgeqag", "view", array(1, 2));
$this->api->setUserAccess("geggeqgeqag", "admin", array(1, 3));
// check rights are set
$this->assertNotEquals(array(), $this->api->getSitesAccessFromUser("geggeqgeqag"));
// delete the user
$this->api->deleteUser("geggeqgeqag");
// try to get it, it should raise an exception
try {
$this->api->getUser("geggeqgeqag");
$this->fail("Exception not raised.");
} catch (Exception $expected) {
$this->assertRegExp("(UsersManager_ExceptionUserDoesNotExist)", $expected->getMessage());
}
// add the same user
$this->api->addUser("geggeqgeqag", "geqgeagae", "test@test.com");
// check access has been deleted
// to do so we recreate the same user login and check if the rights are still there
$this->assertEquals(array(), $this->api->getSitesAccessFromUser("geggeqgeqag"));
}
public function testDeleteUserDeletesUserOptions()
{
Fixture::createSuperUser();
$this->api->addUser("geggeqgeqag", "geqgeagae", "test@test.com");
Option::set(NewsletterSignup::NEWSLETTER_SIGNUP_OPTION . 'geggeqgeqag', 'yes');
$this->api->deleteUser("geggeqgeqag");
$option = Option::get(NewsletterSignup::NEWSLETTER_SIGNUP_OPTION . 'geggeqgeqag');
$this->assertFalse($option);
}
public function testGetUserNoUser()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
// try to get it, it should raise an exception
$this->api->getUser("geggeqgeqag");
}
/**
* normal case
*/
public function testGetUser()
{
$login = "geggeq55eqag";
$password = "mypassword";
$email = "mgeag4544i@geq.com";
$this->api->addUser($login, $password, $email);
$user = $this->model->getUser($login);
// check that all fields are the same
$this->assertEquals($login, $user['login']);
self::assertIsString($user['password']);
self::assertIsString($user['date_registered']);
$this->assertEquals($email, $user['email']);
}
/**
* no user => empty array
*/
public function testGetUsersNoUser()
{
$this->assertEquals($this->api->getUsers(), array());
}
/**
* normal case
* as well as selecting specific user names, comma separated
* also tests setting and getting 'last seen' for the user
*/
public function testGetUsers()
{
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
$this->api->addUser("geggeqge632ge56a4qag", "geqgegeagae", "tesggt@tesgt.com");
$this->api->addUser("geggeqgeqagqegg", "geqgeaggggae", "tesgggt@tesgt.com");
$nowDt = Date::getDatetimeFromTimestamp(time());
$this->model->setLastSeenDatetime('gegg4564eqgeqag', $nowDt);
$users = $this->api->getUsers();
$users = $this->removeNonTestableFieldsFromUsers($users);
$user1 = array('login' => "gegg4564eqgeqag",
'email' => "tegst@tesgt.com",
'superuser_access' => 0,
'uses_2fa' => false,
'last_seen' => $nowDt,
'last_seen_ago' => '00:00:00',
);
$user2 = array('login' => "geggeqge632ge56a4qag",
'email' => "tesggt@tesgt.com",
'superuser_access' => 0,
'uses_2fa' => false,
);
$user3 = array('login' => "geggeqgeqagqegg",
'email' => "tesgggt@tesgt.com",
'superuser_access' => 0,
'uses_2fa' => false,
);
$expectedUsers = array($user1, $user2, $user3);
$this->assertEquals($expectedUsers, $users);
$this->assertEquals(
array($user1),
$this->removeNonTestableFieldsFromUsers($this->api->getUsers('gegg4564eqgeqag'))
);
$this->assertEquals(
array($user1, $user2),
$this->removeNonTestableFieldsFromUsers($this->api->getUsers('gegg4564eqgeqag,geggeqge632ge56a4qag'))
);
}
public function testGetUsersWithViewAccessShouldThrowAnException()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('checkUserHasSomeAdminAccess Fake exception');
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
$this->api->addUser("geggeqge632ge56a4qag", "geqgegeagae", "tesggt@tesgt.com");
$this->api->addUser("geggeqgeqagqegg", "geqgeaggggae", "tesgggt@tesgt.com");
FakeAccess::clearAccess($superUser = false, $admin = array(), $view = array(1), 'gegg4564eqgeqag');
$this->api->getUsers();
}
protected function removeNonTestableFieldsFromUsers($users)
{
foreach ($users as &$user) {
unset($user['password']);
unset($user['token_auth']);
unset($user['date_registered']);
unset($user['ts_password_modified']);
unset($user['invite_status']);
unset($user['invite_expired_at']);
unset($user['invite_token']);
unset($user['invite_link_token']);
unset($user['invite_accept_at']);
unset($user['invited_by']);
}
return $users;
}
/**
* normal case
*/
public function testGetUsersLogin()
{
$this->api->addUser('gegg4564eqgeqag', 'geqgegagae', 'tegst@tesgt.com');
$this->api->addUser("geggeqge632ge56a4qag", "geqgegeagae", "tesggt@tesgt.com");
$this->api->addUser("geggeqgeqagqegg", "geqgeaggggae", "tesgggt@tesgt.com");
$logins = $this->api->getUsersLogin();
$this->assertEquals(array("gegg4564eqgeqag", "geggeqge632ge56a4qag", "geggeqgeqagqegg"), $logins);
}
public function testGetUserLoginFromUserEmail()
{
$this->api->addUser('gegg4564eqgeqag', 'geqgegagae', 'tegst@tesgt.com');
$this->api->addUser("geggeqge632ge56a4qag", "geqgegeagae", "tesggt@tesgt.com");
$this->api->addUser("geggeqgeqagqegg", "geqgeaggggae", "tesgggt@tesgt.com");
$this->assertSame('gegg4564eqgeqag', $this->api->getUserLoginFromUserEmail('tegst@tesgt.com'));
$this->assertSame('geggeqge632ge56a4qag', $this->api->getUserLoginFromUserEmail('tesggt@tesgt.com'));
// test camel case should still find user
$this->assertSame('geggeqge632ge56a4qag', $this->api->getUserLoginFromUserEmail('teSGgT@tesgt.com'));
}
public function testGetUserLoginFromUserEmailShouldThrowExceptionIfUserDoesNotExist()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->api->getUserLoginFromUserEmail('unknownUser@teSsgt.com');
}
public function testGetUserLoginFromUserEmailShouldThrowExceptionIfUserDoesNotHaveAtLeastAdminPermission()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('checkUserHasSomeAdminAccess Fake exception');
FakeAccess::clearAccess($superUser = false, $admin = array(), $view = array(1));
$this->api->getUserLoginFromUserEmail('tegst@tesgt.com');
}
public function testSetUserAccessNoLogin()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
FakeAccess::clearAccess($superUser = false, $admin = array(1), $view = array());
$this->api->setUserAccess("nologin", "view", 1);
}
public function testSetUserAccessWrongAccessSpecified()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAccessValues');
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
FakeAccess::clearAccess($superUser = false, $admin = array(1), $view = array());
$this->api->setUserAccess("gegg4564eqgeqag", "viewnotknown", 1);
}
public function testSetUserAccessShouldFailSuperUserAccessIsNotAllowed()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAccessValues');
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
FakeAccess::clearAccess($superUser = false, $admin = array(1), $view = array());
$this->api->setUserAccess("gegg4564eqgeqag", "superuser", 1);
}
public function testSetUserAccessShouldFailIfLoginIsConfigSuperUserLogin()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
FakeAccess::clearAccess($superUser = false, $admin = array(1), $view = array());
$this->api->setUserAccess('superusertest', 'view', 1);
}
public function testSetUserAccessShouldFailIfLoginIsUserWithSuperUserAccess()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserHasSuperUserAccess');
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
$userUpdater = new UserUpdater();
$userUpdater->setSuperUserAccessWithoutCurrentPassword('gegg4564eqgeqag', true);
FakeAccess::clearAccess($superUser = false, $idSitesAdmin = array(1));
$this->api->setUserAccess('gegg4564eqgeqag', 'view', 1);
}
/**
* idsites = all => apply access to all websites with admin access
*/
public function testSetUserAccessIdsitesIsAll()
{
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
FakeAccess::$superUser = false;
$this->api->setUserAccess("gegg4564eqgeqag", "view", "all");
FakeAccess::$superUser = true;
$access = $this->api->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->flatten($access);
/** @var Access $accessInstance */
$accessInstance = self::$fixture->piwikEnvironment->getContainer()->get('Piwik\Access');
FakeAccess::$superUser = false;
$this->assertEquals(array_keys($access), $accessInstance->getSitesIdWithAdminAccess());
// we want to test the case for which we have actually set some rights
// if this is not OK then change the setUp method and add some admin rights for some websites
$this->assertGreaterThan(0, count(array_keys($access)));
}
/**
* idsites = all AND user is superuser=> apply access to all websites
*/
public function testSetUserAccessIdsitesIsAllSuperuser()
{
FakeAccess::$superUser = true;
$this->addSites(1);
$idSites = [1, 2, 3, 4, 5];
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
$this->api->setUserAccess("gegg4564eqgeqag", "view", "all");
$access = $this->api->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->flatten($access);
$this->assertEquals($idSites, array_keys($access));
}
public function testSetUserAccessShouldNotBeAbleToSetAnyAccessIfIdSitesIsEmpty()
{
$this->expectException(\Exception::class);
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
$this->api->setUserAccess("gegg4564eqgeqag", "view", array());
}
/**
* normal case, access set for only one site
*/
public function testSetUserAccessIdsitesOneSite()
{
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
$idSites = $this->addSites(1);
$this->api->setUserAccess("gegg4564eqgeqag", "view", $idSites);
$access = $this->api->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->flatten($access);
$this->assertEquals($idSites, array_keys($access));
}
/**
* normal case, access set for multiple sites
*/
public function testSetUserAccessIdsitesMultipleSites()
{
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
list($id1, $id2, $id3) = $this->addSites(3);
$this->api->setUserAccess("gegg4564eqgeqag", "view", array($id1, $id3));
$access = $this->api->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->flatten($access);
$this->assertEquals(array($id1, $id3), array_keys($access));
}
/**
* normal case, string idSites comma separated access set for multiple sites
*/
public function testSetUserAccessWithIdSitesIsStringCommaSeparated()
{
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
$this->api->setUserAccess("gegg4564eqgeqag", "view", "1,3");
$access = $this->api->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->flatten($access);
$this->assertEquals(array(1, 3), array_keys($access));
}
/**
* normal case, set different access to different websites for one user
*/
public function testSetUserAccessMultipleCallDistinctAccessSameUser()
{
$this->api->addUser("gegg4564eqgeqag", "geqgegagae", "tegst@tesgt.com");
list($id1, $id2) = $this->addSites(2);
$this->api->setUserAccess("gegg4564eqgeqag", "view", array($id1));
$this->api->setUserAccess("gegg4564eqgeqag", "admin", array($id2));
$access = $this->api->getSitesAccessFromUser("gegg4564eqgeqag");
$access = $this->flatten($access);
$this->assertEquals(array($id1 => 'view', $id2 => 'admin'), $access);
}
/**
* normal case, set different access to different websites for multiple users
*/
public function testSetUserAccessMultipleCallDistinctAccessMultipleUser()
{
$this->api->addUser("user1", "geqgegagae", "tegst@tesgt.com");
$this->api->addUser("user2", "geqgegagae", "tegst2@tesgt.com");
list($id1, $id2, $id3) = $this->addSites(3);
$this->api->setUserAccess("user1", "view", array($id1, $id2));
$this->api->setUserAccess("user2", "admin", array($id1));
$this->api->setUserAccess("user2", "view", array($id3, $id2));
$access1 = $this->api->getSitesAccessFromUser("user1");
$access1 = $this->flatten($access1);
$access2 = $this->api->getSitesAccessFromUser("user2");
$access2 = $this->flatten($access2);
$wanted1 = array($id1 => 'view', $id2 => 'view',);
$wanted2 = array($id1 => 'admin', $id2 => 'view', $id3 => 'view');
$this->assertEquals($wanted1, $access1);
$this->assertEquals($wanted2, $access2);
$access1 = $this->api->getUsersAccessFromSite($id1);
$access2 = $this->api->getUsersAccessFromSite($id2);
$access3 = $this->api->getUsersAccessFromSite($id3);
$wanted1 = array('user1' => 'view', 'user2' => 'admin',);
$wanted2 = array('user1' => 'view', 'user2' => 'view');
$wanted3 = array('user2' => 'view');
$this->assertEquals($wanted1, $access1);
$this->assertEquals($wanted2, $access2);
$this->assertEquals($wanted3, $access3);
$access1 = $this->api->getUsersSitesFromAccess('view');
$access2 = $this->api->getUsersSitesFromAccess('admin');
$wanted1 = array('user1' => array($id1, $id2), 'user2' => array($id2, $id3));
$wanted2 = array('user2' => array($id1));
$this->assertEquals($wanted1, $access1);
$this->assertEquals($wanted2, $access2);
// Test getUsersWithSiteAccess
$users = $this->api->getUsersWithSiteAccess($id1, $access = 'view');
$this->assertEquals(1, count($users));
$this->assertEquals('user1', $users[0]['login']);
$users = $this->api->getUsersWithSiteAccess($id2, $access = 'view');
$this->assertEquals(2, count($users));
$users = $this->api->getUsersWithSiteAccess($id1, $access = 'admin');
$this->assertEquals(1, count($users));
$this->assertEquals('user2', $users[0]['login']);
$users = $this->api->getUsersWithSiteAccess($id3, $access = 'admin');
$this->assertEquals(0, count($users));
}
/**
* we set access for one user for one site several times and check that it is updated
*/
public function testSetUserAccessMultipleCallOverwriteSingleUserOneSite()
{
$this->api->addUser("user1", "geqgegagae", "tegst@tesgt.com");
list($id1, $id2) = $this->addSites(2);
$this->api->setUserAccess("user1", "view", array($id1, $id2));
$this->api->setUserAccess("user1", "admin", array($id1));
$access1 = $this->api->getSitesAccessFromUser("user1");
$access1 = $this->flatten($access1);
$wanted1 = array($id1 => 'admin', $id2 => 'view',);
$this->assertEquals($wanted1, $access1);
}
public function testSetSuperUserAccessShouldFailIfUserHasNotSuperUserPermission()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('checkUserHasSuperUserAccess Fake exception');
$pwd = $this->createCurrentUser();
FakeAccess::$superUser = false;
$this->api->setSuperUserAccess('nologin', false, $pwd);
}
public function testSetSuperUserAccessShouldFailIfUserWithGivenLoginDoesNotExist()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$pwd = $this->createCurrentUser();
$this->api->setSuperUserAccess('nologin', false, $pwd);
}
public function testSetSuperUserAccessShouldFailIfUserIsAnonymous()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionEditAnonymous');
$pwd = $this->createCurrentUser();
$this->api->setSuperUserAccess('anonymous', true, $pwd);
}
public function testSetSuperUserAccessShouldFailIfUserIsOnlyRemainingUserWithSuperUserAccess()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionRemoveSuperUserAccessOnlySuperUser');
$pwd = $this->createCurrentUser();
$this->api->addUser('login1', 'password1', 'test@example.com', false);
$this->api->setSuperUserAccess('login1', true, $pwd);
$this->api->setSuperUserAccess('login1', false, $pwd);
}
public function testSetSuperUserAccessShouldDeleteAllExistingAccessEntries()
{
$pwd = $this->createCurrentUser();
list($id1, $id2) = $this->addSites(2);
$this->api->addUser('login1', 'password1', 'test@example.com', false);
$this->api->setUserAccess('login1', 'view', array($id1));
$this->api->setUserAccess('login1', 'admin', array($id2));
// verify user has access before setting Super User access
$access = $this->flatten($this->api->getSitesAccessFromUser('login1'));
$this->assertEquals(array($id1 => 'view', $id2 => 'admin'), $access);
$this->api->setSuperUserAccess('login1', true, $pwd);
// verify no longer any access
$this->assertEquals(array(), $this->model->getSitesAccessFromUser('login1'));
}
public function testSetSuperUserAccessShouldAddAndRemoveSuperUserAccessOnlyForGivenLogin()
{
$pwd = $this->createCurrentUser();
$this->api->addUser('login1', 'password1', 'test1@example.com', false);
$this->api->addUser('login2', 'password2', 'test2@example.com', false);
$this->api->addUser('login3', 'password3', 'test3@example.com', false);
$this->api->setSuperUserAccess('login2', true, $pwd);
// test add Super User access
$users = $this->api->getUsers();
$this->assertEquals(0, $users[0]['superuser_access']);
$this->assertEquals(1, $users[1]['superuser_access']);
$this->assertEquals('login2', $users[1]['login']);
$this->assertEquals(0, $users[2]['superuser_access']);
// should also accept string '1' to add Super User access
$this->api->setSuperUserAccess('login1', '1', $pwd);
// test remove Super User access
$this->api->setSuperUserAccess('login2', false, $pwd);
$users = $this->api->getUsers();
$this->assertEquals(1, $users[0]['superuser_access']);
$this->assertEquals('login1', $users[0]['login']);
$this->assertEquals(0, $users[1]['superuser_access']);
$this->assertEquals(0, $users[2]['superuser_access']);
$this->api->setSuperUserAccess('login3', true, $pwd);
// should also accept string '0' to remove Super User access
$this->api->setSuperUserAccess('login1', '0', $pwd);
$users = $this->api->getUsers();
$this->assertEquals(0, $users[0]['superuser_access']);
$this->assertEquals(0, $users[1]['superuser_access']);
$this->assertEquals('login3', $users[2]['login']);
$this->assertEquals(1, $users[2]['superuser_access']);
}
public function testGetSitesAccessFromUserWrongUser()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->api->getSitesAccessFromUser("user1");
}
public function testGetUsersAccessFromSiteWrongIdSite()
{
$this->expectException(\Exception::class);
FakeAccess::$superUser = false;
$this->api->getUsersAccessFromSite(1);
}
public function testGetUsersSitesFromAccessWrongSite()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAccessValues');
$this->api->getUsersSitesFromAccess('unknown');
}
public function testUpdateUserNonExistingLogin()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->api->updateUser("lolgin", "password");
}
public function testUpdateUserFailsNoCurrentPassword()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ConfirmWithPassword');
$login = "login";
$user = array(
'login' => $login,
'password' => "geqgeagae",
'email' => "test@test.com"
);
$this->api->addUser($user['login'], $user['password'], $user['email']);
FakeAccess::$identity = 'login';
$this->api->updateUser($login, "passowordOK", false, false, "");
}
public function testUpdateUserFailsWrongCurrentPassword()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_CurrentPasswordNotCorrect');
$login = "login";
$user = array(
'login' => $login,
'password' => "geqgeagae",
'email' => "test@test.com"
);
$this->api->addUser($user['login'], $user['password'], $user['email']);
FakeAccess::$identity = 'login';
$this->api->updateUser($login, "passowordOK", false, false, "geqgeag");
}
public function testUpdateUserFailsWrongCurrentPasswordRequiresThePasswordOfCurrentLoggedInUser()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_CurrentPasswordNotCorrect');
$login = "login";
$user = array(
'login' => $login,
'password' => "geqgeagae",
'email' => "test@test.com"
);
$this->api->addUser($user['login'], $user['password'], $user['email']);
// currently logged in is a super user and not "login". therefore the password of "login" won't work
$this->api->updateUser($login, "passowordOK", false, false, "geqgeag");
}
/**
* no email => keep old ones
*/
public function testUpdateUserNoEmail()
{
$login = "login";
$user = array(
'login' => $login,
'password' => "geqgeagae",
'email' => "test@test.com"
);
$this->api->addUser($user['login'], $user['password'], $user['email']);
FakeAccess::$identity = 'login';
$this->api->updateUser($login, "passowordOK", null, false, "geqgeagae");
$this->checkUserHasNotChanged($user, "passowordOK", null);
}
/**
* check to modify as the user
*/
public function testAddUserIAmTheUser()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionLoginExists');
FakeAccess::$identity = 'login';
$this->testUpdateUserNoEmail();
}
/**
* check to modify as being another user => exception
*/
public function testUpdateUserIAmNotTheUser()
{
$this->expectException(\Exception::class);
FakeAccess::$identity = 'login2';
FakeAccess::$superUser = false;
$this->testUpdateUserNoEmail();
}
/**
* normal case, reused in other tests
*/
public function testUpdateUser()
{
$login = "login";
$user = array(
'login' => $login,
'password' => "geqgeagae",
'email' => "test@test.com"
);
$this->api->addUser($user['login'], $user['password'], $user['email']);
FakeAccess::$identity = 'login';
$this->api->updateUser($login, "passowordOK", "email@geaga.com", false, "geqgeagae");
$this->checkUserHasNotChanged($user, "passowordOK", "email@geaga.com");
}
public function testGetUserByEmailInvalidMail()
{
$this->expectException(\Exception::class);
$this->api->getUserByEmail('email@test.com');
}
public function testGetUserByEmail()
{
$user = array(
'login' => "login",
'password' => "geqgeagae",
'email' => "test@test.com"
);
$this->api->addUser($user['login'], $user['password'], $user['email']);
$userByMail = $this->api->getUserByEmail($user['email']);
$this->assertEquals($user['login'], $userByMail['login']);
$this->assertEquals($user['email'], $userByMail['email']);
}
public function testGetUserPreferenceDefault()
{
$this->addSites(1);
$defaultReportPref = API::PREFERENCE_DEFAULT_REPORT;
$defaultReportDatePref = API::PREFERENCE_DEFAULT_REPORT_DATE;
$this->assertEquals(1, $this->api->getUserPreference($defaultReportPref, 'someUser'));
$this->assertEquals('yesterday', $this->api->getUserPreference($defaultReportDatePref, 'someUser'));
}
public function testGetAvailableRoles()
{
$this->addSites(1);
$roles = $this->api->getAvailableRoles();
$expected = array(
array(
'id' => 'view',
'name' => 'UsersManager_PrivView',
'description' => 'UsersManager_PrivViewDescription',
'helpUrl' => 'https://matomo.org/faq/general/faq_70/'
),
array(
'id' => 'write',
'name' => 'UsersManager_PrivWrite',
'description' => 'UsersManager_PrivWriteDescription',
'helpUrl' => 'https://matomo.org/faq/general/faq_26910'
),
array(
'id' => 'admin',
'name' => 'UsersManager_PrivAdmin',
'description' => 'UsersManager_PrivAdminDescription',
'helpUrl' => 'https://matomo.org/faq/general/faq_69/',
)
);
$this->assertEquals($expected, $roles);
}
public function testGetAvailableCapabilities()
{
$this->addSites(1);
$this->assertSame(array(
0 => array(
'id' => 'tagmanager_write',
'name' => 'UsersManager_PrivWrite',
'description' => 'TagManager_CapabilityWriteDescription',
'helpUrl' => '',
'includedInRoles' => array('write', 'admin'),
'category' => 'TagManager_TagManager',
),
1 => array(
'id' => 'tagmanager_publish_live_container',
'name' => 'TagManager_CapabilityPublishLiveContainer',
'description' => 'TagManager_CapabilityPublishLiveContainerDescription',
'helpUrl' => '',
'includedInRoles' => array('admin'),
'category' => 'TagManager_TagManager',
),
2 => array(
'id' => 'tagmanager_use_custom_templates',
'name' => 'TagManager_CapabilityUseCustomTemplates',
'description' => 'TagManager_CapabilityUseCustomTemplateDescription',
'helpUrl' => '',
'includedInRoles' => array('admin'),
'category' => 'TagManager_TagManager',
)
), $this->api->getAvailableCapabilities());
}
public function testInviteUser()
{
$this->addSites(1);
$user = array(
'login' => "login",
'email' => "test@test.com"
);
$this->api->inviteUser($user['login'], $user['email'], 1);
$user = $this->api->getUser($user['login']);
$this->assertNotEmpty($user['invite_status']);
}
private function addSites($numberOfSites)
{
$idSites = array();
for ($index = 0; $index < $numberOfSites; $index++) {
$name = "test" . ($index + 1);
$idSites[] = APISitesManager::getInstance()->addSite(
$name,
array("http://piwik.net", "http://piwik.com/test/")
);
}
return $idSites;
}
public function provideContainerConfig()
{
return array(
'Piwik\Access' => new FakeAccess()
);
}
private function assertUserNotExists($login)
{
try {
$this->api->getUser($login);
$this->fail("User $login still exists!");
} catch (Exception $expected) {
$this->assertRegExp("(UsersManager_ExceptionUserDoesNotExist)", $expected->getMessage());
}
}
private function createCurrentUser()
{
$identity = FakeAccess::$identity;
FakeAccess::$identity = 'lskfjs';
$pwd = 'testpwd';
try {
$this->api->addUser($identity, $pwd, 'someuser@email.com');
} finally {
FakeAccess::$identity = $identity;
}
return $pwd;
}
}