More on advanced app template:

- Unified way to use Alert
- Added link to restore password to login form
- Refactored restore password
This commit is contained in:
Alexander Makarov
2013-07-21 22:10:19 +04:00
parent dacee193fa
commit b02f01f6be
8 changed files with 109 additions and 94 deletions

View File

@ -112,6 +112,7 @@ class User extends ActiveRecord implements Identity
array('email', 'required'), array('email', 'required'),
array('email', 'email'), array('email', 'email'),
array('email', 'unique', 'message' => 'This email address has already been taken.', 'on' => 'signup'), array('email', 'unique', 'message' => 'This email address has already been taken.', 'on' => 'signup'),
array('email', 'exist', 'message' => 'There is no user with such email.', 'on' => 'requestPasswordResetToken'),
array('password', 'required'), array('password', 'required'),
array('password', 'string', 'min' => 6), array('password', 'string', 'min' => 6),
@ -124,6 +125,7 @@ class User extends ActiveRecord implements Identity
'signup' => array('username', 'email', 'password'), 'signup' => array('username', 'email', 'password'),
'login' => array('username', 'password'), 'login' => array('username', 'password'),
'resetPassword' => array('password'), 'resetPassword' => array('password'),
'requestPasswordResetToken' => array('email'),
); );
} }

View File

