How can I validate current password in the laravel 5.6 - laravel

I try like this :
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ChangePasswordRequest extends FormRequest
{
...
public function rules()
{
return [
'old_password' => 'required|confirmed',
'password' => 'required|min:6',
'password_confirmation' => 'required|min:6|same:password'
];
}
}
I have entered the old password correctly, but there is still a message :
The old password confirmation does not match.
How can I solve this problem?

what you can do is to make a rule. the following will probably solve your problem.
CurrentPassword.php
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Support\Facades\Hash;
class CurrentPassword implements Rule
{
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return Hash::check($value,auth()->user()->password);
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'Current password is incorrect';
}
}
and in your controller, you can make something like this:
$this->validate($request,[
'password_current'=>['required',new CurrentPassword()],
'password'=>'required|string|min:6|confirmed',
]);
$request->user()->update([
'password'=>bcrypt($request->password)
]);

(Laravel v7.x)
You are looking for rule called 'password':
...
'old_password' => 'password',
...
As well you could specify an authentication guard using the rule's first parameter like this:
...
'old_password' => 'password|web',
...
Here is docs:
https://laravel.com/docs/7.x/validation#rule-password

According to the documentation:
Hash::check() function which allows you to check whether the old password entered by a user is correct or not.
if (Hash::check("parameter1", "parameter2")) {
//add logic here
}
parameter1 - user password that has been entered on the form
parameter2 - old password hash stored in a database
It will return true if the old password has been entered correctly and you can add your logic accordingly
new_password and new_confirm_password to be same, you can add your validation in form request like this:
'new_password' => 'required',
'new_confirm_password' => 'required|same:new_password'

The "confirmed" rule doesn't do what you expect it here to do.
If you set confirmed rule on a field old_password it will look for form input old_password_confirmation and check that its value is equal to the value of old_password. It's basically an inverse of same:field with predefined expected name (it will add _confirmation to the original name).
In your case you would use it like this and it will perform same function as your current password_confirmation => same:password rule:
public function rules()
{
return [
'old_password' => 'required',
'password' => 'required|min:6|confirmed',
];
}
For what you want to achieve you could either create your own validation rule or (in my opinion better) check whether the entered password is correct in the controller.

Related

Store json array in the api controller -laravel 8

I'm a little bit confused to how I can store data in my api controller,
My json looks like this:
[
{ a: 1 },
{ a: 2 }
]
I have my rules
$rules = [
'*.a' => 'required',
];
I have my validation
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
$error = $validator->messages()->toJson();
return response($error, 200);
}
and now there's my "problem": I would like to make a cleaner code.
My old option was pass the request->all() to a variable , json decode the contenent and make a foreach cycle to store data as here:
foreach ($datas as $data) {
$data = new rawData([
'a' => $data->a,
]);
$newrawData->save();
}
can I do a cleaner thing?? and How?
You can put your validation logic in a custom form request validator.
First, create the validator
php artisan make:request ExampleRequest
You can find the newly created a new class in app/Http/Requests/ExampleRequest.php and you can add your rules as follows
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ExampleRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'*.a' => 'required',
];
}
}
Now your controller method/action will not be executed unless the request passes the validation rules. you can use it in your controller method as follows:
In app/Http/Controllers/ExampleController.php
public function store(ExampleRequest $request)
{
// Your normal code.
}
that looks quite good. There is only one small thing I would have done differently. But it's a matter of taste.
foreach ($datas as $data) {
rawData::create($data->toArray());
}
And you can you use the request object directly to validate. or you implement an custom Request Object what you pass as parameter in your function.
$request->validate([
'*.a' => 'required',
]);

Controller Method not called with custom Form Request Method

For form validation I made a Request class via php artisan make:request UpdatePlanRequest.
However after using the UpdatePlanRequest class in store the method isn't called anymore.
The UpdatePlanRequest:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdatePlanRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{ //TODO: CHECK IF THE PROTOTYPE IDS ARE OWNED BY THE USER (https://stackoverflow.com/questions/42662579/validate-an-array-of-integers/42693970)
return [
'start_date' => 'required|date',
'end_date' => 'required|date|after:start_date',
'name' => 'required|string'
];
}
}
The controller method:
use App\Http\Requests\UpdatePlanRequest;
public function store(UpdatePlanRequest $request)
{
//
dd('hello');
}
If the function header is store(Request $request) hello is shown, in that example it isn't.
The custom Request class is necessary to call $request->validated(); later for validation purposes according to the docs.
Is there a reason you have your Request class as being abstract? The default class that is created when running php artisan make:request <name> doesn't define the class as being abstract. This seems to work for me, but not when declaring it as abstract.
$request->validated(); is used to retrieve the validated inputs, so just by calling the UpdatePlanRequest it should validate the request
//Try This
use App\Http\Requests\UpdatePlanRequest;
public function store(UpdatePlanRequest $request)
{
$validatedData = $request->validated();
dd('$validatedData');
$profile = new Profile([
'user_id' => $request->get('user_id'),
]);
$profile->save();
echo $request->session()->flash('alert-success', 'Profile details Succefully Added!');
return redirect('create')->with('success', 'Data saved!');
}
Your route will be.
Route::get('profile','ProfileController#store');
Route::post('profile/create','ProfileController#store')->name('create');
Well this works right!
When the method is called, it checks the request class (UpdatePlanRequest). If there is an error, it does not enter the method anymore and you can not see the output of dd() function.
If the data is correct after checking the rules, then dd() will be displayed.
You must manage errors

proengsoft/laravel-jsvalidation How to use Custom Rule Messages?

I use proengsoft/laravel-jsvalidation in combination with a custom FormRequest and custom validation rules that I defined via Validator::extend(...) in a service provider. This works well.
However, when I port my custom rules to the new(ish) custom Rule class in Laravel 5.5+, JsValidator fails at getting my custom Rule messages.
I have this custom rule:
use Illuminate\Contracts\Validation\Rule;
class MyRule implements Rule
{
public function passes($attribute, $value) {
return $value > 10;
}
public function message() {
return 'Your :attribute is pretty small, dawg!';
}
}
My form request uses this rule:
use Illuminate\Foundation\Http\FormRequest;
use App\Rules\MyRule;
class MyRequest extends FormRequest
{
public function authorize() {
return true;
}
public function rules() {
$rules = [
'foo' => 'required|numeric',
'bar' => ['required', new MyRule()],
];
return $rules;
}
}
This should work, but I get thrown an Exception on
{!! JsValidator::formRequest('\App\Http\Requests\MyRequest') !!}
An Exception is thrown from a call to Str::snake(Object(App\Rules\MyRule)) made by Proengsoft\JsValidation\Javascript\MessageParser.php.
JsValidation does not look at the $rule object type before calling Validator->getMessage($attribute, $rule)
where instead it should be calling $rule->messages();
Can I work around this bug somehow, and use laravel-jsvalidation together with my custom Rule and FormRequest -- or does it necessarily require i make a pull request and hope it will be fixed... someday? I'd like to make this work now-ish.
This can be archived by passing JsValidator instance based on rules and message arrays instead of passing the form request. In controller Pass this instance to blade. Read here for more details.
JsValidator::make($rules, $messages, $customAttributes, $selector)
In controller,
$validator = JsValidator::make(
[
'name' => 'required',
],
[
'name.required' => 'Name field is a required field',
]
)
return View::make("Your view", compact($validator));
In blade,
{!! $validator->selector('.wizard_frm') !!}
<form class='wizard_frm'></form>
And in this case we can create object of request class and pass rules function returned array to JsValidator::make if needed.

Updating and Validating email field

