1
0
قرینه از https://github.com/matomo-org/matomo.git synced 2025-08-22 15:07:44 +00:00
Files

1703 خطوط
61 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 Piwik\Access\Capability;
use Piwik\Access\Role\Admin;
use Piwik\Access\Role\View;
use Piwik\Access\Role\Write;
use Piwik\API\Request;
use Piwik\Auth\Password;
use Piwik\Common;
use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Date;
use Piwik\EventDispatcher;
use Piwik\Mail;
use Piwik\NoAccessException;
use Piwik\Option;
use Piwik\Piwik;
use Piwik\Plugins\CoreAdminHome\Emails\UserCreatedEmail;
use Piwik\Plugins\UsersManager\Emails\UserInviteEmail;
use Piwik\Plugins\UsersManager\SystemSettings;
use Piwik\Plugins\SitesManager\API as SitesManagerAPI;
use Piwik\Plugins\UsersManager\API;
use Piwik\Plugins\UsersManager\Model;
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;
class TestCap1 extends Capability
{
public const ID = 'test_cap1';
public function getId(): string
{
return self::ID;
}
public function getCategory(): string
{
return 'Test';
}
public function getName(): string
{
return 'Cap1';
}
public function getDescription(): string
{
return '';
}
public function getIncludedInRoles(): array
{
return [
Admin::ID,
];
}
}
class TestCap2 extends Capability
{
public const ID = 'test_cap2';
public function getId(): string
{
return self::ID;
}
public function getCategory(): string
{
return 'Test';
}
public function getName(): string
{
return 'Cap2';
}
public function getDescription(): string
{
return '';
}
public function getIncludedInRoles(): array
{
return [
Write::ID,
Admin::ID,
];
}
}
class TestCap3 extends Capability
{
public const ID = 'test_cap3';
public function getId(): string
{
return self::ID;
}
public function getCategory(): string
{
return 'Test';
}
public function getName(): string
{
return 'Cap3';
}
public function getDescription(): string
{
return '';
}
public function getIncludedInRoles(): array
{
return [Admin::ID];
}
}
/**
* @group UsersManager
* @group APITest
* @group Plugins
*/
class APITest extends IntegrationTestCase
{
/**
* @var API
*/
private $api;
/**
* @var Model
*/
private $model;
private $login = 'userLogin';
private $password = 'password';
private $email = 'userlogin@password.de';
public function setUp(): void
{
parent::setUp();
$this->api = API::getInstance();
$this->model = new Model();
FakeAccess::clearAccess();
FakeAccess::$superUser = true;
Fixture::createWebsite('2014-01-01 00:00:00');
Fixture::createWebsite('2014-01-01 00:00:00');
Fixture::createWebsite('2014-01-01 00:00:00');
$this->api->addUser($this->login, $this->password, $this->email);
}
public function tearDown(): void
{
Config::getInstance()->General['enable_update_users_email'] = 1;
parent::tearDown();
}
public function testSetUserAccessShouldTriggerRemoveSiteAccessEventIfAccessToAWebsiteIsRemoved()
{
$eventTriggered = false;
$self = $this;
Piwik::addAction('UsersManager.removeSiteAccess', function ($login, $idSites) use (&$eventTriggered, $self) {
$eventTriggered = true;
self::assertEquals($self->login, $login);
self::assertEquals([1, 2], $idSites);
});
$this->api->setUserAccess($this->login, 'noaccess', [1, 2]);
self::assertTrue($eventTriggered, 'UsersManager.removeSiteAccess event was not triggered');
}
public function testSetUserAccessShouldNotTriggerRemoveSiteAccessEventIfAccessIsAdded()
{
$eventTriggered = false;
Piwik::addAction('UsersManager.removeSiteAccess', function () use (&$eventTriggered) {
$eventTriggered = true;
});
$this->api->setUserAccess($this->login, 'admin', [1, 2]);
self::assertFalse($eventTriggered, 'UsersManager.removeSiteAccess event was triggered but should not');
}
public function testGetAllUsersPreferencesIsEmptyWhenNoPreference()
{
$preferences = $this->api->getAllUsersPreferences(['preferenceName']);
self::assertEmpty($preferences);
}
public function testGetAllUsersPreferencesIsEmptyWhenNoPreferenceAndMultipleRequested()
{
$preferences = $this->api->getAllUsersPreferences(['preferenceName', 'randomDoesNotExist']);
self::assertEmpty($preferences);
}
public function testGetUserPreferenceShouldReturnADefaultPreferenceIfNoneIsSet()
{
$siteId = $this->api->getUserPreference(API::PREFERENCE_DEFAULT_REPORT, $this->login);
self::assertEquals('1', $siteId);
}
public function testGetUserPreferenceShouldReturnASetreferenceIfNoneIsSet()
{
$this->api->setUserPreference($this->login, API::PREFERENCE_DEFAULT_REPORT, 5);
$siteId = $this->api->getUserPreference(API::PREFERENCE_DEFAULT_REPORT, $this->login);
self::assertEquals('5', $siteId);
}
public function testInitUserPreferenceWithDefaultShouldSaveTheDefaultPreferenceIfPreferenceIsNotSet()
{
// make sure there is no value saved so it will use default preference
$siteId = Option::get($this->getPreferenceId(API::PREFERENCE_DEFAULT_REPORT));
self::assertFalse($siteId);
$this->api->initUserPreferenceWithDefault($this->login, API::PREFERENCE_DEFAULT_REPORT);
// make sure it did save the preference
$siteId = Option::get($this->getPreferenceId(API::PREFERENCE_DEFAULT_REPORT));
self::assertEquals('1', $siteId);
}
public function testInitUserPreferenceWithDefaultShouldNotSaveTheDefaultPreferenceIfPreferenceIsAlreadySet()
{
// set value so there will already be a default
Option::set($this->getPreferenceId(API::PREFERENCE_DEFAULT_REPORT), '999');
$siteId = Option::get($this->getPreferenceId(API::PREFERENCE_DEFAULT_REPORT));
self::assertEquals('999', $siteId);
$this->api->initUserPreferenceWithDefault($this->login, API::PREFERENCE_DEFAULT_REPORT);
// make sure it did not save the preference
$siteId = Option::get($this->getPreferenceId(API::PREFERENCE_DEFAULT_REPORT));
self::assertEquals('999', $siteId);
}
public function testGetAllUsersPreferencesShouldGetMultiplePreferences()
{
$user2 = 'userLogin2';
$user3 = 'userLogin3';
$this->api->addUser($user2, 'password', 'userlogin2@password.de');
$this->api->setUserPreference($user2, API::PREFERENCE_DEFAULT_REPORT, 'valueForUser2');
$this->api->setUserPreference($user2, 'RandomNOTREQUESTED', 'RandomNOTREQUESTED');
$this->api->addUser($user3, 'password', 'userlogin3@password.de');
$this->api->setUserPreference($user3, API::PREFERENCE_DEFAULT_REPORT, 'valueForUser3');
$this->api->setUserPreference($user3, API::PREFERENCE_DEFAULT_REPORT_DATE, 'otherPreferenceVALUE');
$this->api->setUserPreference($user3, 'RandomNOTREQUESTED', 'RandomNOTREQUESTED');
$expected = [
$user2 => [
API::PREFERENCE_DEFAULT_REPORT => 'valueForUser2',
],
$user3 => [
API::PREFERENCE_DEFAULT_REPORT => 'valueForUser3',
API::PREFERENCE_DEFAULT_REPORT_DATE => 'otherPreferenceVALUE',
],
];
$result = $this->api->getAllUsersPreferences([
API::PREFERENCE_DEFAULT_REPORT,
API::PREFERENCE_DEFAULT_REPORT_DATE,
'randomDoesNotExist',
]);
self::assertSame($expected, $result);
}
public function testGetAllUsersPreferencesWhenLoginContainsUnderscore()
{
$user2 = 'user_Login2';
$this->api->addUser($user2, 'password', 'userlogin2@password.de');
$this->api->setUserPreference($user2, API::PREFERENCE_DEFAULT_REPORT, 'valueForUser2');
$this->api->setUserPreference($user2, API::PREFERENCE_DEFAULT_REPORT_DATE, 'RandomNOTREQUESTED');
$expected = [
$user2 => [
API::PREFERENCE_DEFAULT_REPORT => 'valueForUser2',
],
];
$result = $this->api->getAllUsersPreferences([API::PREFERENCE_DEFAULT_REPORT, 'randomDoesNotExist']);
self::assertSame($expected, $result);
}
public function testSetUserPreferenceThrowsWhenPreferenceNameContainsUnderscore()
{
$this->expectException(\Exception::class);
$user2 = 'userLogin2';
$this->api->addUser($user2, 'password', 'userlogin2@password.de');
$this->api->setUserPreference($user2, 'ohOH_myPreferenceName', 'valueForUser2');
}
public function testAddUserFailsWhenEmailDomainNotAllowed()
{
$this->expectExceptionMessage('UsersManager_ErrorEmailDomainNotAllowed');
$settings = StaticContainer::get(SystemSettings::class);
$settings->allowedEmailDomains->setValue(['example.org', 'password.de', 'matomo.com']);
$this->api->addUser('userLogin2', 'password', 'userlogin2@password.com');
}
public function testUpdateUser()
{
$capturedMails = [];
Piwik::addAction('Mail.send', function (Mail $mail) use (&$capturedMails) {
$capturedMails[] = $mail;
});
$identity = FakeAccess::$identity;
FakeAccess::$identity = $this->login; // ensure password will be checked against this user
$this->api->updateUser($this->login, 'newPassword', 'email@example.com', false, $this->password);
FakeAccess::$identity = $identity;
$model = new Model();
$user = $model->getUser($this->login);
self::assertSame('email@example.com', $user['email']);
$passwordHelper = new Password();
self::assertTrue($passwordHelper->verify(UsersManager::getPasswordHash('newPassword'), $user['password']));
$subjects = array_map(function (Mail $mail) {
return $mail->getSubject();
}, $capturedMails);
self::assertEquals([
'UsersManager_EmailChangeNotificationSubject', // sent twice to old email and new
'UsersManager_EmailChangeNotificationSubject',
'UsersManager_PasswordChangeNotificationSubject',
], $subjects);
}
public function testUpdateUserFailsWhenEmailDomainNotAllowed()
{
$this->expectExceptionMessage('UsersManager_ErrorEmailDomainNotAllowed');
$settings = StaticContainer::get(SystemSettings::class);
$settings->allowedEmailDomains->setValue(['example.org', 'password.de', 'matomo.com']);
$this->api->addUser('userLogin2', 'passwordtest12', 'userlogin2@password.de');
$this->api->updateUser('userLogin2', false, 'email@example.com', false, 'passwordtest12');
}
public function testUpdateUserDoesNotSendEmailsIfTurnedOffInConfig()
{
Config::getInstance()->General['enable_update_users_email'] = 0;
$capturedMails = [];
Piwik::addAction('Mail.send', function (Mail $mail) use (&$capturedMails) {
$capturedMails[] = $mail;
});
$identity = FakeAccess::$identity;
FakeAccess::$identity = $this->login; // en
$this->api->updateUser($this->login, 'newPassword2', 'email2@example.com', false, $this->password);
FakeAccess::$identity = $identity;
$subjects = array_map(function (Mail $mail) {
return $mail->getSubject();
}, $capturedMails);
self::assertEquals([], $subjects);
}
public function testUpdateUserDoesNotSendEmailIfNoChangeAndDoesNotRequirePassword()
{
$capturedMails = [];
Piwik::addAction('Mail.send', function (Mail $mail) use (&$capturedMails) {
$capturedMails[] = $mail;
});
$identity = FakeAccess::$identity;
FakeAccess::$identity = $this->login; // en
$this->api->updateUser($this->login, false, strtoupper($this->email));
FakeAccess::$identity = $identity;
self::assertEquals([], $capturedMails);
}
public function testUpdateUserDoesNotChangePasswordIfFalsey()
{
$model = new Model();
$userBefore = $model->getUser($this->login);
$identity = FakeAccess::$identity;
FakeAccess::$identity = $this->login; // ensure password will be checked against this user
$this->api->updateUser($this->login, false, 'email@example.com', false, $this->password);
FakeAccess::$identity = $identity;
$user = $model->getUser($this->login);
self::assertSame($userBefore['password'], $user['password']);
self::assertSame($userBefore['ts_password_modified'], $user['ts_password_modified']);
}
public function testUpdateUserFailsIfPasswordTooLong()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionInvalidPasswordTooLong');
$this->api->updateUser(
$this->login,
str_pad('foo', UsersManager::PASSWORD_MAX_LENGTH + 1),
'email@example.com',
false,
$this->password
);
}
public function testUpdateUserFailsIfEmailExistsAsOtherUserUsername()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionEmailExistsAsLogin');
$user2 = 'existed@example.com';
$this->api->addUser($user2, 'password', 'userlogin2@password.de');
$this->api->updateUser($this->login, $this->password, $user2, false, $this->password);
}
public function testUpdateCanUpdateUserEmailToOwnUsername()
{
$user2 = 'ownemail@example.com';
$password = 'password';
$this->api->addUser($user2, $password, 'ownemail_wrong@example.com');
FakeAccess::$identity = $user2;
$this->api->updateUser($user2, $password, $user2, false, $password);
$user2Array = $this->api->getUser($user2);
self::assertEquals($user2Array['email'], $user2);
}
public function testCannotCreateUserIfEmailExistsAsUsername()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionEmailExistsAsLogin');
$user2 = 'existed@example.com';
$this->api->addUser($user2, 'password', 'email@example.com');
$this->api->addUser('user3', 'password', $user2);
}
public function testCannotCreateUserIfUsernameExistsAsEmail()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionLoginExistsAsEmail');
$this->api->addUser($this->email, 'password', 'new_user@example.com');
}
public function testGetSitesAccessFromUserForSuperUser()
{
$user2 = 'userLogin2';
$this->api->addUser($user2, 'password', 'userlogin2@password.de');
// new user doesn't have access to anything
$access = $this->api->getSitesAccessFromUser($user2);
self::assertEmpty($access);
$userUpdater = new UserUpdater();
$userUpdater->setSuperUserAccessWithoutCurrentPassword($user2, true);
// super user has admin access for every site
$access = $this->api->getSitesAccessFromUser($user2);
$expected = [
[
'site' => 1,
'access' => 'admin',
],
[
'site' => 2,
'access' => 'admin',
],
[
'site' => 3,
'access' => 'admin',
],
];
self::assertEquals($expected, $access);
}
public function testGetUsersPlusRoleShouldReturnNothingForAnonymousUser()
{
$this->addUserWithAccess('userLogin2', 'view', 1);
$this->setCurrentUser('anonymous', 'view', 1);
$users = $this->api->getUsersPlusRole(1);
self::assertEquals([], $users);
self::assertResultCountHeader(0);
}
public function testGetUsersPlusRoleShouldReturnSelfIfUserDoesNotHaveAdminAccessToSite()
{
$this->addUserWithAccess('userLogin2', 'view', 1);
$this->setCurrentUser('userLogin2', 'view', 1);
$users = $this->api->getUsersPlusRole(1);
$this->cleanUsers($users);
$expected = [
[
'login' => 'userLogin2',
'role' => 'view',
'capabilities' => [],
'email' => 'userLogin2@password.de',
'superuser_access' => '0',
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(1);
}
public function testGetUsersPlusRoleShouldIgnoreOffsetIfLimitIsNotSupplied()
{
$this->addUserWithAccess('userLogin2', 'view', 1);
$this->setCurrentUser('userLogin2', 'view', 1);
$users = $this->api->getUsersPlusRole(1, $limit = null, $offset = 1);
$this->cleanUsers($users);
$expected = [
[
'login' => 'userLogin2',
'role' => 'view',
'capabilities' => [],
'email' => 'userLogin2@password.de',
'superuser_access' => '0',
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(1);
}
public function testGetUsersPlusRoleShouldNotAllowSuperuserFilterIfUserIsNotSuperUser()
{
$this->addUserWithAccess('userLogin2', 'view', 1);
$this->addUserWithAccess('userLogin3', 'superuser', 1);
$this->setCurrentUser('userLogin2', 'view', 1);
$users = $this->api->getUsersPlusRole(1, null, null, null, 'superuser');
$this->cleanUsers($users);
$expected = [
[
'login' => 'userLogin2',
'role' => 'view',
'capabilities' => [],
'email' => 'userLogin2@password.de',
'superuser_access' => '0',
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(1);
}
public function testGetUsersPlusRoleShouldReturnAllUsersAndAccessIfUserHasAdminAccess()
{
$this->addUserWithAccess('userLogin2', 'admin', 1);
$this->addUserWithAccess('userLogin3', 'view', 1);
$this->addUserWithAccess('userLogin4', 'admin', 1);
$this->addUserWithAccess('userLogin5', null, 1);
$this->setCurrentUser('userLogin2', 'admin', 1);
$users = $this->api->getUsersPlusRole(1);
$this->cleanUsers($users);
$expected = [
[
'login' => 'userLogin2',
'role' => 'admin',
'capabilities' => [],
'email' => 'userLogin2@password.de',
'superuser_access' => false,
],
[
'login' => 'userLogin3',
'role' => 'view',
'capabilities' => [],
'superuser_access' => false,
],
[
'login' => 'userLogin4',
'role' => 'admin',
'capabilities' => [],
'superuser_access' => false,
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(3);
}
public function testGetUsersPlusRoleForAdminShouldLimitUsersToThoseWithAccessToSitesAsCurrentUsersAdminSites()
{
$this->addUserWithAccess('userLogin2', 'admin', [1, 2]);
$this->addUserWithAccess('userLogin3', 'view', 1);
$this->addUserWithAccess('userLogin4', 'admin', 1);
$this->addUserWithAccess('userLogin5', null, [1, 2]);
$this->api->setUserAccess('userLogin5', 'view', 2);
$this->setCurrentUser('userLogin2', 'admin', [1, 2]);
$users = $this->api->getUsersPlusRole(1);
$this->cleanUsers($users);
$expected = [
[
'login' => 'userLogin2',
'role' => 'admin',
'capabilities' => [],
'email' => 'userLogin2@password.de',
'superuser_access' => false,
],
[
'login' => 'userLogin3',
'role' => 'view',
'capabilities' => [],
'superuser_access' => false,
],
[
'login' => 'userLogin4',
'role' => 'admin',
'capabilities' => [],
'superuser_access' => false,
],
[
'login' => 'userLogin5',
'role' => 'noaccess',
'capabilities' => [],
'superuser_access' => false,
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(4);
}
public function testGetUsersPlusRoleShouldReturnAllUsersAndAccessIfUserHasSuperuserAccess()
{
$this->addUserWithAccess('userLogin2', 'superuser', 1);
$this->addUserWithAccess('userLogin3', 'view', 1);
$this->addUserWithAccess('userLogin4', 'superuser', 1);
$this->addUserWithAccess('userLogin5', null, 1);
$this->setCurrentUser('userLogin2', 'superuser', 1);
$users = $this->api->getUsersPlusRole(1);
$this->cleanUsers($users);
$expected = [
[
'login' => 'userLogin',
'email' => 'userlogin@password.de',
'superuser_access' => false,
'role' => 'noaccess',
'capabilities' => [],
'uses_2fa' => false,
],
[
'login' => 'userLogin2',
'email' => 'userLogin2@password.de',
'superuser_access' => true,
'role' => 'superuser',
'capabilities' => [],
'uses_2fa' => false,
],
[
'login' => 'userLogin3',
'email' => 'userLogin3@password.de',
'superuser_access' => false,
'role' => 'view',
'capabilities' => [],
'uses_2fa' => false,
],
[
'login' => 'userLogin4',
'email' => 'userLogin4@password.de',
'superuser_access' => true,
'role' => 'superuser',
'capabilities' => [],
'uses_2fa' => false,
],
[
'login' => 'userLogin5',
'email' => 'userLogin5@password.de',
'superuser_access' => false,
'role' => 'noaccess',
'capabilities' => [],
'uses_2fa' => false,
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(5);
}
public function testGetUsersPlusRoleShouldFilterUsersByAccessCorrectly()
{
$this->addUserWithAccess('userLogin2', 'admin', 1);
$this->addUserWithAccess('userLogin3', 'view', 1);
$this->addUserWithAccess('userLogin4', 'superuser', 1);
$this->addUserWithAccess('userLogin5', 'admin', 1);
$this->addUserWithAccess('userLogin6', 'write', 1);
$this->setCurrentUser('userLogin2', 'admin', 1);
$users = $this->api->getUsersPlusRole(1, null, null, null, 'admin');
$this->cleanUsers($users);
$expected = [
[
'login' => 'userLogin2',
'role' => 'admin',
'capabilities' => [],
'email' => 'userLogin2@password.de',
'superuser_access' => false,
],
[
'login' => 'userLogin5',
'role' => 'admin',
'capabilities' => [],
'superuser_access' => false,
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(2);
// check new write role filtering works
$users = $this->api->getUsersPlusRole(1, null, null, null, 'write');
$this->cleanUsers($users);
$expected = [
['login' => 'userLogin6', 'role' => 'write', 'capabilities' => [], 'superuser_access' => false],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(1);
}
public function testGetUsersPlusRoleShouldReturnUsersWithNoAccessCorrectly()
{
$this->addUserWithAccess('userLogin2', 'noaccess', 1);
$this->addUserWithAccess('userLogin3', 'view', 1);
$this->addUserWithAccess('userLogin4', 'superuser', 1);
$this->addUserWithAccess('userLogin5', 'noaccess', 1);
$users = $this->api->getUsersPlusRole(1, null, null, null, 'noaccess');
$this->cleanUsers($users);
$expected = [
[
'login' => 'userLogin',
'role' => 'noaccess',
'superuser_access' => false,
'email' => 'userlogin@password.de',
'capabilities' => [],
'uses_2fa' => false,
],
[
'login' => 'userLogin2',
'role' => 'noaccess',
'superuser_access' => false,
'email' => 'userLogin2@password.de',
'capabilities' => [],
'uses_2fa' => false,
],
[
'login' => 'userLogin5',
'role' => 'noaccess',
'superuser_access' => false,
'email' => 'userLogin5@password.de',
'capabilities' => [],
'uses_2fa' => false,
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(3);
}
public function testGetUsersPlusRoleShouldSearchForSuperUsersCorrectly()
{
$this->addUserWithAccess('userLogin2', 'admin', 1);
$userUpdater = new UserUpdater();
$userUpdater->setSuperUserAccessWithoutCurrentPassword('userLogin2', true);
$this->addUserWithAccess('userLogin3', 'view', 1);
$this->addUserWithAccess('userLogin4', 'superuser', 1);
$this->addUserWithAccess('userLogin5', null, 1);
$this->setCurrentUser('userLogin2', 'superuser', 1);
$users = $this->api->getUsersPlusRole(1, null, null, null, 'superuser');
$this->cleanUsers($users);
$expected = [
[
'login' => 'userLogin2',
'email' => 'userLogin2@password.de',
'superuser_access' => true,
'role' => 'superuser',
'capabilities' => [],
'uses_2fa' => false,
],
[
'login' => 'userLogin4',
'email' => 'userLogin4@password.de',
'superuser_access' => true,
'role' => 'superuser',
'capabilities' => [],
'uses_2fa' => false,
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(2);
}
public function testGetUsersPlusRoleShouldSearchByTextCorrectly()
{
$this->addUserWithAccess('searchTextLogin', 'superuser', 1, 'someemail@email.com');
$this->addUserWithAccess('userLogin2', 'view', 1, 'searchTextdef@email.com');
$this->addUserWithAccess('userLogin3', 'superuser', 1, 'someemail2@email.com');
$this->addUserWithAccess('userLogin4', null, 1);
$this->setCurrentUser('searchTextLogin', 'superuser', 1);
$users = $this->api->getUsersPlusRole(1, null, null, 'searchText');
$this->cleanUsers($users);
$expected = [
[
'login' => 'searchTextLogin',
'email' => 'someemail@email.com',
'superuser_access' => true,
'role' => 'superuser',
'capabilities' => [],
'uses_2fa' => false,
],
[
'login' => 'userLogin2',
'email' => 'searchTextdef@email.com',
'superuser_access' => false,
'role' => 'view',
'capabilities' => [],
'uses_2fa' => false,
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(2);
}
public function testGetUsersPlusRoleShouldApplyLimitAndOffsetCorrectly()
{
$this->addUserWithAccess('searchTextLogin', 'superuser', 1, 'someemail@email.com');
$this->addUserWithAccess('userLogin2', 'view', 1, 'searchTextdef@email.com');
$this->addUserWithAccess('userLogin3', 'superuser', 1, 'someemail2@email.com');
$this->addUserWithAccess('userLogin4', null, 1);
$this->setCurrentUser('searchTextLogin', 'superuser', 1);
$users = $this->api->getUsersPlusRole(1, $limit = 2, $offset = 1);
$this->cleanUsers($users);
$expected = [
[
'login' => 'userLogin',
'email' => 'userlogin@password.de',
'superuser_access' => false,
'role' => 'noaccess',
'capabilities' => [],
'uses_2fa' => false,
],
[
'login' => 'userLogin2',
'email' => 'searchTextdef@email.com',
'superuser_access' => false,
'role' => 'view',
'capabilities' => [],
'uses_2fa' => false,
],
];
self::assertEquals($expected, $users);
self::assertResultCountHeader(5);
}
public function testGetSitesAccessForUserShouldReturnAccessForUser()
{
$this->api->setUserAccess('userLogin', 'admin', [1]);
$this->api->setUserAccess('userLogin', 'view', [2]);
$this->api->setUserAccess('userLogin', 'view', [3]);
$access = $this->api->getSitesAccessForUser('userLogin');
$expected = [
['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'admin', 'capabilities' => []],
['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
];
self::assertEquals($expected, $access);
self::assertResultCountHeader(3);
}
public function testGetUserCapabilitiesAfterFilter()
{
$this->addUserWithAccess('userLoginCapabilities', 'view', 1, 'searchTextdef@email.com');
$this->api->addCapabilities('userLoginCapabilities', 'tagmanager_write', 1);
$access = $this->api->getSitesAccessForUser('userLoginCapabilities', null, 1, null, 'view');
self::assertEquals(['tagmanager_write'], $access[0]['capabilities']);
self::assertResultCountHeader(1);
}
public function testGetSitesAccessForUserShouldIgnoreOffsetIfLimitNotSupplied()
{
$this->api->setUserAccess('userLogin', 'admin', [1]);
$this->api->setUserAccess('userLogin', 'view', [2]);
$this->api->setUserAccess('userLogin', 'view', [3]);
$access = $this->api->getSitesAccessForUser('userLogin', $limit = null, $offset = 1);
$expected = [
['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'admin', 'capabilities' => []],
['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
];
self::assertEquals($expected, $access);
self::assertResultCountHeader(3);
}
public function testGetSitesAccessForUserShouldApplyLimitAndOffsetCorrectly()
{
$this->api->setUserAccess('userLogin', 'admin', [1]);
$this->api->setUserAccess('userLogin', 'view', [2]);
$this->api->setUserAccess('userLogin', 'view', [3]);
$access = $this->api->getSitesAccessForUser('userLogin', $limit = 2, $offset = 1);
$expected = [
['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
];
self::assertEquals($expected, $access);
self::assertResultCountHeader(3);
}
public function testGetSitesAccessForUserShouldSearchSitesCorrectly()
{
Fixture::createWebsite('2010-01-02 00:00:00');
$this->api->setUserAccess('userLogin', 'admin', [1]);
$this->api->setUserAccess('userLogin', 'view', [2]);
$this->api->setUserAccess('userLogin', 'view', [3]);
$this->api->setUserAccess('userLogin', 'view', [4]);
SitesManagerAPI::getInstance()->updateSite(1, 'searchTerm site');
SitesManagerAPI::getInstance()->updateSite(2, null, ['http://searchTerm.com']);
SitesManagerAPI::getInstance()->updateSite(
3,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
'the searchTerm group'
);
$access = $this->api->getSitesAccessForUser('userLogin', null, null, 'searchTerm');
$expected = [
['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
['idsite' => '1', 'site_name' => 'searchTerm site', 'role' => 'admin', 'capabilities' => []],
];
self::assertEquals($expected, $access);
self::assertResultCountHeader(3);
}
public function testGetSitesAccessForUserShouldFilterByAccessCorrectly()
{
$this->api->setUserAccess('userLogin', 'admin', [1]);
$this->api->setUserAccess('userLogin', 'view', [2]);
$this->api->setUserAccess('userLogin', 'view', [3]);
$access = $this->api->getSitesAccessForUser('userLogin', null, null, null, 'view');
$expected = [
['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
];
self::assertEquals($expected, $access);
self::assertResultCountHeader(2);
}
public function testGetSitesAccessForUserShouldLimitSitesIfUserIsAdmin()
{
$this->addUserWithAccess('userLogin2', 'view', [1, 2, 3], 'userlogin2@email.com');
$this->api->setUserAccess('userLogin', 'admin', [1, 2]);
$this->api->setUserAccess('userLogin', 'view', [3]);
$this->setCurrentUser('userLogin', 'admin', [1, 2]);
$access = $this->api->getSitesAccessForUser('userLogin2', null, null, null, 'view');
$expected = [
['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
];
self::assertEquals($expected, $access);
self::assertResultCountHeader(2);
}
public function testGetSitesAccessForUserShouldLimitSitesIfUserIsAdminAndStillSelectNoAccessSitesCorrectly()
{
$this->addUserWithAccess('userLogin2', 'view', [1], 'userlogin2@email.com');
$this->api->setUserAccess('userLogin', 'admin', [1, 2, 3]);
$this->setCurrentUser('userLogin', 'admin', [1, 2, 3]);
$access = $this->api->getSitesAccessForUser('userLogin2', null, null, null, 'noaccess');
$expected = [
['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []],
['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []],
];
self::assertEquals($expected, $access);
self::assertResultCountHeader(2);
}
public function testGetSitesAccessForUserShouldSelectSitesCorrectlyIfAtLeastViewRequested()
{
$this->addUserWithAccess('userLogin2', 'view', [1], 'userlogin2@email.com');
$this->api->setUserAccess('userLogin2', 'admin', [2]);
$access = $this->api->getSitesAccessForUser('userLogin2', null, null, null, 'some');
$expected = [
['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'view', 'capabilities' => []],
['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'admin', 'capabilities' => []],
];
self::assertEquals($expected, $access);
self::assertResultCountHeader(2);
}
public function testGetSitesAccessForUserShouldReportIfUserHasNoAccessToSites()
{
$access = $this->api->getSitesAccessForUser('userLogin');
$expected = [
['idsite' => '1', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []],
['idsite' => '2', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []],
['idsite' => '3', 'site_name' => 'Piwik test', 'role' => 'noaccess', 'capabilities' => []],
];
self::assertEquals($expected, $access);
// test when search returns empty result
$this->api->setUserAccess('userLogin', 'view', 1);
$access = $this->api->getSitesAccessForUser('userLogin', null, null, 'asdklfjds');
$expected = [];
self::assertEquals($expected, $access);
self::assertResultCountHeader(0);
}
public function testSetUserAccessMultipleRolesCannotBeSet()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionMultipleRoleSet');
$this->api->setUserAccess($this->login, ['view', 'admin'], [1]);
}
public function testSetUserAccessNeedsAtLeastOneRole()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionNoRoleSet');
$this->api->setUserAccess($this->login, [TestCap2::ID], [1]);
}
public function testSetUserAccessNeedsAtLeastOneRoleAsString()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAccessValues');
$this->api->setUserAccess($this->login, TestCap2::ID, [1]);
}
public function testSetUserAccessInvalidCapability()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAccessValues');
$this->api->setUserAccess($this->login, ['admin', 'foobar'], [1]);
}
public function testSetUserAccessNeedsAtLeastOneRoleNoneGiven()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionNoRoleSet');
$this->api->setUserAccess($this->login, [], [1]);
}
public function testSetUserAccessCannotSetAdminToAnonymous()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAnonymousAccessNotPossible');
$this->api->setUserAccess('anonymous', 'admin', [1]);
}
public function testSetUserAccessCannotSetWriteToAnonymous()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAnonymousAccessNotPossible');
$this->api->setUserAccess('anonymous', 'write', [1]);
}
public function testSetUserAccessCannotSetViewToAnonymousWithoutPassword()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ConfirmWithPassword');
$_GET['force_api_session'] = 1;
try {
$this->api->setUserAccess('anonymous', 'view', [1]);
} finally {
unset($_GET['force_api_session']);
}
}
public function testSetUserAccessUserDoesNotExist()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->api->setUserAccess('foobar', Admin::ID, [1]);
}
public function testSetUserAccessSetRoleAndCapabilities()
{
$access = [TestCap2::ID, View::ID, TestCap3::ID];
$this->api->setUserAccess($this->login, $access, [1]);
$access = $this->model->getSitesAccessFromUser($this->login);
$expected = [
['site' => '1', 'access' => 'view'],
['site' => '1', 'access' => TestCap2::ID],
['site' => '1', 'access' => TestCap3::ID],
];
self::assertEquals($expected, $access);
}
public function testSetUserAccessSetRoleAsString()
{
$this->api->setUserAccess($this->login, View::ID, [1]);
$access = $this->model->getSitesAccessFromUser($this->login);
self::assertEquals([['site' => '1', 'access' => 'view']], $access);
}
public function testSetUserAccessSetRoleAsArray()
{
$this->api->setUserAccess($this->login, [View::ID], [1]);
$access = $this->model->getSitesAccessFromUser($this->login);
self::assertEquals([['site' => '1', 'access' => 'view']], $access);
}
public function testAddCapabilitiesFailsWhenNotCapabilityIsGivenAsString()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAccessValues');
$this->api->addCapabilities($this->login, View::ID, [1]);
}
public function testAddCapabilitiesFailsWhenNotCapabilityIsGivenAsArray()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAccessValues');
$this->api->addCapabilities($this->login, [TestCap2::ID, View::ID], [1]);
}
public function testAddCapabilitiesFailsWhenUserDoesNotExist()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->api->addCapabilities('foobar', [TestCap2::ID], [1]);
}
public function testAddCapabilitiesDoesNotAddSameCapabilityTwice()
{
$addAccess = [TestCap2::ID, View::ID, TestCap3::ID];
$this->api->setUserAccess($this->login, $addAccess, [1]);
$access = $this->model->getSitesAccessFromUser($this->login);
$expected = [
['site' => '1', 'access' => 'view'],
['site' => '1', 'access' => TestCap2::ID],
['site' => '1', 'access' => TestCap3::ID],
];
self::assertEquals($expected, $access);
$this->api->addCapabilities($this->login, [TestCap2::ID, TestCap3::ID], [1]);
$access = $this->model->getSitesAccessFromUser($this->login);
self::assertEquals($expected, $access);
$this->api->addCapabilities($this->login, [TestCap2::ID, TestCap1::ID, TestCap3::ID], [1]);
$expected[] = ['site' => '1', 'access' => TestCap1::ID];
$access = $this->model->getSitesAccessFromUser($this->login);
self::assertEquals($expected, $access);
}
public function testAddCapabilitiesDoesNotAddCapabilityToUserWithNoRole()
{
self::expectException(\Exception::class);
self::expectExceptionMessage('UsersManager_ExceptionNoCapabilitiesWithoutRole');
$access = $this->model->getSitesAccessFromUser($this->login);
self::assertEquals([], $access);
$this->api->addCapabilities($this->login, array(TestCap2::ID, TestCap3::ID), array(1));
}
public function testAddCapabilitiesDoesNotAddCapabilitiesWhichAreIncludedInRoleAlready()
{
$this->api->setUserAccess($this->login, Write::ID, [1]);
$access = $this->model->getSitesAccessFromUser($this->login);
$expected = [
['site' => '1', 'access' => 'write'],
];
self::assertEquals($expected, $access);
$this->api->addCapabilities($this->login, [TestCap2::ID, TestCap3::ID], [1]);
$expected[] = ['site' => '1', 'access' => TestCap3::ID];
$access = $this->model->getSitesAccessFromUser($this->login);
// did not add TestCap2
self::assertEquals($expected, $access);
}
public function testAddCapabilitiesDoesAddCapabilitiesWhichAreNotIncludedInRoleYetAlready()
{
$this->api->setUserAccess($this->login, Admin::ID, [1]);
$access = $this->model->getSitesAccessFromUser($this->login);
$expected = [
['site' => '1', 'access' => 'admin'],
];
self::assertEquals($expected, $access);
$this->api->addCapabilities($this->login, [TestCap2::ID, TestCap1::ID, TestCap3::ID], [1]);
$access = $this->model->getSitesAccessFromUser($this->login);
self::assertEquals($expected, $access);
}
public function testRemoveCapabilitiesFailsWhenNotCapabilityIsGivenAsString()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAccessValues');
$this->api->removeCapabilities($this->login, View::ID, [1]);
}
public function testRemoveCapabilitiesFailsWhenNotCapabilityIsGivenAsArray()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionAccessValues');
$this->api->removeCapabilities($this->login, [TestCap2::ID, View::ID], [1]);
}
public function testRemoveCapabilitiesFailsWhenUserDoesNotExist()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->api->removeCapabilities('foobar', [TestCap2::ID], [1]);
}
public function testRemoveCapabilities()
{
$addAccess = [View::ID, TestCap2::ID, TestCap3::ID, TestCap1::ID];
$this->api->setUserAccess($this->login, $addAccess, [1]);
$access = $this->getAccessInSite($this->login, 1);
self::assertEquals($addAccess, $access);
$this->api->removeCapabilities($this->login, [TestCap3::ID, TestCap2::ID], 1);
$access = $this->getAccessInSite($this->login, 1);
self::assertEquals([View::ID, TestCap1::ID], $access);
}
public function testSetSuperUserAccessFailsIfCurrentPasswordIsIncorrect()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_CurrentPasswordNotCorrect');
$this->api->setSuperUserAccess($this->login, true, 'asldfkjds');
}
public function testInviteUserInitialIdSiteMissing()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage('UsersManager_AddUserNoInitialAccessError');
Request::processRequest(
'UsersManager.inviteUser',
[
'userLogin' => "testInviteUser",
'email' => "testInviteUser@example.com",
'expiryInDays' => 7,
]
);
}
public function testInviteUserFailsWhenDomainNotAllowed()
{
$this->expectExceptionMessage('UsersManager_ErrorEmailDomainNotAllowed');
$settings = StaticContainer::get(SystemSettings::class);
$settings->allowedEmailDomains->setValue(['example.org', 'matomo.com', 'password.de']);
Request::processRequest(
'UsersManager.inviteUser',
[
'userLogin' => 'foobar',
'email' => 'foobar@matomo.org',
'initialIdSite' => 1,
'expiryInDays' => 7
]
);
}
public function testInviteUserInitialIdSiteError()
{
$this->expectException(\Exception::class);
$this->expectExceptionMessage("An unexpected website was found in the request: website id was set to '10'");
Request::processRequest(
'UsersManager.inviteUser',
[
'userLogin' => "testInviteUser",
'email' => "testInviteUser@example.com",
'initialIdSite' => 10,
'expiryInDays' => 7,
]
);
}
public function testInviteUserAsSuperUser()
{
$eventWasFired = false;
$capturedMails = [];
Piwik::addAction('Mail.send', function (Mail $mail) use (&$capturedMails) {
$capturedMails[] = $mail;
});
EventDispatcher::getInstance()->addObserver(
'UsersManager.inviteUser.end',
function ($userLogin, $email) use (&$eventWasFired) {
self::assertEquals('pendingLoginTest', $userLogin);
self::assertEquals('pendingLoginTest@matomo.org', $email);
$eventWasFired = true;
}
);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
$isPending = $this->model->isPendingUser('pendingLoginTest');
self::assertTrue($isPending);
self::assertTrue($eventWasFired);
self::assertCount(2, $capturedMails);
self::assertInstanceOf(UserCreatedEmail::class, $capturedMails[0]);
self::assertInstanceOf(UserInviteEmail::class, $capturedMails[1]);
}
public function testChangingEmailOfInvitedUserShouldResendInvitation()
{
Fixture::createSuperUser();
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
$isPending = $this->model->isPendingUser('pendingLoginTest');
self::assertTrue($isPending);
$eventWasFired = false;
$capturedMails = [];
Piwik::addAction('Mail.send', function (Mail $mail) use (&$capturedMails) {
$capturedMails[] = $mail;
});
EventDispatcher::getInstance()->addObserver(
'UsersManager.inviteUser.end',
function ($userLogin, $email) use (&$eventWasFired) {
$eventWasFired = true;
}
);
$this->api->updateUser('pendingLoginTest', false, 'pendingLoginTest2@matomo.org', false, Fixture::ADMIN_USER_PASSWORD);
self::assertFalse($eventWasFired); // event should not be fired on email change
self::assertCount(1, $capturedMails);
self::assertInstanceOf(UserInviteEmail::class, $capturedMails[0]);
}
public function testInviteUserAsAdmin()
{
$this->addUserWithAccess('adminUser', 'admin', 1);
$this->setCurrentUser('adminUser', 'admin', 1);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
$user = $this->model->isPendingUser('pendingLoginTest');
self::assertTrue($user);
}
public function testInviteUserAsAdminForAnotherSiteDoesntWork()
{
self::expectException(\Exception::class);
$this->addUserWithAccess('adminUser', 'admin', 1);
$this->setCurrentUser('adminUser', 'admin', 1);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 2);
}
public function testInviteUserAsWriteUserNotAllowed()
{
self::expectException(NoAccessException::class);
$this->addUserWithAccess('anyUser', 'write', 1);
$this->setCurrentUser('anyUser', 'write', 1);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
}
public function testInviteUserAsUserNotAllowed()
{
self::expectException(NoAccessException::class);
$this->addUserWithAccess('anyUser', 'view', 1);
$this->setCurrentUser('anyUser', 'view', 1);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
}
public function testInviteUserExpiredInGivenDays()
{
Date::$now = time(); // freeze time, so it doesn't change between inviting user and comparing the time
$expiredDays = 10;
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1, $expiredDays);
$user = $this->model->getUser('pendingLoginTest');
$expired = Date::factory($user['invite_expired_at'])->getTimestamp();
$now = Date::now()->getTimestamp();
$diff = $expired - $now;
self::assertEquals($expiredDays, $diff / 3600 / 24);
}
public function testResendInviteAsSuperUser()
{
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
$user = $this->model->isPendingUser('pendingLoginTest');
self::assertTrue($user);
$eventWasFired = false;
EventDispatcher::getInstance()->addObserver(
'UsersManager.inviteUser.resendInvite',
function ($userLogin) use (&$eventWasFired) {
self::assertEquals('pendingLoginTest', $userLogin);
$eventWasFired = true;
}
);
$this->api->resendInvite('pendingLoginTest', true);
self::assertTrue($eventWasFired);
}
public function testResendInviteFailsIfUserNotPending()
{
self::expectException(\Exception::class);
self::expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->api->resendInvite('notExistingUser');
}
public function testResendInviteAsInviterWithAdminAccess()
{
$this->addUserWithAccess('adminUser', 'admin', 1);
$this->setCurrentUser('adminUser', 'admin', 1);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
$user = $this->model->isPendingUser('pendingLoginTest');
self::assertTrue($user);
$eventWasFired = false;
EventDispatcher::getInstance()->addObserver(
'UsersManager.inviteUser.resendInvite',
function ($userLogin) use (&$eventWasFired) {
self::assertEquals('pendingLoginTest', $userLogin);
$eventWasFired = true;
}
);
$this->api->resendInvite('pendingLoginTest', 1);
self::assertTrue($eventWasFired);
}
public function testResendInviteFailsAsInviterWithoutAdminAccess()
{
self::expectException(NoAccessException::class);
$this->addUserWithAccess('adminUser', 'write', 1);
// fake admin access for inviting the user
$this->setCurrentUser('adminUser', 'admin', 1);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
$user = $this->model->isPendingUser('pendingLoginTest');
self::assertTrue($user);
// degraded to write access
$this->setCurrentUser('adminUser', 'admin', []);
$this->setCurrentUser('adminUser', 'write', 1);
$this->api->resendInvite('pendingLoginTest');
}
public function testResendInviteFailsAsNotInvitingAdmin()
{
self::expectException(NoAccessException::class);
self::expectExceptionMessage('UsersManager_ExceptionResendInviteDenied');
$this->addUserWithAccess('adminUser', 'admin', 1);
$this->addUserWithAccess('anotherAdminUser', 'admin', 1);
$this->setCurrentUser('adminUser', 'admin', 1);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
$user = $this->model->isPendingUser('pendingLoginTest');
self::assertTrue($user);
// another admin tries to resend invite
$this->setCurrentUser('anotherAdminUser', 'admin', 1);
$this->api->resendInvite('pendingLoginTest', 1);
}
public function testInvitedUserCanBeRemovedBySuperUser()
{
Fixture::createSuperUser();
$this->addUserWithAccess('adminUser', 'admin', 1);
$this->setCurrentUser('adminUser', 'admin', 1);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
$user = $this->model->isPendingUser('pendingLoginTest');
self::assertTrue($user);
$this->setCurrentUser('superUserLogin', 'superuser', 1);
$this->api->deleteUser('pendingLoginTest');
self::assertEmpty($this->model->getUser('pendingLoginTest'));
}
public function testInvitedUserCanBeRemovedByInviter()
{
Fixture::createSuperUser();
$this->addUserWithAccess('adminUser', 'admin', 1);
$this->setCurrentUser('adminUser', 'admin', 1);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
$user = $this->model->isPendingUser('pendingLoginTest');
self::assertTrue($user);
$this->api->deleteUser('pendingLoginTest');
self::assertEmpty($this->model->getUser('pendingLoginTest'));
}
public function testInvitedUserCanNOTBeRemovedByOtherAdmin()
{
self::expectException(\Exception::class);
self::expectExceptionMessage('UsersManager_ExceptionUserDoesNotExist');
$this->addUserWithAccess('adminUser', 'admin', 1);
$this->addUserWithAccess('adminUser2', 'admin', 1);
$this->setCurrentUser('adminUser', 'admin', 1);
$this->api->inviteUser('pendingLoginTest', 'pendingLoginTest@matomo.org', 1);
$user = $this->model->isPendingUser('pendingLoginTest');
self::assertTrue($user);
$this->setCurrentUser('adminUser2', 'admin', 1);
$this->api->deleteUser('pendingLoginTest');
}
private function getAccessInSite($login, $idSite)
{
$access = $this->model->getSitesAccessFromUser($login);
$ids = [];
foreach ($access as $entry) {
if ($entry['site'] == $idSite) {
$ids[] = $entry['access'];
}
}
return $ids;
}
private function getPreferenceId($preferenceName)
{
return $this->login . '_' . $preferenceName;
}
public function provideContainerConfig()
{
return [
'Piwik\Access' => new FakeAccess(),
'usersmanager.user_preference_names' => \Piwik\DI::add(
[
'randomDoesNotExist',
'RandomNOTREQUESTED',
'preferenceName',
]
),
'observers.global' => \Piwik\DI::add(
[
[
'Access.Capability.addCapabilities',
\Piwik\DI::value(function (&$capabilities) {
$capabilities[] = new TestCap1();
$capabilities[] = new TestCap2();
$capabilities[] = new TestCap3();
}),
],
]
),
];
}
private function addUserWithAccess($username, $accessLevel, $idSite, $email = null)
{
$this->api->addUser($username, 'password', $email ?: "$username@password.de");
if ($accessLevel == 'superuser') {
$userUpdater = new UserUpdater();
$userUpdater->setSuperUserAccessWithoutCurrentPassword($username, true);
} elseif ($accessLevel) {
$this->api->setUserAccess($username, $accessLevel, $idSite);
}
}
public function setCurrentUser($username, $accessLevel, $idSite)
{
FakeAccess::$identity = $username;
FakeAccess::$superUser = $accessLevel == 'superuser';
if ($accessLevel == 'view') {
FakeAccess::$idSitesView = is_array($idSite) ? $idSite : [$idSite];
} elseif ($accessLevel == 'admin') {
FakeAccess::$idSitesAdmin = is_array($idSite) ? $idSite : [$idSite];
} elseif ($accessLevel == 'write') {
FakeAccess::$idSitesWrite = is_array($idSite) ? $idSite : [$idSite];
}
}
private static function assertResultCountHeader($expected)
{
self::assertArrayHasKey('X-Matomo-Total-Results', Common::$headersSentInTests, 'X-Matomo-Total-Results header not sent');
self::assertEquals($expected, Common::$headersSentInTests['X-Matomo-Total-Results']);
}
private function cleanUsers(&$users)
{
foreach ($users as &$user) {
unset($user['date_registered']);
unset($user['invite_expired_at']);
unset($user['invite_accept_at']);
unset($user['invite_token']);
unset($user['invite_link_token']);
unset($user['invite_status']);
unset($user['invited_by']);
}
}
}