cruge / components / CrugeWebUser.php

<?php
/**
	CrugeWebUser

	es un gestor que permite manejar al usuario que ha iniciado sesion o que pretende iniciarla.
	consume a : CrugeUser

	esta clase necesita ser instalada en config, mediante:

	'components'=>array(
		'user'=>array(
			'allowAutoLogin'=>true,
			'class' => 'application.modules.cruge.components.CrugeWebUser',
		),

	una vez instalada puede ser accedida mediante:

	Yii::app()->user
	Yii::app()->user->isGuest()

	Todos los demás miembros de CWebUser se proveen, a excepcion de algunos que
	son sobreescritos.

	IMPORTANTE:

	No usar CHttpSession porque interfiere con el uso interno que se le da a $_SESSION dentro de CWebUser en los metodos getState setState.

	para almacenar valores usar $this->setState('nombreVariable','valor') y
	$this->getState('nombreVariable','defaultValue');


	@author: Christian Salazar H. <christiansalazarh@gmail.com> @bluyell
	@license protected/modules/cruge/LICENCE
*/
class CrugeWebUser extends CWebUser implements IWebUser {

	private $_lastError="";
	private $_access=array();	// cache para rbac por checkaccess
	private $_ui=null;
	private $_um =null;

	public function init()
	{
		parent::init();
	}
	/**
		nuevo metodo, para saber el error qe ocurrio, con traduccion incorporada
	*/
	public function getLastError(){
		return $this->_lastError;
	}
	/*	nuevo metodo que se accede via: Yii::app()->user->getUser();
		@returns instancia de ICrugeStoredUser o null
	*/
	public function getUser(){
		return $this->getum()->getUserFromSession($this->getICrugeSession());
	}
	/**
		da acceso directo al valor (solo lectura) de un campo personalizado.

		si el nombre del campo no existe o el usuario no ha inciado sesion se retorna ""

		ejemplo

			echo Yii::app()->user->getField('email');
			echo Yii::app()->user->getField('firstname');
	*/
	public function getField($fieldname){
		$user = $this->getUser();
		if($user != null){
			return $this->getum()->getFieldValue($user,$fieldname);
		}else
		return "";
	}
	/*
		helper para ayudar a controlar rapidamente el acceso a funciones que requieren
		de un usuario, si no hay sesion se emite una excepcion.
	*/
	public function noGuestAllowed(){
		if($this->isGuest)
			throw new CrugeException("debe iniciar sesion");
	}
	/*
		extension que permite consultar si este usuario (aun siendo invitado) tiene
		acceso o no a un determinado token de autenticacion identificado por su itemName.

		ejemplo:

		if(Yii::app()->user->checkAccess('createPostOperation')){
			..create post..
		}else{
			echo "access denied";
		}

		@itemName: nombre del item a ser comprobado para el usuario autenticado
		@params: los argumentos pasados al businessRule
		@descripcion: opcional, si rbacSetupEnabled es true, entonces se usara esta descripcion para crear el CAuthItem requerido cuando este no exista en la lista de operaciones.

		@returns true o false.  (si usuario activo es superadmin retorna true incondicionalmente)
	*/
	public function checkAccess($itemName,$descripcion="",$params=array()){

		// si esta habilitada la bandera de configuracion creara el CAuthItem si es requerido
		// y este no existe.
		//
		if(CrugeUtil::config()->rbacSetupEnabled == true){
			// esto no es eficiente en ambientes de produccion ya configurados plenamente
			// por tanto cuando se hayan establecido todos los permisos entonces
			// habra que deshabilitar este flag (rbacSetupEnabled) en la configuracion mayor
			if(!$this->getrbac()->getAuthItem($itemName))
				$this->getrbac()->createAuthItem($itemName,CAuthItem::TYPE_OPERATION
					,$descripcion);
		}

		if($this->isSuperAdmin){
			return true;
		}
		else
		{
			$ok = $this->getrbac()->checkAccess($itemName,$this->getId(),$params);
			if($ok == false){
				// no tiene el permiso asignado.
				// reportara el error para ser visualizado luego
				if(CrugeUtil::config()->rbacSetupEnabled == true){
					$ai = $this->getrbac()->getAuthItem($itemName);
					if($ai !== null){
						$this->getui()->addError($itemName
							,$this->getrbac()->getAuthItemTypeName($ai->type)
							,$descripcion
							);
					}
				}
			}
			return $ok;
		}
	}

	/*
		redirige al usuario a la pagina indicada por loginUrl en caso de que
		se detecte que es un invitado, luego del login es redirigido a la pagina a donde queria
		ir originalmente.

		este metodo es mejor usado en ambientes en donde no se esta usando a CAccessControlFilter, quien internamente invoca a Yii::app()->user->loginRequired cuando detecta que una regla ha fallado.
	*/
	public function checkLoginRequired(){
		if($this->isGuest)
			$this->loginRequired();
	}
	public function getIsSuperAdmin(){
		return ($this->name == CrugeUtil::config()->superuserName);
	}
	/*
		entrega un componente (CrugeUi) listo para ser usado, que se encarga de dar
		datos para la interfaz de usuario

		ejemplo:

		Yii::app()->user->ui
	*/
	public function getui(){
		if($this->_ui == null)
			$this->_ui = new CrugeUi();
		return $this->_ui;
	}
	public function getum(){
		if($this->_um == null)
			$this->_um = new CrugeUserManager();
		return $this->_um;
	}
	/*
		permite llamar al authManager directamente usando:
		Yii::app()->user->rbac

		previamente se debio declarar a CrugeAuthManager como la clase que administra a
		authmanager, eso se hace en components.
	*/
	public function getRbac(){
		return Yii::app()->getAuthManager();
	}
	/*
		permite conocer el sistema del usuario, si es un guest, el sistema sera nulo,
		si no es guest, dara la lista de sistemas del usuario a las que el pertenece
	*/
	/*
		TODO:


	*/

