Location: PHPKode > projects > OOB-n1 PHP5 Framework > dev/oob/oob_user.php
<?
#OOB/N1 Framework [©�2004,2005 - Nutus]
/**
 @license: BSD
 @author: Pablo Micolini (hide@address.com)
 @author: Victor Stornati (hide@address.com) // update


 Provides user validation (login/logout)
*/

//OOB_module :: includeClass ('personnel','personnel_employee');

class OOB_user extends OOB_internalerror {
	// @implementation cuando un usuario ha sido bloqueado, pero habia alguien logueado, q debe hacer el sistema? sacarlo? nada?
	
	private $user= ID_UNDEFINED;
	private $uname = '';
	private $password = '';
	private $email = '';
	private $session = '';
	private $status= 8; // 0 neeeds auth, 1 ok, 2 temp block, 9 deleted
	private $maxcon= 5;
	private $block_method= 1; // 0 no block, 1 time, 2 statuschange 
	private $block_time= "3600"; //10 minutos
	private $source= "db"; // db, imap
	private $new_validation= "no"; // 0 no, 1 mail, 3 admin
	private $employee = NO_OBJECT;
	
	public function id()
	{
		return $this->get('user');
	}
	
	public function name()
	{
		return $this->get('uname');
	}
	
	/** loads config details, and starts the user. 
 	    if no user set we must believe is a new one */
	public function __construct($user= ID_UNDEFINED) {
		global $ari;
		//load config vars!
		$this->block_method= $ari->get("config")->get('block-method', 'user');
		$this->block_time= $ari->get("config")->get('block-time', 'user');
		$this->source= $ari->get("config")->get('validation-method', 'user');
		$this->new_validation= $ari->get("config")->get('new_validation', 'user');
		if ($user > ID_MINIMAL) {
			$this->user= $user;
			
			if (!$this->fill ())
					{throw new OOB_exception("Invalir user {$user}", "403", "Invalid User", false);}
					
		}  
	}
		
