feat: install Sanctum, scaffold api.php, add FuelType::fromAlias()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,4 +15,17 @@ enum FuelType: string
|
|||||||
{
|
{
|
||||||
return self::from(strtolower($value));
|
return self::from(strtolower($value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function fromAlias(string $alias): self
|
||||||
|
{
|
||||||
|
return match (strtolower($alias)) {
|
||||||
|
'diesel', 'b7_standard' => self::B7Standard,
|
||||||
|
'premium_diesel', 'b7_premium' => self::B7Premium,
|
||||||
|
'petrol', 'unleaded', 'e10' => self::E10,
|
||||||
|
'premium_unleaded', 'e5' => self::E5,
|
||||||
|
'b10' => self::B10,
|
||||||
|
'hvo' => self::Hvo,
|
||||||
|
default => throw new \ValueError("Unknown fuel type alias: {$alias}"),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use Illuminate\Foundation\Configuration\Middleware;
|
|||||||
return Application::configure(basePath: dirname(__DIR__))
|
return Application::configure(basePath: dirname(__DIR__))
|
||||||
->withRouting(
|
->withRouting(
|
||||||
web: __DIR__.'/../routes/web.php',
|
web: __DIR__.'/../routes/web.php',
|
||||||
|
api: __DIR__.'/../routes/api.php',
|
||||||
commands: __DIR__.'/../routes/console.php',
|
commands: __DIR__.'/../routes/console.php',
|
||||||
health: '/up',
|
health: '/up',
|
||||||
)
|
)
|
||||||
|
|||||||
87
config/sanctum.php
Normal file
87
config/sanctum.php
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Cookie\Middleware\EncryptCookies;
|
||||||
|
use Illuminate\Foundation\Http\Middleware\ValidateCsrfToken;
|
||||||
|
use Laravel\Sanctum\Http\Middleware\AuthenticateSession;
|
||||||
|
use Laravel\Sanctum\Sanctum;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Stateful Domains
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Requests from the following domains / hosts will receive stateful API
|
||||||
|
| authentication cookies. Typically, these should include your local
|
||||||
|
| and production domains which access your API via a frontend SPA.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
|
||||||
|
'%s%s',
|
||||||
|
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
|
||||||
|
Sanctum::currentApplicationUrlWithPort(),
|
||||||
|
// Sanctum::currentRequestHost(),
|
||||||
|
))),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Sanctum Guards
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This array contains the authentication guards that will be checked when
|
||||||
|
| Sanctum is trying to authenticate a request. If none of these guards
|
||||||
|
| are able to authenticate the request, Sanctum will use the bearer
|
||||||
|
| token that's present on an incoming request for authentication.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'guard' => ['web'],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Expiration Minutes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value controls the number of minutes until an issued token will be
|
||||||
|
| considered expired. This will override any values set in the token's
|
||||||
|
| "expires_at" attribute, but first-party sessions are not affected.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'expiration' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Token Prefix
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Sanctum can prefix new tokens in order to take advantage of numerous
|
||||||
|
| security scanning initiatives maintained by open source platforms
|
||||||
|
| that notify developers if they commit tokens into repositories.
|
||||||
|
|
|
||||||
|
| See: https://docs.github.com/en/code-security/secret-scanning/about-secret-scanning
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'token_prefix' => env('SANCTUM_TOKEN_PREFIX', ''),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Sanctum Middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When authenticating your first-party SPA with Sanctum you may need to
|
||||||
|
| customize some of the middleware Sanctum uses while processing the
|
||||||
|
| request. You may change the middleware listed below as required.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'middleware' => [
|
||||||
|
'authenticate_session' => AuthenticateSession::class,
|
||||||
|
'encrypt_cookies' => EncryptCookies::class,
|
||||||
|
'validate_csrf_token' => ValidateCsrfToken::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('personal_access_tokens', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->morphs('tokenable');
|
||||||
|
$table->text('name');
|
||||||
|
$table->string('token', 64)->unique();
|
||||||
|
$table->text('abilities')->nullable();
|
||||||
|
$table->timestamp('last_used_at')->nullable();
|
||||||
|
$table->timestamp('expires_at')->nullable()->index();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('personal_access_tokens');
|
||||||
|
}
|
||||||
|
};
|
||||||
20
routes/api.php
Normal file
20
routes/api.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Http\Controllers\Api\AuthController;
|
||||||
|
use App\Http\Controllers\Api\PredictionController;
|
||||||
|
use App\Http\Controllers\Api\StationController;
|
||||||
|
use App\Http\Controllers\Api\StatsController;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
Route::get('/stations', [StationController::class, 'index']);
|
||||||
|
Route::get('/stats/searches', [StatsController::class, 'searches']);
|
||||||
|
Route::get('/prediction', [PredictionController::class, 'index']);
|
||||||
|
|
||||||
|
Route::prefix('auth')->group(function (): void {
|
||||||
|
Route::post('/register', [AuthController::class, 'register']);
|
||||||
|
Route::post('/login', [AuthController::class, 'login']);
|
||||||
|
Route::middleware('auth:sanctum')->group(function (): void {
|
||||||
|
Route::post('/logout', [AuthController::class, 'logout']);
|
||||||
|
Route::get('/me', [AuthController::class, 'me']);
|
||||||
|
});
|
||||||
|
});
|
||||||
28
tests/Unit/Enums/FuelTypeTest.php
Normal file
28
tests/Unit/Enums/FuelTypeTest.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\FuelType;
|
||||||
|
|
||||||
|
it('resolves diesel alias to B7Standard', function () {
|
||||||
|
expect(FuelType::fromAlias('diesel'))->toBe(FuelType::B7Standard);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('resolves petrol alias to E10', function () {
|
||||||
|
expect(FuelType::fromAlias('petrol'))->toBe(FuelType::E10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('resolves unleaded alias to E10', function () {
|
||||||
|
expect(FuelType::fromAlias('unleaded'))->toBe(FuelType::E10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('resolves premium_unleaded alias to E5', function () {
|
||||||
|
expect(FuelType::fromAlias('premium_unleaded'))->toBe(FuelType::E5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('accepts canonical enum values as aliases', function () {
|
||||||
|
expect(FuelType::fromAlias('e10'))->toBe(FuelType::E10);
|
||||||
|
expect(FuelType::fromAlias('b7_standard'))->toBe(FuelType::B7Standard);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws ValueError for unknown alias', function () {
|
||||||
|
FuelType::fromAlias('avgas');
|
||||||
|
})->throws(ValueError::class);
|
||||||
Reference in New Issue
Block a user