mirror of
https://github.com/yiisoft/yii2.git
synced 2025-11-19 16:01:57 +08:00
Merge pull request #2244 from yiisoft/advanced-application-forms
Moved most of the user-related logic into form models
This commit is contained in:
@@ -1,18 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace backend\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii\web\AccessControl;
|
||||
use yii\web\Controller;
|
||||
use common\models\LoginForm;
|
||||
|
||||
/**
|
||||
* Site controller
|
||||
*/
|
||||
class SiteController extends Controller
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
'access' => [
|
||||
'class' => \yii\web\AccessControl::className(),
|
||||
'class' => AccessControl::className(),
|
||||
'rules' => [
|
||||
[
|
||||
'actions' => ['login', 'error'],
|
||||
@@ -28,6 +34,9 @@ class SiteController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function actions()
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -5,7 +5,7 @@ use yii\widgets\ActiveForm;
|
||||
/**
|
||||
* @var yii\web\View $this
|
||||
* @var yii\widgets\ActiveForm $form
|
||||
* @var common\models\LoginForm $model
|
||||
* @var \common\models\LoginForm $model
|
||||
*/
|
||||
$this->title = 'Login';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace common\models;
|
||||
|
||||
use Yii;
|
||||
use common\models\User;
|
||||
use yii\base\Model;
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* LoginForm is the model behind the login form.
|
||||
* Login form
|
||||
*/
|
||||
class LoginForm extends Model
|
||||
{
|
||||
@@ -17,7 +17,7 @@ class LoginForm extends Model
|
||||
private $_user = false;
|
||||
|
||||
/**
|
||||
* @return array the validation rules.
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
|
||||
@@ -6,8 +6,7 @@ use yii\helpers\Security;
|
||||
use yii\web\IdentityInterface;
|
||||
|
||||
/**
|
||||
* Class User
|
||||
* @package common\models
|
||||
* User model
|
||||
*
|
||||
* @property integer $id
|
||||
* @property string $username
|
||||
@@ -19,19 +18,30 @@ use yii\web\IdentityInterface;
|
||||
* @property integer $status
|
||||
* @property integer $created_at
|
||||
* @property integer $updated_at
|
||||
* @property string $password write-only password
|
||||
*/
|
||||
class User extends ActiveRecord implements IdentityInterface
|
||||
{
|
||||
/**
|
||||
* @var string the raw password. Used to collect password input and isn't saved in database
|
||||
*/
|
||||
public $password;
|
||||
|
||||
const STATUS_DELETED = 0;
|
||||
const STATUS_ACTIVE = 10;
|
||||
|
||||
const ROLE_USER = 10;
|
||||
|
||||
public static function create($attributes)
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = new static();
|
||||
$user->setAttributes($attributes);
|
||||
if ($user->save()) {
|
||||
return $user;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
@@ -46,10 +56,7 @@ class User extends ActiveRecord implements IdentityInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an identity by the given ID.
|
||||
*
|
||||
* @param string|integer $id the ID to be looked for
|
||||
* @return IdentityInterface|null the identity object that matches the given ID.
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function findIdentity($id)
|
||||
{
|
||||
@@ -68,7 +75,7 @@ class User extends ActiveRecord implements IdentityInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|string|array current user ID
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
@@ -76,7 +83,7 @@ class User extends ActiveRecord implements IdentityInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string current user auth key
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getAuthKey()
|
||||
{
|
||||
@@ -84,8 +91,7 @@ class User extends ActiveRecord implements IdentityInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $authKey
|
||||
* @return boolean if auth key is valid for current user
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function validateAuthKey($authKey)
|
||||
{
|
||||
@@ -93,6 +99,8 @@ class User extends ActiveRecord implements IdentityInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates password
|
||||
*
|
||||
* @param string $password password to validate
|
||||
* @return bool if password provided is valid for current user
|
||||
*/
|
||||
@@ -101,6 +109,35 @@ class User extends ActiveRecord implements IdentityInterface
|
||||
return Security::validatePassword($password, $this->password_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates password hash from password and sets it to the model
|
||||
*
|
||||
* @param string $password
|
||||
*/
|
||||
public function setPassword($password)
|
||||
{
|
||||
$this->password_hash = Security::generatePasswordHash($password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates new password reset token
|
||||
*/
|
||||
public function generatePasswordResetToken()
|
||||
{
|
||||
$this->password_reset_token = Security::generateRandomKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes password reset token
|
||||
*/
|
||||
public function removePasswordResetToken()
|
||||
{
|
||||
$this->password_reset_token = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
@@ -117,34 +154,7 @@ class User extends ActiveRecord implements IdentityInterface
|
||||
['email', 'filter', 'filter' => 'trim'],
|
||||
['email', 'required'],
|
||||
['email', 'email'],
|
||||
['email', 'unique', 'message' => 'This email address has already been taken.', 'on' => 'signup'],
|
||||
['email', 'exist', 'message' => 'There is no user with such email.', 'on' => 'requestPasswordResetToken'],
|
||||
|
||||
['password', 'required'],
|
||||
['password', 'string', 'min' => 6],
|
||||
['email', 'unique'],
|
||||
];
|
||||
}
|
||||
|
||||
public function scenarios()
|
||||
{
|
||||
return [
|
||||
'signup' => ['username', 'email', 'password', '!status', '!role'],
|
||||
'resetPassword' => ['password'],
|
||||
'requestPasswordResetToken' => ['email'],
|
||||
];
|
||||
}
|
||||
|
||||
public function beforeSave($insert)
|
||||
{
|
||||
if (parent::beforeSave($insert)) {
|
||||
if (($this->isNewRecord || $this->getScenario() === 'resetPassword') && !empty($this->password)) {
|
||||
$this->password_hash = Security::generatePasswordHash($this->password);
|
||||
}
|
||||
if ($this->isNewRecord) {
|
||||
$this->auth_key = Security::generateRandomKey();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace frontend\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii\web\Controller;
|
||||
use common\models\LoginForm;
|
||||
use frontend\models\PasswordResetRequestForm;
|
||||
use frontend\models\ResetPasswordForm;
|
||||
use frontend\models\SignupForm;
|
||||
use frontend\models\ContactForm;
|
||||
use common\models\User;
|
||||
use yii\base\InvalidParamException;
|
||||
use yii\web\BadRequestHttpException;
|
||||
use yii\helpers\Security;
|
||||
use yii\web\Controller;
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* Site controller
|
||||
*/
|
||||
class SiteController extends Controller
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
@@ -34,6 +41,9 @@ class SiteController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function actions()
|
||||
{
|
||||
return [
|
||||
@@ -59,7 +69,7 @@ class SiteController extends Controller
|
||||
}
|
||||
|
||||
$model = new LoginForm();
|
||||
if ($model->load($_POST) && $model->login()) {
|
||||
if ($model->load(Yii::$app->request->post()) && $model->login()) {
|
||||
return $this->goBack();
|
||||
} else {
|
||||
return $this->render('login', [
|
||||
@@ -94,11 +104,13 @@ class SiteController extends Controller
|
||||
|
||||
public function actionSignup()
|
||||
{
|
||||
$model = new User();
|
||||
$model->setScenario('signup');
|
||||
if ($model->load($_POST) && $model->save()) {
|
||||
if (Yii::$app->getUser()->login($model)) {
|
||||
return $this->goHome();
|
||||
$model = new SignupForm();
|
||||
if ($model->load(Yii::$app->request->post())) {
|
||||
$user = $model->signup();
|
||||
if ($user) {
|
||||
if (Yii::$app->getUser()->login($user)) {
|
||||
return $this->goHome();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,16 +121,14 @@ class SiteController extends Controller
|
||||
|
||||
public function actionRequestPasswordReset()
|
||||
{
|
||||
$model = new User();
|
||||
$model->scenario = 'requestPasswordResetToken';
|
||||
if ($model->load($_POST) && $model->validate()) {
|
||||
if ($this->sendPasswordResetEmail($model->email)) {
|
||||
Yii::$app->getSession()->setFlash('success', 'Check your email for further instructions.');
|
||||
return $this->goHome();
|
||||
} else {
|
||||
Yii::$app->getSession()->setFlash('error', 'There was an error sending email.');
|
||||
}
|
||||
$model = new PasswordResetRequestForm();
|
||||
if ($model->load(Yii::$app->request->post()) && $model->sendEmail()) {
|
||||
Yii::$app->getSession()->setFlash('success', 'Check your email for further instructions.');
|
||||
return $this->goHome();
|
||||
} else {
|
||||
Yii::$app->getSession()->setFlash('error', 'There was an error sending email.');
|
||||
}
|
||||
|
||||
return $this->render('requestPasswordResetToken', [
|
||||
'model' => $model,
|
||||
]);
|
||||
@@ -126,21 +136,13 @@ class SiteController extends Controller
|
||||
|
||||
public function actionResetPassword($token)
|
||||
{
|
||||
if (empty($token) || is_array($token)) {
|
||||
throw new BadRequestHttpException('Invalid password reset token.');
|
||||
try {
|
||||
$model = new ResetPasswordForm($token);
|
||||
} catch (InvalidParamException $e) {
|
||||
throw new BadRequestHttpException($e->getMessage());
|
||||
}
|
||||
|
||||
$model = User::find([
|
||||
'password_reset_token' => $token,
|
||||
'status' => User::STATUS_ACTIVE,
|
||||
]);
|
||||
|
||||
if ($model === null) {
|
||||
throw new BadRequestHttpException('Wrong password reset token.');
|
||||
}
|
||||
|
||||
$model->scenario = 'resetPassword';
|
||||
if ($model->load($_POST) && $model->save()) {
|
||||
if ($model->load($_POST) && $model->resetPassword()) {
|
||||
Yii::$app->getSession()->setFlash('success', 'New password was saved.');
|
||||
return $this->goHome();
|
||||
}
|
||||
@@ -149,27 +151,4 @@ class SiteController extends Controller
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
private function sendPasswordResetEmail($email)
|
||||
{
|
||||
$user = User::find([
|
||||
'status' => User::STATUS_ACTIVE,
|
||||
'email' => $email,
|
||||
]);
|
||||
|
||||
if (!$user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user->password_reset_token = Security::generateRandomKey();
|
||||
if ($user->save(false)) {
|
||||
return \Yii::$app->mail->compose('passwordResetToken', ['user' => $user])
|
||||
->setFrom([\Yii::$app->params['supportEmail'] => \Yii::$app->name . ' robot'])
|
||||
->setTo($email)
|
||||
->setSubject('Password reset for ' . \Yii::$app->name)
|
||||
->send();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
55
apps/advanced/frontend/models/PasswordResetRequestForm.php
Normal file
55
apps/advanced/frontend/models/PasswordResetRequestForm.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
namespace frontend\models;
|
||||
|
||||
use common\models\User;
|
||||
use yii\base\Model;
|
||||
|
||||
/**
|
||||
* Password reset request form
|
||||
*/
|
||||
class PasswordResetRequestForm extends Model
|
||||
{
|
||||
public $email;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
['email', 'filter', 'filter' => 'trim'],
|
||||
['email', 'required'],
|
||||
['email', 'email'],
|
||||
['email', 'exist', 'targetClass' => 'User', 'message' => 'There is no user with such email.'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean sends an email
|
||||
*/
|
||||
public function sendEmail()
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = User::find([
|
||||
'status' => User::STATUS_ACTIVE,
|
||||
'email' => $this->email,
|
||||
]);
|
||||
|
||||
if (!$user) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user->generatePasswordResetToken();
|
||||
if ($user->save()) {
|
||||
return \Yii::$app->mail->compose('passwordResetToken', ['user' => $user])
|
||||
->setFrom([\Yii::$app->params['supportEmail'] => \Yii::$app->name . ' robot'])
|
||||
->setTo($this->email)
|
||||
->setSubject('Password reset for ' . \Yii::$app->name)
|
||||
->send();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
66
apps/advanced/frontend/models/ResetPasswordForm.php
Normal file
66
apps/advanced/frontend/models/ResetPasswordForm.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
namespace frontend\models;
|
||||
|
||||
use common\models\User;
|
||||
use yii\base\InvalidParamException;
|
||||
use yii\base\Model;
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* Password reset form
|
||||
*/
|
||||
class ResetPasswordForm extends Model
|
||||
{
|
||||
public $password;
|
||||
|
||||
/**
|
||||
* @var \common\models\User
|
||||
*/
|
||||
private $_user;
|
||||
|
||||
/**
|
||||
* Creates a form model given a token
|
||||
*
|
||||
* @param string $token
|
||||
* @param array $config name-value pairs that will be used to initialize the object properties
|
||||
* @throws \yii\base\InvalidParamException if token is empty or not valid
|
||||
*/
|
||||
public function __construct($token, $config = [])
|
||||
{
|
||||
if (empty($token) || !is_string($token)) {
|
||||
throw new InvalidParamException('Password reset token cannot be blank.');
|
||||
}
|
||||
$this->_user = User::find([
|
||||
'password_reset_token' => $token,
|
||||
'status' => User::STATUS_ACTIVE,
|
||||
]);
|
||||
if (!$this->_user) {
|
||||
throw new InvalidParamException('Wrong password reset token.');
|
||||
}
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array the validation rules.
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
['password', 'required'],
|
||||
['password', 'string', 'min' => 6],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets password.
|
||||
* @return boolean if password was reset.
|
||||
*/
|
||||
public function resetPassword()
|
||||
{
|
||||
$user = $this->_user;
|
||||
$user->password = $this->password;
|
||||
$user->removePasswordResetToken();
|
||||
return $user->save();
|
||||
}
|
||||
}
|
||||
|
||||
49
apps/advanced/frontend/models/SignupForm.php
Normal file
49
apps/advanced/frontend/models/SignupForm.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace frontend\models;
|
||||
|
||||
use common\models\User;
|
||||
use yii\base\Model;
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* Signup form
|
||||
*/
|
||||
class SignupForm extends Model
|
||||
{
|
||||
public $username;
|
||||
public $email;
|
||||
public $password;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
['username', 'filter', 'filter' => 'trim'],
|
||||
['username', 'required'],
|
||||
['username', 'string', 'min' => 2, 'max' => 255],
|
||||
|
||||
['email', 'filter', 'filter' => 'trim'],
|
||||
['email', 'required'],
|
||||
['email', 'email'],
|
||||
['email', 'unique', 'targetClass' => 'User', 'message' => 'This email address has already been taken.'],
|
||||
|
||||
['password', 'required'],
|
||||
['password', 'string', 'min' => 6],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs user up.
|
||||
* @return User saved model
|
||||
*/
|
||||
public function signup()
|
||||
{
|
||||
if ($this->validate()) {
|
||||
return User::create($this->attributes);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use yii\captcha\Captcha;
|
||||
/**
|
||||
* @var yii\web\View $this
|
||||
* @var yii\widgets\ActiveForm $form
|
||||
* @var frontend\models\ContactForm $model
|
||||
* @var \frontend\models\ContactForm $model
|
||||
*/
|
||||
$this->title = 'Contact';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
|
||||
@@ -5,7 +5,7 @@ use yii\widgets\ActiveForm;
|
||||
/**
|
||||
* @var yii\web\View $this
|
||||
* @var yii\widgets\ActiveForm $form
|
||||
* @var common\models\LoginForm $model
|
||||
* @var \common\models\LoginForm $model
|
||||
*/
|
||||
$this->title = 'Login';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
|
||||
@@ -5,7 +5,7 @@ use yii\widgets\ActiveForm;
|
||||
/**
|
||||
* @var yii\web\View $this
|
||||
* @var yii\widgets\ActiveForm $form
|
||||
* @var common\models\User $model
|
||||
* @var \frontend\models\PasswordResetRequestForm $model
|
||||
*/
|
||||
$this->title = 'Request password reset';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
|
||||
@@ -5,7 +5,7 @@ use yii\widgets\ActiveForm;
|
||||
/**
|
||||
* @var yii\web\View $this
|
||||
* @var yii\widgets\ActiveForm $form
|
||||
* @var common\models\User $model
|
||||
* @var \frontend\models\ResetPasswordForm $model
|
||||
*/
|
||||
$this->title = 'Reset password';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
|
||||
@@ -5,7 +5,7 @@ use yii\widgets\ActiveForm;
|
||||
/**
|
||||
* @var yii\web\View $this
|
||||
* @var yii\widgets\ActiveForm $form
|
||||
* @var common\models\User $model
|
||||
* @var \frontend\models\SignupForm $model
|
||||
*/
|
||||
$this->title = 'Signup';
|
||||
$this->params['breadcrumbs'][] = $this->title;
|
||||
|
||||
Reference in New Issue
Block a user