Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/UsersManager/UserAccessFilter.php')
-rw-r--r--plugins/UsersManager/UserAccessFilter.php183
1 files changed, 183 insertions, 0 deletions
diff --git a/plugins/UsersManager/UserAccessFilter.php b/plugins/UsersManager/UserAccessFilter.php
new file mode 100644
index 0000000000..20fd671aa3
--- /dev/null
+++ b/plugins/UsersManager/UserAccessFilter.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://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 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();
+ }
+
+ foreach ($users as $index => $user) {
+ if (!$this->isNonSuperUserAllowedToSeeThisLogin($user['login'])) {
+ unset($users[$index]);
+ }
+ }
+
+ return array_values($users);
+ }
+
+ /**
+ * 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 bool
+ */
+ public function filterUser($user)
+ {
+ if ($this->access->hasSuperUserAccess() || $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->usersWithViewAccess = $this->model->getUsersSitesFromAccess('view');
+ }
+
+ return (
+ (isset($this->usersWithViewAccess[$login]) && array_intersect($this->idSitesWithAdmin, $this->usersWithViewAccess[$login]))
+ ||
+ (isset($this->usersWithAdminAccess[$login]) && array_intersect($this->idSitesWithAdmin, $this->usersWithAdminAccess[$login]))
+ );
+ }
+}