protected function execute(InputInterface $input, OutputInterface $output) { $this->recreateContainerWithWebEnvironment(); $this->initHostAndQueryString($input); if ($this->isTestModeEnabled()) { $indexFile = '/tests/PHPUnit/proxy/'; $this->resetDatabase(); } else { $indexFile = '/'; } $indexFile .= 'index.php'; if (!empty($_GET['pid'])) { $process = new Process($_GET['pid']); if ($process->hasFinished()) { return; } $process->startProcess(); } if ($input->getOption('superuser')) { StaticContainer::addDefinitions(array('observers.global' => \DI\add(array(array('Environment.bootstrapped', function () { Access::getInstance()->setSuperUserAccess(true); }))))); } require_once PIWIK_INCLUDE_PATH . $indexFile; if (!empty($process)) { $process->finishProcess(); } }
private function makeSureTestRunsInContextOfAnonymousUser() { Piwik::postEvent('Request.initAuthenticationObject'); $access = Access::getInstance(); $this->hasSuperUserAccess = $access->hasSuperUserAccess(); $access->setSuperUserAccess(false); $access->reloadAccess(StaticContainer::get('Piwik\\Auth')); Request::reloadAuthUsingTokenAuth(array('token_auth' => 'anonymous')); }
public function setUp() { parent::setUp(); $access = Access::getInstance(); $access->setSuperUserAccess(true); $this->idSiteAccess = APISitesManager::getInstance()->addSite("test", "http://test"); \Piwik\Plugin\Manager::getInstance()->loadPlugins(array('MultiSites', 'VisitsSummary', 'Actions')); \Piwik\Plugin\Manager::getInstance()->installLoadedPlugins(); }
public function test_PiwikUserIsNotCreated_IfPiwikUserAlreadyExists() { Access::getInstance()->setSuperUserAccess(true); UsersManagerAPI::getInstance()->addUser(self::TEST_LOGIN, self::TEST_PASS, '*****@*****.**', $alias = false); Access::getInstance()->setSuperUserAccess(false); $this->authenticateViaLdap(); $user = Db::fetchRow("SELECT login, password, alias, email, token_auth FROM " . Common::prefixTable('user') . " WHERE login = ?", array(self::TEST_LOGIN)); $this->assertNotEmpty($user); $this->assertEquals(array('login' => self::TEST_LOGIN, 'password' => md5(self::TEST_PASS), 'alias' => self::TEST_LOGIN, 'email' => '*****@*****.**', 'token_auth' => UsersManagerAPI::getInstance()->getTokenAuth(self::TEST_LOGIN, md5(self::TEST_PASS))), $user); $this->assertNoAccessInDb(); }
/** * NOTE: This test must be last since the new sites that get added are added in * random order. */ public function testDynamicResolverSitesCreated() { self::$fixture->logVisitsWithDynamicResolver(); // reload access so new sites are viewable Access::getInstance()->setSuperUserAccess(true); // make sure sites aren't created twice $piwikDotNet = API::getInstance()->getSitesIdFromSiteUrl('http://piwik.net'); $this->assertEquals(1, count($piwikDotNet)); $anothersiteDotCom = API::getInstance()->getSitesIdFromSiteUrl('http://anothersite.com'); $this->assertEquals(1, count($anothersiteDotCom)); $whateverDotCom = API::getInstance()->getSitesIdFromSiteUrl('http://whatever.com'); $this->assertEquals(1, count($whateverDotCom)); }
public function setUp() { // drop all tables Db::dropAllTables(); // download data dump if url supplied if (is_file($this->dumpUrl)) { $dumpPath = $this->dumpUrl; } else { $dumpPath = PIWIK_INCLUDE_PATH . '/tmp/logdump.sql.gz'; $bufferSize = 1024 * 1024; $dump = fopen($this->dumpUrl, 'rb'); $outfile = fopen($dumpPath, 'wb'); $bytesRead = 0; while (!feof($dump)) { fwrite($outfile, fread($dump, $bufferSize), $bufferSize); $bytesRead += $bufferSize; } fclose($dump); fclose($outfile); if ($bytesRead <= 40 * 1024 * 1024) { // sanity check throw new Exception("Could not download sql dump!"); } } // unzip the dump if (substr($dumpPath, -3) === ".gz") { $deflatedDumpPath = PIWIK_INCLUDE_PATH . '/tmp/logdump.sql'; // TODO: should depend on name of URL exec("gunzip -c \"" . $dumpPath . "\" > \"{$deflatedDumpPath}\"", $output, $return); if ($return !== 0) { throw new Exception("gunzip failed: " . implode("\n", $output)); } } else { $deflatedDumpPath = $dumpPath; } // load the data into the correct database $user = Config::getInstance()->database['username']; $password = Config::getInstance()->database['password']; Config::getInstance()->database['tables_prefix'] = $this->tablesPrefix; $cmd = "mysql -u \"{$user}\" \"--password={$password}\" {$this->dbName} < \"" . $deflatedDumpPath . "\" 2>&1"; exec($cmd, $output, $return); if ($return !== 0) { throw new Exception("Failed to load sql dump: " . implode("\n", $output)); } // make sure archiving will be called Rules::setBrowserTriggerArchiving(true); // reload access Access::getInstance()->reloadAccess(); $this->getTestEnvironment()->configOverride = array('database' => array('tables_prefix' => $this->tablesPrefix)); $this->getTestEnvironment()->save(); }
public function setUserDefaultReportPreference() { // We initialize the default report user preference for each user (if it hasn't been inited before) for performance, // doing this lets us avoid loading all siteIds (which can be 50k or more) when this preference is requested. // getting the user preference can be called quite often when generating links etc (to get defaultWebsiteId). $usersModel = $this->usersModel; $usersManagerApi = $this->usersManagerApi; Access::getInstance()->doAsSuperUser(function () use($usersModel, $usersManagerApi) { $allUsers = $usersModel->getUsers(array()); foreach ($allUsers as $user) { $usersManagerApi->initUserPreferenceWithDefault($user['login'], API::PREFERENCE_DEFAULT_REPORT); } }); }
/** * Setup the database and create the base tables for all tests */ public function setUp() { parent::setUp(); static::$fixture->extraDefinitions = array_merge(static::provideContainerConfigBeforeClass(), $this->provideContainerConfig()); static::$fixture->createEnvironmentInstance(); Db::createDatabaseObject(); Fixture::loadAllPlugins(new TestingEnvironmentVariables(), get_class($this), self::$fixture->extraPluginsToLoad); Access::getInstance()->setSuperUserAccess(true); if (!empty(self::$tableData)) { self::restoreDbTables(self::$tableData); } PiwikCache::getEagerCache()->flushAll(); PiwikCache::getTransientCache()->flushAll(); MenuAbstract::clearMenus(); }
/** * NOTE: This test must be last since the new sites that get added are added in * random order. * NOTE: This test combines two tests in order to avoid executing the log importer another time. * If the log importer were refactored, the invalid requests test could be a unit test in * python. */ public function test_LogImporter_CreatesSitesWhenDynamicResolverUsed_AndReportsOnInvalidRequests() { $this->simulateInvalidTrackerRequest(); $output = self::$fixture->logVisitsWithDynamicResolver($maxPayloadSize = 3); // reload access so new sites are viewable Access::getInstance()->setSuperUserAccess(true); // make sure sites aren't created twice $piwikDotNet = API::getInstance()->getSitesIdFromSiteUrl('http://piwik.net'); $this->assertEquals(1, count($piwikDotNet)); $anothersiteDotCom = API::getInstance()->getSitesIdFromSiteUrl('http://anothersite.com'); $this->assertEquals(1, count($anothersiteDotCom)); $whateverDotCom = API::getInstance()->getSitesIdFromSiteUrl('http://whatever.com'); $this->assertEquals(1, count($whateverDotCom)); // make sure invalid requests are reported correctly $this->assertContains('The Piwik tracker identified 2 invalid requests on lines: 10, 11', $output); $this->assertContains("The following lines were not tracked by Piwik, either due to a malformed tracker request or error in the tracker:\n\n10, 11", $output); }
public function setUp() { // drop all tables Db::dropAllTables(); // download data dump if url supplied if (is_file($this->dumpUrl)) { $dumpPath = $this->dumpUrl; } else { $dumpPath = PIWIK_INCLUDE_PATH . '/tmp/logdump.sql.gz'; $bytesRead = $this->downloadDumpInPath($dumpPath); // sanity check if ($bytesRead <= 40 * 1024 * 1024) { $str = "Could not download sql dump! You can manually download %s into %s"; throw new Exception(sprintf($str, $this->dumpUrl, $dumpPath)); } } // unzip the dump if (substr($dumpPath, -3) === ".gz") { $deflatedDumpPath = PIWIK_INCLUDE_PATH . '/tmp/logdump.sql'; // TODO: should depend on name of URL exec("gunzip -c \"" . $dumpPath . "\" > \"{$deflatedDumpPath}\"", $output, $return); if ($return !== 0) { throw new Exception("gunzip failed: " . implode("\n", $output)); } } else { $deflatedDumpPath = $dumpPath; } // load the data into the correct database $user = Config::getInstance()->database['username']; $password = Config::getInstance()->database['password']; $host = Config::getInstance()->database['host']; Config::getInstance()->database['tables_prefix'] = $this->tablesPrefix; $cmd = "mysql -h \"{$host}\" -u \"{$user}\" \"--password={$password}\" {$this->dbName} < \"" . $deflatedDumpPath . "\" 2>&1"; exec($cmd, $output, $return); if ($return !== 0) { throw new Exception("Failed to load sql dump: " . implode("\n", $output)); } // make sure archiving will be called Rules::setBrowserTriggerArchiving(true); // reload access Access::getInstance()->reloadAccess(); $testVars = new TestingEnvironmentVariables(); $testVars->configOverride = array('database' => array('tables_prefix' => $this->tablesPrefix)); $testVars->save(); }
public static function updateComponents(Updater $updater, $componentsWithUpdateFile) { $warnings = array(); $errors = array(); $deactivatedPlugins = array(); $coreError = false; if (!empty($componentsWithUpdateFile)) { $currentAccess = Access::getInstance(); $hasSuperUserAccess = $currentAccess->hasSuperUserAccess(); if (!$hasSuperUserAccess) { $currentAccess->setSuperUserAccess(true); } // if error in any core update, show message + help message + EXIT // if errors in any plugins updates, show them on screen, disable plugins that errored + CONTINUE // if warning in any core update or in any plugins update, show message + CONTINUE // if no error or warning, success message + CONTINUE foreach ($componentsWithUpdateFile as $name => $filenames) { try { $warnings = array_merge($warnings, $updater->update($name)); } catch (UpdaterErrorException $e) { $errors[] = $e->getMessage(); if ($name == 'core') { $coreError = true; break; } elseif (\Piwik\Plugin\Manager::getInstance()->isPluginActivated($name)) { \Piwik\Plugin\Manager::getInstance()->deactivatePlugin($name); $deactivatedPlugins[] = $name; } } } if (!$hasSuperUserAccess) { $currentAccess->setSuperUserAccess(false); } } Filesystem::deleteAllCacheOnUpdate(); $result = array('warnings' => $warnings, 'errors' => $errors, 'coreError' => $coreError, 'deactivatedPlugins' => $deactivatedPlugins); /** * Triggered after Piwik has been updated. */ Piwik::postEvent('CoreUpdater.update.end'); return $result; }
public function performSetUp($setupEnvironmentOnly = false) { // TODO: don't use static var, use test env var for this TestingEnvironmentManipulator::$extraPluginsToLoad = $this->extraPluginsToLoad; $this->dbName = $this->getDbName(); if ($this->persistFixtureData) { $this->dropDatabaseInSetUp = false; $this->dropDatabaseInTearDown = false; $this->overwriteExisting = false; $this->removeExistingSuperUser = false; } $testEnv = $this->getTestEnvironment(); $testEnv->testCaseClass = $this->testCaseClass; $testEnv->fixtureClass = get_class($this); $testEnv->dbName = $this->dbName; $testEnv->extraDiEnvironments = $this->extraDiEnvironments; foreach ($this->extraTestEnvVars as $name => $value) { $testEnv->{$name} = $value; } $testEnv->save(); $this->createEnvironmentInstance(); if ($this->dbName === false) { // must be after test config is created $this->dbName = self::getConfig()->database['dbname']; } try { static::connectWithoutDatabase(); if ($this->dropDatabaseInSetUp || $this->resetPersistedFixture) { $this->dropDatabase(); } DbHelper::createDatabase($this->dbName); DbHelper::disconnectDatabase(); Tracker::disconnectCachedDbConnection(); // reconnect once we're sure the database exists self::getConfig()->database['dbname'] = $this->dbName; Db::createDatabaseObject(); Db::get()->query("SET wait_timeout=28800;"); DbHelper::createTables(); self::getPluginManager()->unloadPlugins(); } catch (Exception $e) { static::fail("TEST INITIALIZATION FAILED: " . $e->getMessage() . "\n" . $e->getTraceAsString()); } include "DataFiles/Providers.php"; if (!$this->isFixtureSetUp()) { DbHelper::truncateAllTables(); } // We need to be SU to create websites for tests Access::getInstance()->setSuperUserAccess(); Cache::deleteTrackerCache(); self::resetPluginsInstalledConfig(); $testEnvironment = $this->getTestEnvironment(); static::loadAllPlugins($testEnvironment, $this->testCaseClass, $this->extraPluginsToLoad); self::updateDatabase(); self::installAndActivatePlugins($testEnvironment); $_GET = $_REQUEST = array(); $_SERVER['HTTP_REFERER'] = ''; FakeAccess::$superUserLogin = '******'; File::$invalidateOpCacheBeforeRead = true; if ($this->configureComponents) { IPAnonymizer::deactivate(); $dntChecker = new DoNotTrackHeaderChecker(); $dntChecker->deactivate(); } if ($this->createSuperUser) { self::createSuperUser($this->removeExistingSuperUser); if (!Access::getInstance() instanceof FakeAccess) { $this->loginAsSuperUser(); } APILanguageManager::getInstance()->setLanguageForUser('superUserLogin', 'en'); } SettingsPiwik::overwritePiwikUrl(self::getTestRootUrl()); if ($setupEnvironmentOnly) { return; } PiwikCache::getTransientCache()->flushAll(); if ($this->overwriteExisting || !$this->isFixtureSetUp()) { $this->setUp(); $this->markFixtureSetUp(); $this->log("Database {$this->dbName} marked as successfully set up."); } else { $this->log("Using existing database {$this->dbName}."); } }
public function test_reloadAccess_DoesNotRemoveSuperUserAccess_IfUsedInDoAsSuperUser() { Access::getInstance()->setSuperUserAccess(false); Access::doAsSuperUser(function () { $access = Access::getInstance(); Core_AccessTest::assertTrue($access->hasSuperUserAccess()); $access->reloadAccess(); Core_AccessTest::assertTrue($access->hasSuperUserAccess()); }); }
/** * @return array|bool */ protected function updateComponents() { Access::getInstance(); return Access::doAsSuperUser(function () { $updater = new Updater(); $componentsWithUpdateFile = $updater->getComponentUpdates(); if (empty($componentsWithUpdateFile)) { return false; } $result = $updater->updateComponents($componentsWithUpdateFile); return $result; }); }
/** * @group Plugins */ public function testGetSitesIdFromSiteUrlUser() { $idsite = API::getInstance()->addSite("site1", array("http://www.piwik.net", "http://piwik.com")); $idsite = API::getInstance()->addSite("site2", array("http://piwik.com", "http://piwik.net")); $idsite = API::getInstance()->addSite("site3", array("http://piwik.com", "http://piwik.org")); $saveAccess = Access::getInstance(); APIUsersManager::getInstance()->addUser("user1", "geqgegagae", "*****@*****.**", "alias"); APIUsersManager::getInstance()->setUserAccess("user1", "view", array(1)); APIUsersManager::getInstance()->addUser("user2", "geqgegagae", "*****@*****.**", "alias"); APIUsersManager::getInstance()->setUserAccess("user2", "view", array(1)); APIUsersManager::getInstance()->setUserAccess("user2", "admin", array(3)); APIUsersManager::getInstance()->addUser("user3", "geqgegagae", "*****@*****.**", "alias"); APIUsersManager::getInstance()->setUserAccess("user3", "view", array(1, 2)); APIUsersManager::getInstance()->setUserAccess("user3", "admin", array(3)); $pseudoMockAccess = new FakeAccess(); FakeAccess::$superUser = false; FakeAccess::$identity = 'user1'; FakeAccess::setIdSitesView(array(1)); FakeAccess::setIdSitesAdmin(array()); Access::setSingletonInstance($pseudoMockAccess); $idsites = API::getInstance()->getSitesIdFromSiteUrl('http://piwik.com'); $this->assertEquals(1, count($idsites)); // testing URL normalization $idsites = API::getInstance()->getSitesIdFromSiteUrl('http://www.piwik.com'); $this->assertEquals(1, count($idsites)); $idsites = API::getInstance()->getSitesIdFromSiteUrl('http://piwik.net'); $this->assertEquals(1, count($idsites)); $pseudoMockAccess = new FakeAccess(); FakeAccess::$superUser = false; FakeAccess::$identity = 'user2'; FakeAccess::setIdSitesView(array(1)); FakeAccess::setIdSitesAdmin(array(3)); Access::setSingletonInstance($pseudoMockAccess); $idsites = API::getInstance()->getSitesIdFromSiteUrl('http://piwik.com'); $this->assertEquals(2, count($idsites)); $pseudoMockAccess = new FakeAccess(); FakeAccess::$superUser = false; FakeAccess::$identity = 'user3'; FakeAccess::setIdSitesView(array(1, 2)); FakeAccess::setIdSitesAdmin(array(3)); Access::setSingletonInstance($pseudoMockAccess); $idsites = API::getInstance()->getSitesIdFromSiteUrl('http://piwik.com'); $this->assertEquals(3, count($idsites)); Access::setSingletonInstance($saveAccess); }
/** * Constructor. * * @param string $templateFile The template file to load. Must be in the following format: * `"@MyPlugin/templateFileName"`. Note the absence of .twig * from the end of the name. */ public function __construct($templateFile) { $templateExt = '.twig'; if (substr($templateFile, -strlen($templateExt)) !== $templateExt) { $templateFile .= $templateExt; } $this->template = $templateFile; $this->initializeTwig(); $this->piwik_version = Version::VERSION; $this->userLogin = Piwik::getCurrentUserLogin(); $this->isSuperUser = Access::getInstance()->hasSuperUserAccess(); try { $this->piwikUrl = SettingsPiwik::getPiwikUrl(); } catch (Exception $ex) { // pass (occurs when DB cannot be connected to, perhaps piwik URL cache should be stored in config file...) } }
/** 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 `'Piwik\Auth'` object in * the container to an object that implements the {@link Piwik\Auth} interface. * * **Example** * * use Piwik\Container\StaticContainer; * * public function initAuthenticationObject($activateCookieAuth) * { * StaticContainer::getContainer()->set('Piwik\Auth', new LDAPAuth($activateCookieAuth)); * } * * @param bool $activateCookieAuth Whether authentication based on `$_COOKIE` values should * be allowed. */ Piwik::postEvent('Request.initAuthenticationObject', array($activateCookieAuth = true)); $auth = StaticContainer::get('Piwik\\Auth'); $success = Access::getInstance()->reloadAccess($auth); if (!$success) { throw new Exception('Authentication failed'); } Piwik::checkUserHasViewAccess($idSite); }
/** * 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; $tmpPath = StaticContainer::get('path.tmp'); $directoriesToCheck = array($tmpPath, $tmpPath . '/assets/', $tmpPath . '/cache/', $tmpPath . '/logs/', $tmpPath . '/tcpdf/', $tmpPath . '/templates_c/'); Filechecks::dieIfDirectoriesNotWritable($directoriesToCheck); $this->handleMaintenanceMode(); $this->handleProfiler(); $this->handleSSLRedirection(); Plugin\Manager::getInstance()->loadPluginTranslations(); Plugin\Manager::getInstance()->loadActivatedPlugins(); // 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'); $this->throwIfPiwikVersionIsOlderThanDBSchema(); \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() { * StaticContainer::getContainer()->set('Piwik\Auth', new MyAuthImplementation()); * }); */ Piwik::postEvent('Request.initAuthenticationObject'); try { $authAdapter = StaticContainer::get('Piwik\\Auth'); } catch (Exception $e) { $message = "Authentication object cannot be found in the container. 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"; $ex = new AuthenticationFailedException($message); $ex->setIsHtmlMessage(); throw $ex; } 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(); \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'); }
/** * Sets up access instance. */ public static function createAccessInstance() { Access::setSingletonInstance(null); Access::getInstance(); Piwik::postEvent('Request.initAuthenticationObject'); }
/** * Set an access level to a given user for a list of websites ID. * * If access = 'noaccess' the current access (if any) will be deleted. * If access = 'view' or 'admin' the current access level is deleted and updated with the new value. * * @param string $userLogin The user login * @param string $access Access to grant. Must have one of the following value : noaccess, view, admin * @param int|array $idSites The array of idSites on which to apply the access level for the user. * If the value is "all" then we apply the access level to all the websites ID for which the current authentificated user has an 'admin' access. * * @throws Exception if the user doesn't exist * @throws Exception if the access parameter doesn't have a correct value * @throws Exception if any of the given website ID doesn't exist * * @return bool true on success */ public function setUserAccess($userLogin, $access, $idSites) { $this->checkAccessType($access); $this->checkUserExists($userLogin); $this->checkUserIsNotSuperUser($userLogin); if ($userLogin == 'anonymous' && $access == 'admin') { throw new Exception(Piwik::translate("UsersManager_ExceptionAdminAnonymous")); } // in case idSites is all we grant access to all the websites on which the current connected user has an 'admin' access if ($idSites === 'all') { $idSites = \Piwik\Plugins\SitesManager\API::getInstance()->getSitesIdWithAdminAccess(); } else { $idSites = Site::getIdSitesFromIdSitesString($idSites); } if (empty($idSites)) { throw new Exception('Specify at least one website ID in &idSites='); } // it is possible to set user access on websites only for the websites admin // basically an admin can give the view or the admin access to any user for the websites he manages Piwik::checkUserHasAdminAccess($idSites); $this->deleteUserAccess($userLogin, $idSites); // delete UserAccess $db = Db::get(); // if the access is noaccess then we don't save it as this is the default value // when no access are specified if ($access != 'noaccess') { foreach ($idSites as $idsite) { $db->insert(Common::prefixTable("access"), array("idsite" => $idsite, "login" => $userLogin, "access" => $access)); } } // we reload the access list which doesn't yet take in consideration this new user access Access::getInstance()->reloadAccess(); Cache::deleteTrackerCache(); }
private static function shouldReloadAuthUsingTokenAuth($request) { if (is_null($request)) { $request = self::getDefaultRequest(); } if (!isset($request['token_auth'])) { // no token is given so we just keep the current loaded user return false; } // a token is specified, we need to reload auth in case it is different than the current one, even if it is empty $tokenAuth = Common::getRequestVar('token_auth', '', 'string', $request); // not using !== is on purpose as getTokenAuth() might return null whereas $tokenAuth is '' . In this case // we do not need to reload. return $tokenAuth != Access::getInstance()->getTokenAuth(); }
/** * 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); self::assignCliParametersToRequest(); Translate::loadEnglishTranslation(); $exceptionToThrow = self::createConfigObject(); if (Session::isFileBasedSessions()) { Session::start(); } $this->handleMaintenanceMode(); $this->handleSSLRedirection(); $this->handleProfiler(); $pluginsManager = \Piwik\Plugin\Manager::getInstance(); $pluginsToLoad = Config::getInstance()->Plugins['Plugins']; $pluginsManager->loadPlugins($pluginsToLoad); if ($exceptionToThrow) { throw $exceptionToThrow; } try { Db::createDatabaseObject(); Option::get('TestingIfDatabaseConnectionWorked'); } catch (Exception $exception) { if (self::shouldRethrowException()) { throw $exception; } /** * Triggered if the INI config file has the incorrect format or if certain required configuration * options are absent. * * 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('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')) { $host = 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 (($token_auth = Common::getRequestVar('token_auth', false, 'string')) !== false) { Request::reloadAuthUsingTokenAuth(); } SettingsServer::raiseMemoryLimitIfNecessary(); Translate::reloadLanguage(); $pluginsManager->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('Updater.checkForUpdates'); } catch (Exception $e) { if (self::shouldRethrowException()) { throw $e; } $debugTrace = $e->getTraceAsString(); Piwik_ExitWithMessage($e->getMessage(), $debugTrace, true); } }
/** * Add a website. * Requires Super User access. * * The website is defined by a name and an array of URLs. * @param string $siteName Site name * @param array|string $urls The URLs array must contain at least one URL called the 'main_url' ; * if several URLs are provided in the array, they will be recorded * as Alias URLs for this website. * @param int $ecommerce Is Ecommerce Reporting enabled for this website? * @param null $siteSearch * @param string $searchKeywordParameters Comma separated list of search keyword parameter names * @param string $searchCategoryParameters Comma separated list of search category parameter names * @param string $excludedIps Comma separated list of IPs to exclude from the reports (allows wildcards) * @param null $excludedQueryParameters * @param string $timezone Timezone string, eg. 'Europe/London' * @param string $currency Currency, eg. 'EUR' * @param string $group Website group identifier * @param string $startDate Date at which the statistics for this website will start. Defaults to today's date in YYYY-MM-DD format * @param null|string $excludedUserAgents * @param int $keepURLFragments If 1, URL fragments will be kept when tracking. If 2, they * will be removed. If 0, the default global behavior will be used. * @see getKeepURLFragmentsGlobal. * @param string $type The website type, defaults to "website" if not set. * * @return int the website ID created */ public function addSite($siteName, $urls, $ecommerce = null, $siteSearch = null, $searchKeywordParameters = null, $searchCategoryParameters = null, $excludedIps = null, $excludedQueryParameters = null, $timezone = null, $currency = null, $group = null, $startDate = null, $excludedUserAgents = null, $keepURLFragments = null, $type = null) { Piwik::checkUserHasSuperUserAccess(); $this->checkName($siteName); $urls = $this->cleanParameterUrls($urls); $this->checkUrls($urls); $this->checkAtLeastOneUrl($urls); $siteSearch = $this->checkSiteSearch($siteSearch); list($searchKeywordParameters, $searchCategoryParameters) = $this->checkSiteSearchParameters($searchKeywordParameters, $searchCategoryParameters); $keepURLFragments = (int) $keepURLFragments; self::checkKeepURLFragmentsValue($keepURLFragments); $timezone = trim($timezone); if (empty($timezone)) { $timezone = $this->getDefaultTimezone(); } $this->checkValidTimezone($timezone); if (empty($currency)) { $currency = $this->getDefaultCurrency(); } $this->checkValidCurrency($currency); $db = Db::get(); $url = $urls[0]; $urls = array_slice($urls, 1); $bind = array('name' => $siteName, 'main_url' => $url); $bind['excluded_ips'] = $this->checkAndReturnExcludedIps($excludedIps); $bind['excluded_parameters'] = $this->checkAndReturnCommaSeparatedStringList($excludedQueryParameters); $bind['excluded_user_agents'] = $this->checkAndReturnCommaSeparatedStringList($excludedUserAgents); $bind['keep_url_fragment'] = $keepURLFragments; $bind['timezone'] = $timezone; $bind['currency'] = $currency; $bind['ecommerce'] = (int) $ecommerce; $bind['sitesearch'] = $siteSearch; $bind['sitesearch_keyword_parameters'] = $searchKeywordParameters; $bind['sitesearch_category_parameters'] = $searchCategoryParameters; $bind['ts_created'] = !is_null($startDate) ? Date::factory($startDate)->getDatetime() : Date::now()->getDatetime(); $bind['type'] = $this->checkAndReturnType($type); if (!empty($group) && Piwik::hasUserSuperUserAccess()) { $bind['group'] = trim($group); } else { $bind['group'] = ""; } $db->insert(Common::prefixTable("site"), $bind); $idSite = $db->lastInsertId(); $this->insertSiteUrls($idSite, $urls); // we reload the access list which doesn't yet take in consideration this new website Access::getInstance()->reloadAccess(); $this->postUpdateWebsite($idSite); /** * Triggered after a site has been added. * * @param int $idSite The ID of the site that was added. */ Piwik::postEvent('SitesManager.addSite.end', array($idSite)); return (int) $idSite; }
/** * Assigns a set of generally useful variables to a {@link Piwik\View} instance. * * The following variables assigned: * * **enableMeasurePiwikForSiteId** - The value of the `[Debug] enable_measure_piwik_usage_in_idsite` * INI config option. * **isSuperUser** - True if the current user is the Super User, false if otherwise. * **hasSomeAdminAccess** - True if the current user has admin access to at least one site, * false if otherwise. * **isCustomLogo** - The value of the `branding_use_custom_logo` option. * **logoHeader** - The header logo URL to use. * **logoLarge** - The large logo URL to use. * **logoSVG** - The SVG logo URL to use. * **hasSVGLogo** - True if there is a SVG logo, false if otherwise. * **enableFrames** - The value of the `[General] enable_framed_pages` INI config option. If * true, {@link Piwik\View::setXFrameOptions()} is called on the view. * * Also calls {@link setHostValidationVariablesView()}. * * @param View $view * @api */ protected function setBasicVariablesView($view) { $view->clientSideConfig = PiwikConfig::getInstance()->getClientSideOptions(); $view->enableMeasurePiwikForSiteId = PiwikConfig::getInstance()->Debug['enable_measure_piwik_usage_in_idsite']; $view->isSuperUser = Access::getInstance()->hasSuperUserAccess(); $view->hasSomeAdminAccess = Piwik::isUserHasSomeAdminAccess(); $view->hasSomeViewAccess = Piwik::isUserHasSomeViewAccess(); $view->isUserIsAnonymous = Piwik::isUserIsAnonymous(); $view->hasSuperUserAccess = Piwik::hasUserSuperUserAccess(); $this->addCustomLogoInfo($view); $view->logoHeader = \Piwik\Plugins\API\API::getInstance()->getHeaderLogoUrl(); $view->logoLarge = \Piwik\Plugins\API\API::getInstance()->getLogoUrl(); $view->logoSVG = \Piwik\Plugins\API\API::getInstance()->getSVGLogoUrl(); $view->hasSVGLogo = \Piwik\Plugins\API\API::getInstance()->hasSVGLogo(); $view->superUserEmails = implode(',', Piwik::getAllSuperUserAccessEmailAddresses()); $general = PiwikConfig::getInstance()->General; $view->enableFrames = $general['enable_framed_pages'] || isset($general['enable_framed_logins']) && $general['enable_framed_logins']; if (!$view->enableFrames) { $view->setXFrameOptions('sameorigin'); } self::setHostValidationVariablesView($view); }
/** * Checks that the current user has view access to at least one site. * * @throws Exception if user doesn't have view access to any site. * @api */ public static function checkUserHasSomeViewAccess() { Access::getInstance()->checkUserHasSomeViewAccess(); }
public function testReloadAccessWithMockedAuthValid() { $mock = $this->getMock('\\Piwik\\Auth', array('authenticate', 'getName', 'initSession', 'setTokenAuth', 'setLogin')); $mock->expects($this->once())->method('authenticate')->will($this->returnValue(new AuthResult(AuthResult::SUCCESS, 'login', 'token'))); $mock->expects($this->any())->method('getName')->will($this->returnValue("test name")); $access = Access::getInstance(); $this->assertTrue($access->reloadAccess($mock)); $this->assertFalse($access->hasSuperUserAccess()); }
/** * Used to initialize core Piwik components on a piwik.php request * Eg. when cache is missed and we will be calling some APIs to generate cache */ public static function initCorePiwikInTrackerMode() { if (SettingsServer::isTrackerApiRequest() && self::$initTrackerMode === false) { self::$initTrackerMode = true; require_once PIWIK_INCLUDE_PATH . '/core/Option.php'; Access::getInstance(); Config::getInstance(); try { Db::get(); } catch (Exception $e) { Db::createDatabaseObject(); } \Piwik\Plugin\Manager::getInstance()->loadCorePluginsDuringTracker(); } }
/** * @dataProvider getGetPrettyValueTestCases */ public function testGetPrettyValue($columnName, $value, $expected) { Translate::loadEnglishTranslation(); $access = Access::getInstance(); $access->setSuperUserAccess(true); $idsite = API::getInstance()->addSite("test", "http://test"); $this->assertEquals($expected, MetricsFormatter::getPrettyValue($idsite, $columnName, $value, false, false)); Translate::unloadEnglishTranslation(); }
/** * @return array|bool */ protected function updateComponents() { Access::getInstance(); Piwik::setUserHasSuperUserAccess(); $updater = new Updater(); $componentsWithUpdateFile = CoreUpdater::getComponentUpdates($updater); if (empty($componentsWithUpdateFile)) { return false; } $result = CoreUpdater::updateComponents($updater, $componentsWithUpdateFile); return $result; }
/** * If the token_auth is found in the $request parameter, * the current session will be authenticated using this token_auth. * It will overwrite the previous Auth object. * * @param array $request If null, uses the default request ($_GET) * @return void * @ignore */ public static function reloadAuthUsingTokenAuth($request = null) { // if a token_auth is specified in the API request, we load the right permissions $token_auth = Common::getRequestVar('token_auth', '', 'string', $request); if ($token_auth) { /** * Triggered when authenticating an API request, but only if the **token_auth** * query parameter is found in the request. * * Plugins that provide authentication capabilities should subscribe to this event * and make sure the global authentication object (the object returned by `Registry::get('auth')`) * is setup to use `$token_auth` when its `authenticate()` method is executed. * * @param string $token_auth The value of the **token_auth** query parameter. */ Piwik::postEvent('API.Request.authenticate', array($token_auth)); Access::getInstance()->reloadAccess(); SettingsServer::raiseMemoryLimitIfNecessary(); } }