* @version $Id$ * @access public * @license http://opensource.org/licenses/gpl-3.0.html * Plugin Management */ class auth { protected $dispatcher = null; public function __construct() { $this->dispatcher = $GLOBALS['dispatcher']; } public function __call($method, $arguments) { $event = $this->dispatcher->notifyUntil(new sfEvent($this, 'auth.extensible_function', array( 'method' => $method, 'arguments' => $arguments ))); if (!$event->isProcessed()) { throw new Exception(sprintf('Call to undefined method %s::%s.', get_class($this), $method)); } return $event->getReturnValue(); } /** * AuthenthificationProcess() * Authentification d'un utilisateur * * @param $login * @param $pass * @param $type ='PUBLIC' || 'ADMIN' * @return boolean (true) ou message d'erreur */ public function logIn($login, $pass, $type, $rememberme) { // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.logIn', array('login' => $login, 'password' => $pass, 'type' => $type))); return $this->builtInAuth($login, $pass, $type, $rememberme); } protected function builtInAuth($login, $pass, $type, $rememberme) { $src = LOG_ACCESS; list($login, $pass) = $GLOBALS['sql_object']->DBEscape(array($login, $pass)); // we get user Password salt $data = $GLOBALS['sql_object']->DBSelect(SQL_get_UserInfo($login)); if(isset($data[0]['salt'])) $salt = $data[0]['salt']; else $salt = ''; // will throw an error later $crypt_pass = crypt($pass, $salt); $data = $GLOBALS['sql_object']->DBSelect(SQL_Get_UserInfo4Auth($login, $crypt_pass)); if ($data != 0 && count($data) == 1) { $this->initSession($data, $login); if($rememberme) { $this->setCookieRememberMe(); } if ($type == 'ADMIN') { // si est simple utilisateur if (!array_search ('A' , $_SESSION['userright']) && !array_search ('O' , $_SESSION['userright'])) { $this->logOut(); logfile($src, array($type, $login, 'unauthorized', __METHOD__, $_SERVER['HTTP_USER_AGENT'], get_referer(), $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER['QUERY_STRING'], $_SERVER['HTTP_COOKIE'], i2c_realip())); return _t('divers','errorauth'); } } logfile($src, array($type, $login, 'success', __METHOD__, $_SERVER['HTTP_USER_AGENT'], get_referer(), $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER['QUERY_STRING'], $_SERVER['HTTP_COOKIE'], i2c_realip())); return true; } else { logfile($src, array($type, $login, 'failed', __METHOD__, $_SERVER['HTTP_USER_AGENT'], get_referer(), $_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI'], $_SERVER['QUERY_STRING'], $_SERVER['HTTP_COOKIE'], i2c_realip())); $error_msg = _t('divers','errorauth'); return $error_msg; } } /** * isSimpleUser() * * @return boolean */ public function isSimpleUser() { if(!isset($_SESSION['userright'])) return false; if(!in_array('A', $_SESSION['userright']) && !in_array('O', $_SESSION['userright'])) { return true; } else { return false; } } /** * isSuperAdmin() * * @return boolean */ public function isSuperAdmin() { return $this->hasRight('level'); } /** * logOut() * * @return boolean */ public function logOut() { $_SESSION = array(); session_unset(); session_destroy(); $this->destroyUserCookie(); if(isset($_COOKIE['linea21_uname'])) { list($login, $cookiehash) = explode ('_' , $_COOKIE['linea21_uname']); // we clean user_cookiehash field if set $GLOBALS['sql_object']->DBQuery('UPDATE l21_user SET user_cookiehash="" WHERE user_cookiehash = "' . $GLOBALS['sql_object']->DBEscape($cookiehash) . '" AND lower(user_login) = "'. $GLOBALS['sql_object']->DBEscape($login) . '" ;'); setCookieLinea21('linea21_uname', '', (time() - 3600)); } } /** * hasRight() * * @param string $item * @return bool */ public function hasRight($item, $subitem = false) { // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.has_right', array('element' => $item))); switch ($item) { case 'category_user': if ($this->GetSessionElement('right_category_user') != 'A') return false; else return true; case 'level': if ($this->GetSessionElement('right_level') != 'A') return false; else return true; case 'scale': if ($this->GetSessionElement('right_scale') != 'A') return false; else return true; case 'yellowpages': if ($this->GetSessionElement('right_yellowpages') != 'A') return false; else return true; case 'news': if ($this->GetSessionElement('right_news') != 'U') return true; else return false; case 'project': if ($this->GetSessionElement('right_project') == 'A' || $this->GetSessionElement('right_project') == 'O') return true; case 'task': if ($this->GetSessionElement('right_project') == 'A' || $this->GetSessionElement('right_project') == 'O') return true; else return false; case 'publication': if ($this->GetSessionElement('right_publication') != 'U') return true; else return false; case 'workshop': if ($this->GetSessionElement('right_workshop') != 'U') return true; else return false; case 'workshoprep': if ($this->GetSessionElement('right_workshop') != 'U') return true; else return false; case 'sdi': if ($this->GetSessionElement('right_sdi') != 'U') return true; else return false; case 'dashboard': if ($this->GetSessionElement('right_dashboard') != 'U') return true; else return false; case 'indicator': if (in_array($subitem, $this->GetSessionElement('indicators'))) return true; else return false; default: return false; } } /** * initSession() * Init user session * * @param $data * @return boolean (true) ou message d'erreur */ public function initSession($data, $login) { // préparation du tableau de droits $right['sdi'] = $data[0]['rights_sdi']; $right['dashboard'] = $data[0]['rights_dashboard']; $right['workshop'] = $data[0]['rights_workshop']; $right['project'] = $data[0]['rights_project']; $right['publication'] = $data[0]['rights_publication']; $right['news'] = $data[0]['rights_news']; $right['yellowpages'] = $data[0]['rights_yellowpages']; $right['level'] = $data[0]['rights_level']; $right['scale'] = $data[0]['rights_scale']; $right['category_user'] = $data[0]['rights_category_user']; $_SESSION['authenticated'] = true; $_SESSION['userid'] = base64_encode($data[0]['user_id']); $_SESSION['userwhois'] = base64_encode($data[0]['user_password']); $_SESSION['userlogin'] = $login; $_SESSION['lastcon'] = $data[0]['user_last_con']; $_SESSION['logout_token'] = md5(uniqid(rand(), true)); if(!empty($data[0]['profile_firstname'])) { $_SESSION['userfirstname'] = $data[0]['profile_firstname']; } if(!empty($data[0]['profile_lastname'])) { $_SESSION['userlastname'] = $data[0]['profile_lastname']; } $_SESSION['userright'] = $right; $_SESSION['projects'] = $this->retrieveUserProjects(array('login' => $login, 'pass' => $data[0]['user_password'])); $_SESSION['indicators'] = $this->retrieveProjectsIndicators($_SESSION['projects']); $workgroups = $this->retrieveUserWorkgroups(array('login' => $login, 'pass' => $data[0]['user_password'])); $table['workshop'] = base64_encode($workgroups); $table['lifetime'] = time() + 3600 * 720; $this->destroyUserCookie(); // we update the last connexion field $GLOBALS['sql_object']->DBQuery('UPDATE l21_user SET user_last_con = NOW() where user_id=' . $data[0]['user_id'] . ';'); // Filter data event + return value $r = $this->dispatcher->filter(new sfEvent(__FUNCTION__, 'auth.extend_session', array('data' => $table)), $table); $table = $r->getReturnValue(); $this->setUserCookie($table); return true; } /** * GetSessionElement() * * @param string $item * @return $result */ public function GetSessionElement($item) { // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.get_session_element', array('element' => $item))); switch ($item) { case 'id': return base64_decode($_SESSION['userid']); break; case 'whois': return base64_decode($_SESSION['userwhois']); break; case 'login': return $_SESSION['userlogin']; break; case 'firstname': if(isset($_SESSION['userfirstname'])) return $_SESSION['userfirstname']; break; case 'lastname': if(isset($_SESSION['userlastname'])) return $_SESSION['userlastname']; break; case 'projects': return $_SESSION['projects']; break; case 'indicators': return $_SESSION['indicators']; break; case 'right_level': return $_SESSION['userright']['level']; break; case 'right_sdi': return $_SESSION['userright']['sdi']; break; case 'right_dashboard': return $_SESSION['userright']['dashboard']; break; case 'right_workshop': return $_SESSION['userright']['workshop']; break; case 'right_project': return $_SESSION['userright']['project']; break; case 'right_publication': return $_SESSION['userright']['publication']; break; case 'right_news': return $_SESSION['userright']['news']; break; case 'right_yellowpages': return $_SESSION['userright']['yellowpages']; break; case 'right_scale': return $_SESSION['userright']['scale']; break; case 'right_category_user': return $_SESSION['userright']['category_user']; break; case 'logout_token': return $_SESSION['logout_token']; break; default: return false; break; } } /** * isWorkgroupUser() * check if the current user belongs to a workgroup * used in PUBLIC app * @param $workshop_id * @return boolean */ public function isWorkgroupUser($workshop_id, $sql_object) { // check if user has cookie, if not we exit if(!$this->isAuthenticated()) return false; // if is SuperAdmin we allow the access if($this->isSuperAdmin()) return true; // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.is_workgroup_user', array('id' => $workshop_id))); include_once('../admin/'.SQL.'.inc.php'); // 1 -we check that login and password stored in sessions are corrects $q = SQL_Get_UserInfo4Auth($this->GetSessionElement('login'), $this->GetSessionElement('whois')); $data = $sql_object->DBSelect($q); if ($data != 0 && count($data) == 1 && $data[0]['user_id'] == $this->GetSessionElement('id')) { // 2 - if ok, we check that the user belongs to the given group $r = $sql_object->DBSelect(SQL_Get_isWorkgroupUser($data[0]['user_id'])); if(is_array($r)) { for ($i = 0; $i < count($r); $i++) { if ($workshop_id == $r[$i]['jwu_workshop_id']) { return true; } } } } return false; } /** * isWorkgroupPendingUser() * check if the current user is waiting for * workgroup subscription approval * used in PUBLIC app * @param $workshop_id * @return boolean */ public function isWorkgroupPendingUser($workshop_id, $sql_object) { // check if user has cookie, if not we exit if(!$this->isAuthenticated()) return false; // if is SuperAdmin we allow the access if($this->isSuperAdmin()) return true; // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.is_workgroup_user', array('id' => $workshop_id))); include_once('../admin/'.SQL.'.inc.php'); // 1 -we check that login and password stored in sessions are corrects $q = SQL_Get_UserInfo4Auth($this->GetSessionElement('login'), $this->GetSessionElement('whois')); $data = $sql_object->DBSelect($q); if ($data != 0 && count($data) == 1 && $data[0]['user_id'] == $this->GetSessionElement('id')) { // 2 - if ok, we check that the user belongs to the given group $r = $sql_object->DBSelect(SQL_Get_isWorkgroupPendingUser($data[0]['user_id'])); if(is_array($r)) { for ($i = 0; $i < count($r); $i++) { if ($workshop_id == $r[$i]['jwu_workshop_id']) { return true; } } } } return false; } /** * isProjectManager() * check if a given user is project manager * used in ADMIN app * @param $id_user * @param $sql_object * @param $id_project * @return boolean */ public function isProjectManager($id_user, $sql_object, $id_project) { // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.is_project_manager', array('id' => $id_user, 'project_id' => $id_project))); $data = $sql_object->DBSelect(SQL_Get_isProjectManager($id_user)); for ($i = 0; $i < count($data); $i++) { if ($id_project == $data[$i]['jpm_project_id']) return true; } return false; } /** * isWorkgroupOrganiser() * check if a given user is workgroup organiser * used in ADMIN app * @param $id_user * @param $sql_object * @param $id_workshop * @return boolean */ public function isWorkgroupOrganiser($id_user, $sql_object, $id_workshop) { // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.is_workgroup_organiser', array('id' => $id_user, 'workgroup_id' => $id_workshop))); $data = $sql_object->DBSelect(SQL_Get_isWorkgroupOrganiser($id_user)); if(is_array($data)) { for ($i = 0; $i < count($data); $i++) { if ($id_workshop == $data[$i]['jwu_workshop_id']) return true; } } return false; } public function isAuthenticated() { if(isset($_SESSION['authenticated'])) return true; else return false; } /** * identifyWithLogin() * Authentification d'un utilisateur * par son login seulement * (oubli du mot de passe) * @param $login * @return array */ public function identifyWithLogin($login) { // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.identify_login', array('login' => $login))); $login = $GLOBALS['sql_object']->DBEscape($login); $data = $GLOBALS['sql_object']->DBSelect(SQL_get_UserInfo($login)); if (is_array($data) && count($data) == 1) { logfile(LOG_MAINFILE, array('[action] retrieve forgotten password', 'method=' . __METHOD__, 'login='.$login, 'records_nb=' . count($data), 'returned_value=' . $data[0]['profile_email'] )); return $data[0]; } else { logfile(LOG_MAINFILE, array('[action] retrieve forgotten password', 'method=' . __METHOD__, 'login='.$login, 'returned_value=false')); return false; } } /** * identifyWithEmail() * Authentification d'un utilisateur * par son email * (oubli du mot de passe) * @param $email * @return array */ public function identifyWithEmail($email) { // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.identify_email', array('email' => $email))); $email = $GLOBALS['sql_object']->DBEscape($email); $data = $GLOBALS['sql_object']->DBSelect(SQL_get_UserInfoByEmail($email)); if (is_array($data)) { if(count($data) == 1) { logfile(LOG_MAINFILE, array('[action] retrieve forgotten password', 'method=' . __METHOD__, 'email='.$email, 'records_nb=' . count($data), 'returned_value=' .$data[0]['user_login'] )); return $data[0]; } elseif(count($data) > 1) { logfile(LOG_MAINFILE, array('[action] retrieve forgotten password', 'method=' . __METHOD__, 'email='.$email, 'records_nb=' . count($data), 'returned_value=false' )); return false; } } else { logfile(LOG_MAINFILE, array('[action] retrieve forgotten password', 'method=' . __METHOD__, 'email='.$email, 'records_nb=' . count($data), 'returned_value=false')); return false; } } /** * retrieveUserProjects() * Retrieve Projects for a given user * @param $a array (optional) * @return array */ public function retrieveUserProjects($a = array()) { // user already logged-in if(isset($_SESSION['authenticated'])) { $login = $_SESSION['userlogin']; $crypt_pass = base64_decode($_SESSION['userwhois']); } else { if(isset($a['login'])) { $login = $a['login']; $crypt_pass = $a['pass']; } else { return false; } } // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.retrieve_user_projects', array('login' => $login, 'password' => $crypt_pass))); $data = $GLOBALS['sql_object']->DBSelect(SQL_Get_UserProject($login, $crypt_pass)); $projects = array(); if(isset($data[0]['jpm_project_id'])) { for ($i = 0; $i < count($data); $i++) { array_push($projects, $data[$i]['jpm_project_id']); } } return $projects; } /** * retrieveProjectsIndicators() * Retrieve Indicators for given projects * @param $a array (optional) - containing projects ID * @return array */ public function retrieveProjectsIndicators($a = array()) { if(isset($a)) { $projects = $a; } else { // user already logged-in if(isset($_SESSION['authenticated'])) { $projects = $_SESSION['projects']; } else { $projects = array(); } } // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.retrieve_user_indicators', array('data' => $projects))); $indicators = array(); if(count($projects) > 0) { $data = $GLOBALS['sql_object']->DBSelect(SQL_Get_ProjectIndicators($projects)); for ($i = 0; $i < count($data); $i++) { array_push($indicators, $data[$i]['jps_sdi_id']); } } return $indicators; } /** * retrieveUserWorkgroups() * Retrieve Workgroups for a given user * @param $a array (optional) * @return string */ public function retrieveUserWorkgroups($a = array()) { // user already logged-in if(isset($_SESSION['authenticated'])) { $login = $_SESSION['userlogin']; $crypt_pass = base64_decode($_SESSION['userwhois']); } else { if(isset($a['login'])) { $login = $a['login']; $crypt_pass = $a['pass']; } else { return false; } } // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.retrieve_user_workgroups', array('login' => $login, 'password' => $crypt_pass))); $data_w = $GLOBALS['sql_object']->DBSelect(SQL_Get_UserWorkshop($login, $crypt_pass)); $workgroups = ''; if(is_array($data_w)) { for ($i = 0; $i < count($data_w); $i++) { $workgroups .= "/" . $data_w[$i]['jwu_workshop_id']; } } return $workgroups; } /** * updateSessionPassword() * Mise à jour du mot de passe en session (cas de changement) * @param $newpass * @return boolean */ public function updateSessionPassword($newpass) { // Notify the beginning of the current method; $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.update_cookie_password')); $_SESSION['userwhois'] = base64_encode($newpass); return true; } /** * updateCookieWorkshop() * Update workgroups list in cookie * used in public/ part * * @return void */ function updateCookieWorkshop() { // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.update_cookie_workshop')); $str = base64_encode($this->retrieveUserWorkgroups()); if(isset($_COOKIE['linea21']['lifetime'])) setCookieLinea21('linea21[workshop]', $str, $_COOKIE['linea21']['lifetime']); else setCookieLinea21('linea21[workshop]', $str, time() + 3600 * 720); // should not occur ... } /** * setUserCookie() * set les infos contenu en tableau PHP en cookie * * @param $array * @return void */ public function setUserCookie($array) { // Notify the beginning of the current method // Filter data event + return value $r = $this->dispatcher->filter(new sfEvent(__FUNCTION__, 'auth.set_user_cookie', array('data' => $array)), $array); $array = $r->getReturnValue(); $cookie_expires = $array['lifetime']; if(!is_array($array)) return false; foreach ($array as $key => $value) { setCookieLinea21('linea21[' . $key . ']', $value, $cookie_expires); } } /** * destroyUserCookie() * Détruit les infos contenues en cookie * * @return void */ public function destroyUserCookie() { // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.destroy_user_cookie')); if(!isset($_COOKIE['linea21'])) return false; foreach ($_COOKIE['linea21'] as $key => $value) { setCookieLinea21('linea21[' . $key . ']', '', (time() - 3600)); } } /** * setCookieLastPage() * used for the admin/ part */ public function setCookieLastPage() { // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.set_cookie_lastpage')); if(isset($_SESSION['authenticated'])) { setCookieLinea21('linea21_lastpage', 'index.php?'.$_SERVER['QUERY_STRING'], (time() + 3600 * 720)); setCookieLinea21('linea21_lastuser', $_SESSION['userlogin'], (time() + 3600 * 720)); setCookieLinea21('linea21_lastactivity', time(), (time() + 3600 * 720)); } return true; } /** * setCookieLastPage() * used for the admin/ part */ public function setCookieRememberMe() { if(!defined('REMEMBER_ME') || REMEMBER_ME == 0) return true; // Notify the beginning of the current method $this->dispatcher->notify(new sfEvent(__FUNCTION__, 'auth.set_cookie_rememberme')); if(isset($_SESSION['authenticated'])) { $cookiehash = md5(str_shuffle($_SESSION['userwhois'] . $_SESSION['userlogin'])); setCookieLinea21("linea21_uname", $_SESSION['userlogin'] . '_' . $cookiehash, time()+ REMEMBER_ME); // we create a cookiehash stored in db for automatic connexion $GLOBALS['sql_object']->DBQuery('UPDATE l21_user SET user_cookiehash = "' . $GLOBALS['sql_object']->DBEscape($cookiehash) . '" WHERE lower(user_login) = "' . $_SESSION['userlogin'] . '";'); } return true; } /** * isActive() * check if last activity is less than SESS_INACTIVITY_MAXTIME * If more, destroy the session */ public function isActive() { include_once('../admin/'.SQL.'.inc.php'); if (!$this->isAuthenticated()) { // if rememberme option is disabled, we exit if(!defined('REMEMBER_ME') || REMEMBER_ME == 0) return false; // if rememberme is set if(isset($_COOKIE['linea21_uname'])) { list($login, $cookiehash) = explode ('_' , $_COOKIE['linea21_uname']); $data = $GLOBALS['sql_object']->DBSelect(SQL_Get_UserFromRememberMe($cookiehash, $login)); if ($data != 0 && count($data) == 1) { $this->initSession($data, $login); return true; } } else { return false; } } if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > SESS_INACTIVITY_MAXTIME)) { // last request was more than SESS_INACTIVITY_MAXTIME (in seconds) ago session_unset(); // unset $_SESSION variable for the run-time session_destroy(); // destroy session data in storage $_SESSION = array(); return false; } $_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp return true; } } ?>