PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.0.7
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.0.7
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 2 years 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 2 years 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 2 years ago Translation 2 years ago Twig 2 years ago UpdateCheck 2 years ago Updater 2 years ago Updates 2 years 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 2 years ago DbHelper.php 2 years 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 2 years ago Version.php 2 years ago View.php 2 years ago bootstrap.php 2 years ago dispatch.php 2 years ago testMinimumPhpVersion.php 2 years ago
Access.php
650 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 *
9 */
10 namespace Piwik;
11
12 use Exception;
13 use Piwik\Access\CapabilitiesProvider;
14 use Piwik\API\Request;
15 use Piwik\Access\RolesProvider;
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 $forceApiSessionPost = \Piwik\Common::getRequestVar('force_api_session', 0, 'int', $_POST);
139 $forceApiSessionGet = \Piwik\Common::getRequestVar('force_api_session', 0, 'int', $_GET);
140 $isApiRequest = \Piwik\Piwik::getModule() === 'API' && (\Piwik\Piwik::getAction() === 'index' || !\Piwik\Piwik::getAction());
141 $apiMethod = Request::getMethodIfApiRequest(null);
142 $isGetApiRequest = !empty($apiMethod) && 1 === substr_count($apiMethod, '.') && strpos($apiMethod, '.get') > 0;
143 if ($forceApiSessionPost && $isApiRequest || $forceApiSessionGet && $isApiRequest && $isGetApiRequest) {
144 $request = $forceApiSessionGet && $isApiRequest && $isGetApiRequest ? $_GET : $_POST;
145 $tokenAuth = \Piwik\Common::getRequestVar('token_auth', '', 'string', $request);
146 \Piwik\Session::start();
147 $auth = StaticContainer::get(SessionAuth::class);
148 $auth->setTokenAuth($tokenAuth);
149 $result = $auth->authenticate();
150 // Note: We do not post a failed login event at this point on purpose
151 // If using the SessionAuth doesn't work, the FrontController will try to reload the Auth using
152 // the token_auth only. If that works everything is "fine" and the `force_api_session` parameter was
153 // unneeded. If that fails as well it will trigger the failed login event
154 // See FrontController::init() or Request::reloadAuthUsingTokenAuth()
155 \Piwik\Session::close();
156 // if not successful, we will fallback to regular auth
157 }
158 // access = array ( idsite => accessIdSite, idsite2 => accessIdSite2)
159 if (!$result || !$result->wasAuthenticationSuccessful()) {
160 $result = $this->auth->authenticate();
161 }
162 if (!$result->wasAuthenticationSuccessful()) {
163 return false;
164 }
165 $this->login = $result->getIdentity();
166 $this->token_auth = $result->getTokenAuth();
167 // case the superUser is logged in
168 if ($result->hasSuperUserAccess()) {
169 $this->setSuperUserAccess(true);
170 }
171 return true;
172 }
173 public function getRawSitesWithSomeViewAccess($login)
174 {
175 $sql = self::getSqlAccessSite("access, t2.idsite");
176 return \Piwik\Db::fetchAll($sql, $login);
177 }
178 /**
179 * Returns the SQL query joining sites and access table for a given login
180 *
181 * @param string $select Columns or expression to SELECT FROM table, eg. "MIN(ts_created)"
182 * @return string SQL query
183 */
184 public static function getSqlAccessSite($select)
185 {
186 $access = \Piwik\Common::prefixTable('access');
187 $siteTable = \Piwik\Common::prefixTable('site');
188 return "SELECT " . $select . " FROM " . $access . " as t1\n\t\t\t\tJOIN " . $siteTable . " as t2 USING (idsite) WHERE login = ?";
189 }
190 /**
191 * Make sure a login name is set
192 *
193 * @return true
194 */
195 protected function makeSureLoginNameIsSet()
196 {
197 if (empty($this->login)) {
198 // flag to force non empty login so Super User is not mistaken for anonymous
199 $this->login = 'super user was set';
200 }
201 }
202 protected function loadSitesIfNeeded()
203 {
204 if ($this->hasSuperUserAccess) {
205 if (empty($this->idsitesByAccess['superuser'])) {
206 try {
207 $api = SitesManagerApi::getInstance();
208 $allSitesId = $api->getAllSitesId();
209 } catch (\Exception $e) {
210 $allSitesId = array();
211 }
212 $this->idsitesByAccess['superuser'] = $allSitesId;
213 }
214 } elseif (isset($this->login)) {
215 if (empty($this->idsitesByAccess['view']) && empty($this->idsitesByAccess['write']) && empty($this->idsitesByAccess['admin'])) {
216 // we join with site in case there are rows in access for an idsite that doesn't exist anymore
217 // (backward compatibility ; before we deleted the site without deleting rows in _access table)
218 $accessRaw = $this->getRawSitesWithSomeViewAccess($this->login);
219 foreach ($accessRaw as $access) {
220 $accessType = $access['access'];
221 $this->idsitesByAccess[$accessType][] = $access['idsite'];
222 if ($this->roleProvider->isValidRole($accessType)) {
223 foreach ($this->capabilityProvider->getAllCapabilities() as $capability) {
224 if ($capability->hasRoleCapability($accessType)) {
225 // we automatically add this capability
226 if (!isset($this->idsitesByAccess[$capability->getId()])) {
227 $this->idsitesByAccess[$capability->getId()] = array();
228 }
229 $this->idsitesByAccess[$capability->getId()][] = $access['idsite'];
230 }
231 }
232 }
233 }
234 /**
235 * Triggered after the initial access levels and permissions for the current user are loaded. Use this
236 * event to modify the current user's permissions (for example, making sure every user has view access
237 * to a specific site).
238 *
239 * **Example**
240 *
241 * function (&$idsitesByAccess, $login) {
242 * if ($login == 'somespecialuser') {
243 * return;
244 * }
245 *
246 * $idsitesByAccess['view'][] = $mySpecialIdSite;
247 * }
248 *
249 * @param array[] &$idsitesByAccess The current user's access levels for individual sites. Maps role and
250 * capability IDs to list of site IDs, eg:
251 *
252 * ```
253 * [
254 * 'view' => [1, 2, 3],
255 * 'write' => [4, 5],
256 * 'admin' => [],
257 * ]
258 * ```
259 * @param string $login The current user's login.
260 */
261 \Piwik\Piwik::postEvent('Access.modifyUserAccess', [&$this->idsitesByAccess, $this->login]);
262 }
263 }
264 }
265 /**
266 * We bypass the normal auth method and give the current user Super User rights.
267 * This should be very carefully used.
268 *
269 * @param bool $bool
270 */
271 public function setSuperUserAccess($bool = true)
272 {
273 $this->hasSuperUserAccess = (bool) $bool;
274 if ($bool) {
275 $this->makeSureLoginNameIsSet();
276 } else {
277 $this->resetSites();
278 }
279 }
280 /**
281 * Returns true if the current user is logged in as the Super User
282 *
283 * @return bool
284 */
285 public function hasSuperUserAccess()
286 {
287 return $this->hasSuperUserAccess;
288 }
289 /**
290 * Returns the current user login
291 *
292 * @return string|null
293 */
294 public function getLogin()
295 {
296 return $this->login;
297 }
298 /**
299 * Returns the token_auth used to authenticate this user in the API
300 *
301 * @return string|null
302 */
303 public function getTokenAuth()
304 {
305 return $this->token_auth;
306 }
307 /**
308 * Returns an array of ID sites for which the user has at least a VIEW access.
309 * Which means VIEW OR WRITE or ADMIN or SUPERUSER.
310 *
311 * @return array Example if the user is ADMIN for 4
312 * and has VIEW access for 1 and 7, it returns array(1, 4, 7);
313 */
314 public function getSitesIdWithAtLeastViewAccess()
315 {
316 $this->loadSitesIfNeeded();
317 return array_unique(array_merge($this->idsitesByAccess['view'], $this->idsitesByAccess['write'], $this->idsitesByAccess['admin'], $this->idsitesByAccess['superuser']));
318 }
319 /**
320 * Returns an array of ID sites for which the user has at least a WRITE access.
321 * Which means WRITE or ADMIN or SUPERUSER.
322 *
323 * @return array Example if the user is WRITE for 4 and 8
324 * and has VIEW access for 1 and 7, it returns array(4, 8);
325 */
326 public function getSitesIdWithAtLeastWriteAccess()
327 {
328 $this->loadSitesIfNeeded();
329 return array_unique(array_merge($this->idsitesByAccess['write'], $this->idsitesByAccess['admin'], $this->idsitesByAccess['superuser']));
330 }
331 /**
332 * Returns an array of ID sites for which the user has an ADMIN access.
333 *
334 * @return array Example if the user is ADMIN for 4 and 8
335 * and has VIEW access for 1 and 7, it returns array(4, 8);
336 */
337 public function getSitesIdWithAdminAccess()
338 {
339 $this->loadSitesIfNeeded();
340 return array_unique(array_merge($this->idsitesByAccess['admin'], $this->idsitesByAccess['superuser']));
341 }
342 /**
343 * Returns an array of ID sites for which the user has a VIEW access only.
344 *
345 * @return array Example if the user is ADMIN for 4
346 * and has VIEW access for 1 and 7, it returns array(1, 7);
347 * @see getSitesIdWithAtLeastViewAccess()
348 */
349 public function getSitesIdWithViewAccess()
350 {
351 $this->loadSitesIfNeeded();
352 return $this->idsitesByAccess['view'];
353 }
354 /**
355 * Returns an array of ID sites for which the user has a WRITE access only.
356 *
357 * @return array Example if the user is ADMIN for 4
358 * and has WRITE access for 1 and 7, it returns array(1, 7);
359 * @see getSitesIdWithAtLeastWriteAccess()
360 */
361 public function getSitesIdWithWriteAccess()
362 {
363 $this->loadSitesIfNeeded();
364 return $this->idsitesByAccess['write'];
365 }
366 /**
367 * Throws an exception if the user is not the SuperUser
368 *
369 * @throws \Piwik\NoAccessException
370 */
371 public function checkUserHasSuperUserAccess()
372 {
373 if (!$this->hasSuperUserAccess()) {
374 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilege', array("'superuser'")));
375 }
376 }
377 /**
378 * Returns `true` if the current user has admin access to at least one site.
379 *
380 * @return bool
381 */
382 public function isUserHasSomeWriteAccess()
383 {
384 if ($this->hasSuperUserAccess()) {
385 return true;
386 }
387 $idSitesAccessible = $this->getSitesIdWithAtLeastWriteAccess();
388 return count($idSitesAccessible) > 0;
389 }
390 /**
391 * Returns `true` if the current user has admin access to at least one site.
392 *
393 * @return bool
394 */
395 public function isUserHasSomeAdminAccess()
396 {
397 if ($this->hasSuperUserAccess()) {
398 return true;
399 }
400 $idSitesAccessible = $this->getSitesIdWithAdminAccess();
401 return count($idSitesAccessible) > 0;
402 }
403 /**
404 * If the user doesn't have an WRITE access for at least one website, throws an exception
405 *
406 * @throws \Piwik\NoAccessException
407 */
408 public function checkUserHasSomeWriteAccess()
409 {
410 if (!$this->isUserHasSomeWriteAccess()) {
411 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAtLeastOneWebsite', array('write')));
412 }
413 }
414 /**
415 * If the user doesn't have an ADMIN access for at least one website, throws an exception
416 *
417 * @throws \Piwik\NoAccessException
418 */
419 public function checkUserHasSomeAdminAccess()
420 {
421 if (!$this->isUserHasSomeAdminAccess()) {
422 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAtLeastOneWebsite', array('admin')));
423 }
424 }
425 /**
426 * If the user doesn't have any view permission, throw exception
427 *
428 * @throws \Piwik\NoAccessException
429 */
430 public function checkUserHasSomeViewAccess()
431 {
432 if ($this->hasSuperUserAccess()) {
433 return;
434 }
435 $idSitesAccessible = $this->getSitesIdWithAtLeastViewAccess();
436 if (count($idSitesAccessible) == 0) {
437 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAtLeastOneWebsite', array('view')));
438 }
439 }
440 /**
441 * This method checks that the user has ADMIN access for the given list of websites.
442 * If the user doesn't have ADMIN access for at least one website of the list, we throw an exception.
443 *
444 * @param int|array $idSites List of ID sites to check
445 * @throws \Piwik\NoAccessException If for any of the websites the user doesn't have an ADMIN access
446 */
447 public function checkUserHasAdminAccess($idSites)
448 {
449 if ($this->hasSuperUserAccess()) {
450 return;
451 }
452 $idSites = $this->getIdSites($idSites);
453 $idSitesAccessible = $this->getSitesIdWithAdminAccess();
454 foreach ($idSites as $idsite) {
455 if (!in_array($idsite, $idSitesAccessible)) {
456 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAccessWebsite', array("'admin'", $idsite)));
457 }
458 }
459 }
460 /**
461 * This method checks that the user has VIEW or ADMIN access for the given list of websites.
462 * If the user doesn't have VIEW or ADMIN access for at least one website of the list, we throw an exception.
463 *
464 * @param int|array|string $idSites List of ID sites to check (integer, array of integers, string comma separated list of integers)
465 * @throws \Piwik\NoAccessException If for any of the websites the user doesn't have an VIEW or ADMIN access
466 */
467 public function checkUserHasViewAccess($idSites)
468 {
469 if ($this->hasSuperUserAccess()) {
470 return;
471 }
472 $idSites = $this->getIdSites($idSites);
473 $idSitesAccessible = $this->getSitesIdWithAtLeastViewAccess();
474 foreach ($idSites as $idsite) {
475 if (!in_array($idsite, $idSitesAccessible)) {
476 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAccessWebsite', array("'view'", $idsite)));
477 }
478 }
479 }
480 /**
481 * This method checks that the user has VIEW or ADMIN access for the given list of websites.
482 * If the user doesn't have VIEW or ADMIN access for at least one website of the list, we throw an exception.
483 *
484 * @param int|array|string $idSites List of ID sites to check (integer, array of integers, string comma separated list of integers)
485 * @throws \Piwik\NoAccessException If for any of the websites the user doesn't have an VIEW or ADMIN access
486 */
487 public function checkUserHasWriteAccess($idSites)
488 {
489 if ($this->hasSuperUserAccess()) {
490 return;
491 }
492 $idSites = $this->getIdSites($idSites);
493 $idSitesAccessible = $this->getSitesIdWithAtLeastWriteAccess();
494 foreach ($idSites as $idsite) {
495 if (!in_array($idsite, $idSitesAccessible)) {
496 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionPrivilegeAccessWebsite', array("'write'", $idsite)));
497 }
498 }
499 }
500 public function checkUserIsNotAnonymous()
501 {
502 if ($this->hasSuperUserAccess()) {
503 return;
504 }
505 if (\Piwik\Piwik::isUserIsAnonymous()) {
506 $this->throwNoAccessException(\Piwik\Piwik::translate('General_YouMustBeLoggedIn'));
507 }
508 }
509 private function getSitesIdWithCapability($capability)
510 {
511 if (!empty($this->idsitesByAccess[$capability])) {
512 return $this->idsitesByAccess[$capability];
513 }
514 return array();
515 }
516 public function checkUserHasCapability($idSites, $capability)
517 {
518 if ($this->hasSuperUserAccess()) {
519 return;
520 }
521 $idSites = $this->getIdSites($idSites);
522 $idSitesAccessible = $this->getSitesIdWithCapability($capability);
523 foreach ($idSites as $idsite) {
524 if (!in_array($idsite, $idSitesAccessible)) {
525 $this->throwNoAccessException(\Piwik\Piwik::translate('General_ExceptionCapabilityAccessWebsite', array("'" . $capability . "'", $idsite)));
526 }
527 }
528 // a capability applies only when the user also has at least view access
529 $this->checkUserHasViewAccess($idSites);
530 }
531 /**
532 * @param int|array|string $idSites
533 * @return array
534 * @throws \Piwik\NoAccessException
535 */
536 protected function getIdSites($idSites)
537 {
538 if ($idSites === 'all') {
539 $idSites = $this->getSitesIdWithAtLeastViewAccess();
540 }
541 $idSites = \Piwik\Site::getIdSitesFromIdSitesString($idSites);
542 if (empty($idSites)) {
543 $this->throwNoAccessException("The parameter 'idSite=' is missing from the request.");
544 }
545 return $idSites;
546 }
547 /**
548 * Executes a callback with superuser privileges, making sure those privileges are rescinded
549 * before this method exits. Privileges will be rescinded even if an exception is thrown.
550 *
551 * @param callback $function The callback to execute. Should accept no arguments.
552 * @return mixed The result of `$function`.
553 * @throws Exception rethrows any exceptions thrown by `$function`.
554 * @api
555 */
556 public static function doAsSuperUser($function)
557 {
558 $isSuperUser = self::getInstance()->hasSuperUserAccess();
559 if ($isSuperUser) {
560 return $function();
561 }
562 $access = self::getInstance();
563 $login = $access->getLogin();
564 $shouldResetLogin = empty($login);
565 // make sure to reset login if a login was set by "makeSureLoginNameIsSet()"
566 $access->setSuperUserAccess(true);
567 try {
568 $result = $function();
569 } catch (\Throwable $ex) {
570 $access->setSuperUserAccess($isSuperUser);
571 if ($shouldResetLogin) {
572 $access->login = null;
573 }
574 throw $ex;
575 }
576 if ($shouldResetLogin) {
577 $access->login = null;
578 }
579 $access->setSuperUserAccess($isSuperUser);
580 return $result;
581 }
582 /**
583 * Returns the level of access the current user has to the given site.
584 *
585 * @param int $idSite The site to check.
586 * @return string The access level, eg, 'view', 'admin', 'noaccess'.
587 */
588 public function getRoleForSite($idSite)
589 {
590 if ($this->hasSuperUserAccess || in_array($idSite, $this->getSitesIdWithAdminAccess())) {
591 return 'admin';
592 }
593 if (in_array($idSite, $this->getSitesIdWithWriteAccess())) {
594 return 'write';
595 }
596 if (in_array($idSite, $this->getSitesIdWithViewAccess())) {
597 return 'view';
598 }
599 return 'noaccess';
600 }
601 /**
602 * Returns the capabilities the current user has for a given site.
603 *
604 * @param int $idSite The site to check.
605 * @return string[] The capabilities the user has.
606 */
607 public function getCapabilitiesForSite($idSite)
608 {
609 $result = [];
610 foreach ($this->capabilityProvider->getAllCapabilityIds() as $capabilityId) {
611 if (empty($this->idsitesByAccess[$capabilityId])) {
612 continue;
613 }
614 if (in_array($idSite, $this->idsitesByAccess[$capabilityId])) {
615 $result[] = $capabilityId;
616 }
617 }
618 return $result;
619 }
620 /**
621 * Throw a NoAccessException with the given message, or a more generic 'You need to log in' message if the
622 * user is not currently logged in (e.g. if session has expired).
623 *
624 * @param $message
625 * @throws NoAccessException
626 */
627 private function throwNoAccessException($message)
628 {
629 if (\Piwik\Piwik::isUserIsAnonymous() && !Request::isRootRequestApiRequest()) {
630 $message = \Piwik\Piwik::translate('General_YouMustBeLoggedIn');
631 // Try to detect whether user was previously logged in so that we can display a different message
632 $referrer = \Piwik\Url::getReferrer();
633 $matomoUrl = \Piwik\SettingsPiwik::getPiwikUrl();
634 if ($referrer && $matomoUrl && \Piwik\Url::isValidHost(\Piwik\Url::getHostFromUrl($referrer)) && strpos($referrer, $matomoUrl) === 0) {
635 $message = \Piwik\Piwik::translate('General_YourSessionHasExpired');
636 }
637 }
638 throw new \Piwik\NoAccessException($message);
639 }
640 /**
641 * Returns true if the current user is logged in or not.
642 *
643 * @return bool
644 */
645 public function isUserLoggedIn()
646 {
647 return !empty($this->login);
648 }
649 }
650