	/** user validation made, username and password must be provided */
	public static function login($uname, $pass) {
		global $ari;
		
	
		
		// clean vars
		if (OOB_validatetext :: isClean($uname) && OOB_validatetext :: isClean($pass) && OOB_validatetext :: isPassword($pass)) {
			
			$imap_pass = $pass;
			$pass= md5($pass); 
		
		} else
			return false;
			
			// load config vars
			$source= $ari->get("config")->get('validation-method', 'user');
			$blocktime= $ari->get("config")->get('block-time', 'user');
			$savem = $ari->db->SetFetchMode(ADODB_FETCH_NUM);
			$uname = $ari->db->qMagic ($uname);
			
			// get id where user and pass matches (using proper auth method!)
			// @fixme LOCK ROW TILL FINISH ?
			
			$sql= "SELECT id, password, status FROM oob_user_user WHERE uname = $uname";
			$ari->db->SetFetchMode($savem);
			$rs = $ari->db->Execute($sql);
			
			if (!$rs || $rs->EOF) {
				return false;
			
			} else {
				$userid= $rs->fields[0];
				$password= $rs->fields[1];
				$status= $rs->fields[2];
				$rs->Close();
				
			}
			switch ($source)
			{
				//lo de siempre es una db	
				case "db":
				default:
				 {
							
					if ($password != $pass) 
						{
						// add failed for uid! if pass not match!
						self::addFailed ($userid, "WRONGPASS");
					
						//contamos cuantos fallados tiene, y 
						// si son mas de los q deberia, lo sentimos mucho
						$fallados = self::getFailed ($userid, $blocktime); 
					
						if ($fallados > 10)
							{throw new OOB_exception("BLOCKED User ($uname)", "403", "Su usuario ha sido desactivado, contacte al administrador", true);}
					
						return false;				
				
				
						}
					break;
					}
					
//				case "imap": {
//					
//					$server = $ari->get("config")->get('imap-server', 'user');
//				
//					//if ok, continue, else add failed as pass not match
//					if ($mbox = @imap_open("{" . $server . "}INBOX", "$uname", "$imap_pass", OP_READONLY))
//					{
//						@imap_close ($mbox);
//						
//						 } else {
//						$now = $ari->db->DBTimeStamp(time());
//						$sql = "insert into oob_user_failed (id, user_id, timestamp , reason )
//								values ('','$userid',$now,'IMAP_INVALID')";
//						if ($ari->db->Execute($sql) === false)
//						throw new OOB_exception("Error en DB: {$ari->db->ErrorMsg()}", "010", "Error en la Base de Datos", false);
//					
//						return false;
//					
//					}
//				
//				}
			}
			


			if ($status != 1) {
			throw new OOB_exception("DISABLED", "403", "Su usuario ha sido desactivado, contacte al administrador", false);
			}
			
//valida el permiso de acceso al modulo admin		
			if ($ari->get('mode') == 'admin' ) 
			{
				//verificar permiso
						if ( !seguridad :: isAllowed(seguridad_action :: nameConstructor('adminaccess','access','admin'), '',  new oob_user ($userid)) )
				{
					throw new OOB_exception("Acceso denegado a Usuario {$uname}", "403", "Acceso denegado. Consulte con su administrador", true);
						
				}					
			}		
			
			
			$sessionkey = session_id();
			
			// Con esto grabamos los datos de sesion, para poder loguear al usuario sin problemas 
			session_write_close(); 
			
			
			//stores the login->session key relation (if there is one previously, updates the record.)
			$savem= $ari->db->SetFetchMode(ADODB_FETCH_NUM);
			$sql= "SELECT user_id FROM oob_user_online WHERE sesskey  = '$sessionkey'";
			$ari->db->SetFetchMode($savem);
			$rs = $ari->db->Execute($sql);

			if (!$rs || $rs->EOF) {
				
					$sql = "INSERT INTO oob_user_online (user_id,sesskey )
							values ('$userid','$sessionkey')";

					if ($ari->db->Execute($sql) === false)
					
					throw new OOB_exception("Error en DB: {$ari->db->ErrorMsg()}", "010", "Error en la Base de Datos, o en la asignación de Sesion, recargue la página", false);

				
								
					return  new oob_user ($userid);
			
			} else {
				$useridlogued= $rs->fields[0];
				$rs->Close();
				
							}
						
					if ($useridlogued == $userid)
						return   new oob_user ($userid);
					else {
						$sql= "UPDATE oob_user_online SET  user_id = '$userid' WHERE sesskey  = '$sessionkey'";

						if ($ari->db->Execute($sql) === false)
							throw new OOB_exception("Error en DB: ". $ari->db->ErrorMsg(), "010", "Error en la Base de Datos", false);
					
						return  new oob_user ($userid);
					
						}					


	}	
	
	/** deletes the sessionid->login link.
	 * You can provide a redirection url, default is home  */
	public function logout($redirect ='/') {

				global $ari;
			$sessionkey = session_id();
			$sql= "DELETE FROM oob_user_online WHERE sesskey  = '$sessionkey' AND  user_id = '$this->user'";
			$ari->db->Execute($sql);
			if ($ari->get('mode') == 'admin')
			header( "Location: " . $ari->get("adminaddress") . $redirect);
			else
			header( "Location: " . $ari->get("webaddress") . $redirect);
			exit;		
		
	}

	/** 
 	look for session id->login link, 
 	if exist return user-object, else false.  */
	 public static function isLogued() {
		
		global $ari;
		
			$sessionkey = session_id();
			$savem= $ari->db->SetFetchMode(ADODB_FETCH_NUM);
			$sessionkey = $ari->db->qMagic ($sessionkey);
			$sql= "SELECT user_id FROM oob_user_online WHERE sesskey  = $sessionkey";
			$rs = $ari->db->Execute($sql); 
			
			$ari->db->SetFetchMode($savem);
					
				if (!$rs || $rs->EOF) {
				return false;
			}
			
			if (!$rs->EOF && $rs->RecordCount() == 1) {
			
			$userid = $rs->fields[0];
				$rs->Close();
				return new oob_user ($userid);

			}
		//	return false; // por las dudas?
			throw new OOB_exception("Mas de un Usuario para la misma Sesión", "501", "Ha ocurrido un error inesperado", true);
		
		
	}
	
