update Piwik to version 2.16 (fixes #91)

This commit is contained in:
oliver 2016-04-10 18:55:57 +02:00
commit d885a4baa9
5833 changed files with 418860 additions and 226988 deletions

View file

@ -1,6 +1,6 @@
<?php
/**
* Piwik - Open source web analytics
* Piwik - free/libre analytics platform
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
@ -12,6 +12,7 @@ use Exception;
use Piwik\Access;
use Piwik\Common;
use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Date;
use Piwik\Option;
use Piwik\Piwik;
@ -28,23 +29,31 @@ use Piwik\Tracker\Cache;
* Existing Permissions are listed given a login via "getSitesAccessFromUser", or a website ID via "getUsersAccessFromSite",
* or you can list all users and websites for a given permission via "getUsersSitesFromAccess". Permissions are set and updated
* via the method "setUserAccess".
* See also the documentation about <a href='http://piwik.org/docs/manage-users/' target='_blank'>Managing Users</a> in Piwik.
* See also the documentation about <a href='http://piwik.org/docs/manage-users/' rel='noreferrer' target='_blank'>Managing Users</a> in Piwik.
*/
class API extends \Piwik\Plugin\API
{
const OPTION_NAME_PREFERENCE_SEPARATOR = '_';
/**
* @var Model
*/
private $model;
/**
* @var UserAccessFilter
*/
private $userFilter;
const PREFERENCE_DEFAULT_REPORT = 'defaultReport';
const PREFERENCE_DEFAULT_REPORT_DATE = 'defaultReportDate';
static private $instance = null;
private static $instance = null;
protected function __construct()
public function __construct(Model $model, UserAccessFilter $filter)
{
$this->model = new Model();
$this->model = $model;
$this->userFilter = $filter;
}
/**
@ -52,24 +61,26 @@ class API extends \Piwik\Plugin\API
* 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\Plugins\MyCustomUsersManager\API::getInstance());
* StaticContainer::getContainer()->set('UsersManager_API', \Piwik\Plugins\MyCustomUsersManager\API::getInstance());
*
* @throws Exception
* @return \Piwik\Plugins\UsersManager\API
*/
static public function getInstance()
public static function getInstance()
{
try {
$instance = \Piwik\Registry::get('UsersManager_API');
$instance = StaticContainer::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);
self::$instance = StaticContainer::get('Piwik\Plugins\UsersManager\API');
StaticContainer::getContainer()->set('UsersManager_API', self::$instance);
}
return self::$instance;
}
@ -96,16 +107,72 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
$optionValue = Option::get($this->getPreferenceId($userLogin, $preferenceName));
$optionValue = $this->getPreferenceValue($userLogin, $preferenceName);
if ($optionValue !== false) {
return $optionValue;
}
return $this->getDefaultUserPreference($preferenceName, $userLogin);
}
/**
* Sets a user preference in the DB using the preference's default value.
* @param string $userLogin
* @param string $preferenceName
* @ignore
*/
public function initUserPreferenceWithDefault($userLogin, $preferenceName)
{
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
$optionValue = $this->getPreferenceValue($userLogin, $preferenceName);
if ($optionValue === false) {
$defaultValue = $this->getDefaultUserPreference($preferenceName, $userLogin);
if ($defaultValue !== false) {
$this->setUserPreference($userLogin, $preferenceName, $defaultValue);
}
}
}
/**
* Returns an array of Preferences
* @param $preferenceNames array of preference names
* @return array
* @ignore
*/
public function getAllUsersPreferences(array $preferenceNames)
{
Piwik::checkUserHasSuperUserAccess();
$userPreferences = array();
foreach($preferenceNames as $preferenceName) {
$optionNameMatchAllUsers = $this->getPreferenceId('%', $preferenceName);
$preferences = Option::getLike($optionNameMatchAllUsers);
foreach($preferences as $optionName => $optionValue) {
$lastUnderscore = strrpos($optionName, self::OPTION_NAME_PREFERENCE_SEPARATOR);
$userName = substr($optionName, 0, $lastUnderscore);
$preference = substr($optionName, $lastUnderscore + 1);
$userPreferences[$userName][$preference] = $optionValue;
}
}
return $userPreferences;
}
private function getPreferenceId($login, $preference)
{
return $login . '_' . $preference;
if(false !== strpos($preference, self::OPTION_NAME_PREFERENCE_SEPARATOR)) {
throw new Exception("Preference name cannot contain underscores.");
}
return $login . self::OPTION_NAME_PREFERENCE_SEPARATOR . $preference;
}
private function getPreferenceValue($userLogin, $preferenceName)
{
return Option::get($this->getPreferenceId($userLogin, $preferenceName));
}
private function getDefaultUserPreference($preferenceName, $login)
@ -113,7 +180,10 @@ class API extends \Piwik\Plugin\API
switch ($preferenceName) {
case self::PREFERENCE_DEFAULT_REPORT:
$viewableSiteIds = \Piwik\Plugins\SitesManager\API::getInstance()->getSitesIdWithAtLeastViewAccess($login);
return reset($viewableSiteIds);
if (!empty($viewableSiteIds)) {
return reset($viewableSiteIds);
}
return false;
case self::PREFERENCE_DEFAULT_REPORT_DATE:
return Config::getInstance()->General['default_day'];
default:
@ -137,6 +207,7 @@ class API extends \Piwik\Plugin\API
}
$users = $this->model->getUsers($logins);
$users = $this->userFilter->filterUsers($users);
// Non Super user can only access login & alias
if (!Piwik::hasUserSuperUserAccess()) {
@ -157,7 +228,10 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasSomeAdminAccess();
return $this->model->getUsersLogin();
$logins = $this->model->getUsersLogin();
$logins = $this->userFilter->filterLogins($logins);
return $logins;
}
/**
@ -180,7 +254,10 @@ class API extends \Piwik\Plugin\API
$this->checkAccessType($access);
return $this->model->getUsersSitesFromAccess($access);
$userSites = $this->model->getUsersSitesFromAccess($access);
$userSites = $this->userFilter->filterLoginIndexedArray($userSites);
return $userSites;
}
/**
@ -202,7 +279,10 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasAdminAccess($idSite);
return $this->model->getUsersAccessFromSite($idSite);
$usersAccess = $this->model->getUsersAccessFromSite($idSite);
$usersAccess = $this->userFilter->filterLoginIndexedArray($usersAccess);
return $usersAccess;
}
public function getUsersWithSiteAccess($idSite, $access)
@ -216,7 +296,9 @@ class API extends \Piwik\Plugin\API
return array();
}
$logins = $this->userFilter->filterLogins($logins);
$logins = implode(',', $logins);
return $this->getUsers($logins);
}
@ -240,13 +322,27 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasSuperUserAccess();
$this->checkUserExists($userLogin);
$this->checkUserHasNotSuperUserAccess($userLogin);
// Super users have 'admin' access for every site
if (Piwik::hasTheUserSuperUserAccess($userLogin)) {
$return = array();
$siteManagerModel = new \Piwik\Plugins\SitesManager\Model();
$sites = $siteManagerModel->getAllSites();
foreach ($sites as $site) {
$return[] = array(
'site' => $site['idsite'],
'access' => 'admin'
);
}
return $return;
}
return $this->model->getSitesAccessFromUser($userLogin);
}
/**
* Returns the user information (login, password md5, alias, email, date_registered, etc.)
* Returns the user information (login, password hash, alias, email, date_registered, etc.)
*
* @param string $userLogin the user login
*
@ -257,11 +353,13 @@ class API extends \Piwik\Plugin\API
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
$this->checkUserExists($userLogin);
return $this->model->getUser($userLogin);
$user = $this->model->getUser($userLogin);
return $this->userFilter->filterUser($user);
}
/**
* Returns the user information (login, password md5, alias, email, date_registered, etc.)
* Returns the user information (login, password hash, alias, email, date_registered, etc.)
*
* @param string $userEmail the user email
*
@ -272,7 +370,9 @@ class API extends \Piwik\Plugin\API
Piwik::checkUserHasSuperUserAccess();
$this->checkUserEmailExists($userEmail);
return $this->model->getUserByEmail($userEmail);
$user = $this->model->getUserByEmail($userEmail);
return $this->userFilter->filterUser($user);
}
private function checkLogin($userLogin)
@ -300,6 +400,7 @@ class API extends \Piwik\Plugin\API
if (empty($alias)) {
$alias = $userLogin;
}
return $alias;
}
@ -318,7 +419,7 @@ class API extends \Piwik\Plugin\API
*
* @exception in case of an invalid parameter
*/
public function addUser($userLogin, $password, $email, $alias = false)
public function addUser($userLogin, $password, $email, $alias = false, $_isPasswordHashed = false)
{
Piwik::checkUserHasSuperUserAccess();
@ -326,10 +427,16 @@ class API extends \Piwik\Plugin\API
$this->checkEmail($email);
$password = Common::unsanitizeInputValue($password);
UsersManager::checkPassword($password);
if (!$_isPasswordHashed) {
UsersManager::checkPassword($password);
$passwordTransformed = UsersManager::getPasswordHash($password);
} else {
$passwordTransformed = $password;
}
$alias = $this->getCleanAlias($alias, $userLogin);
$passwordTransformed = UsersManager::getPasswordHash($password);
$token_auth = $this->getTokenAuth($userLogin, $passwordTransformed);
@ -341,10 +448,10 @@ class API extends \Piwik\Plugin\API
/**
* Triggered after a new user is created.
*
*
* @param string $userLogin The new user's login handle.
*/
Piwik::postEvent('UsersManager.addUser.end', array($userLogin));
Piwik::postEvent('UsersManager.addUser.end', array($userLogin, $email, $password, $alias));
}
/**
@ -392,7 +499,17 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserIsNotAnonymous();
return $this->model->getUsersHavingSuperUserAccess();
$users = $this->model->getUsersHavingSuperUserAccess();
foreach($users as &$user) {
// remove token_auth in API response
unset($user['token_auth']);
}
// we do not filter these users by access and return them all since we need to print this information in the
// UI and they are allowed to see this.
return $users;
}
/**
@ -409,6 +526,7 @@ class API extends \Piwik\Plugin\API
Piwik::checkUserHasSuperUserAccessOrIsTheUser($userLogin);
$this->checkUserIsNotAnonymous($userLogin);
$userInfo = $this->getUser($userLogin);
$passwordHasBeenUpdated = false;
if (empty($password)) {
$password = $userInfo['password'];
@ -418,6 +536,8 @@ class API extends \Piwik\Plugin\API
UsersManager::checkPassword($password);
$password = UsersManager::getPasswordHash($password);
}
$passwordHasBeenUpdated = true;
}
if (empty($alias)) {
@ -432,7 +552,7 @@ class API extends \Piwik\Plugin\API
$this->checkEmail($email);
}
$alias = $this->getCleanAlias($alias, $userLogin);
$alias = $this->getCleanAlias($alias, $userLogin);
$token_auth = $this->getTokenAuth($userLogin, $password);
$this->model->updateUser($userLogin, $password, $email, $alias, $token_auth);
@ -441,10 +561,12 @@ class API extends \Piwik\Plugin\API
/**
* Triggered after an existing user has been updated.
*
* Event notify about password change.
*
* @param string $userLogin The user's login handle.
* @param boolean $passwordHasBeenUpdated Flag containing information about password change.
*/
Piwik::postEvent('UsersManager.updateUser.end', array($userLogin));
Piwik::postEvent('UsersManager.updateUser.end', array($userLogin, $passwordHasBeenUpdated, $email, $password, $alias));
}
/**
@ -460,6 +582,7 @@ class API extends \Piwik\Plugin\API
{
Piwik::checkUserHasSuperUserAccess();
$this->checkUserIsNotAnonymous($userLogin);
if (!$this->userExists($userLogin)) {
throw new Exception(Piwik::translate("UsersManager_ExceptionDeleteDoesNotExist", $userLogin));
}
@ -508,10 +631,32 @@ class API extends \Piwik\Plugin\API
public function userEmailExists($userEmail)
{
Piwik::checkUserIsNotAnonymous();
Piwik::checkUserHasSomeViewAccess();
return $this->model->userEmailExists($userEmail);
}
/**
* Returns the first login name of an existing user that has the given email address. If no user can be found for
* this user an error will be returned.
*
* @param string $userEmail
* @return bool true if the user is known
*/
public function getUserLoginFromUserEmail($userEmail)
{
Piwik::checkUserIsNotAnonymous();
Piwik::checkUserHasSomeAdminAccess();
$this->checkUserEmailExists($userEmail);
$user = $this->model->getUserByEmail($userEmail);
// any user with some admin access is allowed to find any user by email, no need to filter by access here
return $user['login'];
}
/**
* Set an access level to a given user for a list of websites ID.
*
@ -562,6 +707,12 @@ class API extends \Piwik\Plugin\API
// when no access are specified
if ($access != 'noaccess') {
$this->model->addUserAccess($userLogin, $access, $idSites);
} else {
if (!empty($idSites) && !is_array($idSites)) {
$idSites = array($idSites);
}
Piwik::postEvent('UsersManager.removeSiteAccess', array($userLogin, $idSites));
}
// we reload the access list which doesn't yet take in consideration this new user access
@ -632,15 +783,13 @@ class API extends \Piwik\Plugin\API
* Generates a unique MD5 for the given login & password
*
* @param string $userLogin Login
* @param string $md5Password MD5ied string of the password
* @throws Exception
* @param string $md5Password hashed string of the password (using current hash function; MD5-named for historical reasons)
* @return string
*/
public function getTokenAuth($userLogin, $md5Password)
{
if (strlen($md5Password) != 32) {
throw new Exception(Piwik::translate('UsersManager_ExceptionPasswordMD5HashExpected'));
}
UsersManager::checkPasswordHash($md5Password, Piwik::translate('UsersManager_ExceptionPasswordMD5HashExpected'));
return md5($userLogin . $md5Password);
}
}