Tarea #1086 -> Añadir mecanismo para cambiar la contraseña

git-svn-id: https://192.168.0.254/svn/Proyectos.Incam_PROFIND_Web/trunk@21 3fe1ab16-cfe0-e34b-8c9f-7d8c168d430d
This commit is contained in:
roberto 2012-09-24 23:14:37 +00:00
parent 69f172d869
commit a33b0e762b
14 changed files with 425 additions and 25 deletions

View File

@ -137,7 +137,7 @@ $config = array(
// application-level parameters that can be accessed
// using Yii::app()->params['paramName']
'params'=>array(
'frontpage' => 'http://localhost',
'frontpage' => 'http://localhost/index.php',
'email_remitente' => 'mantenimiento@rodax-software.com',
),
);

View File

@ -35,7 +35,7 @@ class EmpresaController extends Controller {
*/
public function actionModificar($id) {
if ($id != Yii::app()->user->id_empresa)
throw new CHttpException(404, 'The requested page does not exist.');
throw new CHttpException(404, Yii::t('profind', 'La página solicitada no existe.'));
$model = $this->loadModel($id);
@ -70,7 +70,7 @@ class EmpresaController extends Controller {
public function loadModel($id) {
$model = Empresa::model()->findByPk($id);
if ($model === null)
throw new CHttpException(404, 'The requested page does not exist.');
throw new CHttpException(404, Yii::t('profind', 'La página solicitada no existe.'));
return $model;
}

View File

@ -159,7 +159,7 @@ class EquipoController extends Controller {
public function loadModel($id) {
$model = Usuario::model()->findByPk($id);
if ($model === null)
throw new CHttpException(404, 'The requested page does not exist.');
throw new CHttpException(404, Yii::t('profind', 'La página solicitada no existe.'));
return $model;
}

View File

@ -18,9 +18,6 @@ class RegistroUsuarioController extends Controller {
'actions' => array('registrar', 'activar'),
'users' => array('*')
),
array('allow',
'users' => array('@')
),
array('deny'),
);
}

View File

@ -0,0 +1,185 @@
<?php
class SeguridadUsuarioController extends Controller {
public $defaultAction = 'recuperar';
/**
* Realiza la recuperación de la contraseña de un usuario.
* Este método es llamado por AJAX desde la página de entrada.
*
*/
public function actionRecuperar() {
$formulario = new FormularioRecuperarPassword;
$resultado = array();
// if it is ajax validation request
if (isset($_POST['ajax']) && $_POST['ajax'] === 'recuperar-form') {
$formulario->email = $_POST['FormularioRecuperar_email'];
if (!$formulario->validate()) {
foreach ($formulario->getErrors() as $campo => $error) {
$resultado[$campo] = $error;
}
echo function_exists('json_encode') ? json_encode($resultado) : CJSON::encode($resultado);
Yii::app()->end();
}
$usuario = Usuario::model()->findByAttributes(array('email' => $formulario->email));
if ($usuario) {
$this->enviarMailRecuperacion($usuario);
$resultado['status'] = '200';
$resultado['titulo'] = Yii::t('profind', 'Recuperación de su cuenta en PROFIND');
$resultado['texto'] = Yii::t('profind', 'En unos momentos recibirá un un correo con los pasos necesarios para recuperar su cuenta en PROFIND.');
echo function_exists('json_encode') ? json_encode($resultado) : CJSON::encode($resultado);
Yii::app()->end();
}
}
$this->redirect(Yii::app()->params['frontpage']);
}
/**
* Cambiar la contraseña del usuario desde la página de entrada.
* Este método es llamado por AJAX desde la página de entrada.
* Envia un email de notificación al usuario.
* @param integer ID del usuario
*/
public function actionCambiarPasswordExt() {
$formulario = new FormularioExtCambiarPassword;
$resultado = array();
if (isset($_POST['ajax']) && $_POST['ajax'] === 'cambiar-password-form-ext') {
$formulario->key = $_POST['FormularioCambiarPassword_key'];
$formulario->email = $_POST['FormularioCambiarPassword_email'];
$formulario->password = $_POST['FormularioCambiarPassword_password'];
$formulario->passwordRepetida = $_POST['FormularioCambiarPassword_password_repetida'];
if ($formulario->validate()) {
$usuario = Usuario::model()->findByAttributes(array('email' => $formulario->email));
if ($this->_cambiarPassword($usuario->id, $formulario->password)) {
$resultado['status'] = '200';
$resultado['titulo'] = Yii::t('profind', 'Password modificada');
$resultado['texto'] = Yii::t('profind', 'Se ha modificado su password en PROFIND.');
echo function_exists('json_encode') ? json_encode($resultado) : CJSON::encode($resultado);
Yii::app()->end();
} else {
foreach ($formulario->getErrors() as $campo => $error) {
$resultado[$campo] = $error;
}
echo function_exists('json_encode') ? json_encode($resultado) : CJSON::encode($resultado);
Yii::app()->end();
}
} else {
foreach ($formulario->getErrors() as $campo => $error) {
$resultado[$campo] = $error;
}
echo function_exists('json_encode') ? json_encode($resultado) : CJSON::encode($resultado);
Yii::app()->end();
}
}
$this->redirect(Yii::app()->params['frontpage']);
}
/**
* Cambiar la contraseña del usuario desde el formulario de la aplicación.
* Envia un email de notificación al usuario.
* @param integer ID del usuario
*/
public function actionCambiarPassword($id) {
if ($id != Yii::app()->user->id)
throw new CHttpException(404, Yii::t('profind', 'La página solicitada no existe.'));
$formulario = new FormularioCambiarPassword;
if (isset($_POST['ajax']) && $_POST['ajax'] === 'cambiar-password-form') {
echo CActiveForm::validate($formulario);
Yii::app()->end();
}
if (isset($_POST['FormularioCambiarPassword'])) {
$formulario->attributes = $_POST['FormularioCambiarPassword'];
if ($formulario->validate() && $this->_cambiarPassword($id, $formulario->password)) {
Yii::app()->user->setFlash('success', Yii::t('profind', 'Se ha modificado la contraseña'));
$this->redirect(array('usuario/modificar', 'id' => $id));
} else {
Yii::app()->user->setFlash('error', Yii::t('profind', 'No se ha podido modificar la contraseña'));
Yii::app()->user->setFlash('error', CHtml::errorSummary($formulario));
}
}
$this->render('cambiar_password', array('formulario' => $formulario));
}
/**
* Realiza el proceso interno de cambiar la contraseña a un usuario.
* Envia un email de notificación al usuario.
* Este método es privado y de uso interno al controlador.
* @param integer ID del usuario
* @param string nueva contraseña del usuario
* @return boolean si se ha podido hacer o no el cambio
*/
private function _cambiarPassword($id, $nueva_password) {
$usuario = Usuario::model()->findByPk($id);
if (!isset($usuario))
throw new CHttpException(404, Yii::t('profind', 'La página solicitada no existe.'));
$usuario->password = $usuario->encrypt($nueva_password);
$usuario->clave_seguridad = $usuario->encrypt(microtime() . $usuario->password);
if ($usuario->save()) {
$this->enviarMailNotificacionCambioPassword($usuario);
return true;
} else
return false;
}
/**
* Envía un mail de recuperación de password a un usuario con una URL.
* @param Usuario $usuario Usuario al que se le enviará el mail de recuperación
*/
private function enviarMailRecuperacion($usuario) {
Yii::import('ext.yii-mail.YiiMailMessage');
$url_modificacion = Yii::app()->params['frontpage'] . '?' . 'key=' . $usuario->clave_seguridad . '&email=' . urlencode($usuario->email);
$mensaje = new YiiMailMessage;
$mensaje->from = Yii::app()->params['email_remitente'];
$mensaje->setTo($usuario->email);
$mensaje->subject = Yii::t('profind', 'Recuperación de su cuenta en PROFIND');
$mensaje->view = 'recuperacion_password_usuario';
$mensaje->setBody(array(
'url' => $url_modificacion,
'email' => $usuario->email
), 'text/html'
);
Yii::app()->mail->send($mensaje);
}
/**
* Envía un mail confirmando el cambio de password a un usuario.
* También se envio una URL de recuperacion por si fuera un cambio no permitido.
* @param Usuario $usuario Usuario al que se le enviará el mail de notificación
*/
private function enviarMailNotificacionCambioPassword($usuario) {
Yii::import('ext.yii-mail.YiiMailMessage');
$url_recuperacion = $this->createAbsoluteUrl('recuperarUsuario/recuperar', array("key" => $usuario->clave_seguridad, "email" => $usuario->email));
$mensaje = new YiiMailMessage;
$mensaje->from = Yii::app()->params['email_remitente'];
$mensaje->setTo($usuario->email);
$mensaje->subject = Yii::t('profind', 'Se ha modificado su password en PROFIND');
$mensaje->view = 'notificacion_cambio_password_usuario';
$mensaje->setBody(array(
'url' => $url_recuperacion,
'email' => $usuario->email
), 'text/html'
);
Yii::app()->mail->send($mensaje);
}
}

View File

@ -2,6 +2,8 @@
class UsuarioController extends Controller {
public $defaultAction = 'modificar';
/**
* @return array action filters
*/
@ -19,7 +21,7 @@ class UsuarioController extends Controller {
public function accessRules() {
return array(
array('allow', // allow admin user to perform 'admin' and 'delete' actions
'actions' => array('modificar', 'index'),
'actions' => array('modificar', 'cambiarPassword'),
'users' => array('@'),
),
array('deny', // deny all users
@ -35,8 +37,8 @@ class UsuarioController extends Controller {
*/
public function actionModificar($id) {
if ($id != Yii::app()->user->id)
throw new CHttpException(404, 'The requested page does not exist.');
throw new CHttpException(404, Yii::t('profind', 'La página solicitada no existe.'));
$model = $this->loadModel($id);
// Uncomment the following line if AJAX validation is needed
@ -55,13 +57,6 @@ class UsuarioController extends Controller {
));
}
/**
* Lists all models.
*/
public function actionIndex() {
$this->actionModificar(Yii::app()->user->id);
}
/**
* Returns the data model based on the primary key given in the GET variable.
* If the data model is not found, an HTTP exception will be raised.
@ -70,7 +65,7 @@ class UsuarioController extends Controller {
public function loadModel($id) {
$model = Usuario::model()->findByPk($id);
if ($model === null)
throw new CHttpException(404, 'The requested page does not exist.');
throw new CHttpException(404, Yii::t('profind', 'La página solicitada no existe.'));
return $model;
}
@ -84,5 +79,4 @@ class UsuarioController extends Controller {
Yii::app()->end();
}
}
}

View File

@ -0,0 +1,34 @@
<?php
/**
*
*/
class FormularioCambiarPassword extends CFormModel {
public $passwordAnterior;
public $password;
public $passwordRepetida;
/**
*
*/
public function rules() {
return array(
array('passwordAnterior, password, passwordRepetida', 'required'),
array('password, passwordRepetida', 'length', 'max' => 128, 'min' => 6, 'message' => Yii::t('profind', 'La contraseña debe al menos 6 caracteres.')),
array('passwordRepetida', 'compare', 'compareAttribute' => 'password', 'message' => Yii::t('profind', 'La confirmación de contraseña no coincide.')),
array('passwordAnterior', 'comprobarPasswordAnterior'),
);
}
/**
* Comprobar que la anterior contraseña es correcta
*/
public function comprobarPasswordAnterior($attribute, $params) {
if (!$this->hasErrors()) {
$usuario = Usuario::model()->findByPk(Yii::app()->user->id);
if ($usuario->password != Usuario::model()->encrypt($this->passwordAnterior))
$this->addError($this->passwordAnterior, Yii::t('profind', 'La contraseña anterior no es correcta.'));
}
}
}

View File

@ -0,0 +1,53 @@
<?php
/**
*
*/
class FormularioExtCambiarPassword extends CFormModel {
public $key;
public $email;
public $password;
public $passwordRepetida;
/**
*
*/
public function rules() {
return array(
array('key, email, password, passwordRepetida', 'required'),
array('email', 'email'),
array('email', 'existeEmail'),
array('password, passwordRepetida', 'length', 'max' => 128, 'min' => 6, 'message' => Yii::t('profind', 'La contraseña debe al menos 6 caracteres.')),
array('passwordRepetida', 'compare', 'compareAttribute' => 'password', 'message' => Yii::t('profind', 'La confirmación de contraseña no coincide.')),
array('key', 'comprobarKey'),
);
}
/**
* Comprobar que existe un usuario con el email recibido.
*/
public function existeEmail($attribute, $params) {
if (!$this->hasErrors()) {
$usuario = Usuario::model()->findByAttributes(array(
'email' => $this->email
));
if (!isset($usuario))
$this->addError($this->key, Yii::t('profind', 'Los datos para cambiar la contraseña no son válidos.'));
}
}
/**
* Comprobar que la key recibida corresponde al email recibido.
*/
public function comprobarKey($attribute, $params) {
if (!$this->hasErrors()) {
$usuario = Usuario::model()->findByAttributes(array(
'clave_seguridad' => $this->key,
'email' => $this->email
));
if (!isset($usuario))
$this->addError($this->key, Yii::t('profind', 'Los datos para cambiar la contraseña no son válidos.'));
}
}
}

View File

@ -0,0 +1,32 @@
<?php
/**
*
*/
class FormularioRecuperarPassword extends CFormModel {
public $email;
/**
*
*/
public function rules() {
return array(
array('email', 'required'),
array('email', 'email'),
array('email', 'existeEmailUsuario'),
);
}
/**
*
*/
public function existeEmailUsuario($attribute, $params) {
if (!$this->hasErrors()) {
$usuario = Usuario::model()->findByAttributes(array('email' => $this->email));
if ($usuario === null)
$this->addError($attribute, Yii::t('profind', 'Email incorrecto'));
}
}
}

View File

@ -0,0 +1,18 @@
<html>
<head>
<title>Se ha modificado su password en PROFIND</title>
</head>
<body>
<h3>Se ha modificado su password en PROFIND</h3>
<p>Ha recibido este correo como confirmación de su reciente cambio de contraseña en <a href="http://www.profindtic.com/">http://www.profindtic.com</a>.</p>
<p>Si su contraseña de <a href="http://www.profindtic.com/">http://www.profindtic.com</a> fue cambiada sin su conocimento, pulse en el siguiente enlace para cambiarla de nuevo:<br>
<a href="<?php echo $url; ?>"><?php echo $url; ?></a>
</p>
<p>
Este correo se ha enviado desde <a href="http://www.profindtic.com/">http://www.profindtic.com</a>.<br>
No responda a este correo ya que ha sido generado automáticamente para su información.
</p>
<p>El equipo de <a href="http://www.profindtic.com/">PROFIND</a></p>
</body>
</html>

View File

@ -0,0 +1,17 @@
<html>
<head>
<title>Recuperación de su cuenta en PROFIND</title>
</head>
<body>
<h3>Recuperación de su cuenta en PROFIND</h3>
<p>Ha recibido este correo en respuesta a su solicitud de recuperación de su cuenta en <a href="http://www.profindtic.com/">PROFIND</a>.</p>
<p>Para completar el proceso pulse en el siguiente enlace<br>
<a href="<?php echo $url; ?>"><?php echo $url; ?></a>
</p>
<p>
Este correo se ha enviado desde <a href="http://www.profindtic.com/">http://www.profindtic.com</a>.<br>
No responda a este correo ya que ha sido generado automáticamente para su información.
</p>
<p>El equipo de <a href="http://www.profindtic.com/">PROFIND</a></p>
</body>
</html>

View File

@ -33,6 +33,8 @@
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><?php echo Yii::app()->user->name; ?> <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><?php echo CHtml::link(Yii::t('profind', 'Cambiar la password'), $this->createUrl('seguridadUsuario/cambiarPassword', array('id' => Yii::app()->user->id))); ?></li>
<li class="divider"></li>
<li><?php echo CHtml::link(Yii::t('profind', 'Salir'), $this->createUrl('site/logout')); ?></li>
</ul>
</li>

View File

@ -0,0 +1,59 @@
<?php $this->pageTitle=Yii::t('profind', 'Cambiar la password'); ?>
<div class="row-fluid">
<div class="span12">
<h3 class="heading"><?php echo Yii::t('profind', 'Cambiar la password'); ?></h3>
<div class="row-fluid">
<div class="span8">
<?php if ($formulario->hasErrors()) { ?>
<div class="alert alert-error">
<a data-dismiss="alert" class="close">×</a>
<?php
echo CHtml::errorSummary($formulario, '<strong>' . Yii::t('profind', 'Se han encontrado errores') . '</strong>', '', array('firstError' => true));
?>
</div>
<?php } ?>
<?php
$form = $this->beginWidget('CActiveForm', array(
'id' => 'cambiar-password-form',
'enableAjaxValidation' => true,
'htmlOptions' => array(
'class' => 'form-horizontal'
)
));
?>
<fieldset>
<div class="control-group formSep">
<?php echo $form->labelEx($formulario, 'passwordAnterior', array('class' => 'control-label')); ?>
<div class="controls">
<?php echo $form->passwordField($formulario, 'passwordAnterior', array('class' => 'input-xlarge')); ?>
</div>
</div>
<div class="control-group">
<div class="sepH_b">
<?php echo $form->labelEx($formulario, 'password', array('class' => 'control-label')); ?>
<div class="controls">
<?php echo $form->passwordField($formulario, 'password', array('class' => 'input-xlarge')); ?>
</div>
</div>
<?php echo $form->labelEx($formulario, 'passwordRepetida', array('class' => 'control-label')); ?>
<div class="controls">
<?php echo $form->passwordField($formulario, 'passwordRepetida', array('class' => 'input-xlarge')); ?>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary"><?php echo Yii::t('profind', 'Cambiar la contraseña'); ?></button>
<button class="btn"><?php echo Yii::t('profind', 'Cancelar'); ?></button>
</div>
</fieldset>
<?php $this->endWidget(); ?>
</div>
<div class="span4">
</div>
</div>
</div>
</div>

View File

@ -3,13 +3,12 @@
<h3 class="heading"><?php echo Yii::t('profind', 'Perfil del agente'); ?></h3>
<div class="row-fluid">
<div class="span8">
<?php if($model->hasErrors()) { ?>
<?php if ($model->hasErrors()) { ?>
<div class="alert alert-error">
<a data-dismiss="alert" class="close">×</a>
<?php echo CHtml::errorSummary($model,
'<strong>' . Yii::t('profind', 'Se han encontrado errores') . '</strong>',
'',
array('firstError' => true)); ?>
<?php
echo CHtml::errorSummary($model, '<strong>' . Yii::t('profind', 'Se han encontrado errores') . '</strong>', '', array('firstError' => true));
?>
</div>
<?php } ?>
@ -22,7 +21,7 @@
)
));
?>
<fieldset>
<div class="control-group formSep">
<div class="sepH_b">
@ -46,6 +45,16 @@
</div>
</div>
<div class="control-group formSep">
<?php echo $form->labelEx($model, 'password', array('class' => 'control-label')); ?>
<div class="controls">
<label class="control-label">
<?php echo CHtml::link(Yii::t('profind', 'Cambiar la password'), $this->createUrl('seguridadUsuario/cambiarPassword', array('id' => Yii::app()->user->id))); ?>
</label>
</div>
</div>
<div class="control-group formSep">
<?php echo $form->labelEx($model, 'telefono', array('class' => 'control-label')); ?>
<div class="controls">