diff --git a/apps/advanced/backend/controllers/SiteController.php b/apps/advanced/backend/controllers/SiteController.php
index ecf684c..6a9ff5c 100644
--- a/apps/advanced/backend/controllers/SiteController.php
+++ b/apps/advanced/backend/controllers/SiteController.php
@@ -1,18 +1,24 @@
 <?php
-
 namespace backend\controllers;
 
 use Yii;
+use yii\web\AccessControl;
 use yii\web\Controller;
-use common\models\LoginForm;
+use common\models\forms\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 [
diff --git a/apps/advanced/backend/views/site/login.php b/apps/advanced/backend/views/site/login.php
index 1326203..92d3d79 100644
--- a/apps/advanced/backend/views/site/login.php
+++ b/apps/advanced/backend/views/site/login.php
@@ -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\forms\LoginForm $model
  */
 $this->title = 'Login';
 $this->params['breadcrumbs'][] = $this->title;
diff --git a/apps/advanced/common/models/User.php b/apps/advanced/common/models/User.php
index af3c997..0630c5b 100644
--- a/apps/advanced/common/models/User.php
+++ b/apps/advanced/common/models/User.php
@@ -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
@@ -22,16 +21,14 @@ use yii\web\IdentityInterface;
  */
 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;
 
+	/**
+	 * @inheritdoc
+	 */
 	public function behaviors()
 	{
 		return [
@@ -46,10 +43,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 +62,7 @@ class User extends ActiveRecord implements IdentityInterface
 	}
 
 	/**
-	 * @return int|string|array current user ID
+	 * @inheritdoc
 	 */
 	public function getId()
 	{
@@ -76,7 +70,7 @@ class User extends ActiveRecord implements IdentityInterface
 	}
 
 	/**
-	 * @return string current user auth key
+	 * @inheritdoc
 	 */
 	public function getAuthKey()
 	{
@@ -84,8 +78,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 +86,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,13 +96,13 @@ class User extends ActiveRecord implements IdentityInterface
 		return Security::validatePassword($password, $this->password_hash);
 	}
 
+	/**
+	 * @inheritdoc
+	 */
 	public function rules()
 	{
 		return [
-			['status', 'default', 'value' => self::STATUS_ACTIVE],
 			['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
-
-			['role', 'default', 'value' => self::ROLE_USER],
 			['role', 'in', 'range' => [self::ROLE_USER]],
 
 			['username', 'filter', 'filter' => 'trim'],
@@ -117,34 +112,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;
-	}
 }
diff --git a/apps/advanced/common/models/LoginForm.php b/apps/advanced/common/models/forms/LoginForm.php
similarity index 94%
rename from apps/advanced/common/models/LoginForm.php
rename to apps/advanced/common/models/forms/LoginForm.php
index 38888d9..c69050f 100644
--- a/apps/advanced/common/models/LoginForm.php
+++ b/apps/advanced/common/models/forms/LoginForm.php
@@ -1,12 +1,12 @@
 <?php
+namespace common\models\forms;
 
-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()
 	{
diff --git a/apps/advanced/common/models/forms/PasswordResetRequestForm.php b/apps/advanced/common/models/forms/PasswordResetRequestForm.php
new file mode 100644
index 0000000..552445b
--- /dev/null
+++ b/apps/advanced/common/models/forms/PasswordResetRequestForm.php
@@ -0,0 +1,55 @@
+<?php
+namespace common\models\forms;
+
+use common\models\User;
+use yii\base\Model;
+use yii\helpers\Security;
+
+/**
+ * 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()
+	{
+		$user = User::find([
+			'status' => User::STATUS_ACTIVE,
+			'email' => $this->email,
+		]);
+
+		if (!$user) {
+			return false;
+		}
+
+		$user->password_reset_token = Security::generateRandomKey();
+		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;
+	}
+}
+ 
\ No newline at end of file
diff --git a/apps/advanced/common/models/forms/ResetPasswordForm.php b/apps/advanced/common/models/forms/ResetPasswordForm.php
new file mode 100644
index 0000000..b6ad043
--- /dev/null
+++ b/apps/advanced/common/models/forms/ResetPasswordForm.php
@@ -0,0 +1,69 @@
+<?php
+namespace common\models\forms;
+
+use common\models\User;
+use yii\base\InvalidParamException;
+use yii\base\Model;
+use yii\helpers\Security;
+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
+	 * @throws \yii\base\InvalidParamException if token is empty or not valid
+	 */
+	public function __construct($token)
+	{
+		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.');
+		}
+	}
+
+	/**
+	 * @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;
+		if ($user->validate()) {
+			$user->password_hash = Security::generatePasswordHash($this->password);
+			$user->password_reset_token = '';
+			return $user->save();
+		} else {
+			return false;
+		}
+	}
+}
+ 
\ No newline at end of file
diff --git a/apps/advanced/common/models/forms/SignupForm.php b/apps/advanced/common/models/forms/SignupForm.php
new file mode 100644
index 0000000..ef3ad79
--- /dev/null
+++ b/apps/advanced/common/models/forms/SignupForm.php
@@ -0,0 +1,59 @@
+<?php
+namespace common\models\forms;
+
+use common\models\User;
+use yii\base\Model;
+use yii\helpers\Security;
+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()) {
+			$user = new User();
+			$user->username = $this->username;
+			$user->email = $this->email;
+			$user->password_hash = Security::generatePasswordHash($this->password);
+			$user->auth_key = Security::generateRandomKey();
+			$user->role = User::ROLE_USER;
+			$user->status = USer::STATUS_ACTIVE;
+			if ($user->save()) {
+				return $user;
+			}
+		}
+		return null;
+	}
+}
+ 
\ No newline at end of file
diff --git a/apps/advanced/frontend/controllers/SiteController.php b/apps/advanced/frontend/controllers/SiteController.php
index 649d1f3..2f45db5 100644
--- a/apps/advanced/frontend/controllers/SiteController.php
+++ b/apps/advanced/frontend/controllers/SiteController.php
@@ -1,17 +1,24 @@
 <?php
-
 namespace frontend\controllers;
 
-use Yii;
-use yii\web\Controller;
-use common\models\LoginForm;
+use common\models\forms\LoginForm;
+use common\models\forms\PasswordResetRequestForm;
+use common\models\forms\ResetPasswordForm;
+use common\models\forms\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.');
-		}
-
-		$model = User::find([
-			'password_reset_token' => $token,
-			'status' => User::STATUS_ACTIVE,
-		]);
-
-		if ($model === null) {
-			throw new BadRequestHttpException('Wrong password reset token.');
+		try {
+			$model = new ResetPasswordForm($token);
+		} catch (InvalidParamException $e) {
+			throw new BadRequestHttpException($e->getMessage());
 		}
 
-		$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;
-	}
 }
diff --git a/apps/advanced/frontend/views/site/login.php b/apps/advanced/frontend/views/site/login.php
index 635b9ae..4892065 100644
--- a/apps/advanced/frontend/views/site/login.php
+++ b/apps/advanced/frontend/views/site/login.php
@@ -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\forms\LoginForm $model
  */
 $this->title = 'Login';
 $this->params['breadcrumbs'][] = $this->title;
diff --git a/apps/advanced/frontend/views/site/requestPasswordResetToken.php b/apps/advanced/frontend/views/site/requestPasswordResetToken.php
index bb13a5f..9cbddf5 100644
--- a/apps/advanced/frontend/views/site/requestPasswordResetToken.php
+++ b/apps/advanced/frontend/views/site/requestPasswordResetToken.php
@@ -5,7 +5,7 @@ use yii\widgets\ActiveForm;
 /**
  * @var yii\web\View $this
  * @var yii\widgets\ActiveForm $form
- * @var common\models\User $model
+ * @var common\models\forms\PasswordResetRequestForm $model
  */
 $this->title = 'Request password reset';
 $this->params['breadcrumbs'][] = $this->title;
diff --git a/apps/advanced/frontend/views/site/resetPassword.php b/apps/advanced/frontend/views/site/resetPassword.php
index ec9f949..b2b8f33 100644
--- a/apps/advanced/frontend/views/site/resetPassword.php
+++ b/apps/advanced/frontend/views/site/resetPassword.php
@@ -5,7 +5,7 @@ use yii\widgets\ActiveForm;
 /**
  * @var yii\web\View $this
  * @var yii\widgets\ActiveForm $form
- * @var common\models\User $model
+ * @var common\models\forms\ResetPasswordForm $model
  */
 $this->title = 'Reset password';
 $this->params['breadcrumbs'][] = $this->title;
diff --git a/apps/advanced/frontend/views/site/signup.php b/apps/advanced/frontend/views/site/signup.php
index 3bb57fc..c45f378 100644
--- a/apps/advanced/frontend/views/site/signup.php
+++ b/apps/advanced/frontend/views/site/signup.php
@@ -5,7 +5,7 @@ use yii\widgets\ActiveForm;
 /**
  * @var yii\web\View $this
  * @var yii\widgets\ActiveForm $form
- * @var common\models\User $model
+ * @var common\models\forms\SignupForm $model
  */
 $this->title = 'Signup';
 $this->params['breadcrumbs'][] = $this->title;