	 public static function lostPass($user) //DO
	{
	}
	
	 public static function validateLost($code, $user) //DO 
	{
	}
	
	/** Returs the value for the given var */ 	
 	public function get ($var)
 	{
 		return $this-> $var;
 	}

	/** Sets the variable (var), with the value (value) */ 	
 	public function set ($var, $value)
 	{
		$this->$var= $value;
 	} 	

	/** Stores/Updates user object in the DB */	
	public function store() {
		global $ari;
		// clean vars !
	
		
			 if (!OOB_validatetext :: isClean($this->uname) || !OOB_validatetext :: isCorrectLength ($this->uname, 4, 64))
			 {
			 $ari->error->addError ("oob_user", "INVALID_USER");
			 } else {
			 	 if ($this->user == ID_UNDEFINED) 
			 	 // si es nuevo, debo revisar que no exista de antes!
			 	{
			 $savem= $ari->db->SetFetchMode(ADODB_FETCH_NUM);
			 $uname = $ari->db->qMagic($this->uname);
			$sql= "SELECT id as cuenta FROM oob_user_user WHERE uname = $uname";
			$rs = $ari->db->Execute($sql);
			$ari->db->SetFetchMode($savem);
			
		
			if (!$rs->EOF && $rs->fields[0]!= 0) {
				
			
			$this->error()->addError ("INVALID_USER");
			$rs->Close();
			}
			
			
			
			}
			}//--
			
			  if ($this->password != -1)
			  {
			  if (!OOB_validatetext :: isClean($this->password) ||!OOB_validatetext :: isPassword($this->password) )
			 $this->error()->addError ( "INVALID_PASS"); 
			  }
			  
			  if ( 	!OOB_validatetext :: isEmail($this->email)  )
			   $this->error()->addError ("INVALID_EMAIL");
			  
			  if ( 	!OOB_validatetext :: isNumeric($this->status) )
			  $this->error()->addError ("INVALID_STATUS", true);
			
			$employee_id = "0";
			
			if (is_a ($this->employee, "personnel_employee") )
			{	$employee_id = $ari->db->qMagic($this->employee->get('id'));	}
			
			if (!$this->error()->getErrors())
			 {
			 	
			 	$this->uname =$ari->db->qMagic($this->uname);
			 	$this->email =$ari->db->qMagic($this->email);
			 	
			 	if ($this->password == -1)
			 	$passql = "";
			 	else
			 	{
			 	//	$this->password =$ari->db->qMagic( $this->password);
			 		$this->password = md5 ($this->password);
			 		$passql = "password = '$this->password',";
			 	
			 	}
				
				if ($this->user > 0)
					{
					// update data
					$ari->db->StartTrans();
					$sql= "UPDATE oob_user_user SET uname = $this->uname ,$passql email = $this->email, status = '$this->status'  WHERE id = '$this->user'";
					$ari->db->Execute($sql);
					
					
					$ari->db->CompleteTrans();
					
					if ($ari->db->HasFailedTrans())
					throw new OOB_exception("Error en DB: {$ari->db->ErrorMsg()}", "010", "Error en la Base de Datos", false); //return false;
					else
					{
					$this->password = -1;
					return true;}
					
					} else {
			// insert new and set userid with new id
					$ari->db->StartTrans();
										
					$sql= "INSERT INTO oob_user_user 
						   ( uname, password, email, connections, status, EmployeeID)
						   VALUES ( $this->uname, '$this->password', $this->email ,'1','$this->status', $employee_id)
						   	";
					$ari->db->Execute($sql);

					$rs = $ari->db->CompleteTrans();
					if ($ari->db->HasFailedTrans())
					throw new OOB_exception("Error en DB: {$ari->db->ErrorMsg()}", "010", "Error en la Base de Datos", false); //return false;
					else
					{
					
					$this->user = $ari->db->Insert_ID();
					$this->password = -1;
					
					return true;}
					}
			} else {
			// no validan los datos

			 return false; //devuelve un objeto de error con los errores!
			}

	}	

