PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.6.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.6.0
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Access.php
matomo / app / core Last commit date
API 7 months ago Access 7 months ago Application 1 year ago Archive 7 months ago ArchiveProcessor 7 months ago Archiver 2 years ago AssetManager 7 months ago Auth 7 months ago Category 7 months ago Changes 7 months ago CliMulti 1 year ago Columns 7 months ago Concurrency 7 months ago Config 7 months ago Container 7 months ago CronArchive 7 months ago DataAccess 7 months ago DataFiles 2 years ago DataTable 7 months ago Db 7 months ago DeviceDetector 1 year ago Email 2 years ago Exception 1 year ago Http 1 year ago Intl 7 months ago Log 2 years ago Mail 1 year ago Measurable 7 months ago Menu 7 months ago Metrics 7 months ago Notification 7 months ago Period 7 months ago Plugin 7 months ago Policy 7 months ago ProfessionalServices 1 year ago Report 1 year ago ReportRenderer 1 year ago Request 7 months ago Scheduler 7 months ago Segment 7 months ago Session 7 months ago Settings 7 months ago Tracker 7 months ago Translation 1 year ago Twig 1 year ago UpdateCheck 7 months ago Updater 7 months ago Updates 7 months ago Validators 1 year ago View 7 months ago ViewDataTable 7 months ago Visualization 1 year ago Widget 1 year ago .htaccess 2 years ago Access.php 7 months ago Archive.php 7 months ago ArchiveProcessor.php 7 months ago AssetManager.php 1 year ago Auth.php 7 months ago AuthResult.php 7 months ago BaseFactory.php 2 years ago Cache.php 2 years ago CacheId.php 1 year ago CliMulti.php 7 months ago Common.php 7 months ago Config.php 1 year ago Console.php 1 year ago Context.php 2 years ago Cookie.php 1 year ago CronArchive.php 7 months ago DI.php 1 year ago DataArray.php 1 year ago DataTable.php 7 months ago Date.php 7 months ago Db.php 1 year ago DbHelper.php 7 months ago Development.php 1 year ago ErrorHandler.php 7 months ago EventDispatcher.php 1 year ago ExceptionHandler.php 7 months ago FileIntegrity.php 1 year ago Filechecks.php 1 year ago Filesystem.php 1 year ago FrontController.php 7 months ago Http.php 7 months ago IP.php 1 year ago Log.php 7 months ago LogDeleter.php 1 year ago Mail.php 1 year ago Metrics.php 7 months ago NoAccessException.php 2 years ago Nonce.php 7 months ago Notification.php 7 months ago NumberFormatter.php 1 year ago Option.php 1 year ago Period.php 1 year ago Piwik.php 7 months ago Plugin.php 1 year ago Process.php 1 year ago Profiler.php 7 months ago ProxyHeaders.php 2 years ago ProxyHttp.php 1 year ago QuickForm2.php 1 year ago RankingQuery.php 7 months ago ReportRenderer.php 1 year ago Request.php 1 year ago Segment.php 7 months ago Sequence.php 7 months ago Session.php 1 year ago SettingsPiwik.php 1 year ago SettingsServer.php 1 year ago Singleton.php 2 years ago Site.php 7 months ago SiteContentDetector.php 1 year ago SupportedBrowser.php 2 years ago TCPDF.php 1 year ago Theme.php 1 year ago Timer.php 2 years ago Tracker.php 1 year ago Twig.php 7 months ago Unzip.php 1 year ago UpdateCheck.php 1 year ago Updater.php 1 year ago UpdaterErrorException.php 2 years ago Updates.php 1 year ago Url.php 7 months ago UrlHelper.php 1 year ago Version.php 7 months ago View.php 7 months ago bootstrap.php 1 year ago dispatch.php 2 years ago testMinimumPhpVersion.php 7 months ago
Access.php
648 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 */
9 namespace Piwik;
10
11 use Exception;
12 use Piwik\Access\CapabilitiesProvider;
13 use Piwik\API\Request;
14 use Piwik\Access\RolesProvider;
15 use Piwik\Request\AuthenticationToken;
16 use Piwik\Container\StaticContainer;
17 use Piwik\Plugins\SitesManager\API as SitesManagerApi;
18 use Piwik\Session\SessionAuth;
19 /**
20 * Singleton that manages user access to Piwik resources.
21 *
22 * To check whether a user has access to a resource, use one of the {@link Piwik Piwik::checkUser...}
23 * methods.
24 *
25 * In Piwik there are four different access levels:
26 *
27 * - **no access**: Users with this access level cannot view the resource.
28 * - **view access**: Users with this access level can view the resource, but cannot modify it.
29 * - **admin access**: Users with this access level can view and modify the resource.
30 * - **Super User access**: Only the Super User has this access level. It means the user can do
31 * whatever they want.
32 *
33 * Super user access is required to set some configuration options.
34 * All other options are specific to the user or to a website.
35 *
36 * Access is granted per website. Uses with access for a website can view all
37 * data associated with that website.
38 *
39 */
40 class Access
41 {
42 /**
43 * Array of idsites available to the current user, indexed by permission level
44 * @see getSitesIdWith*()
45 *
46 * @var array
47 */
48 protected $idsitesByAccess = null;
49 /**
50 * Login of the current user
51 *
52 * @var string
53 */
54 protected $login = null;
55 /**
56 * token_auth of the current user
57 *
58 * @var string
59 */
60 protected $token_auth = null;
61 /**
62 * Defines if the current user is the Super User
63 * @see hasSuperUserAccess()
64 *
65 * @var bool
66 */
67 protected $hasSuperUserAccess = \false;
68 /**
69 * Authentification object (see Auth)
70 *
71 * @var Auth
72 */
73 private $auth = null;
74 /**
75 * Gets the singleton instance. Creates it if necessary.
76 *
77 * @return self
78 */
79 public static function getInstance()
80 {
81 return StaticContainer::get('Piwik\\Access');
82 }
83 /**
84 * @var CapabilitiesProvider
85 */
86 protected $capabilityProvider;
87 /**
88 * @var RolesProvider
89 */
90 private $roleProvider;
91 /**
92 * Constructor
93 */
94 public function __construct(?RolesProvider $roleProvider = null, ?CapabilitiesProvider $capabilityProvider = null)
95 {
96 if (!isset($roleProvider)) {
97 $roleProvider = StaticContainer::get('Piwik\\Access\\RolesProvider');
98 }
99 if (!isset($capabilityProvider)) {
100 $capabilityProvider = StaticContainer::get('Piwik\\Access\\CapabilitiesProvider');
101 }
102 $this->roleProvider = $roleProvider;
103 $this->capabilityProvider = $capabilityProvider;
104 $this->resetSites();
105 }
106 private function resetSites()
107 {
108 $this->idsitesByAccess = array('view' => array(), 'write' => array(), 'admin' => array(), 'superuser' => array());
109 }
110 /**
111 * Loads the access levels for the current user.
112 *
113 * Calls the authentication method to try to log the user in the system.
114 * If the user credentials are not correct we don't load anything.
115 * If the login/password is correct the user is either the SuperUser or a normal user.
116 * We load the access levels for this user for all the websites.
117 *
118 * @param null|Auth $auth Auth adapter
119 * @return bool true on success, false if reloading access failed (when auth object wasn't specified and user is not enforced to be Super User)
120 */
121 public function reloadAccess(?\Piwik\Auth $auth = null)
122 {
123 $this->resetSites();
124 if (isset($auth)) {
125 $this->auth = $auth;
126 }
127 if ($this->hasSuperUserAccess()) {
128 $this->makeSureLoginNameIsSet();
129 return \true;
130 }
131 $this->token_auth = null;
132 $this->login = null;
133 // if the Auth wasn't set, we may be in the special case of setSuperUser(), otherwise we fail TODO: docs + review
134 if (!isset($this->auth)) {
135 return \false;
136 }
137 $result = null;
138 $isApiRequest = \Piwik\Piwik::getModule() === 'API' && (\Piwik\Piwik::getAction() === 'index' || !\Piwik\Piwik::getAction());
139 $apiMethod = Request::getMethodIfApiRequest(null);
140 $isGetApiRequest = !empty($apiMethod) && 1 === substr_count($apiMethod, '.') && strpos($apiMethod, '.get') > 0;
141 $token = StaticContainer::get(AuthenticationToken::class);
142 if ($isApiRequest && $token->isSessionToken() && ($token->wasTokenAuthProvidedSecurely() || $isGetApiRequest)) {
143 $tokenAuth = $token->getAuthToken();
144 \Piwik\Session::start();
145 $auth = StaticContainer::get(SessionAuth::class);
146 $auth->setTokenAuth($tokenAuth);
147 $result = $auth->authenticate();
148 // Note: We do not post a failed login event at this point on purpose
149 // If using the SessionAuth doesn't work, the FrontController will try to reload the Auth using
150 // the token_auth only. If that works everything is "fine" and the `force_api_session` parameter was
151 // unneeded. If that fails as well it will trigger the failed login event
152 // See FrontController::init() or Request::reloadAuthUsingTokenAuth()
153 \Piwik\Session::close();
154 // if not successful, we will fallback to regular auth
155 }
156 // access = array ( idsite => accessIdSite, idsite2 => accessIdSite2)
157 if (!$result || !$result->wasAuthenticationSuccessful()) {
158 $result = $this->auth->authenticate();
159 }
160 if (!$result->wasAuthenticationSuccessful()) {
161 return \false;
162 }
163 $this->login = $result->getIdentity();
164 $this->token_auth = $result->getTokenAuth();
165 // case the superUser is logged in
166 if ($result->hasSuperUserAccess()) {
167 $this->setSuperUserAccess(\true);
168 }
169 return \true;
170 }
171 public function getRawSitesWithSomeViewAccess($login)
172 {
173 $sql = self::getSqlAccessSite("access, t2.idsite");
174 return \Piwik\Db::fetchAll($sql, $login);
175 }
176 /**
177 * Returns the SQL query joining sites and access table for a given login
178 *
179 * @param string $select Columns or expression to SELECT FROM table, eg. "MIN(ts_created)"
180 * @return string SQL query
181 */
182 public static function getSqlAccessSite($select)
183 {
184 $access = \Piwik\Common::prefixTable('access');
185 $siteTable = \Piwik\Common::prefixTable('site');
186 return "SELECT " . $select . " FROM `" . $access . "` as t1\n\t\t\t\tJOIN `" . $siteTable . "` as t2 USING (idsite) WHERE login = ?";
187 }
188 /**
189 * Make sure a login name is set
190 */
191 protected function makeSureLoginNameIsSet() : void
192 {
193 if (empty($this->login)) {
194 // flag to force non empty login so Super User is not mistaken for anonymous
195 $this->login = 'super user was set';
196 }
197 }
198 protected function loadSitesIfNeeded()
199 {
200 if ($this->hasSuperUserAccess) {
201 if (empty($this->idsitesByAccess['superuser'])) {
202 try {
203 $api = SitesManagerApi::getInstance();
204 $allSitesId = $api->getAllSitesId();
205 } catch (\Exception $e) {
206 $allSitesId = array();
207 }
208 $this->idsitesByAccess['superuser'] = $allSitesId;
209 }
210 } elseif (isset($this->login)) {
211 if (empty($this->idsitesByAccess['view']) && empty($this->idsitesByAccess['write']) && empty($this->idsitesByAccess['admin'])) {
212 // we join with site in case there are rows in access for an idsite that doesn't exist anymore
213 // (backward compatibility ; before we deleted the site without deleting rows in _access table)
214 $accessRaw = $this->getRawSitesWithSomeViewAccess($this->login);
215 foreach ($accessRaw as $access) {
216 $accessType = $access['access'];
217 $this->idsitesByAccess[$accessType][] = $access['idsite'];
218 if ($this->roleProvider->isValidRole($accessType)) {
219 foreach ($this->capabilityProvider->getAllCapabilities() as $capability) {
220 if ($capability->hasRoleCapability($accessType)) {
221 // we automatically add this capability
222 if (!isset($this->idsitesByAccess[$capability->getId()])) {
223 $this->idsitesByAccess[$capability->getId()] = array();
224 }
225 $this->idsitesByAccess[$capability->getId()][] = $access['idsite'];
226 }
227 }
228 }
229 }
230 /**
231 * Triggered after the initial access levels and permissions for the current user are loaded. Use this
232 * event to modify the current user's permissions (for example, making sure every user has view access
233 * to a specific site).
234 *
235 * **Example**
236 *
237 * function (&$idsitesByAccess, $login) {
238 * if ($login == 'somespecialuser') {
239 * return;
240 * }
241 *
242 * $idsitesByAccess['view'][] = $mySpecialIdSite;
243 * }
244 *
245 * @param array[] &$idsitesByAccess The current user's access levels for individual sites. Maps role and
246 * capability IDs to list of site IDs, eg:
247 *
248 * ```
249 * [
250 * 'view' => [1, 2, 3],
251 * 'write' => [4, 5],
252 * 'admin' => [],
253 * ]
254 * ```
255 * @param string $login The current user's login.
256 */
257 \Piwik\Piwik::postEvent('Access.modifyUserAccess', [&$this->idsitesByAccess, $this->login]);
258 }
259 }
260 }
261 /**
262 * We bypass the normal auth method and give the current user Super User rights.
263 * This should be very carefully used.
264 *
265 * @param bool $bool
266 */
267 public function setSuperUserAccess($bool = \true)
268 {
269 $this->hasSuperUserAccess = (bool) $bool;
270 if ($bool) {
271 $this->makeSureLoginNameIsSet();
272 } else {
273 $this->resetSites();
274 }
275 }
276 /**
277 * Returns true if the current user is logged in as the Super User
278 *
279 * @return bool
280 */
281 public function hasSuperUserAccess()
282 {
283 return $this->hasSuperUserAccess;
284 }
285 /**
286 * Returns the current user login
287 *
288 * @return string|null
289 */
290 public function getLogin()
291 {
292 return $this->login;
293 }
294 /**
295 * Returns the token_auth used to authenticate this user in the API
296 *
297 * @return string|null
298 */
299 public function getTokenAuth()
300 {
301 return $this->token_auth;
302 }
303 /**
304 * Returns an array of ID sites for which the user has at least a VIEW access.
305 * Which means VIEW OR WRITE or ADMIN or SUPERUSER.
306 *
307 * @return array Example if the user is ADMIN for 4
308 * and has VIEW access for 1 and 7, it returns array(1, 4, 7);
309 */
310 public function getSitesIdWithAtLeastViewAccess()
311 {
312 $this->loadSitesIfNeeded();
313 return array_unique(array_merge($this->idsitesByAccess['view'], $this->idsitesByAccess['write'], $this->idsitesByAccess['admin'], $this->idsitesByAccess['superuser']));
314 }
315 /**
316 * Returns an array of ID sites for which the user has at least a WRITE access.
317 * Which means WRITE or ADMIN or SUPERUSER.
318 *
319 * @return array Example if the user is WRITE for 4 and 8
320 * and has VIEW access for 1 and 7, it returns array(4, 8);
321 */
322 public function getSitesIdWithAtLeastWriteAccess()
323 {
324 $this->loadSitesIfNeeded();
325 return array_unique(array_merge($this->idsitesByAccess['write'], $this->idsitesByAccess['admin'], $this->idsitesByAccess['superuser']));
326 }
327 /**
328 * Returns an array of ID sites for which the user has an ADMIN access.
329 *
330 * @return array Example if the user is ADMIN for 4 and 8
331 * and has VIEW access for 1 and 7, it returns array(4, 8);
332 */
333 public function getSitesIdWithAdminAccess()
334 {
335 $this->loadSitesIfNeeded();
336 return array_unique(array_merge($this->idsitesByAccess['admin'], $this->idsitesByAccess['superuser']));
337 }
338 /**
339 * Returns an array of ID sites for which the user has a VIEW access only.
340 *
341 * @return array Example if the user is ADMIN for 4
342 * and has VIEW access for 1 and 7, it returns array(1, 7);
343 * @see getSitesIdWithAtLeastViewAccess()
344 */
345 public function getSitesIdWithViewAccess()
346 {
347 $this->loadSitesIfNeeded();
348 return $this->idsitesByAccess['view'];
349 }
350 /**
351 * Returns an array of ID sites for which the user has a WRITE access only.
352 *
353 * @return array Example if the user is ADMIN for 4
354 * and has WRITE access for 1 and 7, it returns array(1, 7);
355 * @see getSitesIdWithAtLeastWriteAccess()
356 */
357 public function getSitesIdWithWriteAccess()
358 {
359 $this->loadSitesIfNeeded();
360 return $this->idsitesByAccess['write'];
361 }
362 /**
363 * Throws an exception if the user is not the SuperUser
364 *
365 * @throws \Piwik\NoAccessException
366 */
367 public function checkUserHasSuperUserAccess()
368 {
369 if (!$this->hasSuperUserAccess()) {
370 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilege', array("'superuser'")));
371 }
372 }
373 /**
374 * Returns `true` if the current user has admin access to at least one site.
375 *
376 * @return bool
377 */
378 public function isUserHasSomeWriteAccess()
379 {
380 if ($this->hasSuperUserAccess()) {
381 return \true;
382 }
383 $idSitesAccessible = $this->getSitesIdWithAtLeastWriteAccess();
384 return count($idSitesAccessible) > 0;
385 }
386 /**
387 * Returns `true` if the current user has admin access to at least one site.
388 *
389 * @return bool
390 */
391 public function isUserHasSomeAdminAccess()
392 {
393 if ($this->hasSuperUserAccess()) {
394 return \true;
395 }
396 $idSitesAccessible = $this->getSitesIdWithAdminAccess();
397 return count($idSitesAccessible) > 0;
398 }
399 /**
400 * If the user doesn't have an WRITE access for at least one website, throws an exception
401 *
402 * @throws \Piwik\NoAccessException
403 */
404 public function checkUserHasSomeWriteAccess()
405 {
406 if (!$this->isUserHasSomeWriteAccess()) {
407 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAtLeastOneWebsite', array('write')));
408 }
409 }
410 /**
411 * If the user doesn't have an ADMIN access for at least one website, throws an exception
412 *
413 * @throws \Piwik\NoAccessException
414 */
415 public function checkUserHasSomeAdminAccess()
416 {
417 if (!$this->isUserHasSomeAdminAccess()) {
418 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAtLeastOneWebsite', array('admin')));
419 }
420 }
421 /**
422 * If the user doesn't have any view permission, throw exception
423 *
424 * @throws \Piwik\NoAccessException
425 */
426 public function checkUserHasSomeViewAccess()
427 {
428 if ($this->hasSuperUserAccess()) {
429 return;
430 }
431 $idSitesAccessible = $this->getSitesIdWithAtLeastViewAccess();
432 if (count($idSitesAccessible) == 0) {
433 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAtLeastOneWebsite', array('view')));
434 }
435 }
436 /**
437 * This method checks that the user has ADMIN access for the given list of websites.
438 * If the user doesn't have ADMIN access for at least one website of the list, we throw an exception.
439 *
440 * @param int|array $idSites List of ID sites to check
441 * @throws \Piwik\NoAccessException If for any of the websites the user doesn't have an ADMIN access
442 */
443 public function checkUserHasAdminAccess($idSites)
444 {
445 if ($this->hasSuperUserAccess()) {
446 return;
447 }
448 $idSites = $this->getIdSites($idSites);
449 $idSitesAccessible = $this->getSitesIdWithAdminAccess();
450 foreach ($idSites as $idsite) {
451 if (!in_array($idsite, $idSitesAccessible)) {
452 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAccessWebsite', array("'admin'", $idsite)));
453 }
454 }
455 }
456 /**
457 * This method checks that the user has VIEW or ADMIN access for the given list of websites.
458 * If the user doesn't have VIEW or ADMIN access for at least one website of the list, we throw an exception.
459 *
460 * @param int|array|string $idSites List of ID sites to check (integer, array of integers, string comma separated list of integers)
461 * @throws \Piwik\NoAccessException If for any of the websites the user doesn't have an VIEW or ADMIN access
462 */
463 public function checkUserHasViewAccess($idSites)
464 {
465 if ($this->hasSuperUserAccess()) {
466 return;
467 }
468 $idSites = $this->getIdSites($idSites);
469 $idSitesAccessible = $this->getSitesIdWithAtLeastViewAccess();
470 foreach ($idSites as $idsite) {
471 if (!in_array($idsite, $idSitesAccessible)) {
472 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAccessWebsite', array("'view'", $idsite)));
473 }
474 }
475 }
476 /**
477 * This method checks that the user has VIEW or ADMIN access for the given list of websites.
478 * If the user doesn't have VIEW or ADMIN access for at least one website of the list, we throw an exception.
479 *
480 * @param int|array|string $idSites List of ID sites to check (integer, array of integers, string comma separated list of integers)
481 * @throws \Piwik\NoAccessException If for any of the websites the user doesn't have an VIEW or ADMIN access
482 */
483 public function checkUserHasWriteAccess($idSites)
484 {
485 if ($this->hasSuperUserAccess()) {
486 return;
487 }
488 $idSites = $this->getIdSites($idSites);
489 $idSitesAccessible = $this->getSitesIdWithAtLeastWriteAccess();
490 foreach ($idSites as $idsite) {
491 if (!in_array($idsite, $idSitesAccessible)) {
492 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAccessWebsite', array("'write'", $idsite)));
493 }
494 }
495 }
496 public function checkUserIsNotAnonymous()
497 {
498 if ($this->hasSuperUserAccess()) {
499 return;
500 }
501 if (\Piwik\Piwik::isUserIsAnonymous()) {
502 $this->throwNoAccessException(\Piwik\Piwik::translate('General_YouMustBeLoggedIn'));
503 }
504 }
505 private function getSitesIdWithCapability($capability)
506 {
507 if (!empty($this->idsitesByAccess[$capability])) {
508 return $this->idsitesByAccess[$capability];
509 }
510 return array();
511 }
512 public function checkUserHasCapability($idSites, $capability)
513 {
514 if ($this->hasSuperUserAccess()) {
515 return;
516 }
517 $idSites = $this->getIdSites($idSites);
518 $idSitesAccessible = $this->getSitesIdWithCapability($capability);
519 foreach ($idSites as $idsite) {
520 if (!in_array($idsite, $idSitesAccessible)) {
521 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionCapabilityAccessWebsite', array("'" . $capability . "'", $idsite)));
522 }
523 }
524 // a capability applies only when the user also has at least view access
525 $this->checkUserHasViewAccess($idSites);
526 }
527 /**
528 * @param int|array|string $idSites
529 * @return array
530 * @throws \Piwik\NoAccessException
531 */
532 protected function getIdSites($idSites)
533 {
534 if ($idSites === 'all') {
535 $idSites = $this->getSitesIdWithAtLeastViewAccess();
536 }
537 $idSites = \Piwik\Site::getIdSitesFromIdSitesString($idSites);
538 if (empty($idSites)) {
539 $this->throwNoAccessException("The parameter 'idSite=' is missing from the request.");
540 }
541 return $idSites;
542 }
543 /**
544 * Executes a callback with superuser privileges, making sure those privileges are rescinded
545 * before this method exits. Privileges will be rescinded even if an exception is thrown.
546 *
547 * Use this method with care, as it might open up attack vectors
548 *
549 * @param callback $function The callback to execute. Should accept no arguments.
550 * @return mixed The result of `$function`.
551 * @throws Exception rethrows any exceptions thrown by `$function`.
552 * @api
553 */
554 public static function doAsSuperUser($function)
555 {
556 $isSuperUser = self::getInstance()->hasSuperUserAccess();
557 if ($isSuperUser) {
558 return $function();
559 }
560 $access = self::getInstance();
561 $login = $access->getLogin();
562 $shouldResetLogin = empty($login);
563 // make sure to reset login if a login was set by "makeSureLoginNameIsSet()"
564 $access->setSuperUserAccess(\true);
565 try {
566 $result = $function();
567 } catch (\Throwable $ex) {
568 $access->setSuperUserAccess($isSuperUser);
569 if ($shouldResetLogin) {
570 $access->login = null;
571 }
572 throw $ex;
573 }
574 if ($shouldResetLogin) {
575 $access->login = null;
576 }
577 $access->setSuperUserAccess($isSuperUser);
578 return $result;
579 }
580 /**
581 * Returns the level of access the current user has to the given site.
582 *
583 * @param int $idSite The site to check.
584 * @return string The access level, eg, 'view', 'admin', 'noaccess'.
585 */
586 public function getRoleForSite($idSite)
587 {
588 if ($this->hasSuperUserAccess || in_array($idSite, $this->getSitesIdWithAdminAccess())) {
589 return 'admin';
590 }
591 if (in_array($idSite, $this->getSitesIdWithWriteAccess())) {
592 return 'write';
593 }
594 if (in_array($idSite, $this->getSitesIdWithViewAccess())) {
595 return 'view';
596 }
597 return 'noaccess';
598 }
599 /**
600 * Returns the capabilities the current user has for a given site.
601 *
602 * @param int $idSite The site to check.
603 * @return string[] The capabilities the user has.
604 */
605 public function getCapabilitiesForSite($idSite)
606 {
607 $result = [];
608 foreach ($this->capabilityProvider->getAllCapabilityIds() as $capabilityId) {
609 if (empty($this->idsitesByAccess[$capabilityId])) {
610 continue;
611 }
612 if (in_array($idSite, $this->idsitesByAccess[$capabilityId])) {
613 $result[] = $capabilityId;
614 }
615 }
616 return $result;
617 }
618 /**
619 * Throw a NoAccessException with the given message, or a more generic 'You need to log in' message if the
620 * user is not currently logged in (e.g. if session has expired).
621 *
622 * @param $message
623 * @throws NoAccessException
624 */
625 private function throwNoAccessException($message)
626 {
627 if (\Piwik\Piwik::isUserIsAnonymous() && !Request::isRootRequestApiRequest()) {
628 $message = \Piwik\Piwik::translate('General_YouMustBeLoggedIn');
629 // Try to detect whether user was previously logged in so that we can display a different message
630 $referrer = \Piwik\Url::getReferrer();
631 $matomoUrl = \Piwik\SettingsPiwik::getPiwikUrl();
632 if ($referrer && $matomoUrl && \Piwik\Url::isValidHost(\Piwik\Url::getHostFromUrl($referrer)) && strpos($referrer, $matomoUrl) === 0) {
633 $message = \Piwik\Piwik::translate('General_YourSessionHasExpired');
634 }
635 }
636 throw new \Piwik\NoAccessException($message);
637 }
638 /**
639 * Returns true if the current user is logged in or not.
640 *
641 * @return bool
642 */
643 public function isUserLoggedIn()
644 {
645 return !empty($this->login);
646 }
647 }
648