Testing Error messages to be shown for user - php

I'm trying to write a test to assert that my login page displays an error when the user enters an incorrect username or password.
#if ($errors->any())
<p>Looks like you’ve entered the wrong username or password.
<a href="{{route('password.request')}}">
Click here</a> to reset your password“ </p></div>
#endif
The functionality is working fine and I can see the errors on page, but for some reason, I can't get my test to pass.
->assertSessionHasErrors() is working fine, while ->assertSeeText() is not detecting the error messages in text.
`
public function userSeesErrorMessage() {
$user = factory('App\User')->create([
'password' => bcrypt($password = 'test'),
]);
$response = $this->followingRedirects()
->post('/login', [
'email' => $user->email,
'password' => 'incorrectPassword'
]);
$response->assertSeeText('Looks like you’ve entered the wrong username or password. Click here to reset your password');
}`
The response seem to contain the whole document's HTML, except for the part about the errors.
Any help would be much appreciated.

There might be a few reasons why this does does not work. Easiest thing you could do is to set a header for a referer. This way the validation will know where to redirect you back, because currently you're not submitting a form and the redirect is sending you to a page where you might not display the errors:
$response = $this->followingRedirects()
->post(
'/login',
[
'email' => $user->email,
'password' => 'incorrectPassword'
],
['referer' => '/login']
);
Another issue might be that the session errors are lost within the redirects, where you can try following the redirect separately:
$r = $this->post('/login', [
'email' => $user->email,
'password' => 'incorrectPassword'
]);
$r->assertStatus(302);
$r->assertSessionHasErrors('email');
$r = $this->followRedirects($r);
$r->assertSeeText('Looks like you’ve entered the wrong username or password. Click here to reset your password');

Related

Session put does not seem to be working properly

I'm working with Laravel 5.8 and I wanted to make sure that users can submit a form only every 2 hours (as long as a session is alive).
So I tried this at the Controller:
if(Session::has('request_has_been_sent')){
return redirect()->back()->with('error', 'You just submitted a request and cannot submit a new one');
}else{
$withDraw = WithdrawWallet::create([
'balance_value' => $request->balance_wallet,
'can_draw' => $request->can_draw,
'shaba_number' => $request->shaba_number,
'first_name' => $request->first_name,
'last_name' => $request->last_name,
'description' => $request->desc,
'status' => 'pending',
'user_id' => auth()->user()->usr_id,
]);
Session::put('request_has_been_sent');
}
return redirect()->back()->with('success','Your request was sent');
So by this, everytime a user submits a new request, session request_has_been_sent must be set.
Therefore at the next time user submits the form, if the session was still alive, the message You just submitted a request and cannot submit a new one appears.
But now the problem is it does not work. In fact user can still submit another request, right after submitting a request.
This means that the session is not set somehow.
So what's going wrong here? How can I properly do this?
You can set session using set and put method
Session::put('name','value');
Retrieve it using get
Session::get('name')
So in your case you need to set your session use
Session::put('request_has_been_sent','yes');
And to check if it is set or not use
if(Session::get('request_has_been_sent')){
Docs: https://laravel.com/docs/5.0/session
I think your only problem here is not setting the session value to anything you need to set it to something or else laravel will ignore it.
Session::put('request_has_been_sent', true);
// Check if it exists, this will check if it exists without getting it
Session::has('request_has_been_sent')
Once the user is logged out al the user sesion wil be flushd out. Which means user and create and WithdrawWallet and logout and then login again and then user can create another WithdrawWallet so to fix that you can use cache
$cacheKey = WithdrawWallet::class.'.'.auth()->user()->usr_id;
if (Cache::has($cacheKey)) {
return redirect()->back()->with('error', 'You just submitted a request and cannot submit a new one');
} else {
$withDraw = Cache::remember($cacheKey, now()->addHours(2), function () use ($request){
return WithdrawWallet::create([
'balance_value' => $request->balance_wallet,
'can_draw' => $request->can_draw,
'shaba_number' => $request->shaba_number,
'first_name' => $request->first_name,
'last_name' => $request->last_name,
'description' => $request->desc,
'status' => 'pending',
'user_id' => auth()->user()->usr_id,
]);
});
}
return redirect()->back()->with('success', 'Your request was sent');

How Can I manual pass information to the register controller in Laravel

To create a user without the end-user having to type in the details.
Something akin to
User::classcreate([
'email' => $email,
'password' => $rand_pass,
.....
]);
Thanks for the ideas and feedback in advance :)
The use case is.
The end-user invites another user to use the service by typing in their email and it creates a user with a random password before sending a email to the new user with their created details.
You're almost there with your code. It should look like this:
User::create([
'email' => $email,
'password' => bcrypt($rand_pass),
]);
But if you want to hash the password, you should also send the password to that user through email (which is not very secure). When the users logs in for the first time, you should at least require him to change the password.
You can simply use create() method of your User model:
$userData = [
'email' => 'some#email.com',
'password' => 'somepassword'
];
$newUser = User::create($userData);
You'll also need your password hashed in order for it to work with Laravel's authorization. Add the following to your user model - it will hash password before it's saved to the database:
public function setPasswordAttribute($password)
{
$this->attributes['password'] = Hash::make($password);
}

