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