From 7f2534e72033725d081313997c2174ffcffe4d92 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Sat, 10 Jul 2010 01:17:09 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=20Piwik=20=E5=88=B0=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=BA=93=E4=B8=AD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit +YUCHENG HU+ git-svn-id: https://svn.code.sf.net/p/hawebs/svn@422 a2543c7e-f6e9-4f8a-8bff-1ffc34733512 --- oss/piwik/trunk/core/Access.php | 383 ++++++++++++++++++++++++++++++++ 1 file changed, 383 insertions(+) create mode 100644 oss/piwik/trunk/core/Access.php diff --git a/oss/piwik/trunk/core/Access.php b/oss/piwik/trunk/core/Access.php new file mode 100644 index 00000000..9c3b6d70 --- /dev/null +++ b/oss/piwik/trunk/core/Access.php @@ -0,0 +1,383 @@ +idsitesByAccess = array( + 'view' => array(), + 'admin' => array(), + 'superuser' => array() + ); + } + + /** + * Loads the access levels for the current user. + * + * Calls the authentication method to try to log the user in the system. + * If the user credentials are not correct we don't load anything. + * If the login/password is correct the user is either the SuperUser or a normal user. + * We load the access levels for this user for all the websites. + * + * @return true on success, false if reloading access failed (when auth object wasn't specified and user is not enforced to be Super User) + */ + public function reloadAccess(Piwik_Auth $auth = null) + { + if(!is_null($auth)) + { + $this->auth = $auth; + } + + // if the Piwik_Auth wasn't set, we may be in the special case of setSuperUser(), otherwise we fail + if(is_null($this->auth)) + { + if($this->isSuperUser()) + { + return $this->reloadAccessSuperUser(); + } + return false; + } + + // access = array ( idsite => accessIdSite, idsite2 => accessIdSite2) + $result = $this->auth->authenticate(); + + if(!$result->isValid()) + { + return false; + } + $this->login = $result->getIdentity(); + $this->token_auth = $result->getTokenAuth(); + + // case the superUser is logged in + if($result->getCode() == Piwik_Auth_Result::SUCCESS_SUPERUSER_AUTH_CODE) + { + return $this->reloadAccessSuperUser(); + } + // case valid authentification (normal user logged in) + + // we join with site in case there are rows in access for an idsite that doesn't exist anymore + // (backward compatibility ; before we deleted the site without deleting rows in _access table) + $accessRaw = Piwik_FetchAll(self::getSqlAccessSite("access, t2.idsite"), $this->login); + foreach($accessRaw as $access) + { + $this->idsitesByAccess[$access['access']][] = $access['idsite']; + } + return true; + } + + /** + * Returns the SQL query joining sites and access table for a given login + * + * @param $select eg. "MIN(ts_created)" + * @return string SQL query + */ + static public function getSqlAccessSite($select) + { + return "SELECT ". $select ." + FROM ".Piwik_Common::prefixTable('access'). " as t1 + JOIN ".Piwik_Common::prefixTable('site')." as t2 USING (idsite) ". + " WHERE login = ?"; + } + + /** + * Reload super user access + * + * @return bool + */ + protected function reloadAccessSuperUser() + { + $this->isSuperUser = true; + $this->idsitesByAccess['superuser'] = Piwik_SitesManager_API::getInstance()->getAllSitesId(); + return true; + } + + /** + * We bypass the normal auth method and give the current user Super User rights. + * This should be very carefully used. + */ + public function setSuperUser($bool = true) + { + if($bool) + { + $this->reloadAccessSuperUser(); + } + else + { + $this->isSuperUser = false; + $this->idsitesByAccess['superuser'] = array(); + } + } + + /** + * Returns true if the current user is logged in as the super user + * + * @return bool + */ + public function isSuperUser() + { + return $this->isSuperUser; + } + + /** + * Returns the current user login + * + * @return string|null + */ + public function getLogin() + { + return $this->login; + } + + /** + * Returns the token_auth used to authenticate this user in the API + * + * @return string|null + */ + public function getTokenAuth() + { + return $this->token_auth; + } + + /** + * Returns an array of ID sites for which the user has at least a VIEW access. + * Which means VIEW or ADMIN or SUPERUSER. + * + * @return array Example if the user is ADMIN for 4 + * and has VIEW access for 1 and 7, it returns array(1, 4, 7); + */ + public function getSitesIdWithAtLeastViewAccess() + { + return array_unique(array_merge( + $this->idsitesByAccess['view'], + $this->idsitesByAccess['admin'], + $this->idsitesByAccess['superuser']) + ); + } + + /** + * Returns an array of ID sites for which the user has an ADMIN access. + * + * @return array Example if the user is ADMIN for 4 and 8 + * and has VIEW access for 1 and 7, it returns array(4, 8); + */ + public function getSitesIdWithAdminAccess() + { + return array_unique(array_merge( + $this->idsitesByAccess['admin'], + $this->idsitesByAccess['superuser']) + ); + } + + + /** + * Returns an array of ID sites for which the user has a VIEW access only. + * + * @return array Example if the user is ADMIN for 4 + * and has VIEW access for 1 and 7, it returns array(1, 7); + * @see getSitesIdWithAtLeastViewAccess() + */ + public function getSitesIdWithViewAccess() + { + return $this->idsitesByAccess['view']; + } + + /** + * Throws an exception if the user is not the SuperUser + * + * @throws Exception + */ + public function checkUserIsSuperUser() + { + if($this->isSuperUser === false) + { + throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionPrivilege', array("'superuser'"))); + } + } + + /** + * If the user doesn't have an ADMIN access for at least one website, throws an exception + * + * @throws Exception + */ + public function checkUserHasSomeAdminAccess() + { + if($this->isSuperUser()) + { + return; + } + $idSitesAccessible = $this->getSitesIdWithAdminAccess(); + if(count($idSitesAccessible) == 0) + { + throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionPrivilegeAtLeastOneWebsite', array('admin'))); + } + } + + /** + * If the user doesn't have any view permission, throw exception + * + * @throws Exception + */ + public function checkUserHasSomeViewAccess() + { + $idSitesAccessible = $this->getSitesIdWithAtLeastViewAccess(); + if(count($idSitesAccessible) == 0) + { + throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionPrivilegeAtLeastOneWebsite', array('view'))); + } + } + + /** + * This method checks that the user has ADMIN access for the given list of websites. + * If the user doesn't have ADMIN access for at least one website of the list, we throw an exception. + * + * @param int|arrayOfIntegers List of ID sites to check + * @throws Exception If for any of the websites the user doesn't have an ADMIN access + */ + public function checkUserHasAdminAccess( $idSites ) + { + if($idSites === 'all') + { + $idSites = $this->getSitesIdWithAtLeastViewAccess(); + } + if(!is_array($idSites)) + { + $idSites = Piwik_Site::getIdSitesFromIdSitesString($idSites); + } + $idSitesAccessible = $this->getSitesIdWithAdminAccess(); + foreach($idSites as $idsite) + { + if(!in_array($idsite, $idSitesAccessible)) + { + throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionPrivilegeAccessWebsite', array("'admin'", $idsite))); + } + } + } + + /** + * This method checks that the user has VIEW or ADMIN access for the given list of websites. + * If the user doesn't have VIEW or ADMIN access for at least one website of the list, we throw an exception. + * + * @param int|arrayOfIntegers|string List of ID sites to check (integer, array of integers, string comma separated list of integers) + * @throws Exception If for any of the websites the user doesn't have an VIEW or ADMIN access + */ + public function checkUserHasViewAccess( $idSites ) + { + if($idSites === 'all') + { + $idSites = $this->getSitesIdWithAtLeastViewAccess(); + } + + if(!is_array($idSites)) + { + $idSites = Piwik_Site::getIdSitesFromIdSitesString($idSites); + } + $idSitesAccessible = $this->getSitesIdWithAtLeastViewAccess(); + + foreach($idSites as $idsite) + { + if(!in_array($idsite, $idSitesAccessible)) + { + throw new Piwik_Access_NoAccessException(Piwik_TranslateException('General_ExceptionPrivilegeAccessWebsite', array("'view'", $idsite))); + } + } + } +} + +/** + * + * Exception thrown when a user doesn't have sufficient access. + * + * @package Piwik + * @subpackage Piwik_Access + */ +class Piwik_Access_NoAccessException extends Exception +{}