Issue with the reset password form

Hi all,

I’m building an admin area for my website. It is almost complete and I want to give the non super user the ability to change the password. (super users can set it anyway)

My model for the users is Admin

My controller is AdmincmsController

My view for changing password is change.php

I’m using following code

** One specialthing to consider is I do not use a database field for "new_password" I just defined them in the model as public variables. (I have inserted it below)

In Admincms model




public $old_password;

public $new_password;

public function equalPasswords() {

	$record=$this->findByAttributes(array('username_email'=>Yii::app()->user->getName()));

		if (!empty(Yii::app()->user->non_super_username) && !empty($this->old_password) && !empty($this->new_password)) {

			if ($record->password == md5($this->old_password))

				$this->password = $this->new_password;

		}

	}

public function beforeSave() {

 if (!empty($this->password))

 $this->password = md5($this->password);

return true;

}



AdmincmsController.php




public function actionChangepw($id)

	{

		$model=$this->loadModel($id);

		

		// Uncomment the following line if AJAX validation is needed

		// $this->performAjaxValidation($model);


		if(isset($_POST['Adminuser']))

		{

			$model->attributes=$_POST['Adminuser'];

			$model->equalPasswords();

			if($model->save())

				$this->redirect(array('view','id'=>$model->userid));

		}


		$this->render('changepw',array(

			'model'=>$model,

		));

	}



The views (change.php)-> (form)




<div class="row">

	<?php echo $form->labelEx($model,'Old password'); ?>

	<?php echo $form->passwordField($model,'old_password',array('size'=>60,'maxlength'=>100)); ?>

	<?php echo $form->error($model,'old_password'); ?>

</div>

<div class="row">

	<?php echo $form->labelEx($model,'New password'); ?>

	<?php echo $form->passwordField($model,'new_password',array('size'=>60,'maxlength'=>100)); ?>

	<?php echo $form->error($model,'old_password'); ?>

</div>



I’m calling the function “equalPasswords()” in the controller because calling like below in the model itself was giving out an error




public function rules()

{

return array(		

	array('old_password', 'new_password','equalPasswords'),

	);

}



If you could please point me to some suitable tutorial or a guide.

Any help in this is much appreciated.

Thanks

Can somebody help me please ?

Sorry for the stupid question, but what’s the problem? Are you getting an error or something not working as it should.

I’m assuming the latter. Can you confirm that your last if statement is true and being called?

Cheers,

Matt

Also, your afterSave() method has a logic flaw, in that it will encrypt the pwd each time the record is saved, regardless of the field being updated.

What I would do is use the rules as you’ve done but with a scenario.




public function rules()

{

    return array(           

        // You'll have to figure out how to hash old_password before comparing.

        array('old_password', 'compare', 'compareAttribute'=>'password', 'on'=>'changePwd'),

        array('old_password, new_password', 'required', 'on' => 'changePwd'),

    );

}



In your controller, you’ll have to set the scenario to ‘changePwd’ as follows.




public function actionChangepw($id)

{

    $model=$this->loadModel($id);

    $model->setScenario('changePwd');


    if(isset($_POST['Adminuser']))

    {

        $model->attributes=$_POST['Adminuser'];


        if ($model->validate())

        {

            $model->password = md5($model->new_password);


            if ($model->save())

            {

                $this->redirect(array('view','id'=>$model->userid));

            }


            $this->render('changepw',array(

                'model'=>$model,

            ));

        }

    }

}



Note, this hasn’t been tested.

Cheers,

Matt

Hi Matt,

Thanks a lot for helping. I figured out somethings. I still have a problem. That is Yii is automatically getting the value in the database for the password field (when editing or inserting password) Do you or anybody kow how to stop this?

Thanks

Sure we can help. Can you please post your controller (changePwd action) and your complete model. Which field is being loaded from the DB - the $model->password field?

Cheers,

Matt

Thanks again for offering help in this matter.

My model





class Adminuser extends CActiveRecord

{

	public $groupname;

	public $old_password;

	public $new_password;

	public $confirm_password;

	public $reset_password;

	

