Marco C
Marco C

Reputation: 111

CakePHP 3 how to edit user without changing password (hashed)

I have my UsersController with my edit.ctp view. When I browse /users/edit/1, I see password field filled with ***** (filled with hash in entity User.php, using DefaultPasswordHasher). My UsersTable.php has password has required.

So, I can try:

unset($user->password); // in edit() from UsersController.php

and setting [require => false] in edit.ctp

When I save, I get

The user could not be saved. Please, try again.

Because in my UsersTable.php I have:

$validator
    ->requirePresence('password', 'create')
    ->notEmpty('password');

If I try to leave blank from controller I get error, if I try to fill with actual password, it hashes again.

How could I edit any user without change his password? Can I set this from model or I need to make password as not required?

Thanks in advance

Upvotes: 3

Views: 1426

Answers (1)

Andy Hoffner
Andy Hoffner

Reputation: 3327

Couple of things:

Firstly, if you haven't already, you may want to mark the password field as hidden to prevent it from exposing the hash in toArray calls or JSON views.

Secondly, any data field provided to patchEntity will be validated and saved (as you've discovered), even if the value for the field is blank.

If you look at the entity with debug($user) you'll notice it tracks which fields are "dirty", and since patchEntity saw you submitted a password field (even if it was blank), it set the User entity's password to blank and marked it as "dirty". Even if you later call unset($user->password) it's still got a record of it being dirty, and so it'll attempt to validate a value for it.

You could potentially mark the field clean with $export->setDirty('password', false); but then when a new password was submitted in the form it wouldn't be saved.

A better option would be to check if the password field was blank before calling patchEntity, and unset it then:

if ($this->request->is(['patch', 'post', 'put'])) {
    $data = $this->request->getData();
    if(empty($data['password'])){
        unset($data['password']);
    }
    $user = $this->Users->patchEntity($user, $data);

Upvotes: 4

Related Questions