I have created the password route, view and method in UserController@getProfilePassword
and UserController@postProfilePassword
At the moment, if I fill out the new_password
field, it gets hashed and submitted to the database correctly, then I can login with the new password.
But I need to be able to validate the new_password
and new_password_confirm
to make sure they're the same and validate the user's current password as well.
How can I do that?
EDIT: I added $this->validate
to the method, but now I keep getting the error The password confirmation confirmation does not match.
even though they do match as I am using a simple password. Also I think I need to check against the current password manually as validator
won't do it for me.
public function getProfilePassword(Request $request) {
return view('profile/password', ['user' => Auth::user()]);
}
public function postProfilePassword(Request $request) {
$user = Auth::user();
$this->validate($request, [
'old_password' => 'required',
'password' => 'required|min:4',
'password_confirmation' => 'required|confirmed'
]);
$user->password = Hash::make(Input::get('new_password'));
$user->save();
}
And this is the view
<form action="{{ route('profile/updatepassword') }}" method="post" enctype="multipart/form-data">
<div class="form-group">
<label for="name">Current Password</label>
<input type="password" name="old_password" class="form-control" id="old_password">
</div>
<div class="form-group">
<label for="name">Password</label>
<input type="password" name="password" class="form-control" id="password">
</div>
<div class="form-group">
<label for="name">New Password</label>
<input type="password" name="password_confirmation" class="form-control" id="password_confirmation">
</div>
<button type="submit" class="btn btn-primary">Change Password</button>
<input type="hidden" value="{{ Session::token() }}" name="_token">
</form>
In your form. blade, ensure that the password input field has a name attribute of name="password" -> it has to be password , Also, add an attribute of name="password_confirmation" to the Confirm Password text input box, and it will work.
By default, Laravel 'confirmed' validator adds the error message to the original field and not to the field which usually contains the confirmed value.
There's a Hash::check()
function which allows you to check whether the old password entered by user is correct or not.
usage
if (Hash::check("param1", "param2")) {
//add logic here
}
param1 - user password that has been entered on the form
param2 - old password hash stored in database
it will return true if old password has been entered correctly and you can add your logic accordingly
for new_password
and new_confirm_password
to be same, you can add your validation in form request like
'new_password' => 'required',
'new_confirm_password' => 'required|same:new_password'
If you only need the functionality of a custom rule once throughout your application, you may use a Closure instead of a rule object. The Closure receives the attribute's name, the attribute's value, and a $fail callback that should be called if validation fails
$request->validate([
'new_password' => 'required|confirmed|min:4',
'current_password' => ['required', function ($attribute, $value, $fail) use ($user) {
if (!\Hash::check($value, $user->password)) {
return $fail(__('The current password is incorrect.'));
}
}],
]);
https://laravel.com/docs/5.6/validation#using-closures
In Laravel 6 there is a new rule called password
,according to docs
The field under validation must match the authenticated user's password. You may specify an authentication guard using the rule's first parameter:
'password' => 'password:api'
so the validation rules can be as simple as :
'current_password' => 'required|password',
'password' => 'required|string|min:8|confirmed',
You can do this by creating a custom validation rule (for this example I'm using current_password
and new_password
as the input names).
Put this in AppServiceProvider::boot()
:
Validator::extend('current_password', function ($attribute, $value, $parameters, $validator) {
$user = User::find($parameters[0]);
return $user && Hash::check($value, $user->password);
});
Now you can use the following in your controller:
$user = auth()->user(); // or pass an actual user here
$this->validate($request, [
'current_password' => 'required_with:new_password|current_password,'.$user->id,
]);
Using laravel 5.8/6.0, here is what i do(without much additional code)
Step 1: Validate
$data = request()->validate([
'firstname' => ['required', 'string', 'max:255'],
'lastname' => ['required', 'string', 'max:255'],
'username' => ['bail', 'nullable', 'string', 'max:255', 'unique:users'],
'email' => ['bail', 'nullable', 'string', 'email:rfc,strict,dns,spoof,filter', 'max:255', 'unique:users'],
'new_password' => ['nullable', 'string', 'min:8'],
'confirm_new_password' => ['nullable', 'required_with:new_password', 'same:new_password'],
'current_password' => ['required', function ($attribute, $value, $fail) {
if (!\Hash::check($value, Auth::user()->password)) {
return $fail(__('The current password is incorrect.'));
}
}]
]);
Step 2: If validation is passed
For example:
if(request(input)){
$data += ['input' => request(input)];
}
For example:
Auth::user()->account->update($data);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With