1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
<?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;
use Piwik\Access;
/**
* This class offers methods to filter a list of users, logins, or anything that is related to users/logins.
*
* * By default a super user is allowed to see all users.
* * A user having admin access is allowed to see all other users that have view or admin access to the same access.
* * A user not having any admin access is only allowed to see the own user.
*
* The methods in this class make sure to only return the data for logins / users the current user actually has
* permission to see.
*
* FYI: The anonymous user is not treated in any special way. The anonymous user is a regular user with no access or
* view access only and can only see itself.
*/
class UserAccessFilter
{
/**
* @var Model
*/
private $model;
/**
* @var Access
*/
private $access;
/**
* Holds a list of all idSites the current user has view access to. Only used for caching.
* @var array
*/
private $idSitesWithAdmin;
/**
* Holds a list of all user logins that have admin access. Only used for caching
* @var array Array ('loginName' => array(idsites...))
*/
private $usersWithAdminAccess;
/**
* Holds a list of all user logins that have write access. Only used for caching
* @var array Array ('loginName' => array(idsites...))
*/
private $usersWithWriteAccess;
/**
* Holds a list of all user logins that have view access. Only used for caching
* @var array Array ('loginName' => array(idsites...))
*/
private $usersWithViewAccess;
public function __construct(Model $model, Access $access)
{
$this->model = $model;
$this->access = $access;
}
/**
* Removes all array values where the current user has no permission to see the existence of a given login index/key.
* @param array $arrayIndexedByLogin An array that is indexed by login / usernames. Eg:
* array('username1' => 5, 'username2' => array(...), ...)
* @return array
*/
public function filterLoginIndexedArray($arrayIndexedByLogin)
{
if ($this->access->hasSuperUserAccess()) {
return $arrayIndexedByLogin; // this part is not needed but makes it faster for super user.
}
$allowedLogins = $this->filterLogins(array_keys($arrayIndexedByLogin));
return array_intersect_key($arrayIndexedByLogin, array_flip($allowedLogins));
}
/**
* Removes all users from the list of the given users where the current user has no permission to see the existence
* of that other user.
* @param array $users An array of arrays. Each inner array must have a key 'login'. Eg:
* array(array('login' => 'username1'), array('login' => 'username2'), ...)
* @return array
*/
public function filterUsers($users)
{
if ($this->access->hasSuperUserAccess()) {
return $users;
}
if (!$this->access->isUserHasSomeAdminAccess()) {
// keep only own user if it is in the list
foreach ($users as $user) {
if ($this->isOwnLogin($user['login'])) {
return array($user);
}
}
return array();
}
return array_values(array_filter($users, function ($user) {
$isPendingVisible = empty($user['invite_token']) || $this->isOwnLogin($user['invited_by']);
return $isPendingVisible && $this->isNonSuperUserAllowedToSeeThisLogin($user['login']);
}));
}
/**
* Returns the given user only if the current user has permission to see the given user
* @param array $user An array containing a key 'login'
* @return array|null
*/
public function filterUser($user)
{
if (
$this->access->hasSuperUserAccess()
|| (!empty($user['login']) && $this->isNonSuperUserAllowedToSeeThisLogin($user['login']))
) {
return $user;
}
}
/**
* Removes all logins from the list of logins where the current user has no permission to see them.
*
* @param string[] $logins An array of logins / usernames. Eg array('username1', 'username2')
* @return array
*/
public function filterLogins($logins)
{
if ($this->access->hasSuperUserAccess()) {
return $logins;
}
if (!$this->access->isUserHasSomeAdminAccess()) {
// keep only own user if it is in the list
foreach ($logins as $login) {
if ($this->isOwnLogin($login)) {
return array($login);
}
}
return array();
}
foreach ($logins as $index => $login) {
if (!$this->isNonSuperUserAllowedToSeeThisLogin($login)) {
unset($logins[$index]);
}
}
return array_values($logins);
}
protected function isNonSuperUserAllowedToSeeThisLogin($login)
{
// we do not test for super user access here for better performance as we would otherwise test for access for
// each single login in the other calling methods.
return $this->hasAccessToSameSite($login) || $this->isOwnLogin($login);
}
private function isOwnLogin($login)
{
return $login === $this->access->getLogin();
}
private function hasAccessToSameSite($login)
{
// users is allowed to see other users having view or admin access to these sites
if (!isset($this->idSitesWithAdmin)) {
$this->idSitesWithAdmin = $this->access->getSitesIdWithAdminAccess();
$this->usersWithAdminAccess = $this->model->getUsersSitesFromAccess('admin');
$this->usersWithWriteAccess = $this->model->getUsersSitesFromAccess('write');
$this->usersWithViewAccess = $this->model->getUsersSitesFromAccess('view');
}
return (
(isset($this->usersWithViewAccess[$login]) && array_intersect($this->idSitesWithAdmin, $this->usersWithViewAccess[$login]))
|| (isset($this->usersWithWriteAccess[$login]) && array_intersect($this->idSitesWithAdmin, $this->usersWithWriteAccess[$login]))
|| (isset($this->usersWithAdminAccess[$login]) && array_intersect($this->idSitesWithAdmin, $this->usersWithAdminAccess[$login]))
);
}
}
|