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