e7abdb880f
+YUCHENG HU+ git-svn-id: https://svn.code.sf.net/p/hawebs/svn@450 a2543c7e-f6e9-4f8a-8bff-1ffc34733512
640 lines
17 KiB
PHP
640 lines
17 KiB
PHP
<?php
|
|
/**
|
|
* Piwik - Open source web analytics
|
|
*
|
|
* @link http://piwik.org
|
|
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
|
|
* @version $Id: API.php 2265 2010-06-03 17:46:05Z vipsoft $
|
|
*
|
|
* @category Piwik_Plugins
|
|
* @package Piwik_UsersManager
|
|
*/
|
|
|
|
/**
|
|
*
|
|
* @package Piwik_UsersManager
|
|
*/
|
|
class Piwik_UsersManager_API
|
|
{
|
|
static private $instance = null;
|
|
|
|
/**
|
|
* @return Piwik_UsersManager_API
|
|
*/
|
|
static public function getInstance()
|
|
{
|
|
if (self::$instance == null)
|
|
{
|
|
$c = __CLASS__;
|
|
self::$instance = new $c();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
const PREFERENCE_DEFAULT_REPORT = 'defaultReport';
|
|
const PREFERENCE_DEFAULT_REPORT_DATE = 'defaultReportDate';
|
|
|
|
/**
|
|
* Sets a user preference
|
|
* @param $userLogin
|
|
* @param $preferenceName
|
|
* @param $preferenceValue
|
|
* @return void
|
|
*/
|
|
public function setUserPreference($userLogin, $preferenceName, $preferenceValue)
|
|
{
|
|
Piwik::checkUserIsSuperUserOrTheUser($userLogin);
|
|
Piwik_SetOption($this->getPreferenceId($userLogin, $preferenceName), $preferenceValue);
|
|
}
|
|
|
|
/**
|
|
* Gets a user preference
|
|
* @param $userLogin
|
|
* @param $preferenceName
|
|
* @param $preferenceValue
|
|
* @return void
|
|
*/
|
|
public function getUserPreference($userLogin, $preferenceName)
|
|
{
|
|
Piwik::checkUserIsSuperUserOrTheUser($userLogin);
|
|
return Piwik_GetOption($this->getPreferenceId($userLogin, $preferenceName));
|
|
}
|
|
|
|
private function getPreferenceId($login, $preference)
|
|
{
|
|
return $login . '_' . $preference;
|
|
}
|
|
|
|
/**
|
|
* Returns the list of all the users
|
|
*
|
|
* @return array the list of all the users
|
|
*/
|
|
public function getUsers()
|
|
{
|
|
Piwik::checkUserIsSuperUser();
|
|
|
|
$db = Zend_Registry::get('db');
|
|
$users = $db->fetchAll("SELECT * FROM ".Piwik_Common::prefixTable("user")." ORDER BY login ASC");
|
|
return $users;
|
|
}
|
|
|
|
/**
|
|
* Returns the list of all the users login
|
|
*
|
|
* @return array the list of all the users login
|
|
*/
|
|
public function getUsersLogin()
|
|
{
|
|
Piwik::checkUserHasSomeAdminAccess();
|
|
|
|
$db = Zend_Registry::get('db');
|
|
$users = $db->fetchAll("SELECT login FROM ".Piwik_Common::prefixTable("user")." ORDER BY login ASC");
|
|
$return = array();
|
|
foreach($users as $login)
|
|
{
|
|
$return[] = $login['login'];
|
|
}
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* For each user, returns the list of website IDs where the user has the supplied $access level.
|
|
* If a user doesn't have the given $access to any website IDs,
|
|
* the user will not be in the returned array.
|
|
*
|
|
* @param string Access can have the following values : 'view' or 'admin'
|
|
*
|
|
* @return array The returned array has the format
|
|
* array(
|
|
* login1 => array ( idsite1,idsite2),
|
|
* login2 => array(idsite2),
|
|
* ...
|
|
* )
|
|
*
|
|
*/
|
|
public function getUsersSitesFromAccess( $access )
|
|
{
|
|
Piwik::checkUserIsSuperUser();
|
|
|
|
$this->checkAccessType($access);
|
|
|
|
$db = Zend_Registry::get('db');
|
|
$users = $db->fetchAll("SELECT login,idsite
|
|
FROM ".Piwik_Common::prefixTable("access")
|
|
." WHERE access = ?", $access);
|
|
$return = array();
|
|
foreach($users as $user)
|
|
{
|
|
$return[$user['login']][] = $user['idsite'];
|
|
}
|
|
return $return;
|
|
|
|
}
|
|
|
|
/**
|
|
* For each user, returns his access level for the given $idSite.
|
|
* If a user doesn't have any access to the $idSite ('noaccess'),
|
|
* the user will not be in the returned array.
|
|
*
|
|
* @param string website ID
|
|
*
|
|
* @return array The returned array has the format
|
|
* array(
|
|
* login1 => 'view',
|
|
* login2 => 'admin',
|
|
* login3 => 'view',
|
|
* ...
|
|
* )
|
|
*/
|
|
public function getUsersAccessFromSite( $idSite )
|
|
{
|
|
Piwik::checkUserHasAdminAccess( $idSite );
|
|
|
|
$db = Zend_Registry::get('db');
|
|
$users = $db->fetchAll("SELECT login,access
|
|
FROM ".Piwik_Common::prefixTable("access")
|
|
." WHERE idsite = ?", $idSite);
|
|
$return = array();
|
|
foreach($users as $user)
|
|
{
|
|
$return[$user['login']] = $user['access'];
|
|
}
|
|
return $return;
|
|
|
|
}
|
|
|
|
/**
|
|
* For each website ID, returns the access level of the given $userLogin.
|
|
* If the user doesn't have any access to a website ('noaccess'),
|
|
* this website will not be in the returned array.
|
|
* If the user doesn't have any access, the returned array will be an empty array.
|
|
*
|
|
* @param string User that has to be valid
|
|
*
|
|
* @return array The returned array has the format
|
|
* array(
|
|
* idsite1 => 'view',
|
|
* idsite2 => 'admin',
|
|
* idsite3 => 'view',
|
|
* ...
|
|
* )
|
|
*/
|
|
public function getSitesAccessFromUser( $userLogin )
|
|
{
|
|
Piwik::checkUserIsSuperUser();
|
|
$this->checkUserExists($userLogin);
|
|
$this->checkUserIsNotSuperUser($userLogin);
|
|
|
|
$db = Zend_Registry::get('db');
|
|
$users = $db->fetchAll("SELECT idsite,access
|
|
FROM ".Piwik_Common::prefixTable("access")
|
|
." WHERE login = ?", $userLogin);
|
|
$return = array();
|
|
foreach($users as $user)
|
|
{
|
|
$return[] = array(
|
|
'site' => $user['idsite'],
|
|
'access' => $user['access'],
|
|
);
|
|
}
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Returns the user information (login, password md5, alias, email, date_registered, etc.)
|
|
*
|
|
* @param string the user login
|
|
*
|
|
* @return array the user information
|
|
*/
|
|
public function getUser( $userLogin )
|
|
{
|
|
Piwik::checkUserIsSuperUserOrTheUser($userLogin);
|
|
$this->checkUserExists($userLogin);
|
|
$this->checkUserIsNotSuperUser($userLogin);
|
|
|
|
$db = Zend_Registry::get('db');
|
|
$user = $db->fetchRow("SELECT *
|
|
FROM ".Piwik_Common::prefixTable("user")
|
|
." WHERE login = ?", $userLogin);
|
|
return $user;
|
|
}
|
|
|
|
/**
|
|
* Returns the user information (login, password md5, alias, email, date_registered, etc.)
|
|
*
|
|
* @param string the user email
|
|
*
|
|
* @return array the user information
|
|
*/
|
|
public function getUserByEmail( $userEmail )
|
|
{
|
|
Piwik::checkUserIsSuperUser();
|
|
$this->checkUserEmailExists($userEmail);
|
|
|
|
$db = Zend_Registry::get('db');
|
|
$user = $db->fetchRow("SELECT *
|
|
FROM ".Piwik_Common::prefixTable("user")
|
|
." WHERE email = ?", $userEmail);
|
|
return $user;
|
|
}
|
|
|
|
private function checkLogin($userLogin)
|
|
{
|
|
if($this->userExists($userLogin))
|
|
{
|
|
throw new Exception(Piwik_TranslateException('UsersManager_ExceptionLoginExists', $userLogin));
|
|
}
|
|
|
|
Piwik::checkValidLoginString($userLogin);
|
|
}
|
|
|
|
private function checkPassword($password)
|
|
{
|
|
if(!$this->isValidPasswordString($password))
|
|
{
|
|
throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidPassword'));
|
|
}
|
|
}
|
|
|
|
private function checkEmail($email)
|
|
{
|
|
if($this->userEmailExists($email))
|
|
{
|
|
throw new Exception(Piwik_TranslateException('UsersManager_ExceptionEmailExists', $email));
|
|
}
|
|
|
|
if(!Piwik::isValidEmailString($email))
|
|
{
|
|
throw new Exception(Piwik_TranslateException('UsersManager_ExceptionInvalidEmail'));
|
|
}
|
|
}
|
|
|
|
private function getCleanAlias($alias,$userLogin)
|
|
{
|
|
if(empty($alias))
|
|
{
|
|
$alias = $userLogin;
|
|
}
|
|
return $alias;
|
|
}
|
|
|
|
private function getCleanPassword($password)
|
|
{
|
|
// if change here, should also edit the installation process
|
|
// to change how the root pwd is saved in the config file
|
|
return md5($password);
|
|
}
|
|
|
|
/**
|
|
* Add a user in the database.
|
|
* A user is defined by
|
|
* - a login that has to be unique and valid
|
|
* - a password that has to be valid
|
|
* - an alias
|
|
* - an email that has to be in a correct format
|
|
*
|
|
* @see userExists()
|
|
* @see isValidLoginString()
|
|
* @see isValidPasswordString()
|
|
* @see isValidEmailString()
|
|
*
|
|
* @exception in case of an invalid parameter
|
|
*/
|
|
public function addUser( $userLogin, $password, $email, $alias = false )
|
|
{
|
|
Piwik::checkUserIsSuperUser();
|
|
|
|
$this->checkLogin($userLogin);
|
|
$this->checkUserIsNotSuperUser($userLogin);
|
|
$this->checkPassword($password);
|
|
$this->checkEmail($email);
|
|
|
|
$alias = $this->getCleanAlias($alias,$userLogin);
|
|
$passwordTransformed = $this->getCleanPassword($password);
|
|
|
|
$token_auth = $this->getTokenAuth($userLogin, $passwordTransformed);
|
|
|
|
$db = Zend_Registry::get('db');
|
|
|
|
$db->insert( Piwik_Common::prefixTable("user"), array(
|
|
'login' => $userLogin,
|
|
'password' => $passwordTransformed,
|
|
'alias' => $alias,
|
|
'email' => $email,
|
|
'token_auth' => $token_auth,
|
|
'date_registered' => Piwik_Date::now()->getDatetime()
|
|
)
|
|
);
|
|
|
|
// we reload the access list which doesn't yet take in consideration this new user
|
|
Zend_Registry::get('access')->reloadAccess();
|
|
|
|
}
|
|
|
|
/**
|
|
* Updates a user in the database.
|
|
* Only login and password are required (case when we update the password).
|
|
* When the password changes, the key token for this user will change, which could break
|
|
* its API calls.
|
|
*
|
|
* @see addUser() for all the parameters
|
|
*/
|
|
public function updateUser( $userLogin, $password = false, $email = false, $alias = false )
|
|
{
|
|
Piwik::checkUserIsSuperUserOrTheUser($userLogin);
|
|
$this->checkUserIsNotAnonymous( $userLogin );
|
|
$this->checkUserIsNotSuperUser($userLogin);
|
|
$userInfo = $this->getUser($userLogin);
|
|
|
|
if(empty($password))
|
|
{
|
|
$password = $userInfo['password'];
|
|
}
|
|
else
|
|
{
|
|
$this->checkPassword($password);
|
|
$password = $this->getCleanPassword($password);
|
|
}
|
|
|
|
if(empty($alias))
|
|
{
|
|
$alias = $userInfo['alias'];
|
|
}
|
|
|
|
if(empty($email))
|
|
{
|
|
$email = $userInfo['email'];
|
|
}
|
|
|
|
if($email != $userInfo['email'])
|
|
{
|
|
$this->checkEmail($email);
|
|
}
|
|
|
|
$alias = $this->getCleanAlias($alias,$userLogin);
|
|
$token_auth = $this->getTokenAuth($userLogin,$password);
|
|
|
|
$db = Zend_Registry::get('db');
|
|
|
|
$db->update( Piwik_Common::prefixTable("user"),
|
|
array(
|
|
'password' => $password,
|
|
'alias' => $alias,
|
|
'email' => $email,
|
|
'token_auth' => $token_auth,
|
|
),
|
|
"login = '$userLogin'"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Delete a user and all its access, given its login.
|
|
*
|
|
* @param string the user login.
|
|
*
|
|
* @exception if the user doesn't exist
|
|
*
|
|
* @return bool true on success
|
|
*/
|
|
public function deleteUser( $userLogin )
|
|
{
|
|
Piwik::checkUserIsSuperUser();
|
|
$this->checkUserIsNotAnonymous( $userLogin );
|
|
$this->checkUserIsNotSuperUser($userLogin);
|
|
if(!$this->userExists($userLogin))
|
|
{
|
|
throw new Exception(Piwik_TranslateException("UsersManager_ExceptionDeleteDoesNotExist", $userLogin));
|
|
}
|
|
|
|
$this->deleteUserOnly( $userLogin );
|
|
$this->deleteUserAccess( $userLogin );
|
|
}
|
|
|
|
/**
|
|
* Returns true if the given userLogin is known in the database
|
|
*
|
|
* @return bool true if the user is known
|
|
*/
|
|
public function userExists( $userLogin )
|
|
{
|
|
$count = Piwik_FetchOne("SELECT count(*)
|
|
FROM ".Piwik_Common::prefixTable("user"). "
|
|
WHERE login = ?", $userLogin);
|
|
return $count != 0;
|
|
}
|
|
|
|
/**
|
|
* Returns true if user with given email (userEmail) is known in the database
|
|
*
|
|
* @return bool true if the user is known
|
|
*/
|
|
public function userEmailExists( $userEmail )
|
|
{
|
|
Piwik::checkUserHasSomeAdminAccess();
|
|
$count = Piwik_FetchOne("SELECT count(*)
|
|
FROM ".Piwik_Common::prefixTable("user"). "
|
|
WHERE email = ?", $userEmail);
|
|
return $count != 0;
|
|
}
|
|
|
|
/**
|
|
* 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 Access to grant. Must have one of the following value : noaccess, view, admin
|
|
* @param string The user login
|
|
* @param int|array 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.
|
|
*
|
|
* @exception if the user doesn't exist
|
|
* @exception if the access parameter doesn't have a correct value
|
|
* @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_TranslateException("UsersManager_ExceptionAdminAnonymous"));
|
|
}
|
|
|
|
// in case idSites is null we grant access to all the websites on which the current connected user
|
|
// has an 'admin' access
|
|
if($idSites === 'all')
|
|
{
|
|
$idSites = Piwik_SitesManager_API::getInstance()->getSitesIdWithAdminAccess();
|
|
}
|
|
// in case the idSites is an integer we build an array
|
|
elseif(!is_array($idSites))
|
|
{
|
|
$idSites = Piwik_Site::getIdSitesFromIdSitesString($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 = Zend_Registry::get('db');
|
|
|
|
// 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( Piwik_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
|
|
Zend_Registry::get('access')->reloadAccess();
|
|
}
|
|
|
|
/**
|
|
* Throws an exception is the user login doesn't exist
|
|
*
|
|
* @param string user login
|
|
* @exception if the user doesn't exist
|
|
*/
|
|
private function checkUserExists( $userLogin )
|
|
{
|
|
if(!$this->userExists($userLogin))
|
|
{
|
|
throw new Exception(Piwik_TranslateException("UsersManager_ExceptionUserDoesNotExist", $userLogin));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Throws an exception is the user email cannot be found
|
|
*
|
|
* @param string user email
|
|
* @exception if the user doesn't exist
|
|
*/
|
|
private function checkUserEmailExists( $userEmail )
|
|
{
|
|
if(!$this->userEmailExists($userEmail))
|
|
{
|
|
throw new Exception(Piwik_TranslateException("UsersManager_ExceptionUserDoesNotExist", $userEmail));
|
|
}
|
|
}
|
|
|
|
private function checkUserIsNotAnonymous( $userLogin )
|
|
{
|
|
if($userLogin == 'anonymous')
|
|
{
|
|
throw new Exception(Piwik_TranslateException("UsersManager_ExceptionEditAnonymous"));
|
|
}
|
|
}
|
|
private function checkUserIsNotSuperUser( $userLogin )
|
|
{
|
|
if($userLogin == Zend_Registry::get('config')->superuser->login)
|
|
{
|
|
throw new Exception(Piwik_TranslateException("UsersManager_ExceptionSuperUser"));
|
|
}
|
|
}
|
|
|
|
private function checkAccessType($access)
|
|
{
|
|
$accessList = Piwik_Access::getListAccess();
|
|
|
|
// do not allow to set the superUser access
|
|
unset($accessList[array_search("superuser", $accessList)]);
|
|
|
|
if(!in_array($access,$accessList))
|
|
{
|
|
throw new Exception(Piwik_TranslateException("UsersManager_ExceptionAccessValues", implode(", ", $accessList)));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Delete a user given its login.
|
|
* The user's access are not deleted.
|
|
*
|
|
* @param string the user login.
|
|
*
|
|
*/
|
|
private function deleteUserOnly( $userLogin )
|
|
{
|
|
$db = Zend_Registry::get('db');
|
|
$db->query("DELETE FROM ".Piwik_Common::prefixTable("user")." WHERE login = ?", $userLogin);
|
|
|
|
Piwik_PostEvent('UsersManager.deleteUser', $userLogin);
|
|
}
|
|
|
|
|
|
/**
|
|
* Delete the user access for the given websites.
|
|
* The array of idsite must be either null OR the values must have been checked before for their validity!
|
|
*
|
|
* @param string the user login
|
|
* @param array array of idsites on which to delete the access. If null then delete all the access for this user.
|
|
*
|
|
* @return bool true on success
|
|
*/
|
|
private function deleteUserAccess( $userLogin, $idSites = null )
|
|
{
|
|
$db = Zend_Registry::get('db');
|
|
|
|
if(is_null($idSites))
|
|
{
|
|
$db->query( "DELETE FROM ".Piwik_Common::prefixTable("access").
|
|
" WHERE login = ?",
|
|
array( $userLogin) );
|
|
}
|
|
else
|
|
{
|
|
foreach($idSites as $idsite)
|
|
{
|
|
$db->query( "DELETE FROM ".Piwik_Common::prefixTable("access").
|
|
" WHERE idsite = ? AND login = ?",
|
|
array($idsite, $userLogin)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Generates a unique MD5 for the given login & password
|
|
*
|
|
* @param string Login
|
|
* @param string MD5ied string of the password
|
|
*/
|
|
public function getTokenAuth($userLogin, $md5Password)
|
|
{
|
|
if(strlen($md5Password) != 32)
|
|
{
|
|
throw new Exception(Piwik_TranslateException('UsersManager_ExceptionPasswordMD5HashExpected'));
|
|
}
|
|
return md5($userLogin . $md5Password );
|
|
}
|
|
|
|
/**
|
|
* Returns true if the password is complex enough (at least 6 characters and max 26 characters)
|
|
*
|
|
* @param string email
|
|
* @return bool
|
|
*/
|
|
private function isValidPasswordString( $input )
|
|
{
|
|
$l = strlen($input);
|
|
return $l >= 6 && $l <= 26;
|
|
}
|
|
}
|