@ -8,7 +8,6 @@ use common\models\LoginForm;
use frontend\models\ContactForm; use frontend\models\ContactForm;
use common\models\User; use common\models\User;
use yii\web\HttpException; use yii\web\HttpException;
use frontend\models\SendPasswordResetTokenForm;
class SiteController extends Controller class SiteController extends Controller
{ {
@ -48,7 +47,7 @@ class SiteController extends Controller
{ {
$model = new ContactForm; $model = new ContactForm;
if ($model->load($_POST) && $model->contact(Yii::$app->params['adminEmail'])) { if ($model->load($_POST) && $model->contact(Yii::$app->params['adminEmail'])) {
Yii::$app->session->setFlash('contactFormSubmitted'); Yii::$app->session->setFlash('success', 'Thank you for contacting us. We will respond to you as soon as possible.');
return $this->refresh(); return $this->refresh();
} else { } else {
return $this->render('contact', array( return $this->render('contact', array(
@ -77,37 +76,70 @@ class SiteController extends Controller
)); ));
} }
public function actionResetPassword($token = null) public function actionRequestPasswordReset()
{ {
if ($token) { $model = new User();
$model = User::find(array( $model->scenario = 'requestPasswordResetToken';
'password_reset_token' => $token, if ($model->load($_POST) && $model->validate()) {
'status' => User::STATUS_ACTIVE, if ($this->sendPasswordResetEmail($email)) {
)); Yii::$app->getSession()->setFlash('success', 'Check your email for further instructions.');
if (!$model) {
throw new HttpException(400, 'Wrong password reset token.');
}
$model->scenario = 'resetPassword';
if ($model->load($_POST) && $model->save()) {
// TODO: confirm that password was successfully saved
$this->redirect('index'); $this->redirect('index');
} else {
Yii::$app->getSession()->setFlash('error', 'There was an error sending email.');
} }
}
$this->render('requestPasswordResetToken', array(
'model' => $model,
));
}
$this->render('resetPassword', array( public function actionResetPassword($token)
'model' => $model, {
)); $model = User::find(array(
'password_reset_token' => $token,
'status' => User::STATUS_ACTIVE,
));
if (!$model) {
throw new HttpException(400, 'Wrong password reset token.');
} }
else {
$model = new SendPasswordResetTokenForm(); $model->scenario = 'resetPassword';
if ($model->load($_POST) && $model->sendEmail()) { if ($model->load($_POST) && $model->save()) {
// TODO: confirm that password reset token was sent Yii::$app->getSession()->setFlash('success', 'New password was saved.');
$this->redirect('index'); $this->redirect('index');
}
$this->render('sendPasswordResetTokenForm', array(
'model' => $model,
));
} }
$this->render('resetPassword', array(
'model' => $model,
));
}
private function sendPasswordResetEmail($email)
{
$user = User::find(array(
'status' => User::STATUS_ACTIVE,
'email' => $email,
));
if (!$user) {
return false;
}
$user->password_reset_token = Security::generateRandomKey();
if ($user->save(false)) {
$fromEmail = \Yii::$app->params['supportEmail'];
$name = '=?UTF-8?B?' . base64_encode(\Yii::$app->name . ' robot') . '?=';
$subject = '=?UTF-8?B?' . base64_encode('Password reset for ' . \Yii::$app->name) . '?=';
$body = $this->renderPartial('/emails/passwordResetToken', array(
'user' => $this,
));
$headers = "From: $name <{$fromEmail}>\r\n" .
"MIME-Version: 1.0\r\n" .
"Content-type: text/plain; charset=UTF-8";
return mail($fromEmail, $subject, $body, $headers);
}
return false;
} }
} }

View File

@ -1,59 +0,0 @@
<?php
namespace frontend\models;
use yii\base\Model;
use common\models\User;
use yii\base\View;
use yii\helpers\Security;
/**
* SendPasswordResetTokenForm is the model behind requesting password reset token form.
*/
class SendPasswordResetTokenForm extends Model
{
public $email;
/**
* @return array the validation rules.
*/
public function rules()
{
return array(
array('email', 'required'),
array('email', 'email'),
);
}
public function sendEmail()
{
if($this->validate()) {
/** @var User $user */
$user = User::find(array(
'email' => $this->email,
'status' => User::STATUS_ACTIVE,
));
if ($user) {
$user->password_reset_token = Security::generateRandomKey();
if ($user->save(false)) {
$view = new View(array(
'context' => \Yii::$app->controller,
));
$fromEmail = \Yii::$app->params['supportEmail'];
$name = '=?UTF-8?B?' . base64_encode(\Yii::$app->name . ' robot') . '?=';
$subject = '=?UTF-8?B?' . base64_encode('Password reset for ' . \Yii::$app->name) . '?=';
$body = $view->render('/emails/passwordResetToken', array(
'user' => $user,
));
$headers = "From: $name <{$fromEmail}>\r\n" .
"MIME-Version: 1.0\r\n" .
"Content-type: text/plain; charset=UTF-8";
mail($fromEmail, $subject, $body, $headers);
return true;
}
}
}
return false;
}
}

View File

@ -3,6 +3,7 @@ use frontend\config\AppAsset;
use yii\helpers\Html; use yii\helpers\Html;
use yii\widgets\Menu; use yii\widgets\Menu;
use yii\widgets\Breadcrumbs; use yii\widgets\Breadcrumbs;
use frontend\widgets\Alert;
/** /**
* @var $this \yii\base\View * @var $this \yii\base\View
@ -54,6 +55,9 @@ AppAsset::register($this);
<?php echo Breadcrumbs::widget(array( <?php echo Breadcrumbs::widget(array(
'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : array(), 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : array(),
)); ?> )); ?>
<?php echo Alert::widget()?>
<?php echo $content; ?> <?php echo $content; ?>
<hr> <hr>

View File

@ -13,12 +13,6 @@ $this->params['breadcrumbs'][] = $this->title;
?> ?>
<h1><?php echo Html::encode($this->title); ?></h1> <h1><?php echo Html::encode($this->title); ?></h1>
<?php if (Yii::$app->session->hasFlash('contactFormSubmitted')): ?>
<div class="alert alert-success">
Thank you for contacting us. We will respond to you as soon as possible.
</div>
<?php return; endif; ?>
<p> <p>
If you have business inquiries or other questions, please fill out the following form to contact us. Thank you. If you have business inquiries or other questions, please fill out the following form to contact us. Thank you.
</p> </p>

View File

@ -22,3 +22,5 @@ $this->params['breadcrumbs'][] = $this->title;
<?php echo Html::submitButton('Login', array('class' => 'btn btn-primary')); ?> <?php echo Html::submitButton('Login', array('class' => 'btn btn-primary')); ?>
</div> </div>
<?php ActiveForm::end(); ?> <?php ActiveForm::end(); ?>
<p>If you forgot your password you can <?php echo Html::a('reset it', array('site/requestPasswordReset'))?>.</p>

View File

@ -5,7 +5,7 @@ use yii\widgets\ActiveForm;
/** /**
* @var yii\base\View $this * @var yii\base\View $this
* @var yii\widgets\ActiveForm $form * @var yii\widgets\ActiveForm $form
* @var frontend\models\SendPasswordResetTokenForm $model * @var frontend\models\User $model
*/ */
$this->title = 'Request password reset'; $this->title = 'Request password reset';
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;

View File

@ -0,0 +1,40 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace frontend\widgets;
use yii\helpers\Html;
/**
* Alert widget renders a message from session flash. You can set message as following:
*
* - \Yii::$app->getSession()->setFlash('error', 'This is the message');
* - \Yii::$app->getSession()->setFlash('success', 'This is the message');
* - \Yii::$app->getSession()->setFlash('info', 'This is the message');
*
* @author Alexander Makarov <sam@rmcerative.ru>
*/
class Alert extends \yii\bootstrap\Alert
{
public function init()
{
if ($this->body = \Yii::$app->getSession()->getFlash('error')) {
Html::addCssClass($this->options, 'alert-error');
} elseif ($this->body = \Yii::$app->getSession()->getFlash('success')) {
Html::addCssClass($this->options, 'alert-success');
} elseif ($this->body = \Yii::$app->getSession()->getFlash('info')) {
Html::addCssClass($this->options, 'alert-info');
} elseif ($this->body = \Yii::$app->getSession()->getFlash('warning')) {
} else {
// no message passed, no need to render widget
return;
}
parent::init();
}
}