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? (30 h 09 min)

You also get:

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

Already a member? Login here

Comments & Discussion

S
Sisifo ✓ Link copied!

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."

PK
Povilas Korop ✓ Link copied!

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

PA
Pantelis Antoniadis ✓ Link copied!

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

Thanks for sharing your approach!

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.