/** * @group Core */ public function testFuncionality() { $value = 'newValue'; $key = 'newKey'; Registry::set($key, $value); $this->assertEquals($value, Registry::get($key)); $this->assertTrue(Registry::isRegistered($key)); }
/** * You can create your own Users Plugin to override this class. * Example of how you would overwrite the UsersManager_API with your own class: * Call the following in your plugin __construct() for example: * * Registry::set('UsersManager_API',Piwik_MyCustomUsersManager_API::getInstance()); * * @throws Exception * @return \Piwik\Plugins\UsersManager\API */ public static function getInstance() { try { $instance = \Piwik\Registry::get('UsersManager_API'); if (!$instance instanceof API) { // Exception is caught below and corrected throw new Exception('UsersManager_API must inherit API'); } self::$instance = $instance; } catch (Exception $e) { self::$instance = new self(); \Piwik\Registry::set('UsersManager_API', self::$instance); } return self::$instance; }
/** * Constructor. * * @param PasswordResetter $passwordResetter * @param AuthInterface $auth * @param SessionInitializer $authenticatedSessionFactory \ */ public function __construct($passwordResetter = null, $auth = null, $sessionInitializer = null) { parent::__construct(); if (empty($passwordResetter)) { $passwordResetter = new PasswordResetter(); } $this->passwordResetter = $passwordResetter; if (empty($auth)) { $auth = \Piwik\Registry::get('auth'); } $this->auth = $auth; if (empty($sessionInitializer)) { $sessionInitializer = new SessionInitializer(); } $this->sessionInitializer = $sessionInitializer; }
/** * anonymous = in the session * authenticated user = in the session and in DB */ public function saveLanguage() { $language = Common::getRequestVar('language'); // Prevent CSRF only when piwik is not installed yet (During install user can change language) if (DbHelper::isInstalled()) { $this->checkTokenInUrl(); } LanguagesManager::setLanguageForSession($language); if (\Piwik\Registry::isRegistered('access')) { $currentUser = Piwik::getCurrentUserLogin(); if ($currentUser && $currentUser !== 'anonymous') { API::getInstance()->setLanguageForUser($currentUser, $language); } } Url::redirectToReferrer(); }
/** * Initializes the authentication object. * Listens to Request.initAuthenticationObject hook. */ function initAuthenticationObject($allowCookieAuthentication = false) { $auth = new Auth(); \Piwik\Registry::set('auth', $auth); $action = Piwik::getAction(); if (Piwik::getModule() === 'API' && (empty($action) || $action == 'index') && $allowCookieAuthentication !== true) { return; } $authCookieName = Config::getInstance()->General['login_cookie_name']; $authCookieExpiry = 0; $authCookiePath = Config::getInstance()->General['login_cookie_path']; $authCookie = new Cookie($authCookieName, $authCookieExpiry, $authCookiePath); $defaultLogin = '******'; $defaultTokenAuth = 'anonymous'; if ($authCookie->isCookieFound()) { $defaultLogin = $authCookie->get('login'); $defaultTokenAuth = $authCookie->get('token_auth'); } $auth->setLogin($defaultLogin); $auth->setTokenAuth($defaultTokenAuth); }
/** * Must be called before dispatch() * - checks that directories are writable, * - loads the configuration file, * - loads the plugin, * - inits the DB connection, * - etc. * * @throws Exception * @return void */ public function init() { static $initialized = false; if ($initialized) { return; } $initialized = true; try { Registry::set('timer', new Timer()); $directoriesToCheck = array('/tmp/', '/tmp/assets/', '/tmp/cache/', '/tmp/logs/', '/tmp/tcpdf/', '/tmp/templates_c/'); Filechecks::dieIfDirectoriesNotWritable($directoriesToCheck); Translate::loadEnglishTranslation(); $exceptionToThrow = self::createConfigObject(); $this->handleMaintenanceMode(); $this->handleProfiler(); $this->handleSSLRedirection(); Plugin\Manager::getInstance()->loadPluginTranslations('en'); Plugin\Manager::getInstance()->loadActivatedPlugins(); if ($exceptionToThrow) { throw $exceptionToThrow; } // try to connect to the database try { Db::createDatabaseObject(); Db::fetchAll("SELECT DATABASE()"); } catch (Exception $exception) { if (self::shouldRethrowException()) { throw $exception; } Log::debug($exception); /** * Triggered when Piwik cannot connect to the database. * * This event can be used to start the installation process or to display a custom error * message. * * @param Exception $exception The exception thrown from creating and testing the database * connection. */ Piwik::postEvent('Db.cannotConnectToDb', array($exception), $pending = true); throw $exception; } // try to get an option (to check if data can be queried) try { Option::get('TestingIfDatabaseConnectionWorked'); } catch (Exception $exception) { if (self::shouldRethrowException()) { throw $exception; } Log::debug($exception); /** * Triggered when Piwik cannot access database data. * * This event can be used to start the installation process or to display a custom error * message. * * @param Exception $exception The exception thrown from trying to get an option value. */ Piwik::postEvent('Config.badConfigurationFile', array($exception), $pending = true); throw $exception; } // Init the Access object, so that eg. core/Updates/* can enforce Super User and use some APIs Access::getInstance(); /** * Triggered just after the platform is initialized and plugins are loaded. * * This event can be used to do early initialization. * * _Note: At this point the user is not authenticated yet._ */ Piwik::postEvent('Request.dispatchCoreAndPluginUpdatesScreen'); \Piwik\Plugin\Manager::getInstance()->installLoadedPlugins(); // ensure the current Piwik URL is known for later use if (method_exists('Piwik\\SettingsPiwik', 'getPiwikUrl')) { SettingsPiwik::getPiwikUrl(); } /** * Triggered before the user is authenticated, when the global authentication object * should be created. * * Plugins that provide their own authentication implementation should use this event * to set the global authentication object (which must derive from {@link Piwik\Auth}). * * **Example** * * Piwik::addAction('Request.initAuthenticationObject', function() { * Piwik\Registry::set('auth', new MyAuthImplementation()); * }); */ Piwik::postEvent('Request.initAuthenticationObject'); try { $authAdapter = Registry::get('auth'); } catch (Exception $e) { throw new Exception("Authentication object cannot be found in the Registry. Maybe the Login plugin is not activated?\n <br />You can activate the plugin by adding:<br />\n <code>Plugins[] = Login</code><br />\n under the <code>[Plugins]</code> section in your config/config.ini.php"); } Access::getInstance()->reloadAccess($authAdapter); // Force the auth to use the token_auth if specified, so that embed dashboard // and all other non widgetized controller methods works fine if (Common::getRequestVar('token_auth', false, 'string') !== false) { Request::reloadAuthUsingTokenAuth(); } SettingsServer::raiseMemoryLimitIfNecessary(); Translate::reloadLanguage(); \Piwik\Plugin\Manager::getInstance()->postLoadPlugins(); /** * Triggered after the platform is initialized and after the user has been authenticated, but * before the platform has handled the request. * * Piwik uses this event to check for updates to Piwik. */ Piwik::postEvent('Platform.initialized'); } catch (Exception $e) { if (self::shouldRethrowException()) { throw $e; } $debugTrace = $e->getTraceAsString(); Piwik_ExitWithMessage($e->getMessage(), $debugTrace, true); } }
/** * Authenticate user and password. Redirect if successful. * * @param string $login user name * @param string $md5Password md5 hash of password * @param bool $rememberMe Remember me? * @param string $urlToRedirect URL to redirect to, if successfully authenticated * @return string failure message if unable to authenticate */ protected function authenticateAndRedirect($login, $md5Password, $rememberMe, $urlToRedirect = false) { Nonce::discardNonce('Login.login'); \Piwik\Registry::get('auth')->initSession($login, $md5Password, $rememberMe); if (empty($urlToRedirect)) { $urlToRedirect = Url::getCurrentUrlWithoutQueryString(); } Url::redirectToUrl($urlToRedirect); }
public static function authenticateSuperUserOrAdmin($tokenAuth, $idSite) { if (empty($tokenAuth)) { return false; } Piwik::postEvent('Request.initAuthenticationObject'); /** @var \Piwik\Auth $auth */ $auth = Registry::get('auth'); $auth->setTokenAuth($tokenAuth); $auth->setLogin(null); $access = $auth->authenticate(); if (!empty($access) && $access->hasSuperUserAccess()) { return true; } // Now checking the list of admin token_auth cached in the Tracker config file if (!empty($idSite) && $idSite > 0) { $website = Cache::getCacheWebsiteAttributes($idSite); if (array_key_exists('admin_token_auth', $website) && in_array($tokenAuth, $website['admin_token_auth'])) { return true; } } Common::printDebug("WARNING! token_auth = {$tokenAuth} is not valid, Super User / Admin was NOT authenticated"); return false; }
private function processPasswordChange($userLogin) { $alias = Common::getRequestVar('alias'); $email = Common::getRequestVar('email'); $newPassword = false; $password = Common::getRequestvar('password', false); $passwordBis = Common::getRequestvar('passwordBis', false); if (!empty($password) || !empty($passwordBis)) { if ($password != $passwordBis) { throw new Exception(Piwik::translate('Login_PasswordsDoNotMatch')); } $newPassword = $password; } // UI disables password change on invalid host, but check here anyway if (!Url::isValidHost() && $newPassword !== false) { throw new Exception("Cannot change password with untrusted hostname!"); } if (Piwik::isUserIsSuperUser()) { $superUser = Config::getInstance()->superuser; $updatedSuperUser = false; if ($newPassword !== false) { $newPassword = Common::unsanitizeInputValue($newPassword); $md5PasswordSuperUser = md5($newPassword); $superUser['password'] = $md5PasswordSuperUser; $updatedSuperUser = true; } if ($superUser['email'] != $email) { $superUser['email'] = $email; $updatedSuperUser = true; } if ($updatedSuperUser) { Config::getInstance()->superuser = $superUser; Config::getInstance()->forceSave(); } } else { APIUsersManager::getInstance()->updateUser($userLogin, $newPassword, $email, $alias); if ($newPassword !== false) { $newPassword = Common::unsanitizeInputValue($newPassword); } } // logs the user in with the new password if ($newPassword !== false) { \Piwik\Registry::get('auth')->initSession($userLogin, md5($newPassword), $rememberMe = false); } }
private function processPasswordChange($userLogin) { $alias = Common::getRequestVar('alias'); $email = Common::getRequestVar('email'); $newPassword = false; $password = Common::getRequestvar('password', false); $passwordBis = Common::getRequestvar('passwordBis', false); if (!empty($password) || !empty($passwordBis)) { if ($password != $passwordBis) { throw new Exception(Piwik::translate('Login_PasswordsDoNotMatch')); } $newPassword = $password; } // UI disables password change on invalid host, but check here anyway if (!Url::isValidHost() && $newPassword !== false) { throw new Exception("Cannot change password with untrusted hostname!"); } APIUsersManager::getInstance()->updateUser($userLogin, $newPassword, $email, $alias); if ($newPassword !== false) { $newPassword = Common::unsanitizeInputValue($newPassword); } // logs the user in with the new password if ($newPassword !== false) { $sessionInitializer = new SessionInitializer(); $auth = \Piwik\Registry::get('auth'); $auth->setLogin($userLogin); $auth->setPassword($password); $sessionInitializer->initSession($auth, $rememberMe = false); } }
/** * Initializes the authentication object. * Listens to Request.initAuthenticationObject hook. */ function initAuthenticationObject($activateCookieAuth = false) { $auth = new Auth(); \Piwik\Registry::set('auth', $auth); $this->initAuthenticationFromCookie($auth, $activateCookieAuth); }
/** * Authenticate user and password. Redirect if successful. * * @param string $login user name * @param string $md5Password md5 hash of password * @param bool $rememberMe Remember me? * @param string $urlToRedirect URL to redirect to, if successfully authenticated * @return string failure message if unable to authenticate */ protected function authenticateAndRedirect($login, $md5Password, $rememberMe, $urlToRedirect = 'index.php') { Nonce::discardNonce('Login.login'); \Piwik\Registry::get('auth')->initSession($login, $md5Password, $rememberMe); Url::redirectToUrl($urlToRedirect); }
/** Do cookie authentication. This way, the token can remain secret. */ private function authenticate($idSite) { /** * Triggered immediately before the user is authenticated. * * This event can be used by plugins that provide their own authentication mechanism * to make that mechanism available. Subscribers should set the `'auth'` object in * the {@link Piwik\Registry} to an object that implements the {@link Piwik\Auth} interface. * * **Example** * * use Piwik\Registry; * * public function initAuthenticationObject($allowCookieAuthentication) * { * Registry::set('auth', new LDAPAuth($allowCookieAuthentication)); * } * * @param bool $allowCookieAuthentication Whether authentication based on `$_COOKIE` values should * be allowed. */ Piwik::postEvent('Request.initAuthenticationObject', array($allowCookieAuthentication = true)); $auth = \Piwik\Registry::get('auth'); $success = Access::getInstance()->reloadAccess($auth); if (!$success) { throw new Exception('Authentication failed'); } Piwik::checkUserHasViewAccess($idSite); }
public function ApiRequestAuthenticate($tokenAuth) { \Piwik\Registry::get('auth')->setLogin($login = null); \Piwik\Registry::get('auth')->setTokenAuth($tokenAuth); }
/** * Renders the current view. Also sends the stored 'Content-Type' HTML header. * See {@link setContentType()}. * * @return string Generated template. */ public function render() { try { $this->currentModule = Piwik::getModule(); $this->currentAction = Piwik::getAction(); $userLogin = Piwik::getCurrentUserLogin(); $this->userLogin = $userLogin; $count = SettingsPiwik::getWebsitesCountToDisplay(); $sites = APISitesManager::getInstance()->getSitesWithAtLeastViewAccess($count); usort($sites, function ($site1, $site2) { return strcasecmp($site1["name"], $site2["name"]); }); $this->sites = $sites; $this->url = Common::sanitizeInputValue(Url::getCurrentUrl()); $this->token_auth = Piwik::getCurrentUserTokenAuth(); $this->userHasSomeAdminAccess = Piwik::isUserHasSomeAdminAccess(); $this->userIsSuperUser = Piwik::isUserIsSuperUser(); $this->latest_version_available = UpdateCheck::isNewestVersionAvailable(); $this->disableLink = Common::getRequestVar('disableLink', 0, 'int'); $this->isWidget = Common::getRequestVar('widget', 0, 'int'); if (Config::getInstance()->General['autocomplete_min_sites'] <= count($sites)) { $this->show_autocompleter = true; } else { $this->show_autocompleter = false; } $this->loginModule = Piwik::getLoginPluginName(); $user = APIUsersManager::getInstance()->getUser($userLogin); $this->userAlias = $user['alias']; } catch (Exception $e) { // can fail, for example at installation (no plugin loaded yet) } try { $this->totalTimeGeneration = Registry::get('timer')->getTime(); $this->totalNumberOfQueries = Profiler::getQueryCount(); } catch (Exception $e) { $this->totalNumberOfQueries = 0; } ProxyHttp::overrideCacheControlHeaders('no-store'); @header('Content-Type: ' . $this->contentType); // always sending this header, sometimes empty, to ensure that Dashboard embed loads (which could call this header() multiple times, the last one will prevail) @header('X-Frame-Options: ' . (string) $this->xFrameOptions); return $this->renderTwigTemplate(); }
/** * Renders the current view. Also sends the stored 'Content-Type' HTML header. * See {@link setContentType()}. * * @return string Generated template. */ public function render() { try { $this->currentModule = Piwik::getModule(); $this->currentAction = Piwik::getAction(); $this->url = Common::sanitizeInputValue(Url::getCurrentUrl()); $this->token_auth = Piwik::getCurrentUserTokenAuth(); $this->userHasSomeAdminAccess = Piwik::isUserHasSomeAdminAccess(); $this->userIsSuperUser = Piwik::hasUserSuperUserAccess(); $this->latest_version_available = UpdateCheck::isNewestVersionAvailable(); $this->disableLink = Common::getRequestVar('disableLink', 0, 'int'); $this->isWidget = Common::getRequestVar('widget', 0, 'int'); $this->cacheBuster = UIAssetCacheBuster::getInstance()->piwikVersionBasedCacheBuster(); $this->loginModule = Piwik::getLoginPluginName(); $user = APIUsersManager::getInstance()->getUser($this->userLogin); $this->userAlias = $user['alias']; } catch (Exception $e) { // can fail, for example at installation (no plugin loaded yet) } try { $this->totalTimeGeneration = Registry::get('timer')->getTime(); $this->totalNumberOfQueries = Profiler::getQueryCount(); } catch (Exception $e) { $this->totalNumberOfQueries = 0; } ProxyHttp::overrideCacheControlHeaders('no-store'); @header('Content-Type: ' . $this->contentType); // always sending this header, sometimes empty, to ensure that Dashboard embed loads (which could call this header() multiple times, the last one will prevail) @header('X-Frame-Options: ' . (string) $this->xFrameOptions); return $this->renderTwigTemplate(); }
/** * Helper method used to redirect the current HTTP request to another module/action. * * This function will exit immediately after executing. * * @param string $moduleToRedirect The plugin to redirect to, eg. `"MultiSites"`. * @param string $actionToRedirect Action, eg. `"index"`. * @param int|null $websiteId The new idSite query parameter, eg, `1`. * @param string|null $defaultPeriod The new period query parameter, eg, `'day'`. * @param string|null $defaultDate The new date query parameter, eg, `'today'`. * @param array $parameters Other query parameters to append to the URL. * @api */ public function redirectToIndex($moduleToRedirect, $actionToRedirect, $websiteId = null, $defaultPeriod = null, $defaultDate = null, $parameters = array()) { try { $this->doRedirectToUrl($moduleToRedirect, $actionToRedirect, $websiteId, $defaultPeriod, $defaultDate, $parameters); } catch (Exception $e) { // no website ID to default to, so could not redirect } if (Piwik::hasUserSuperUserAccess()) { Piwik_ExitWithMessage("Error: no website was found in this Piwik installation.\n\t\t\t<br />Check the table '" . Common::prefixTable('site') . "' in your database, it should contain your Piwik websites.", false, true); } if (!Piwik::isUserIsAnonymous()) { $emails = implode(',', Piwik::getAllSuperUserAccessEmailAddresses()); $errorMessage = sprintf(Piwik::translate('CoreHome_NoPrivilegesAskPiwikAdmin'), $currentLogin, "<br/><a href='mailto:" . $emails . "?subject=Access to Piwik for user {$currentLogin}'>", "</a>"); $errorMessage .= "<br /><br /> <b><a href='index.php?module=" . Registry::get('auth')->getName() . "&action=logout'>› " . Piwik::translate('General_Logout') . "</a></b><br />"; Piwik_ExitWithMessage($errorMessage, false, true); } echo FrontController::getInstance()->dispatch(Piwik::getLoginPluginName(), false); exit; }
/** * Returns the name of the Login plugin currently being used. * Must be used since it is not allowed to hardcode 'Login' in URLs * in case another Login plugin is being used. * * @return string */ public static function getLoginPluginName() { return Registry::get('auth')->getName(); }
public function performTearDown() { // Note: avoid run SQL in the *tearDown() metohds because it randomly fails on Travis CI // with error Error while sending QUERY packet. PID=XX $this->tearDown(); self::unloadAllPlugins(); if ($this->dropDatabaseInTearDown) { $this->dropDatabase(); } DataTableManager::getInstance()->deleteAll(); Option::clearCache(); Site::clearCache(); Cache::deleteTrackerCache(); Config::getInstance()->clear(); ArchiveTableCreator::clear(); \Piwik\Plugins\ScheduledReports\API::$cache = array(); \Piwik\Registry::unsetInstance(); \Piwik\EventDispatcher::getInstance()->clearAllObservers(); $_GET = $_REQUEST = array(); Translate::unloadEnglishTranslation(); Config::unsetInstance(); \Piwik\Config::getInstance()->Plugins; // make sure Plugins exists in a config object for next tests that use Plugin\Manager // since Plugin\Manager uses getFromGlobalConfig which doesn't init the config object }
public function clearInMemoryCaches() { DataTableManager::getInstance()->deleteAll(); Option::clearCache(); Site::clearCache(); Cache::deleteTrackerCache(); Config::getInstance()->clear(); ArchiveTableCreator::clear(); \Piwik\Plugins\ScheduledReports\API::$cache = array(); \Piwik\Registry::unsetInstance(); \Piwik\EventDispatcher::getInstance()->clearAllObservers(); $_GET = $_REQUEST = array(); Translate::unloadEnglishTranslation(); Config::unsetInstance(); \Piwik\Config::getInstance()->Plugins; // make sure Plugins exists in a config object for next tests that use Plugin\Manager // since Plugin\Manager uses getFromGlobalConfig which doesn't init the config object }
/** * Helper method used to redirect the current HTTP request to another module/action. * * This function will exit immediately after executing. * * @param string $moduleToRedirect The plugin to redirect to, eg. `"MultiSites"`. * @param string $actionToRedirect Action, eg. `"index"`. * @param int|null $websiteId The new idSite query parameter, eg, `1`. * @param string|null $defaultPeriod The new period query parameter, eg, `'day'`. * @param string|null $defaultDate The new date query parameter, eg, `'today'`. * @param array $parameters Other query parameters to append to the URL. * @api */ public function redirectToIndex($moduleToRedirect, $actionToRedirect, $websiteId = null, $defaultPeriod = null, $defaultDate = null, $parameters = array()) { $userPreferences = new UserPreferences(); if (empty($websiteId)) { $websiteId = $userPreferences->getDefaultWebsiteId(); } if (empty($defaultDate)) { $defaultDate = $userPreferences->getDefaultDate(); } if (empty($defaultPeriod)) { $defaultPeriod = $userPreferences->getDefaultPeriod(); } $parametersString = ''; if (!empty($parameters)) { $parametersString = '&' . Url::getQueryStringFromParameters($parameters); } if ($websiteId) { $url = "index.php?module=" . $moduleToRedirect . "&action=" . $actionToRedirect . "&idSite=" . $websiteId . "&period=" . $defaultPeriod . "&date=" . $defaultDate . $parametersString; Url::redirectToUrl($url); exit; } if (Piwik::hasUserSuperUserAccess()) { Piwik_ExitWithMessage("Error: no website was found in this Piwik installation.\n\t\t\t<br />Check the table '" . Common::prefixTable('site') . "' in your database, it should contain your Piwik websites.", false, true); } $currentLogin = Piwik::getCurrentUserLogin(); if (!empty($currentLogin) && $currentLogin != 'anonymous') { $emails = implode(',', Piwik::getAllSuperUserAccessEmailAddresses()); $errorMessage = sprintf(Piwik::translate('CoreHome_NoPrivilegesAskPiwikAdmin'), $currentLogin, "<br/><a href='mailto:" . $emails . "?subject=Access to Piwik for user {$currentLogin}'>", "</a>"); $errorMessage .= "<br /><br /> <b><a href='index.php?module=" . Registry::get('auth')->getName() . "&action=logout'>› " . Piwik::translate('General_Logout') . "</a></b><br />"; Piwik_ExitWithMessage($errorMessage, false, true); } echo FrontController::getInstance()->dispatch(Piwik::getLoginPluginName(), false); exit; }
/** * Initializes the authentication object. * Listens to Request.initAuthenticationObject hook. */ public function initAuthenticationObject($activateCookieAuth = false) { $auth = new LoginShibbolethAuth(); \Piwik\Registry::set('auth', $auth); Login::initAuthenticationFromCookie($auth, $activateCookieAuth); }