Skip to main content

AuthController and Review Conclusion

Premium
4 min read

The final Controller that we didn't finalize is AuthController. In fact, it's pretty small and doesn't need many changes—only a few small ones.

app/Http/Controllers/Api/AuthController.php

use App\Models\User;
 
class AuthController extends ApiController
{
public function login(LoginUserRequest $request)
{
$request->validated($request->all());
$credentials = $request->only('email', 'password');
 
if (! Auth::attempt($credentials)) {
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
'password' => ['The provided credentials are incorrect.'],
]);
}
 
$user = User::firstWhere('email', $request->email);
$token = $user?->createToken('authToken', Abilities::getAbilities($user), now()->addHours(8))->plainTextToken;
 
$user = auth()->user();
$token = $user->createToken('authToken', Abilities::getAbilities($user), now()->addHours(8))->plainTextToken;
 
return $this->responseSuccess(
'Authenticated',
[
// 'user' => $user,
'token' => $token,
],
);
 
return $this->responseSuccess('Authenticated', ['token' => $token]);
}
 
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();
 
return $this->responseSuccess('Logged out');
}
}

What I've changed here:

  1. Removed the line $request->validated($request->all()); - what did that even mean?..
  2. Removed the DB call to User::firstWhere() - by this time, the User would be logged in already, so we can call auth()->user()
  3. Simplify the responseSucces() to fit in one line for readability

TESTS (Yup, Again!)

And yes, surprise, surprise - the login/logout mechanism also didn't have any tests either. Let's fix this!

php artisan make:test AuthTest

tests/Feature/AuthTest.php

namespace Tests\Feature;
 
use App\Models\User;
use App\Permissions\V1\Abilities;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
 
class AuthTest extends TestCase
{
use RefreshDatabase;
 
public function test_user_can_login_with_correct_credentials()
{
$user = User::factory()->create([
'email' => '[email protected]',
'password' => bcrypt('password123'),
]);
 
$response = $this
->postJson('/api/login', [
'email' => '[email protected]',
'password' => 'password123',
]);
 
$response->assertStatus(200)
->assertJsonStructure([
'message',
'data' => [
'token'
]
]);
}
 
public function test_user_cannot_login_with_incorrect_credentials()
{
$user = User::factory()->create([
'email' => '[email protected]',
'password' => bcrypt('password123'),
]);
 
$response = $this
->postJson('/api/login', [
'email' => '[email protected]',
'password' => 'wrongpassword',
]);
 
$response->assertStatus(422)
->assertJsonValidationErrors(['email', 'password']);
}
 
public function test_login_validation_requires_email_and_password()
{
$response = $this
->postJson('/api/login', [
'email' => '',
'password' => '',
]);
 
$response->assertStatus(422)
->assertJsonValidationErrors(['email', 'password']);
}
 
public function test_user_can_logout()
{
$user = User::factory()->create();
$token = $user->createToken('authToken', Abilities::getAbilities($user), now()->addHours(8))->plainTextToken;
 
$response = $this
->withHeader('Authorization', 'Bearer ' . $token)
->postJson('/api/logout');
 
$response->assertStatus(200)
->assertJson([
'message' => 'Logged out'
]);
}
}

Our final test suite consists of 22 tests now. All green!

Here's the...

The Full Lesson is Only for Premium Members

Want to access all of our courses? (36 h 00 min)

You also get:

61 courses
Premium tutorials
Access to repositories
Private Discord
Get Premium for $129/year or $29/month

Already a member? Login here

Sisifo avatar

I really enjoyed this type of course based on a real-world code example. It was very helpful. While in-depth courses on specific topics are incredibly useful when focused on a matching feature, these "real-life" courses provide a valuable insight into the reality we face, where it's not always a "feature playground."

👍 4
Povilas Korop avatar

Thanks for the nice words! Motivation for me to continue similar "real-life" reviews in the future.

Pantelis Antoniadis avatar
Pantelis Antoniadis

To write good code, you sometimes have to write bad code :)

Thanks for sharing your approach!

👍 1

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.