wire auth api

This commit is contained in:
Yisroel Baum 2026-05-23 23:21:07 +03:00
parent 9e70fae38d
commit eff7c5c281
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9
12 changed files with 137 additions and 19 deletions

View file

@ -2,23 +2,29 @@
namespace App\Providers;
use App\Auth\BcryptPasswordHasher;
use App\Auth\Clock;
use App\Auth\PasswordHasher;
use App\Auth\RandomTokenGenerator;
use App\Auth\SystemClock;
use App\Auth\TokenGenerator;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
//
$this->app->bind(
PasswordHasher::class,
BcryptPasswordHasher::class,
);
$this->app->bind(
TokenGenerator::class,
RandomTokenGenerator::class,
);
$this->app->bind(
Clock::class,
SystemClock::class,
);
}
}

View file

@ -0,0 +1,24 @@
<?php
namespace App\Providers;
use App\Auth\EloquentSessionRepository;
use App\Auth\SessionRepository;
use App\User\EloquentUserRepository;
use App\User\UserRepository;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->bind(
UserRepository::class,
EloquentUserRepository::class
);
$this->app->bind(
SessionRepository::class,
EloquentSessionRepository::class
);
}
}

View file

@ -6,6 +6,7 @@ use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
->withRouting(
api: __DIR__ . '/../routes/api.php',
commands: __DIR__ . '/../routes/console.php',
health: '/up',
)

View file

@ -1,7 +1,9 @@
<?php
use App\Providers\AppServiceProvider;
use App\Providers\RepositoryServiceProvider;
return [
AppServiceProvider::class,
RepositoryServiceProvider::class,
];

View file

@ -12,11 +12,16 @@ $allowedOrigins = array_values(array_filter(array_map(
)));
return [
'paths' => ['login', 'logout', 'me'],
'paths' => ['api/*'],
'allowed_methods' => ['GET', 'POST', 'OPTIONS'],
'allowed_origins' => $allowedOrigins,
'allowed_origins_patterns' => [],
'allowed_headers' => ['Content-Type', 'X-Requested-With', 'Accept', 'Origin'],
'allowed_headers' => [
'Content-Type',
'X-Requested-With',
'Accept',
'Origin',
],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,

View file

@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('email')->unique();
$table->string('password_hash');
});
}
public function down(): void
{
Schema::dropIfExists('users');
}
};

View file

@ -0,0 +1,23 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('sessions', function (Blueprint $table) {
$table->string('token')->primary();
$table->foreignId('user_id')->constrained('users');
$table->dateTime('created_at');
$table->dateTime('expires_at');
});
}
public function down(): void
{
Schema::dropIfExists('sessions');
}
};

View file

@ -8,5 +8,8 @@ class DatabaseSeeder extends Seeder
{
public function run(): void
{
$this->call([
UserSeeder::class,
]);
}
}

View file

@ -0,0 +1,22 @@
<?php
namespace Database\Seeders;
use App\Auth\PasswordHasher;
use App\Shared\ValueObject\EmailAddress;
use App\User\CreateUserDto;
use App\User\UserRepository;
use Illuminate\Database\Seeder;
class UserSeeder extends Seeder
{
public function run(): void
{
$userRepository = app(UserRepository::class);
$passwordHasher = app(PasswordHasher::class);
$userRepository->create(new CreateUserDto(
email: new EmailAddress('test@example.com'),
passwordHash: $passwordHasher->hash('password123!@#'),
));
}
}

10
backend/routes/api.php Normal file
View file

@ -0,0 +1,10 @@
<?php
use App\Controllers\AuthController;
use App\Http\Middleware\AuthMiddleware;
use Illuminate\Support\Facades\Route;
Route::post('/login', [AuthController::class, 'login']);
Route::post('/logout', [AuthController::class, 'logout']);
Route::get('/me', [AuthController::class, 'me'])
->middleware(AuthMiddleware::class);

View file

@ -12,7 +12,7 @@ class CorsTest extends TestCase
'Origin' => 'https://rabbigerzi.com',
'Access-Control-Request-Method' => 'POST',
'Access-Control-Request-Headers' => 'content-type',
])->options('/login');
])->options('/api/login');
$response->assertNoContent();
$response->assertHeader(

View file

@ -20,7 +20,7 @@ export const useAuthStore = defineStore('auth', () => {
isSubmitting.value = true
try {
const response = await fetch(`${API_BASE_URL}/login`, {
const response = await fetch(`${API_BASE_URL}/api/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'include',
@ -46,7 +46,7 @@ export const useAuthStore = defineStore('auth', () => {
async function fetchUser(): Promise<void> {
try {
const response = await fetch(`${API_BASE_URL}/me`, {
const response = await fetch(`${API_BASE_URL}/api/me`, {
credentials: 'include',
})
@ -64,7 +64,7 @@ export const useAuthStore = defineStore('auth', () => {
async function logout(): Promise<void> {
try {
await fetch(`${API_BASE_URL}/logout`, {
await fetch(`${API_BASE_URL}/api/logout`, {
method: 'POST',
credentials: 'include',
})