	/*  retorna el numero de usuario, tomado de la sesion iniciada
		si se quiere obtener acceso al usuario completo:
			Yii::app()->user->getUser()->getPrimaryKey()
	*/
	public function getId(){

		$_crugesesion = $this->getICrugeSession();
		if($_crugesesion == null)
			return CrugeUtil::config()->guestUserId;
		$userModel = $this->getum()->getUserFromSession($_crugesesion);
		if($userModel != null)
			return $userModel->getPrimaryKey();
		return CrugeUtil::config()->guestUserId;
	}
	public function getIsGuest(){
		return ($this->getId() == CrugeUtil::config()->guestUserId);
	}
	public function getName(){
		$model = $this->getICrugeSession();
		if($model != null){
			return $model->getSessionName();
		}
		else
		return CrugeTranslator::t("invitado");
	}
	public function getEmail(){
		$u = $this->getUser();
		if($u != null)
			return $u->email;
		return "";
	}


	/**
		se SUPONE que este metodo fue llamado tras un $identity->authenticate exitoso,
		por tanto estamos garantizando que identity->getId() tiene un identificador valido de
		un ICrugeStoredUser o un 0 si no se autentico.

		***el argumento $duration es pedido solo por compatibilidad, no se usa aqui.***

		la duracion del identificador en memoria de sesion dependera de la duracion de
		configuracion de PHP CONFIG, pero no asi la duracion del objeto de sesion (CrugeSession)
		el cual durara y sera reutilizado hasta que caduque o sea cerrado.
	*/
	public function login(/*IUserIdentity*/$identity,$duration = 0){

		if(get_class($identity) != 'CrugeUser')
			throw new CrugeException(
				"Por favor cambie las referencias a '".get_class($identity)."' por 'CrugeUser'"
			);


		Yii::log(__CLASS__."\nlogin\n","info");

		$this->_lastError = "";
		$this->clearSessionId();

		// carga el filtro de sesion habilitado para este modulo:
		$filtro = $this->getum()->getSessionFilter();

		// toma al usuario autenticado
		$user = $identity->getUser();
		if($user == null) {
			// no hay un usuario identificado para iniciar una sesion
			Yii::log(__CLASS__."\ngetUser is null\n","info");
			$this->_lastError = CrugeTranslator::t("debe autenticarse");
			return false;
		}

		$system = $this->getum()->getDefaultSystem();
		if($system == null)
		{
			Yii::log(__CLASS__."::login. systemName:".$_sname." no hallado.","error");
			throw new CrugeException("debe crear un registro en la tabla cruge_system");
		}

		// aplica credenciales sobre el sistema para obtener una sesion
		Yii::log(__CLASS__."\nfiltro->startSession\n","info");
		if(($usersession = $filtro->startSession($user,$system)) != null)
		{
			Yii::log(__CLASS__."\nfiltro->startSession OK\n","info");

			if($filtro->onStore($usersession)){
				// ahora si...guarda el identificador de sesion que getId devolvera
				$this->setSessionId($usersession->getPrimaryKey());
				$filtro->onLogin($usersession);
				return true;
			}
			else{
				Yii::log(CHtml::errorSummary($usersession,"error al guardar una sesion"),"error");
				$this->_lastError = CrugeTranslator::t("Error al almacenar sesion");
				return false;
			}
		}
		else
		{
			Yii::log(__CLASS__."\nfiltro->startSession error.\n".$filtro->getLastErrorDescr(),"info");

			$this->_lastError = $filtro->getLastErrorDescr();
			return false;
		}
	}
	public function logout($destroySession=true){
		$result=false;
		$usersession = $this->getICrugeSession();
		if($usersession != null){
			$filtro = $this->getum()->getSessionFilter();
			$usersession->logout();
			if($filtro->onStore($usersession)){
				$filtro->onLogout($usersession);
				$result=true;
			}
			else{
				Yii::log(CHtml::errorSummary($usersession,"error al guardar una sesion"),"error");
				$this->_lastError = CrugeTranslator::t("Error al almacenar sesion");
			}
		}
		parent::logout($destroySession);
		return $result;
	}
	/**HASTA AQUI llegan los metodos de la interfaz IWebUser*/

	/**

		estas funciones de aqui para abajo no pertenecen a la interfaz: IWebUser

	*/
	private function getSessionId(){
		return $this->getState('_sessionid_','0');
	}
	private function setSessionId($newValue){
		$this->setState('_sessionid_',$newValue);
	}
	private function clearSessionId(){
		$this->setState('_sessionid_','0');
	}
	/*
		carga una sesion de acuerdo al id persistente en cookies,
		pero al buscarlo lo revalida a ver si esta vigente, sino deriva en un evento
		de onSessionExpired
	*/
	private function getICrugeSession() {
		// idsession usado al momento del login almacenado en la memoria de sesion
		$model = $this->getum()->loadSession($this->getSessionId());
		if($model != null){
			if($model->validateSession()){
				return $model;
			}else{
				//if($model->isSessionExpired())
				$this->getum()->getSessionFilter()->onSessionExpired($model);
				// retorna null porque la sesion expiro.
				return null;
			}
		}
		else
		return null;
	}
};
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.