Update password

Hello,

I would like to ask you how you empty password field at update (user/profile) page? Currently I have password hash in the password field at user edit page. Password should be changed only if the password field is not empty at the user edit page.

common/models/User.php


<?php


namespace common\models;


use yii\base\NotSupportedException;

use yii\db\ActiveRecord;

use yii\web\IdentityInterface;

use Yii;


class User extends ActiveRecord implements IdentityInterface

{


	public static function findIdentity($id)

	{

		return static::findOne($id);

	}


	public static function findIdentityByAccessToken($token, $type = null)

	{

		throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');

	}


	public static function findByUsername($username, $scope = null)

	{

		$query = static::find()->where(['username' => $username]);

		if ($scope !== null)

		{

			if (is_array($scope))

			{

				foreach ($scope as $value)

				{

					$query->$value();

				}

			} else

			{

				$query->$scope();

			}

		}

		return $query->one();

	}


	public function getId()

	{

		return $this->id;

	}


	public function getAuthKey()

	{

		return $this->authKey;

	}


	public function validateAuthKey($authKey)

	{

		return $this->authKey === $authKey;

	}


	public function validatePassword($password)

	{

		return Yii::$app->security->validatePassword($password, $this->password);

	}


	public function beforeSave($insert)

	{

		if (parent::beforeSave($insert))

		{

			if ($this->isNewRecord)

			{

				$this->generateAuthKey();

			}

			return true;

		}

		return false;

	}


	public function generateAuthKey()

	{

		$this->authKey = Yii::$app->security->generateRandomString();

	}


	public function setPassword($password)

	{

		$this->password = Yii::$app->security->generatePasswordHash($password);

	}


}



backend/models/User.php


<?php


namespace backend/models;


class User extends \common\models\User

{


	public $controllerNamespace = 'backend\controllers';


	public static function tableName()

	{

		return 'user';

	}


	public function rules()

	{

		return [

			[['username'], 'required'],

			[['password'], 'required', 'on' => ['create']],

			[['username', 'password'], 'trim'],

			[['password'], 'string', 'min' => 6, 'max' => 30],

			[['username'], 'unique'],

			['username', 'match', 'pattern' => '/^[a-zA-Z0-9_-]+$/'],

			['username', 'string', 'min' => 3, 'max' => 30],

		];

	}


	public function scenarios()

	{

		return [

			'create' => ['username', 'password'],

			'update' => ['username', 'password']

		];

	}


	public function beforeSave($insert)

	{

		if (parent::beforeSave($insert))

		{

			if ($this->isNewRecord || (!$this->isNewRecord && $this->password))

			{

				$this->setPassword($this->password);

				$this->generateAuthKey();

			}

			return true;

		}

		return false;

	}


	public function afterSave($insert, $changedAttributes)

	{

		parent::afterSave($insert, $changedAttributes);

	}


}

backend/controllers/UserController.php


<?php


namespace backend/controllers;


use Yii;

use yii\web\Controller;

use yii\filters\VerbFilter;

use yii\filters\AccessControl;

use backend/models\User;


class UserController extends Controller

{


	public function behaviors()

	{

		return [

			'access' => [

				'class' => AccessControl::className(),

				'rules' => [

					[

						'allow' => true,

						'roles' => ['@'],

					],

				],

			],

			'verbs' => [

				'class' => VerbFilter::className(),

				'actions' => [

					'index' => ['get'],

					'create' => ['get', 'post'],

					'update' => ['get', 'put', 'post'],

					'delete' => ['post', 'delete'],

				],

			],

		];

	}


	public function actionIndex()

	{

		$searchModel = new UserSearch();

		$dataProvider = $searchModel->search(Yii::$app->request->queryParams);


		return $this->render('index', [

					'searchModel' => $searchModel,

					'dataProvider' => $dataProvider,

		]);

	}


	public function actionCreate()

	{

		$user = new User(['scenario' => 'create']);

		if ($user->load(Yii::$app->request->post()))

		{

			if ($user->validate())

			{

				if ($user->save(false))

				{

					return $this->redirect(['/setting/user']);

				}

			}

		}


		return $this->render('create', [

					'model' => $user,

		]);

	}


	public function actionUpdate($id)

	{

		$user = $this->findModel($id);

		$user->setScenario('update');

		if ($user->load(Yii::$app->request->post()))

		{

			if ($user->validate())

			{

				if ($user->save(false))

				{

					return $this->redirect(['/setting/user']);

				}

			}

		}


		return $this->render('update', [

					'model' => $user,

		]);

	}


	public function actionDelete($id)

	{

		$this->findModel($id)->delete();


		return $this->redirect(['index']);

	}


	protected function findModel($id)

	{

		if (($model = User::findIdentity($id)) !== null)

		{

			return $model;

		}

	}




Thanks.

Rename "password" column to "password_hash" (or anything that is consistent with your naming conventions) in the database. The corresponding attribute will be appear in your model class automatically. Now add a public property with name "password" to your model manually. Use the former to store the password hash and the latter to store and validate input.

Hello, thanks for answer.

My column for password hash was named "password" in database. I try put "public $password;" to backend/models/User.php

Password field is empty at edit page - its OK.

Bugs:

a)Password field in database is empty when inserting

b)Password field in database does not change when updating

The main point here is to use one model attribute to store the password and another one to store the hash. That’s why I recommended renaming “password” column to “password_hash” or similar.

Thanks, it works!