Home > OS >  Updating User profile resets password even if no new password is entered with Laravel 9 and Livewire
Updating User profile resets password even if no new password is entered with Laravel 9 and Livewire

Time:08-22

When updating a User profile, password is being reset even though a new password is not being entered. Existing password should be retained if no new one is entered.

livewire/user/edit.blade.php

...
<div >
    <div >
        <label for="new_password" >
            New Password
        </label>
        <div >
            <input wire:model="new_password" type="password" name="new_password" id="new_password"
                    autocomplete="new-password"
                    >
        </div>
        @error('new_password')<span
            >{{ $message }}</span>
        @enderror
    </div>

    <div >
        <label for="new_password_confirmation" >
            Confirm Password
        </label>
        <div >
            <input wire:model="new_password_confirmation" type="password" name="new_password_confirmation" id="new_confirmation"
                    >
        </div>
    </div>
</div>
...

Livewire/User/edit.php

...
class Edit extends Component
{
    public $first_name;
    public $last_name;
    public $email;
    public $password;
    public $new_password = '';
    public $new_password_confirmation = '';
    public $role;


    public function mount(User $user)
    {
        $this->user = $user;
        $this->first_name = $user->first_name;
        $this->last_name = $user->last_name;
        $this->email = $user->email;
        $this->password = $user->password;
        $this->role = $user->role;
    }

    public function updateUser($id)
    {
        $record = User::find($id);

        $this->validate([
            'new_password' => ['confirmed'],
        ]);

        $record->update([
            'first_name' => $this->first_name,
            'last_name' => $this->last_name,
            'email' => $this->email,
            'role' => $this->role,
            'password' => bcrypt($this->new_password) ? : $record->password,
        ]);

        session()->flash('success', 'User Successfully Updated');

        return redirect()->route('user.edit', $record->id);
    }

    public function render()
    {
        return view('livewire.user.edit');
    }
}

CodePudding user response:

Your setting $new_password to an empty string.

public $new_password = '';

But you evaluate whether it’s null in your updateUser method.

I would start by setting public $new_password = null;

Then in updateUser update your new_password check to:

'password' => $this->new_password ? bcrypt($this->new_password) : bcrypt($record->password),

You could also leave the property set as empty string and check for empty($this->new_password) but I prefer the null route.

CodePudding user response:

A few notes first,

  • Livewire has a $rules property that you should use, and declare the rules separately - see https://laravel-livewire.com/docs/2.x/input-validation
  • Instead of doing updateUser($id) and then $record = User::find($id);, you can just do updateUser(User $user) through "model route binding"
  • You may want to update the current user instead, so update $this->user instead of fetching it again through the parameter

Your actual issue though, instead of updating all properties at once, move the array to a variable, and then push the password only if it was changed.

$userData = [
    'first_name' => $this->first_name,
    'last_name' => $this->last_name,
    'email' => $this->email,
    'role' => $this->role,
];

if (filled($this->new_password)) {
    $this->validate([
        'new_password' => ['confirmed'],
    ]);

    $userData['password'] = bcrypt($this->new_password);
}

$record->update($userData);

CodePudding user response:

I would have a simple if there to be more explicit, but if you prefer a quick, inline solution to your problem then this should do:

'password' => bcrypt($this->new_password ?: $record->password),
  • Related