user2268281
user2268281

Reputation: 87

CakePHP - Password confirmation not allowing user to submit registration

I'm trying to set up validation for user registration but I'm having troubles. When I only have the email,role and password fields in the $validation array (remove the others) it works and will save a new user. When I try to add the other fields it fails and gives the flash message error "The user could not be saved. Please, try again."

I'm pretty sure it's the re_password check. When I remove the validation for that it works. However, the re_password validation does display an error when the passwords are different, so I'm not sure where to look

Here's my users table

id  |  email  |  password  |  location  | website  | role  | created |  modified

Here's the validation requirements. To get it to save a new user I have to remove everything but email, password and role.

public $validate = array(
    'email' => 'email'
    ,
    'password' => array(
        'required' => array(
            'rule' => array('minLength', '8'),
            'message' => 'A password with a minimum length of 8 characters is required'
        )
    ),
    're_password' => array(
        'required' => array(
            'rule' => array('equalTo', 'password' ), 
            'message' => 'Both password fields must be filled out'
        )
    ),
    'role' => array(
        'valid' => array(
            'rule' => array('inList', array('admin', 'author')),
            'message' => 'Please enter a valid role',
            'allowEmpty' => false
        )
    ),
     'location' => array(
        'valid' => array(
            'rule' => array('notEmpty'),
            'message' => 'Please select a location'
        )
    )
);

Here's the form (the options array is above, figured it's not necessary to show)

    echo $this->Form->input('email');
    echo $this->Form->input('password');
    echo $this->Form->input('re_password', array('type'=>'password', 'label'=>'Re-Enter Password', 'value'=>'', 'autocomplete'=>'off'));
    echo $this->Form->input('location', array('options' => $options, 'label' => 'Select Nearest Location'));
    echo $this->Form->input('website',array('label'=>'Enter your website, such as www.example.com. ')); 
    echo $this->Form->input('role', array('type' => 'hidden', 'default' => 'user'));

Here's the re_password checking function in the User model

function check_user_password($userid) { 
    $salt = Configure::read('Security.salt');
    $this->User->id = $userid;
    $hashed_password = $this->User->field('password');
    // check password  
    if($hashed_password == md5($data['User']['re_password'].$salt)) {  
        return true;
    } else {
        return false;
    }
}   

And finally, here's the add function in UsersController

public function add() {  
        if ($this->request->is('post')) {  
            $this->User->create();     //create initiates a form on User/add.ctp
            if ($this->User->save($this->request->data)) {  //save the form data
                $this->Session->setFlash(__('The user has been saved'));
                $this->redirect(array('controller' => 'demos', 'action' => 'index'));
            } else {
                $this->Session->setFlash(__('The user could not be saved. Please, try again.'));
            }
        }
    }

Please let me know if there's anything else you need to see

Upvotes: 1

Views: 5901

Answers (3)

tropicalm
tropicalm

Reputation: 51

Attention, in @luboss answer, where he declares:

function equalToField($array, $field) {
    return strcmp($this->data[$this->alias][key($array)], $this->data[$this->alias][$field]) == 0;
}

That cannot work as we are comparing inconsistent fields: the left member of strcmp has already been hashed, but not the right member. This happens as a CakePHP automation because the field is called password.

The way I got this to work was to reuse the hashing function in the equalToField helper:

public function equalToField($array, $field) {
    $valueFirstOccurrence = $this->data[$this->alias][$field];
    $valueSecondOccurrence = Security::hash($this->data[$this->alias][key($array)], $type = 'sha1', $salt = true) ;
    return !strcmp($valueFirstOccurrence, $valueSecondOccurrence);
}

Other point : If you are interested in adding a minLength validation field for your password field, you want to read this good post first: minLength data validation is not working with Auth component for CakePHP

Upvotes: 0

Krishna
Krishna

Reputation: 1540

Hi Please use following code for your requirement :

override equalTo function by putting your own method in user model:

function equalTo( $field=array(), $compare_field=null ) 
{
    foreach( $field as $key => $value ){
        $v1 = $value;
        $v2 = $this->data[$this->name][ $compare_field ];
        if($v1 !== $v2) {
            return FALSE;
        } else {
           continue;
        }
    }
    return TRUE;

}

Upvotes: 0

user2074884
user2074884

Reputation:

I believe that your re_passwords valiadtion rule equalTo compares its value to string password and not the actual field. I like to use custom functions for this.

so try replacing re_passwords rule array

 //'rule' => array('equalTo', 'password' ),
'rule' => array('equalToField', 'password'),

and declare equalToField function in that model

function equalToField($array, $field) {
    return strcmp($this->data[$this->alias][key($array)], $this->data[$this->alias][$field]) == 0;
}

** Also in the future when you seem to have a problem with validation rules try this in your controllers action (its faster than removing every single rule)

if ($this->User->save($this->request->data)) {
    ...
} else {
    debug($this->User->validationErrors);
    ...
}

I hope this helps.

Upvotes: 4

Related Questions