	/**

	 * Returns the static model of the specified AR class.

	 * @return Adminuser the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}


	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'adminuser';

	}


	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array( 

			array('username_email, name, adminuser_groupid', 'required'),

			array('adminuser_groupid', 'numerical', 'integerOnly'=>true),

			array('confirm_password', 'required', 'on'=>'changepassword, Create, Update'), //checking the "confirm_password" is blank on changepassword, Create, Update scenarios

			array('password', 'required', 'on'=>'changepassword, Create, Update'), // the password and confirm_password cannot be put together to check if they are blank (may be because confirm_password is not a database field)

			array('password', 'compare', 'compareAttribute'=>'confirm_password'),

			array('confirm_password', 'safe'),

			array('username_email', 'length', 'max'=>128),

			array('name', 'length', 'max'=>30),

			array('password', 'length', 'max'=>100),

			// The following rule is used by search().'password','Incorrect username or password.'

			// Please remove those attributes that should not be searched.

			array('userid, username_email, name, adminuser_groupid', 'safe', 'on'=>'search'),

		);

	}

	

	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

			'adminuserGroup' => array(self::BELONGS_TO, 'AdminuserGroup', 'adminuser_groupid'),

		);

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'userid' => 'Userid',

			'username_email' => 'Username Email',

			'name' => 'Name',

			'adminuser_groupid' => 'Admin user Group',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

	 */

	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;

		$criteria->select = 'ag.groupname,userid,username_email,name,t.adminuser_groupid';

		$criteria->compare('userid',$this->userid);

		$criteria->compare('username_email',$this->username_email,true);

		$criteria->compare('name',$this->name,true);

		$criteria->join = 'INNER JOIN adminuser_group ag ON ag.adminuser_groupid = t.adminuser_groupid';


		return new CActiveDataProvider(get_class($this), array(

			'criteria'=>$criteria,

		));

	}

	public function get_users()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;

		$criteria->select = 'ag.groupname,userid,username_email,name,t.adminuser_groupid';

		$criteria->join = 'INNER JOIN adminuser_group ag ON ag.adminuser_groupid = t.adminuser_groupid';


		return new CActiveDataProvider('Adminuser', array(

			'criteria'=>$criteria,

		));

	}

	public function get_groupname()

	{             

		$list = array();

		$criteria = new CDbCriteria;

		$criteria->select = 'ag.groupname, t.adminuser_groupid';

		$criteria->join = 'INNER JOIN adminuser_group ag ON ag.adminuser_groupid = t.adminuser_groupid';

		$result_arr = Adminuser::model()->findall($criteria);

		foreach($result_arr as $row) {

			$list[$row["adminuser_groupid"]] = $row["groupname"];	

		}

        return $list;

	}

	public function validateAndChangepassword() {

	/* 

		pre: this function is used in changing password by user him self. Used the AdminUserController.php "actionChangepassword" 

		post: Function will update the "adminuser" table with new password and return true if the update was successful and return false if it failed.

	*/

		

		$rows = "";

		$newpw = md5 ($this->new_password);

		$oldpw = md5 ($this->old_password);

		$connection = Yii::app()->db;

		$sql = 'UPDATE adminuser SET password="' . $newpw . '" WHERE userid=' . Yii::app()->user->userid . ' AND 	password ="' . $oldpw . '"';

		$command = $connection->createCommand($sql);

		$rows=$command->execute();

		if(empty($rows))

			return false;

		else

			return true;

	}

	public function resetPasswordOrUpdateOthers($reset_password = 0) {

	/* 

		pre: this function is used in resetting the user password by administrator. Used the AdminUserController.php "actionUpdate" 

		accepting one parameter to check if the admin wants to reset the password (reset password checkbox is checked in the form)

		

		post:	if password also be need to be resetted it will return either the encrypeted password to be sent to the database.

				else it will return false 

				IF $reset_password = 0 (reset password checkbox is NOT checked in the form) then we are updating other fields without updating the password.

				if row are affected return true

				otherwise return false

	*/

		if ($reset_password==1) { //(reset password checkbox is checked in the form)

			if (!empty($this->reset_password) && !empty($this->password) && !empty($this->confirm_password)) {

				$this->confirm_password = $this->encrypt($this->confirm_password);

				$connection = Yii::app()->db;

				$sql = 'UPDATE adminuser SET username_email="' . $this->username_email . '", name="' . $this->name . '" , adminuser_groupid=' . $this->adminuser_groupid . ', password="' . $this->confirm_password . '" WHERE userid=' . $this->userid . '';

				$command = $connection->createCommand($sql);

				$rows=$command->execute();

			}

			if(empty($rows))

				return false;

			else

				return true;

		}

		else { //(reset password checkbox is NOT checked in the form) Password is not updated

			if (!empty($this->username_email) && !empty($this->name) && !empty($this->adminuser_groupid)) {

				$connection = Yii::app()->db;

				$sql = 'UPDATE adminuser SET username_email="' . $this->username_email . '", name="' . $this->name . '" , adminuser_groupid=' . $this->adminuser_groupid . ' WHERE userid=' . $this->userid . '';

				$command = $connection->createCommand($sql);

				$rows=$command->execute();

			}

			if(empty($rows))

				return false;

			else

				return true;

		}

	}	

		

	public function encrypt($param) {

		$param = md5($param);

		return $param;

	}

	public function returnUsername() {

		$logged_email = Yii::app()->user->getName();

		$record=$this->findByAttributes(array('username_email'=>$logged_email));

		$logged_username =  $record->name;

		return $logged_username;

	}

	

}




