PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.2.1
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.2.1
5.13.0 5.12.1 5.12.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 1 year ago Access 1 year ago Application 1 year ago Archive 1 year ago ArchiveProcessor 1 year ago Archiver 2 years ago AssetManager 1 year ago Auth 1 year ago Category 2 years ago Changes 1 year ago CliMulti 1 year ago Columns 1 year ago Concurrency 1 year ago Config 1 year ago Container 1 year ago CronArchive 1 year ago DataAccess 1 year ago DataFiles 2 years ago DataTable 1 year ago Db 1 year ago DeviceDetector 1 year ago Email 2 years ago Exception 1 year ago Http 1 year ago Intl 1 year ago Log 2 years ago Mail 1 year ago Measurable 1 year ago Menu 1 year ago Metrics 1 year ago Notification 1 year ago Period 1 year ago Plugin 1 year ago ProfessionalServices 1 year ago Report 1 year ago ReportRenderer 1 year ago Scheduler 1 year ago Segment 1 year ago Session 1 year ago Settings 1 year ago Tracker 1 year ago Translation 1 year ago Twig 1 year ago UpdateCheck 1 year ago Updater 1 year ago Updates 1 year ago Validators 1 year ago View 1 year ago ViewDataTable 1 year ago Visualization 1 year ago Widget 1 year ago .htaccess 2 years ago Access.php 1 year ago Archive.php 1 year ago ArchiveProcessor.php 1 year ago AssetManager.php 1 year ago Auth.php 2 years ago AuthResult.php 2 years ago BaseFactory.php 2 years ago Cache.php 2 years ago CacheId.php 1 year ago CliMulti.php 1 year ago Common.php 1 year ago Config.php 1 year ago Console.php 1 year ago Context.php 2 years ago Cookie.php 1 year ago CronArchive.php 1 year ago DI.php 1 year ago DataArray.php 1 year ago DataTable.php 1 year ago Date.php 1 year ago Db.php 1 year ago DbHelper.php 1 year ago Development.php 1 year ago ErrorHandler.php 1 year ago EventDispatcher.php 1 year ago ExceptionHandler.php 1 year ago FileIntegrity.php 1 year ago Filechecks.php 1 year ago Filesystem.php 1 year ago FrontController.php 1 year ago Http.php 1 year ago IP.php 1 year ago Log.php 2 years ago LogDeleter.php 1 year ago Mail.php 1 year ago Metrics.php 1 year ago NoAccessException.php 2 years ago Nonce.php 1 year ago Notification.php 1 year ago NumberFormatter.php 1 year ago Option.php 1 year ago Period.php 1 year ago Piwik.php 1 year ago Plugin.php 1 year ago Process.php 1 year ago Profiler.php 1 year ago ProxyHeaders.php 2 years ago ProxyHttp.php 1 year ago QuickForm2.php 1 year ago RankingQuery.php 1 year ago ReportRenderer.php 1 year ago Request.php 1 year ago Segment.php 1 year ago Sequence.php 2 years ago Session.php 1 year ago SettingsPiwik.php 1 year ago SettingsServer.php 1 year ago Singleton.php 2 years ago Site.php 1 year 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 1 year 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 1 year ago UrlHelper.php 1 year ago Version.php 1 year ago View.php 1 year ago bootstrap.php 1 year 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