tags:

views:

125

answers:

1

Hi, I am learning cakephp by myself. I tried to create a user controller with a changepassword function. It works, but I am not sure if this is the best way, and I could not googled up useful tutorials on this. Here is my code:

class UsersController extends AppController {

    var $name = 'Users';

    function login() {
    }

    function logout() {
        $this->redirect($this->Auth->logout());
    }

    function changepassword() {
        $session=$this->Session->read();
        $id=$session['Auth']['User']['id'];
        $user=$this->User->find('first',array('conditions' => array('id' => $id)));
        $this->set('user',$user);
        if (!empty($this->data)) {
            if ($this->Auth->password($this->data['User']['password'])==$user['User']['password']) {
                if ($this->data['User']['passwordn']==$this->data['User']['password2']) {
                // Passwords match, continue processing
                $data=$this->data;
                $this->data=$user;
                $this->data['User']['password']=$this->Auth->password($data['User']['passwordn']);
                $this->User->id=$id;
                $this->User->save($this->data);
                $this->Session->setFlash('Password changed.');
                $this->redirect(array('controller'=>'Toners','action' => 'index'));
                } else {
                    $this->Session->setFlash('New passwords differ.');
                    }
            } else {
                $this->Session->setFlash('Typed passwords did not match.');
            }
        }
    }
}

password is the old password, passwordn is the new one, password2 is the new one retyped. Is there any other, more coomon way to do it in cake?

+2  A: 

I see that you validate and manipulate data in the controller. Doing this in a model is generally a better practice. I implemented similar functionality just a few days ago. My change_password() method looks somewhat like this:

# app/controllers/users_controller.php
function change_password() {
    if (!empty($this->data)) {
        if ($this->User->save($this->data)) {
            $this->Session->setFlash('Password has been changed.');
            // call $this->redirect() here
        } else {
            $this->Session->setFlash('Password could not be changed.');
        }
    } else {
        $this->data = $this->User->findById($this->Auth->user('id'));
    }
}

And here's a stripped down version of the view used with that method:

# app/views/users/change_password.ctp
echo $this->Form->create('User');
echo $this->Form->input('id');
echo $this->Form->input('current_password');
echo $this->Form->input('password1'));
echo $this->Form->input('password2');
echo $this->Form->end('Submit');

The code that does something interesting is in the model. I added the fields from the form to the validate property and wrote custom validation methods. This allows me to use password1 and password2 fields in any other place in the application, for example, on the registration form.

# app/models/user.php
var $validate = array(
    'current_password' => array(
        'rule' => 'checkCurrentPassword',
        'message' => '...'
    ),
    'password1' => array(
        'rule' => 'checkPasswordStrength',
        'message' => '...',
    ),
    'password2' => array(
        'rule' => 'passwordsMatch',
        'message' => '...',
    )
);

Finally, in the beforeSave() callback of the model I set password to the hash of password1 to prepare the data to be stored it in the database.

Mike
Nice, thanks for your answer, it helped me to think more cake-like. I have one problem now: I could not find out how to check the current_password in the data against the stored one because I did not manage to call Auth->password($this->data['current_password']) from the model code (user.php).How to do this?
sipiatti
If you want to read more about the approach that I presented, it is known as "fat models, skinny controllers" and may be applied to any MVC framework.Although the Auth component is not available from a model, all the `password()` method does is call the hash() method of the Security library, which can be used from a model: `Security::hash($password, null, true);`.
Mike
Thanks Mike, I've learned a lot. Salutations!
sipiatti