Courses

Laravel API Code Review and Refactor

AuthController and Review Conclusion

You're reading a FREE PREVIEW of a PREMIUM course.

Link to the repository

[Only for premium members]

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 15 lessons of this course? (56 min read)

You also get:

  • 76 courses
  • Premium tutorials
  • Access to repositories
  • Private Discord