	/** Deletes user object from the DB*/
	public function delete() {
		global $ari;
		// sets status 9 for a user-id
		if ($this->user > 0 && $this->status != 9) {

			$sql= "UPDATE oob_user_user SET  status = '9' WHERE id = '$this->user'";
			if ($ari->db->Execute($sql))
				return true;
			else
				throw new OOB_exception("Error en DB: {$ari->db->ErrorMsg()}", "010", "Error en la Base de Datos", false);
					

		} else {
			if ($this->status == 9)
			$this->error()->addError ("ALREADY_DELETED");
			else
					 $this->error()->addError ( "NO_SUCH_USER");
			
			return false;
		}
	}
	
	/** Returs the users on the system. status = (enabled/deleted/pending/bloqued/all) shows users */
	static public function userList ($status = 'enabled', $sort = 'uname')
	{
	global $ari;
	


	if (in_array ($status, oob_user::getStatus ("ALL", false)) && $status != "all")
	{
	$estado = "WHERE status = " . oob_user::getStatus($status, false);
	}
	else
	{
		if ($status == "all")
			{$estado = "";}
		else
			{$estado = "WHERE status = 1";}
	}

	if (in_array ($sort, oob_user::getOrders()))
		$sortby = "ORDER BY $sort";
	else
		$sortby = "ORDER BY uname";

			$savem= $ari->db->SetFetchMode(ADODB_FETCH_NUM);
			$sql= "SELECT id FROM oob_user_user  $estado $sortby";
			$rs = $ari->db->Execute($sql);

			$ari->db->SetFetchMode($savem);
				if ($rs && !$rs->EOF) { // aca cambie sin probar, hay q ver si anda!
					while (!$rs->EOF) {
					$return[] = new oob_user ($rs->fields[0]);
					$rs->MoveNext();
					}			
			$rs->Close();
			} else
			{return false;}

		return $return;
	}

	/** Shows the available sorting ways for users */
	static public function getOrders()
	{
	$return[] = "uname";
	$return[] = "id";
	$return[] = "email";
	$return[] = "status";
	
	return $return;
	}

	/** Shows the available status for users, or all */	
	static public function getMethods()
	{

	$return[] = "enabled";
	$return[] = "deleted";
	$return[] = "pending";
	$return[] = "bloqued";
	$return[] = "all";
	
	return $return;
	}
	
	/** Shows the user status or all available status 
	 * $one = ID or "status_string" returns the user status; or "ALL" to return an array.
	 * $id => if true, returns a number, else a string.
	 * */
		static public function getStatus ( $one = "ALL" ,$id = true) 
	{ // 0 neeeds auth, 1 ok, 2 temp block, 9 deleted

	$return[1] = "enabled";
	$return[2] = "bloqued";
	$return[0] = "pending";
	$return[9] = "deleted";
	
	if ($id != true)
	$return = array_flip ($return);
	
	if ($one !== "ALL")
	
	{
		if ($return[$one] !== "" )
		{$return = $return[$one];}
		else
		{$return =  false;}

	}
	
	
	return $return;
	}

	/** Updates a given array of users (id), with the status provided. */
	static public function updateStatusFor ($data, $status = false)
	{
	
	if (!in_array($status, oob_user::getMethods()))
	{throw new OOB_exception("User gave a POST value that is unexistant", "403", "Información inválida desde el Usuario", true);}
	
		foreach ($data as $usuario)
		{
		$new = new oob_user ($usuario);
			
		if (OOB_validatetext::isNumeric($status))
			{$new->set ('status', $status);}
		
		else
			{$new->set ('status', oob_user::getStatus($status, false));}
		
		if (!$new->store())
			{throw new OOB_exception("System Error - STATUS:{$status} is invalid", "501", "System Error", true);}
		}

	}
	
