Commit 90ed7762 by Alexander Makarov

implemented password reset

parent 4b83aff0
...@@ -6,6 +6,7 @@ Yii::setAlias('backend', __DIR__ . '/../../backend'); ...@@ -6,6 +6,7 @@ Yii::setAlias('backend', __DIR__ . '/../../backend');
return array( return array(
'adminEmail' => 'admin@example.com', 'adminEmail' => 'admin@example.com',
'supportEmail' => 'support@example.com',
'components.cache' => array( 'components.cache' => array(
'class' => 'yii\caching\FileCache', 'class' => 'yii\caching\FileCache',
......
...@@ -12,6 +12,7 @@ use yii\web\Identity; ...@@ -12,6 +12,7 @@ use yii\web\Identity;
* @property integer $id * @property integer $id
* @property string $username * @property string $username
* @property string $password_hash * @property string $password_hash
* @property string $password_reset_token
* @property string $email * @property string $email
* @property string $auth_key * @property string $auth_key
* @property integer $role * @property integer $role
...@@ -66,7 +67,7 @@ class User extends ActiveRecord implements Identity ...@@ -66,7 +67,7 @@ class User extends ActiveRecord implements Identity
public function validateAuthKey($authKey) public function validateAuthKey($authKey)
{ {
return $this->auth_key === $authKey; return $this->getAuthKey() === $authKey;
} }
public function validatePassword($password) public function validatePassword($password)
...@@ -84,7 +85,7 @@ class User extends ActiveRecord implements Identity ...@@ -84,7 +85,7 @@ class User extends ActiveRecord implements Identity
array('email', 'filter', 'filter' => 'trim'), array('email', 'filter', 'filter' => 'trim'),
array('email', 'required'), array('email', 'required'),
array('email', 'email'), array('email', 'email'),
array('email', 'unique', 'message' => 'This email address has already been taken.'), array('email', 'unique', 'message' => 'This email address has already been taken.', 'on' => 'signup'),
array('password', 'required'), array('password', 'required'),
array('password', 'string', 'min' => 6), array('password', 'string', 'min' => 6),
...@@ -96,16 +97,17 @@ class User extends ActiveRecord implements Identity ...@@ -96,16 +97,17 @@ class User extends ActiveRecord implements Identity
return array( return array(
'signup' => array('username', 'email', 'password'), 'signup' => array('username', 'email', 'password'),
'login' => array('username', 'password'), 'login' => array('username', 'password'),
'resetPassword' => array('password'),
); );
} }
public function beforeSave($insert) public function beforeSave($insert)
{ {
if (parent::beforeSave($insert)) { if (parent::beforeSave($insert)) {
if (($this->isNewRecord || $this->getScenario() === 'resetPassword') && !empty($this->password)) {
$this->password_hash = SecurityHelper::generatePasswordHash($this->password);
}
if ($this->isNewRecord) { if ($this->isNewRecord) {
if (!empty($this->password)) {
$this->password_hash = SecurityHelper::generatePasswordHash($this->password);
}
$this->auth_key = SecurityHelper::generateRandomKey(); $this->auth_key = SecurityHelper::generateRandomKey();
} }
return true; return true;
......
...@@ -12,7 +12,9 @@ class m130524_201442_init extends \yii\db\Migration ...@@ -12,7 +12,9 @@ class m130524_201442_init extends \yii\db\Migration
$this->createTable('tbl_user', array( $this->createTable('tbl_user', array(
'id' => Schema::TYPE_PK, 'id' => Schema::TYPE_PK,
'username' => Schema::TYPE_STRING.' NOT NULL', 'username' => Schema::TYPE_STRING.' NOT NULL',
'auth_key' => Schema::TYPE_STRING.'(32) NOT NULL',
'password_hash' => Schema::TYPE_STRING.' NOT NULL', 'password_hash' => Schema::TYPE_STRING.' NOT NULL',
'password_reset_token' => Schema::TYPE_STRING.'(32)',
'email' => Schema::TYPE_STRING.' NOT NULL', 'email' => Schema::TYPE_STRING.' NOT NULL',
'role' => 'tinyint NOT NULL DEFAULT 10', 'role' => 'tinyint NOT NULL DEFAULT 10',
......
...@@ -7,6 +7,8 @@ use yii\web\Controller; ...@@ -7,6 +7,8 @@ use yii\web\Controller;
use common\models\LoginForm; 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 frontend\models\SendPasswordResetTokenForm;
class SiteController extends Controller class SiteController extends Controller
{ {
...@@ -74,4 +76,38 @@ class SiteController extends Controller ...@@ -74,4 +76,38 @@ class SiteController extends Controller
'model' => $model, 'model' => $model,
)); ));
} }
public function actionResetPassword($token = null)
{
if ($token) {
$model = User::find(array(
'password_reset_token' => $token,
'status' => User::STATUS_ACTIVE,
));
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->render('resetPassword', array(
'model' => $model,
));
}
else {
$model = new SendPasswordResetTokenForm();
if ($model->load($_POST) && $model->sendEmail()) {
// TODO: confirm that password reset token was sent
$this->redirect('index');
}
$this->render('sendPasswordResetTokenForm', array(
'model' => $model,
));
}
}
} }
<?php
namespace frontend\models;
use yii\base\Model;
use common\models\User;
use yii\base\View;
use yii\helpers\SecurityHelper;
/**
* 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 = SecurityHelper::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;
}
}
<?php
use yii\helpers\Html;
/**
* @var yii\base\View $this
* @var common\models\User $user;
*/
$resetLink = $this->context->createUrl('site/resetPassword', array('token' => $user->password_reset_token));
?>
Hello <?php echo Html::encode($user->username)?>,
Follow the link below to reset your password:
<?php Html::a(Html::encode($resetLink), $resetLink)?>
\ No newline at end of file
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/**
* @var yii\base\View $this
* @var yii\widgets\ActiveForm $form
* @var common\models\User $model
*/
$this->title = 'Reset password';
$this->params['breadcrumbs'][] = $this->title;
?>
<h1><?php echo Html::encode($this->title); ?></h1>
<p>Please choose your new password:</p>
<?php $form = ActiveForm::begin(array('options' => array('class' => 'form-horizontal'))); ?>
<?php echo $form->field($model, 'password')->passwordInput(); ?>
<div class="form-actions">
<?php echo Html::submitButton('Save', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/**
* @var yii\base\View $this
* @var yii\widgets\ActiveForm $form
* @var frontend\models\SendPasswordResetTokenForm $model
*/
$this->title = 'Request password reset';
$this->params['breadcrumbs'][] = $this->title;
?>
<h1><?php echo Html::encode($this->title); ?></h1>
<p>Please fill out your email. A link to reset password will be sent there.</p>
<?php $form = ActiveForm::begin(array('options' => array('class' => 'form-horizontal'))); ?>
<?php echo $form->field($model, 'email')->textInput(); ?>
<div class="form-actions">
<?php echo Html::submitButton('Send', array('class' => 'btn btn-primary')); ?>
</div>
<?php ActiveForm::end(); ?>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment