I'm trying to test if the current password is same as in DB.
my simplified controller:
class ChangePasswordController extends Controller
{
public function update(Request $request, User $user)
{
$this->validate($request, [
'current_password' => ['required', new CurrentPassword()],
'password' => 'required|string|min:6|confirmed'
]);
$user->update([
'password' => bcrypt($request->password)
]);
}
}
in my custom CurrentPassword rule i'm checking the hash like this:
class CurrentPassword implements Rule
{
public function passes($attribute, $value)
{
$check = Hash::check($value, auth()->user()->password);
dump($check);
return $check;
}
public function message()
{
return 'Current password is incorrect.';
}
}
and my test for the custom rule is:
/** #test */
public function an_authenticated_user_may_change_own_password()
{
$this->withoutExceptionHandling();
$user = factory(User::class)->create([
'password' => '1234'
]);
$this->actingAs($user)->patch("/profile/{$user->id}/password", [
'current_password' => '1234',
'password' => 'mynewpassword',
'password_confirmation' => 'mynewpassword'
]);
$this->assertTrue(Hash::check('mynewpassword', $user->fresh()->password));
}
unfortunately i'm getting an error:
1)
Tests\Feature\UpdatePasswordTest::an_authenticated_user_may_change_own_password
Illuminate\Validation\ValidationException: The given data was invalid.
i don't understand why this is happining. My dump($check); returns false when i run this test. My $value is '1234' and the auth()->user()->password returns also '1234'. Maybe somebody have an idee what I'm doing wrong.
this test is getting green:
/** #test */
public function current_password_must_be_valid()
{
$user = factory(User::class)->create([
'password' => '1234'
]);
$this->actingAs($user)->patch("/profile/{$user->id}/password", [
'current_password' => '12345',
'password' => 'mynewpassword',
'password_confirmation' => 'mynewpassword'
])->assertSessionHasErrors('current_password');
}
You should hash your password in your factory as well, otherwise Eloquent will store it in cleartext (that's why auth()->user()->password returns '1234')
public function current_password_must_be_valid()
{
$user = factory(User::class)->create([
'password' => Hash::make('1234'); // remember to import the Hash facade
]);
...
}
Related
ImportController
<?php
namespace App\Http\Controllers;
use App\Models\User;
use App\Talent\ImportData\Requests\ImportDataRequest;
use Illuminate\Support\Facades\Hash;
use Rap2hpoutre\FastExcel\FastExcel;
class ImportController extends Controller
{
public function __construct(private User $user)
{
}
public function import(ImportDataRequest $request)
{
$validated = $request->validated();
$collection = (new FastExcel)->import($validated['file'], function ($rows) {
$user = $this->user->create([
'name' => $rows['First Name'] . " " . $rows['Last Name'],
'email' => $rows['Email'],
'password' => Hash::make('Introcept#123'),
'role' => $rows['Role']
]);
$employee = $user->employees()->create([
'status' => $rows['Status'],
'first_name' => $rows['First Name'],
'last_name' => $rows['Last Name'],
'email' => $rows['Email'],
'contact_number' => $rows['Contact Number'],
'date_of_birth' => $rows['Date of Birth'],
'current_address' => $rows['Current Address'],
'pan_number' => $rows['Pan Number'],
'bank_account_number' => $rows['Bank Account Number'],
]);
$education = $employee->education()->create([
'education_level' => $rows['Education Level'],
'passed_year' => $rows['Passed Year'],
'institution' => $rows['Institution'],
]);
$employment = $employee->employment()->create([
'organization' => $rows['Organization'],
'join_date' => $rows['Join Date'],
'current_position' => $rows['Current Position'],
'work_schedule' => $rows['Work Schedule'],
'team' => $rows['Team'],
'manager' => $rows['Manager'],
'superpowers' => $rows['Superpower'],
]);
$employment->manages()->create([
'employee_id' => $rows['Manages'],
]);
});
}
}
ImportData Request
<?php
namespace App\Talent\ImportData\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ImportDataRequest 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<string, mixed>
*/
public function rules()
{
return [
'file'=>'required|mimes:csv,xlsx'
];
}
}
I am creating an API where the admin can import data from an excel file. Here, I am using the Fast Excel package in order to import data. Everything is working fine, but I have no idea how I can validate excel data before saving it into the database. I am pretty new to Laravel and any help will be really appreciated. Thank you
I am looking forward to learn Livewire and its test as well. Now I have created component for registering users and it is working fine, but when I try to do a test I get this error:
Failed asserting that an array has the key 'redirect'.
Here are the parts of the code:
RegisterTest
class RegisterTest extends TestCase
{
use RefreshDatabase;
/** #test */
public function can_register()
{
Livewire::test('auth.register')
->set('name', 'user')
->set('email', 'user#outlook.com')
->set('password', 'secret')
->set('password_confirmation', 'secret')
->call('register')
->assertRedirect('/');
}
}
Component
public $name = '';
public $email = '';
public $password = '';
public $password_confirmation = '';
public function register()
{
$data = $this->validate([
'name' => 'required|string',
'email' => 'required|email',
'password' => 'required|confirmed|min:8|string'
]);
User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
return redirect('/');
}
This is pretty easy.
Add the following file:
->assertHasNoErrors(['name', 'email', 'password']);
before
->assertRedirect('/');
line and you will see it will fail. This is because your validation tells password should be minimum 8 characters and in your test it is 6 (you used secret as password)
When I register a new user and I want to sign him in by using auth attempt it doesn't work while the user is saved to database
static function register()
{
if(self::$validate['message'])
{
$user = User::create([
'name' => self::$values['name'],
'email' => self::$values['email'],
'password' => Hash::make(self::$values['password'])
]);
Auth::attempt($user,true);
Auth::attempt($user->only(['email','password']));
return result::repsonse(true);
} else
return self::$validate;
}
You can use Auth::login() method
static function register()
{
if(self::$validate['message'])
{
$user = User::create([
'name' => self::$values['name'],
'email' => self::$values['email'],
'password' => Hash::make(self::$values['password'])
]);
Auth::login($user);
return result::repsonse(true);
} else
return self::$validate;
}
I have these request file to register a new customer, I want to be the response json when the validation fails, how can I do that?
This is the request class
<?php
namespace App\Http\Requests\Validations;
use App\Http\Requests\Request;
class RegisterCustomerRequest extends Request
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'name' => 'required|min:3|max:255',
'email' => 'required|email|max:255|unique:customers',
'password' => 'required|string|min:6|confirmed',
'agree' => 'required',
];
}
}
And the registration function:
public function register(RegisterCustomerRequest $request)
{
$customer = Customer::create([
'name' => $request->name,
'email' => $request->email,
'password' => $request->password,
'accepts_marketing' => $request->subscribe,
'verification_token' => Str::random(40),
'active' => 0,
]);
// Sent email address verification notich to customer
$customer->notify(new EmailVerificationNotification($customer));
$customer->generateToken();
event(new Registered($customer));
return new CustomerResource($customer);
}
in your RegisterCustomerRequest you can override default method failedValidation as below
protected function failedValidation(Validator $validator)
{
if ($this->ajax()){
throw new HttpResponseException($this->respondWithError(419,'VALIDATION_ERROR',$validator->errors()));
} else{
throw (new ValidationException($validator))
->errorBag($this->errorBag)
->redirectTo($this->getRedirectUrl());
}
}
also you can write your own response inside $this->ajax() like below
if ($this->ajax()){
return response()->json($validator->errors(),419);
}
I want when I finished register it redirects me to the dashboard page (Auto login after the register).
this is the user register code :
public function store(Request $request)
{
$this->validator($request->all())->validate();
$apprenant = Apprenant::create([
'nom' => $request['nom'],
'prenom' => $request['prenom'],
'email' => $request['email'],
'niveau' => $request['niveau'],
'password' => Hash::make($request['password']),
]);
return redirect('/apprenant/dashboard');
}
But when I finished registring it redirects me to the login page
Hi if you are create a guard then run this code for after register login
Auth::guard(guard_name)->loginUsingId($id);
// example
public function register(Request $req)
{
$user = new User; // define here your model
$user->name = $req->name;
$user->email = $req->email;
$user->password = Hash::make($req->password);
if($user->save()){
Auth::guard(guard_name)->loginUsingId($user->id);
}
}
// logout overite
public function logout()
{
Auth::guard('guard_name')->logout();
return redirect("login_path");
}
When creating a new user, create() method, should return a new model object.
Use Auth::loginUsingId($apprenant->id); before redirecting to dashboard:
public function store(Request $request)
{
$this->validator($request->all())->validate();
$apprenant = Apprenant::create([
'nom' => $request['nom'],
'prenom' => $request['prenom'],
'email' => $request['email'],
'niveau' => $request['niveau'],
'password' => Hash::make($request['password']),
]);
Auth::loginUsingId($apprenant->id);
return redirect('/apprenant/dashboard');
}
source
https://laravel.com/docs/5.7/authentication#other-authentication-methods
Write this line before redirecting to the dashboard:
\Auth::login($apprenant);
or just,
auth()->login($apprenant);
That means, you code will look like:
public function store(Request $request)
{
$this->validator($request->all())->validate();
$apprenant = Apprenant::create([
'nom' => $request['nom'],
'prenom' => $request['prenom'],
'email' => $request['email'],
'niveau' => $request['niveau'],
'password' => Hash::make($request['password']),
]);
//login the user
\Auth::login($apprenant);
return redirect('/apprenant/dashboard');
}