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

UserAccessFilter.php « UsersManager « plugins - github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: e331c20bb3c1bc84ef15b53da18997d3522f5751 (plain)
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
<?php
/**
 * Matomo - free/libre analytics platform
 *
 * @link https://matomo.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()
            || (!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->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]))
        );
    }
}