action in the controller




public function actionUpdate($id)

	{

		$model = $this->loadModel($id);

		if (isset($_POST['Adminuser'])) {

			$model->attributes = $_POST['Adminuser'];

				if ($_POST['Adminuser']['reset_password']==1) {

					if ($_POST['Adminuser']['password'] == $_POST['Adminuser']['confirm_password']) {

						$model->setScenario('Update');

						$model->reset_password = $_POST['Adminuser']['reset_password'];

						$model->confirm_password = $_POST['Adminuser']['confirm_password'];

						if ($model->resetPasswordOrUpdateOthers($model->reset_password))

							$this->redirect(array('view','id'=>$model->userid));

					}

					else { $this->redirect(array('Update','id'=>$model->userid)); }

				}			

				else if ($model->resetPasswordOrUpdateOthers()) {

					$model->setScenario('do_not_update_password');

					$model->saveAttributes(array('username_email', 'name','adminuser_groupid'));

					$this->redirect(array('view','id'=>$model->userid));

				}

				else {

					$this->redirect(array('Update','id'=>$model->userid));

				}

		}

		$this->render('update',array(

			'model'=>$model,

		));

	}



My validation in the model does not work. You will see that I’m doing some validation in the controller also. If we are doing so how can we pass the custom error messages like “Password and confirm password fields does not match” or An error happened please try again.

Thanks

It’s generally not a good idea to do validation in your controllers because it may lead to unnecessarily complex apps that are hard to read/maintain. If you want to use it though, you could use,

Model:




    public $customErrors=array();


    /**

     */

    public function addCustomError($attribute, $error) {

        $this->customErrors[] = array($attribute, $error);

    }


    /**

     */

    protected function beforeValidate() {

        $r = parent::beforeValidate();

//        if ($this->scenario == 'xxx') {

//          ...

//        }

        foreach ($this->customErrors as $param) {

            $this->addError($param[0], $param[1]);

        }

        return $r;

    }



Controller:




$model->addCustomError('name', 'Description');



The above solution comes from the last posting in this post.

Not sure if this solves all of your problems.

Also, try to split up your resetPasswordOrUpdateOthers method. It seems a too large and general.

Cheers,

Matt

Hi Matt,

Thanks again for your kind help. Your reply was very helpful in solving some of my questions.

Thanks again.

Regards,

Isuru

Follow this tutorial -

http://www.yiiframework.com/wiki/718/change-password-with-tbactiveform

Can you please stop bumping 3+ year old topics that have already been solved with your "solutions"? Thanks!

Haha I have to laugh aloud behind my screen imagining Yiistarter still searching for an answer and receive this comment after 3 years :lol:. And then someone who post his first post with a complaint about it, I love this forum! :-*