From f5116210333f7b380afd45bac880756eca0c8b6f Mon Sep 17 00:00:00 2001 From: Edson Salvatore Date: Sun, 3 May 2026 22:26:39 -0500 Subject: [PATCH] feat: criado controller e rota para adicionar jogos na wishlist --- app/Http/Controllers/WishlistController.php | 49 +++++++++++ bootstrap/app.php | 1 + composer.json | 1 + composer.lock | 65 +++++++++++++- config/sanctum.php | 84 +++++++++++++++++++ ...59_create_personal_access_tokens_table.php | 33 ++++++++ routes/api.php | 22 +++++ 7 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/WishlistController.php create mode 100644 config/sanctum.php create mode 100644 database/migrations/2026_05_04_031659_create_personal_access_tokens_table.php create mode 100644 routes/api.php diff --git a/app/Http/Controllers/WishlistController.php b/app/Http/Controllers/WishlistController.php new file mode 100644 index 0000000..2b1499d --- /dev/null +++ b/app/Http/Controllers/WishlistController.php @@ -0,0 +1,49 @@ +validate([ + 'game_id' => 'required|string', + 'is_wishlist' => 'boolean', + 'is_favorite' => 'boolean', + 'saved_for_later' => 'boolean', + 'price_alert' => 'boolean', + ]); + + // 2. Pega o ID do usuário que a nossa fechadura extraiu do Token JWT + $userId = $request->get('auth_id'); + + // 3. Salva no banco. + // O updateOrCreate procura se esse usuário já tem esse jogo na lista. + // Se tiver, ele apenas atualiza as flags (ex: ativa o price_alert). Se não tiver, ele cria um novo. + $wishlistItem = WishlistItem::updateOrCreate( + [ + 'user_id' => $userId, + 'game_id' => $validated['game_id'], + ], + [ + 'is_wishlist' => $validated['is_wishlist'] ?? false, + 'is_favorite' => $validated['is_favorite'] ?? false, + 'saved_for_later' => $validated['saved_for_later'] ?? false, + 'price_alert' => $validated['price_alert'] ?? false, + ] + ); + + // 4. Devolve a resposta de sucesso + return response()->json([ + 'message' => 'Jogo salvo na lista com sucesso!', + 'data' => $wishlistItem + ], 201); + } +} \ No newline at end of file diff --git a/bootstrap/app.php b/bootstrap/app.php index 55973c5..4ac926e 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -7,6 +7,7 @@ use Illuminate\Foundation\Configuration\Middleware; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( web: __DIR__.'/../routes/web.php', + api: __DIR__.'/../routes/api.php', commands: __DIR__.'/../routes/console.php', health: '/up', ) diff --git a/composer.json b/composer.json index 8bc24f5..442c9c8 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,7 @@ "php": "^8.3", "firebase/php-jwt": "^7.0", "laravel/framework": "^13.0", + "laravel/sanctum": "^4.0", "laravel/tinker": "^3.0" }, "require-dev": { diff --git a/composer.lock b/composer.lock index bb77584..194f5e9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "16d1bbc8c7c72342cf2d5a5239006285", + "content-hash": "799357756a72b497e671e503d0a08756", "packages": [ { "name": "brick/math", @@ -1400,6 +1400,69 @@ }, "time": "2026-04-20T16:07:33+00:00" }, + { + "name": "laravel/sanctum", + "version": "v4.3.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/sanctum.git", + "reference": "e3b85d6e36ad00e5db2d1dcc27c81ffdf15cbf76" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/e3b85d6e36ad00e5db2d1dcc27c81ffdf15cbf76", + "reference": "e3b85d6e36ad00e5db2d1dcc27c81ffdf15cbf76", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^11.0|^12.0|^13.0", + "illuminate/contracts": "^11.0|^12.0|^13.0", + "illuminate/database": "^11.0|^12.0|^13.0", + "illuminate/support": "^11.0|^12.0|^13.0", + "php": "^8.2", + "symfony/console": "^7.0|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.6", + "orchestra/testbench": "^9.15|^10.8|^11.0", + "phpstan/phpstan": "^1.10" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Sanctum\\SanctumServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Sanctum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Sanctum provides a featherweight authentication system for SPAs and simple APIs.", + "keywords": [ + "auth", + "laravel", + "sanctum" + ], + "support": { + "issues": "https://github.com/laravel/sanctum/issues", + "source": "https://github.com/laravel/sanctum" + }, + "time": "2026-02-07T17:19:31+00:00" + }, { "name": "laravel/serializable-closure", "version": "v2.0.13", diff --git a/config/sanctum.php b/config/sanctum.php new file mode 100644 index 0000000..44527d6 --- /dev/null +++ b/config/sanctum.php @@ -0,0 +1,84 @@ + 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' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class, + 'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class, + 'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class, + ], + +]; diff --git a/database/migrations/2026_05_04_031659_create_personal_access_tokens_table.php b/database/migrations/2026_05_04_031659_create_personal_access_tokens_table.php new file mode 100644 index 0000000..40ff706 --- /dev/null +++ b/database/migrations/2026_05_04_031659_create_personal_access_tokens_table.php @@ -0,0 +1,33 @@ +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'); + } +}; diff --git a/routes/api.php b/routes/api.php new file mode 100644 index 0000000..7e31c57 --- /dev/null +++ b/routes/api.php @@ -0,0 +1,22 @@ +json(['message' => 'A API esta viva e sem fechadura!']); +}); + +// Todas as rotas dentro deste grupo passam pela fechadura JWT +Route::middleware(['jwt.auth'])->group(function () { + + // Rota de teste antiga + Route::get('/teste-fechadura', function (Request $request) { + return response()->json(['usuario_logado_id' => $request->get('auth_id')]); + }); + + // A nossa nova rota real de adicionar aos favoritos! + Route::post('/wishlist', [WishlistController::class, 'store']); + +}); \ No newline at end of file