Im creating a update page, where the user can change his email, but it needs a password confirmation for that. But before this, it needs some kind of validation, first to check if the current email is correct and also if the new email is available to be saved, and after the password is correct than be updated.
But im having some trouble in making the request, validation, can someone tell me if this is correct? (dont mind the dd i putted, is just for testing).
$user = Auth::user();
$this->validate($request, array(
'current_email' => 'required|email|unique:users,email,'. $user->id,
'email' => 'required|email|unique:users',
'verify_password' => 'required|min:6'
));
//Verify information user before updating
if($user->email != $request->current_email){
dd("Current Email is not the same");
}
if($user->password != bcrypt($request->verify_password)){
dd("Password incorrect, will not update");
}
dd("update, is ok now");
First write this in your console.
php artisan make:provider ValidationServiceProvider
Then replace your app\Providers\ValidationServiceProvider with
namespace App\Providers;
use Validator;
use Illuminate\Support\ServiceProvider;
class ValidationServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot() {
Validator::extend('old_password', function($attribute, $value, $parameters, $validator) {
return auth()->validate([
'email' => auth()->user()->email,
'password' => $value
]);
});
}
/**
* Register the service provider.
*
* #return void
*/
public function register() {
//
}
}
Now add it to providers in config\app.php, like
App\Providers\ValidationServiceProvider::class,
Now replace your method definition with
$user = auth()->user();
$validator = Validator::make($request, array(
'current_email' => 'required|email|exists:users,email,id,'. $user->id,
'email' => 'required|email|unique:users',
'verify_password' => 'required|min:6|old_password'
));
if($validator->fails()) {
return redirect()->back()->withErrors($validator)->withInput();
}
dd("Good to go!!!");
First of all I have replaced your current_email unique validation with exists. Why? Have a look here
The method I have used here for validation is called Custom Validation. More details here
Let me know if you face any issues :)
What you have will work, but there are a couple of things that I would recommend.
First, you already have the $request, so you should get the user from that. While Auth::user() and $request->user() do return the same thing, the later will not require the use of a facade and therefore is a little quicker.
Second, I would validate the before you validate the request body. It doesn't make sense to spend the resources validating the $request if the password is not correct.
Third, you can put your $user->email == $request->current_email check in the validation using the exists rule. It would be something like "exists:users,email,id,$user->id".
How you display the errors will be up to how the request is being done. Take a look at the Displaying Validation Errors section for submitting a form and the AJAX Requests and Validation for AJAX requests.

laravel : sanitize request data before validation

there is a UpdateUserRequest form request that verify fields value against its rules defined in rules mathod .it has rules() and authorize() methods by default. i want prevent verifying and updating empty fields (such as password) .
using sometimes in rules is not useful as html inputs will be present in POST request even if they are empty.
array:6 [▼
"_method" => "PATCH"
"_token" => "Cz79rRez2f6MG0tTU17nVwXD0X1lNGH1hA7OORjm"
"name" => "john"
"email" => "mymail#gmail.com"
"password" => ""
"password_confirmation" => ""
]
so i should remove empty keys of POST request before using sometimes in rules.
the question is : Where is the best place to purge Request array?
is there any laravel build in method to manage such situations?
P.S :Solution:
#Bogdon solution is still valid and works, but there is another simple ,nice ,neat solution adopted from here:
just override all() method inside form request
class RegistrationRequest extends Request
{
...
public function all()
{
$attributes = parent::all();
if(isset($attributes['password']) && empty($attributes['password']))
{
unset($attributes['password']);
}
$this->replace($attributes);
return parent::all();
}
...
}
To make this work you'll need to modify the contents of the App\Http\Requests\Request class to allow a way to sanitize the input (class code taken from this Laracasts post):
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
abstract class Request extends FormRequest
{
/**
* Validate the input.
*
* #param \Illuminate\Validation\Factory $factory
* #return \Illuminate\Validation\Validator
*/
public function validator($factory)
{
return $factory->make(
$this->sanitizeInput(), $this->container->call([$this, 'rules']), $this->messages()
);
}
/**
* Sanitize the input.
*
* #return array
*/
protected function sanitizeInput()
{
if (method_exists($this, 'sanitize'))
{
return $this->container->call([$this, 'sanitize']);
}
return $this->all();
}
}
After that you just need to write add sanitize method in the UpdateUserRequest class that removes the password field from the input when it's empty:
public function sanitize()
{
if (empty($this->get('password'))) {
// Get all input
$input = $this->all();
// Remove the password field
unset($input['password']);
// Replace the input with the modified one
$this->replace($input);
}
return $this->all();
}
Now using the sometimes rule for the password field will work:
public function rules()
{
return [
// Other rules go here
'password' => 'sometimes|required|confirmed'
];
}
I'm not sure about the best way to purge the fields, but this is how I currently handle user updates on my system.
I find the user based on the $id passed through and then update the appropriate records. I assume that name and email will never be empty, it is only the password that can be empty - and so we can just set the name and email fields to the values passed in and then use an if statement to check if the password field is empty or not and update accordingly.
Something along the lines of this is what I use:
public function update($id)
{
$user = User::find($id);
$user->name = Input::get('name');
$user->email = Input::get('email');
if (Input::get('password') != "")
{
$user->password = Hash::make(Input::get('password'));
}
$user->save();
}

Resources