	/** Fills the user with the DB data */
	private function fill ()
	{
	global $ari;

			//load info
			$savem= $ari->db->SetFetchMode(ADODB_FETCH_ASSOC);
			$sql= "SELECT Uname, Password, Email, Connections, Status, EmployeeID 
				   FROM OOB_User_User 
				   WHERE id = '$this->user'";
			$rs = $ari->db->Execute($sql);
			
			$ari->db->SetFetchMode($savem);
			if (!$rs || $rs->EOF) 
			{
				return false;
			}
			if (!$rs->EOF) 
			{
				$this->uname= $rs->fields["Uname"];
				$this->password= -1;
				$this->email= $rs->fields["Email"];
				$this->maxcon= $rs->fields["Connections"];
				$this->status= $rs->fields["Status"];
				if (!empty($rs->fields['EmployeeID']) && OOB_validatetext :: isNumeric($rs->fields['EmployeeID']) && $rs->fields['EmployeeID'] > ID_MINIMAL)
				{	$this->employee = new personnel_employee($rs->fields['EmployeeID']);	}
			}
			$rs->Close();
			return true;
	
	}

	/** gets the amout of failed login attemps for a given user-id, with a block time */
	private function getFailed ($userid, $blocktime){
	global $ari;
	
					$userid = $ari->db->qMagic ($userid);
					$savem = $ari->db->SetFetchMode(ADODB_FETCH_NUM);
					$block = $ari->db->DBTimeStamp(time() - $blocktime );
					$sql= "SELECT count(id) as cuenta  FROM oob_user_failed WHERE timestamp > $block AND user_id = $userid";
					$ari->db->SetFetchMode($savem);
					$rs = $ari->db->Execute($sql);
					$cuenta = 0;
					if (!$rs->EOF) {
						$cuenta = $rs->fields[0];
						$rs->Close();
					}
	
	return $cuenta;
	}
	
	/** logs a failed attempted login to the Db for a given user */
	private function addFailed ($userid, $message = "UNDEFINED")
	{
		global $ari;
		
						$now = $ari->db->DBTimeStamp(time());
						$msg = $ari->db->qMagic ($message);
						$sql = "INSERT INTO oob_user_failed ( user_id, timestamp , reason )
								values ('$userid',$now,$msg)";
						if ($ari->db->Execute($sql) === false)
							throw new OOB_exception("Error en DB: {$ari->db->ErrorMsg()}", "010", "Error en la Base de Datos", false);
						
	}
	 

  	/**	Devuelve true si ya existe el nombre de usuario pasado como parametro */
	static public function exists ($uName, $clausula = '')
	{
		global $ari;
		
		$uName = $ari->db->qMagic(trim($uName));
		$savem= $ari->db->SetFetchMode(ADODB_FETCH_ASSOC);
		
		$sql= "SELECT True as Existe 
			   FROM OOB_User_User
			   WHERE Uname = $uName $clausula";
		
		$rs = $ari->db->Execute($sql);
		$ari->db->SetFetchMode($savem);

		if (!$rs->EOF && $rs->fields['Existe']) 
		{	$return = true;		}
		else
		{	$return = false;	}
		
		$rs->Close();
		return $return;
	}
	