Laravel random to database

What i'm try to do: Then user registered on my website he's got a email with confirmation random code.
My controller looks like that:
$activation_code = str_random(40);
/*
* Register user.
*/
$user = Sentry::register([
'username' => Input::get('username'),
'email' => Input::get('email'),
'password' => Input::get('password'),
'language_id' => $language->id,
'activation_code' => $activation_code
]);
$user->slug = Str::slug($user->username);
$user->save();
But then i check databse, the activation_code cell is empty. What i'm doing wrong? Thanks for answers!
I assume you meant the activation column not table, check your fillable array and make sure its in there.
EDIT
Scratch that, it looks like like your auto activating the user, no activation code necessary in that case.
FIXED! Works fine with:
$activationCode = $user->getActivationCode();

Get a user by username and password with Laravel

I need to do some extra checks on a user, I would like to get the user by username and password.
Firstly:
Is there a built in function that gets a user by username and password without authenticating them?
Secondly:
If the above is no, then how do I correctly hash the password, because if I use Hash::make( $password ) and then compare to the database, it is not the same... You would usually use Hash::check but I need to actually get the user by username and password.
In Laravel 5.2
You can use Auth::once($credentials) to validate credentials and thereafter Auth::getUser(); to get the user.
$credentials = Request::only('username', 'password');
if(!Auth::once($credentials)) {
// Invalid user credentials; throw Exception.
}
$user = Auth::getUser();
First:
If you want to check if user data to authentication is correct you can use:
if (Auth::validate($credentials))
{
//
}
But if you want to get user from database with user and password, you can use:
$user = User::whereName($username)->wherePassword(Hash::make($password))->first();
Second
To store password in database you should use Hash::make($password) as you showed and it works without any problems. Using Auth::validate should solve the issue.
Yes, there is a built in function you should use. I recommend you to read the docs. But here's a good example, it's pretty self-evident:
$input = array(
'username' => Input::get('username'),
'password' => Input::get('password'),
);
$remember = (boolean)Input::get('remember'); //'Remember me' checkbox
if (Auth::attempt($input, $remember)) {
return Redirect::intended('dashboard')->with("success", "You're logged in!"); //Redirect the user to the page intended to go to, with the dashboard page as default
}
Registering a user looks something like this:
$input = array(
'username' => Input::get('username'),
'email' => Input::get('email'),
'password' => Hash::make(Input::get('password')) //Encrypt password
);
$user = User::create($input);
I also recommend you to read about input validation. I hope this helps, good luck.
Edit: I didn't read the "without authenticating them" part. You should use Auth::validate($input) as Marcin already explained.
Laravel 5.7
To check a users credentials without logging them in, I had to do this:
$user = User::whereEmail($request->email)->first();
$user = password_verify($request->password, optional($user)->getAuthPassword()) ? $user : false;
Laravel auth validation makes use of https://www.php.net/manual/en/function.password-verify.php

laravel auth::attempt() gives error when specifying a known username

Hi i'm new to laravel and was trying to use the auth system.
the problem i'm having is that when verifying the users username and password by auth::attemp() I end up with a 'whoops something went wrong page' but only when there is a known username being specified. When i'm inputting an unkown username i get the expected error page.
i've created an user by:
// add user
$user = new User;
$user->username = 'John';
$user->password = Hash::make('Doe');
$user->email = 'info#mail.com';
$user->save();
the route i've created for the post method looks like this:
Route::post('login', function(){
$credentials = array(
'username' => Input::get('username'),
'password' => Input::get('password')
);
// check credentials
if (Auth::attempt($credentials)) {
// go to index if login is successful
return Redirect::to('/');
}
// fail
return Redirect::to('login')->with('error' , 'Wrong username or password');
});
Now as i've said the error message is being shown if I specify an username wich is not (in this case) 'John'. when is do use 'John' I end up with an error no matter the password is correct or incorrect.
my question: What am i doing wrong here? and how to fix it?
It turned out to be a really stupid mistake. I edited the User model (app/models/User.php), this was causing the problem. I've reverted back to the original and everything works fine now!
Thanks for the help guys!

Categories