	/**
     * Esta funcion valida q los empleados q vienen en el string existan
     * el formato de la cadena es la siguiente
     * LastNameEmployee1, FirstNameEmployee1 EMPLOYEE_SEPARATOR LastNameEmployee2, FirstNameEmployee2......
     * La funcion devuelve un array con los usuarios correspondientes a los empleados q se encontraron, 
     * en caso de q un empleado no exista su lugar en el array lo ocupara un valor booleano false
	 */
	static public function getUsersByString( $string )
	{
	  	$users = array();  	 
	  	$string = trim($string);
	  	$i = 0;
	  	 	
	  	if ($string == "")
	  	{	return false;	}
	  	 
	  	//creo un array con los nombres y apellidos de los empleados
	  	$array_employee = explode(EMPLOYEE_SEPARATOR,$string);
	  	
	  	if (! is_array($array_employee) )
	  	{
	  		$array_employee = array();	
	  		$array_employee[0] = $string;	
	  	}//end if

	  	//recorro el array y separo los nombres y los apellidos
	  	foreach($array_employee as $e)
		{	
			$e = trim($e);
			if ($e != "")
			{
				//busco la posicion del separador de nombres
		  	 	$pos_coma = strpos ($e, NAME_SEPARATOR);
		  	 	
		  	 	if ($pos_coma)
				{ //encontro la posicion
		 			$lastName = trim(substr($e,0,$pos_coma));
					$firstName = trim(str_replace( NAME_SEPARATOR, "", substr($e,$pos_coma+1,strlen($e)-1)));
				}
		  	 	else
				{
					//ver q pasa si no tiene coma
		 			$lastName = $e;
		 			$firstName = '';
				}//end if 
				$users[$i]['employeename'] = $lastName ." ". $firstName;
				$users[$i]['object'] = OOB_User :: getUserByEmployeeName($lastName, $firstName);
				$i++;
			}//end if		
		}//end foreach 				
		
		return $users;
	}//end fucntion	
	
	
	/** Retorna el usuario cuyo empleado tiene el nombre y apellido 
	 *  pasado por parametro 
	 */ 	
 	static public function getUserByEmployeeName ($lastName = '',$firstName = '' )
 	{
		global $ari;
		
		if ( $lastName == '' && $firstName == '' )
		{	return false;	}
		
		//load info
		$savem= $ari->db->SetFetchMode(ADODB_FETCH_ASSOC);
		
		$firstName = trim($ari->db->qMagic($firstName));
		$lastName = trim($ari->db->qMagic($lastName));
		
	 	$sql = "SELECT `OOB_User_User`.`ID` AS `UserID`, `OOB_User_User`.`Uname`,
					   `OOB_User_User`.`Password`, `OOB_User_User`.`Email`,
					   `OOB_User_User`.`Connections`, `OOB_User_User`.`Status` AS `UserStatus`,
				       `OOB_User_User`.`EmployeeID`, `Personnel_Employee`.`LastName`, 
			 		   `Personnel_Employee`.`FirstName`, `Personnel_Employee`.`BirthDate`, 
					   `Personnel_Employee`.`EmployeeNumber`, `Personnel_Employee`.`Description`, 
					   `Personnel_Employee`.`Status` AS `EmployeeStatus`
				FROM `Personnel_Employee`, `OOB_User_User`	 		
				WHERE `OOB_User_User`.`EmployeeID` = `Personnel_Employee`.`ID`
			    AND `Personnel_Employee`.`LastName` = $lastName
			    AND `Personnel_Employee`.`FirstName` = $firstName
			    AND `Personnel_Employee`.`Status` = '" . USED . "'";
	
		$rs = $ari->db->SelectLimit($sql,1,0);
		$ari->db->SetFetchMode($savem);
		if (!$rs || $rs->EOF) 
		{	$return = false;	}
		else 
		{	
			$return = new oob_user (ID_UNDEFINED);
			$return->user = $rs->fields["UserID"];
			$return->uname = $rs->fields["Uname"];
			$return->password = $rs->fields["Password"];
			$return->email = $rs->fields["Email"];
			$return->maxcon = $rs->fields["Connections"];
			$return->status = $rs->fields["UserStatus"];				
				
			$employee = new personnel_employee(ID_UNDEFINED);
			$employee->set("id",$rs->fields["EmployeeID"]);
			$employee->set("lastName", $rs->fields["LastName"]);
			$employee->set("firstName",$rs->fields["FirstName"]);			
			$employee->set("birthDate", new Date($rs->fields['BirthDate']) );
			$employee->set("employeeNumber", $rs->fields["EmployeeNumber"]);	
			$employee->set("description", $rs->fields["Description"]);
			$employee->set("status",$rs->fields["EmployeeStatus"]);
				
			$return->employee = $employee;

		}//end if
		$rs->Close();
		return $return;
 	}//end function			    
		
/** Linkea con el grupo standard para usuarios que se generan solo,'
 * y hace falta q pertenezcan a algun lado para darles permisos, vio?
 */
	public function linkStandardGroup ()
{
	global $ari;
	 

	$id_grupo = $ari->get("config")->get('new-group', 'user');
	$grupo = new seguridad_group ($id_grupo);
	$grupo->addUser ($this );

				
					
}
}//end class
?>
Return current item: OOB-n1 PHP5 Framework