diff --git a/app/Http/Controllers/TournamentController.php b/app/Http/Controllers/TournamentController.php index a95041f..c7ce245 100644 --- a/app/Http/Controllers/TournamentController.php +++ b/app/Http/Controllers/TournamentController.php @@ -10,6 +10,7 @@ use App\Models\User; use Illuminate\Http\Request; use Inertia\Inertia; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\ValidationException; @@ -201,19 +202,23 @@ class TournamentController extends Controller ->with('success', 'Tournament deleted successfully!'); } - public function addTeam(Competition $tournament, Request $request) + public function addTeam(Request $request, Competition $tournament) { + Log::info($request); // Check if user is tournament owner if ($tournament->owner != Auth::id()) { + Log::error('User is not authorized to add a team to this tournament.'); + Log::error('userId: ' . Auth::id() . ' tournamentOwnerId: ' . $tournament->owner); return redirect()->back()->with('error', 'You are not authorized to add a team to this tournament.'); } // Validate the request data $validator = Validator::make($request->all(), [ - 'team_id' => 'required|exists:teams,id', + 'teamName' => 'required|exists:teams,string', ]); if ($validator->fails()) { + Log::error('Validation failed for addTeam', $validator->errors()); return redirect()->back()->withErrors($validator)->withInput(); } @@ -228,9 +233,8 @@ class TournamentController extends Controller } $tournament->teams()->attach($team->id); - - - return redirect()->route('tournaments.show', $tournament->id) - ->with('success', 'Team added successfully!'); + return response()->json([ + 'tournament' => $tournament, + ]); } } diff --git a/app/Http/Requests/ApiCreateUserRequest.php b/app/Http/Requests/ApiCreateUserRequest.php new file mode 100644 index 0000000..d820d29 --- /dev/null +++ b/app/Http/Requests/ApiCreateUserRequest.php @@ -0,0 +1,32 @@ +|string> + */ + public function rules(): array + { + $rules = [ + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'email', 'unique:users', 'max:255'], + 'password' => ['required', 'string', 'min:8', 'max:255', 'confirmed'], + ]; + + return $rules; + } +} diff --git a/app/Http/Requests/ApiLoginRequest.php b/app/Http/Requests/ApiLoginRequest.php new file mode 100644 index 0000000..e502f9d --- /dev/null +++ b/app/Http/Requests/ApiLoginRequest.php @@ -0,0 +1,31 @@ +|string> + */ + public function rules(): array + { + $rules = [ + 'email' => ['required', 'email', 'max:255'], + 'password' => ['required', 'min:8'], + ]; + + return $rules; + } +} diff --git a/app/Http/Resources/UserResource.php b/app/Http/Resources/UserResource.php new file mode 100644 index 0000000..c8b4b4c --- /dev/null +++ b/app/Http/Resources/UserResource.php @@ -0,0 +1,24 @@ + + */ + public function toArray(Request $request): array + { + return [ + 'id' => $this->id, + 'name' => $this->name, + 'email' => $this->email, + 'email_verified_at' => $this->email_verified_at, + ]; + } +} diff --git a/app/Models/User.php b/app/Models/User.php index bbeca75..8af70a9 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -6,11 +6,12 @@ use Illuminate\Database\Eloquent\Concerns\HasUuids; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { /** @use HasFactory<\Database\Factories\UserFactory> */ - use HasFactory, Notifiable, HasUuids; + use HasApiTokens, HasFactory, Notifiable, HasUuids; /** * The attributes that are mass assignable. diff --git a/app/Providers/TelescopeServiceProvider.php b/app/Providers/TelescopeServiceProvider.php new file mode 100644 index 0000000..19730b2 --- /dev/null +++ b/app/Providers/TelescopeServiceProvider.php @@ -0,0 +1,64 @@ +hideSensitiveRequestDetails(); + + $isLocal = $this->app->environment('local'); + + Telescope::filter(function (IncomingEntry $entry) use ($isLocal) { + return $isLocal || + $entry->isReportableException() || + $entry->isFailedRequest() || + $entry->isFailedJob() || + $entry->isScheduledTask() || + $entry->hasMonitoredTag(); + }); + } + + /** + * Prevent sensitive request details from being logged by Telescope. + */ + protected function hideSensitiveRequestDetails(): void + { + if ($this->app->environment('local')) { + return; + } + + Telescope::hideRequestParameters(['_token']); + + Telescope::hideRequestHeaders([ + 'cookie', + 'x-csrf-token', + 'x-xsrf-token', + ]); + } + + /** + * Register the Telescope gate. + * + * This gate determines who can access Telescope in non-local environments. + */ + protected function gate(): void + { + Gate::define('viewTelescope', function ($user) { + return in_array($user->email, [ + 'unurled@unurled.me' + ]); + }); + } +} diff --git a/bootstrap/app.php b/bootstrap/app.php index af5f248..1916f8c 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -11,6 +11,8 @@ use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets; return Application::configure(basePath: dirname(__DIR__)) ->withRouting( + api: __DIR__ . '/../routes/api.php', + apiPrefix: '/api', web: __DIR__ . '/../routes/web.php', commands: __DIR__ . '/../routes/console.php', health: '/up', diff --git a/bootstrap/providers.php b/bootstrap/providers.php index 9a7c963..2bdaf3f 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -2,5 +2,6 @@ return [ App\Providers\AppServiceProvider::class, - \SocialiteProviders\Manager\ServiceProvider::class + App\Providers\TelescopeServiceProvider::class, + SocialiteProviders\Manager\ServiceProvider::class, ]; diff --git a/composer.json b/composer.json index b2f93f7..ca7d1aa 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,9 @@ "inertiajs/inertia-laravel": "^2.0.2", "laravel/framework": "^12.16.0", "laravel/octane": "^2.10", + "laravel/sanctum": "^4.0", "laravel/socialite": "^5.21", + "laravel/telescope": "^5.9", "laravel/tinker": "^2.10.1", "socialiteproviders/keycloak": "^5.3", "tightenco/ziggy": "^2.5.3" diff --git a/composer.lock b/composer.lock index 2632dcb..4d6a65c 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": "bd02b3c2ddadea250049517b0d891770", + "content-hash": "90f578634e9ad91141f8e8a896ed417a", "packages": [ { "name": "brick/math", @@ -1637,6 +1637,70 @@ }, "time": "2025-02-11T13:34:40+00:00" }, + { + "name": "laravel/sanctum", + "version": "v4.1.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/sanctum.git", + "reference": "a360a6a1fd2400ead4eb9b6a9c1bb272939194f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/a360a6a1fd2400ead4eb9b6a9c1bb272939194f5", + "reference": "a360a6a1fd2400ead4eb9b6a9c1bb272939194f5", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^11.0|^12.0", + "illuminate/contracts": "^11.0|^12.0", + "illuminate/database": "^11.0|^12.0", + "illuminate/support": "^11.0|^12.0", + "php": "^8.2", + "symfony/console": "^7.0" + }, + "require-dev": { + "mockery/mockery": "^1.6", + "orchestra/testbench": "^9.0|^10.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^11.3" + }, + "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": "2025-04-23T13:03:38+00:00" + }, { "name": "laravel/serializable-closure", "version": "v2.0.4", @@ -1770,6 +1834,75 @@ }, "time": "2025-05-19T12:56:37+00:00" }, + { + "name": "laravel/telescope", + "version": "v5.9.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/telescope.git", + "reference": "403d4ad1ecfe126139f5cf29cabd6b1c816c46a2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/telescope/zipball/403d4ad1ecfe126139f5cf29cabd6b1c816c46a2", + "reference": "403d4ad1ecfe126139f5cf29cabd6b1c816c46a2", + "shasum": "" + }, + "require": { + "ext-json": "*", + "laravel/framework": "^8.37|^9.0|^10.0|^11.0|^12.0", + "php": "^8.0", + "symfony/console": "^5.3|^6.0|^7.0", + "symfony/var-dumper": "^5.0|^6.0|^7.0" + }, + "require-dev": { + "ext-gd": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "laravel/octane": "^1.4|^2.0|dev-develop", + "orchestra/testbench": "^6.40|^7.37|^8.17|^9.0|^10.0", + "phpstan/phpstan": "^1.10", + "phpunit/phpunit": "^9.0|^10.5|^11.5" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Telescope\\TelescopeServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Telescope\\": "src/", + "Laravel\\Telescope\\Database\\Factories\\": "database/factories/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Mohamed Said", + "email": "mohamed@laravel.com" + } + ], + "description": "An elegant debug assistant for the Laravel framework.", + "keywords": [ + "debugging", + "laravel", + "monitoring" + ], + "support": { + "issues": "https://github.com/laravel/telescope/issues", + "source": "https://github.com/laravel/telescope/tree/v5.9.1" + }, + "time": "2025-06-10T21:42:27+00:00" + }, { "name": "laravel/tinker", "version": "v2.10.1", diff --git a/config/auth.php b/config/auth.php index 59214a1..940329e 100644 --- a/config/auth.php +++ b/config/auth.php @@ -39,7 +39,12 @@ return [ 'web' => [ 'driver' => 'session', 'provider' => 'users', - ] + ], + + 'api' => [ + 'driver' => 'passport', + 'provider' => 'users', + ], ], /* diff --git a/config/passport.php b/config/passport.php new file mode 100644 index 0000000..c3b41b3 --- /dev/null +++ b/config/passport.php @@ -0,0 +1,46 @@ + 'web', + + /* + |-------------------------------------------------------------------------- + | Encryption Keys + |-------------------------------------------------------------------------- + | + | Passport uses encryption keys while generating secure access tokens for + | your application. By default, the keys are stored as local files but + | can be set via environment variables when that is more convenient. + | + */ + + 'private_key' => env('PASSPORT_PRIVATE_KEY'), + + 'public_key' => env('PASSPORT_PUBLIC_KEY'), + + /* + |-------------------------------------------------------------------------- + | Passport Database Connection + |-------------------------------------------------------------------------- + | + | By default, Passport's models will utilize your application's default + | database connection. If you wish to use a different connection you + | may specify the configured name of the database connection here. + | + */ + + 'connection' => env('PASSPORT_CONNECTION'), + +]; 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/config/telescope.php b/config/telescope.php new file mode 100644 index 0000000..9c492b2 --- /dev/null +++ b/config/telescope.php @@ -0,0 +1,207 @@ + env('TELESCOPE_ENABLED', true), + + /* + |-------------------------------------------------------------------------- + | Telescope Domain + |-------------------------------------------------------------------------- + | + | This is the subdomain where Telescope will be accessible from. If the + | setting is null, Telescope will reside under the same domain as the + | application. Otherwise, this value will be used as the subdomain. + | + */ + + 'domain' => env('TELESCOPE_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | Telescope Path + |-------------------------------------------------------------------------- + | + | This is the URI path where Telescope will be accessible from. Feel free + | to change this path to anything you like. Note that the URI will not + | affect the paths of its internal API that aren't exposed to users. + | + */ + + 'path' => env('TELESCOPE_PATH', 'telescope'), + + /* + |-------------------------------------------------------------------------- + | Telescope Storage Driver + |-------------------------------------------------------------------------- + | + | This configuration options determines the storage driver that will + | be used to store Telescope's data. In addition, you may set any + | custom options as needed by the particular driver you choose. + | + */ + + 'driver' => env('TELESCOPE_DRIVER', 'database'), + + 'storage' => [ + 'database' => [ + 'connection' => env('DB_CONNECTION', 'mysql'), + 'chunk' => 1000, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Telescope Queue + |-------------------------------------------------------------------------- + | + | This configuration options determines the queue connection and queue + | which will be used to process ProcessPendingUpdate jobs. This can + | be changed if you would prefer to use a non-default connection. + | + */ + + 'queue' => [ + 'connection' => env('TELESCOPE_QUEUE_CONNECTION', null), + 'queue' => env('TELESCOPE_QUEUE', null), + 'delay' => env('TELESCOPE_QUEUE_DELAY', 10), + ], + + /* + |-------------------------------------------------------------------------- + | Telescope Route Middleware + |-------------------------------------------------------------------------- + | + | These middleware will be assigned to every Telescope route, giving you + | the chance to add your own middleware to this list or change any of + | the existing middleware. Or, you can simply stick with this list. + | + */ + + 'middleware' => [ + 'web', + Authorize::class, + ], + + /* + |-------------------------------------------------------------------------- + | Allowed / Ignored Paths & Commands + |-------------------------------------------------------------------------- + | + | The following array lists the URI paths and Artisan commands that will + | not be watched by Telescope. In addition to this list, some Laravel + | commands, like migrations and queue commands, are always ignored. + | + */ + + 'only_paths' => [ + // 'api/*' + ], + + 'ignore_paths' => [ + 'livewire*', + 'nova-api*', + 'pulse*', + ], + + 'ignore_commands' => [ + // + ], + + /* + |-------------------------------------------------------------------------- + | Telescope Watchers + |-------------------------------------------------------------------------- + | + | The following array lists the "watchers" that will be registered with + | Telescope. The watchers gather the application's profile data when + | a request or task is executed. Feel free to customize this list. + | + */ + + 'watchers' => [ + Watchers\BatchWatcher::class => env('TELESCOPE_BATCH_WATCHER', true), + + Watchers\CacheWatcher::class => [ + 'enabled' => env('TELESCOPE_CACHE_WATCHER', true), + 'hidden' => [], + 'ignore' => [], + ], + + Watchers\ClientRequestWatcher::class => env('TELESCOPE_CLIENT_REQUEST_WATCHER', true), + + Watchers\CommandWatcher::class => [ + 'enabled' => env('TELESCOPE_COMMAND_WATCHER', true), + 'ignore' => [], + ], + + Watchers\DumpWatcher::class => [ + 'enabled' => env('TELESCOPE_DUMP_WATCHER', true), + 'always' => env('TELESCOPE_DUMP_WATCHER_ALWAYS', false), + ], + + Watchers\EventWatcher::class => [ + 'enabled' => env('TELESCOPE_EVENT_WATCHER', true), + 'ignore' => [], + ], + + Watchers\ExceptionWatcher::class => env('TELESCOPE_EXCEPTION_WATCHER', true), + + Watchers\GateWatcher::class => [ + 'enabled' => env('TELESCOPE_GATE_WATCHER', true), + 'ignore_abilities' => [], + 'ignore_packages' => true, + 'ignore_paths' => [], + ], + + Watchers\JobWatcher::class => env('TELESCOPE_JOB_WATCHER', true), + + Watchers\LogWatcher::class => [ + 'enabled' => env('TELESCOPE_LOG_WATCHER', true), + 'level' => 'error', + ], + + Watchers\MailWatcher::class => env('TELESCOPE_MAIL_WATCHER', true), + + Watchers\ModelWatcher::class => [ + 'enabled' => env('TELESCOPE_MODEL_WATCHER', true), + 'events' => ['eloquent.*'], + 'hydrations' => true, + ], + + Watchers\NotificationWatcher::class => env('TELESCOPE_NOTIFICATION_WATCHER', true), + + Watchers\QueryWatcher::class => [ + 'enabled' => env('TELESCOPE_QUERY_WATCHER', true), + 'ignore_packages' => true, + 'ignore_paths' => [], + 'slow' => 100, + ], + + Watchers\RedisWatcher::class => env('TELESCOPE_REDIS_WATCHER', true), + + Watchers\RequestWatcher::class => [ + 'enabled' => env('TELESCOPE_REQUEST_WATCHER', true), + 'size_limit' => env('TELESCOPE_RESPONSE_SIZE_LIMIT', 64), + 'ignore_http_methods' => [], + 'ignore_status_codes' => [], + ], + + Watchers\ScheduleWatcher::class => env('TELESCOPE_SCHEDULE_WATCHER', true), + Watchers\ViewWatcher::class => env('TELESCOPE_VIEW_WATCHER', true), + ], +]; diff --git a/database/migrations/2025_07_04_223322_create_personal_access_tokens_table.php b/database/migrations/2025_07_04_223322_create_personal_access_tokens_table.php new file mode 100644 index 0000000..e828ad8 --- /dev/null +++ b/database/migrations/2025_07_04_223322_create_personal_access_tokens_table.php @@ -0,0 +1,33 @@ +id(); + $table->morphs('tokenable'); + $table->string('name'); + $table->string('token', 64)->unique(); + $table->text('abilities')->nullable(); + $table->timestamp('last_used_at')->nullable(); + $table->timestamp('expires_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('personal_access_tokens'); + } +}; diff --git a/database/migrations/2025_07_04_225603_create_telescope_entries_table.php b/database/migrations/2025_07_04_225603_create_telescope_entries_table.php new file mode 100644 index 0000000..700a83f --- /dev/null +++ b/database/migrations/2025_07_04_225603_create_telescope_entries_table.php @@ -0,0 +1,70 @@ +getConnection()); + + $schema->create('telescope_entries', function (Blueprint $table) { + $table->bigIncrements('sequence'); + $table->uuid('uuid'); + $table->uuid('batch_id'); + $table->string('family_hash')->nullable(); + $table->boolean('should_display_on_index')->default(true); + $table->string('type', 20); + $table->longText('content'); + $table->dateTime('created_at')->nullable(); + + $table->unique('uuid'); + $table->index('batch_id'); + $table->index('family_hash'); + $table->index('created_at'); + $table->index(['type', 'should_display_on_index']); + }); + + $schema->create('telescope_entries_tags', function (Blueprint $table) { + $table->uuid('entry_uuid'); + $table->string('tag'); + + $table->primary(['entry_uuid', 'tag']); + $table->index('tag'); + + $table->foreign('entry_uuid') + ->references('uuid') + ->on('telescope_entries') + ->onDelete('cascade'); + }); + + $schema->create('telescope_monitoring', function (Blueprint $table) { + $table->string('tag')->primary(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + $schema = Schema::connection($this->getConnection()); + + $schema->dropIfExists('telescope_entries_tags'); + $schema->dropIfExists('telescope_entries'); + $schema->dropIfExists('telescope_monitoring'); + } +}; diff --git a/database/migrations/2025_07_05_074720_create_oauth_auth_codes_table.php b/database/migrations/2025_07_05_074720_create_oauth_auth_codes_table.php new file mode 100644 index 0000000..c700b50 --- /dev/null +++ b/database/migrations/2025_07_05_074720_create_oauth_auth_codes_table.php @@ -0,0 +1,39 @@ +char('id', 80)->primary(); + $table->foreignId('user_id')->index(); + $table->foreignUuid('client_id'); + $table->text('scopes')->nullable(); + $table->boolean('revoked'); + $table->dateTime('expires_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('oauth_auth_codes'); + } + + /** + * Get the migration connection name. + */ + public function getConnection(): ?string + { + return $this->connection ?? config('passport.connection'); + } +}; diff --git a/database/migrations/2025_07_05_074721_create_oauth_access_tokens_table.php b/database/migrations/2025_07_05_074721_create_oauth_access_tokens_table.php new file mode 100644 index 0000000..3e50f7f --- /dev/null +++ b/database/migrations/2025_07_05_074721_create_oauth_access_tokens_table.php @@ -0,0 +1,41 @@ +char('id', 80)->primary(); + $table->foreignId('user_id')->nullable()->index(); + $table->foreignUuid('client_id'); + $table->string('name')->nullable(); + $table->text('scopes')->nullable(); + $table->boolean('revoked'); + $table->timestamps(); + $table->dateTime('expires_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('oauth_access_tokens'); + } + + /** + * Get the migration connection name. + */ + public function getConnection(): ?string + { + return $this->connection ?? config('passport.connection'); + } +}; diff --git a/database/migrations/2025_07_05_074722_create_oauth_refresh_tokens_table.php b/database/migrations/2025_07_05_074722_create_oauth_refresh_tokens_table.php new file mode 100644 index 0000000..afb3c55 --- /dev/null +++ b/database/migrations/2025_07_05_074722_create_oauth_refresh_tokens_table.php @@ -0,0 +1,37 @@ +char('id', 80)->primary(); + $table->char('access_token_id', 80)->index(); + $table->boolean('revoked'); + $table->dateTime('expires_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('oauth_refresh_tokens'); + } + + /** + * Get the migration connection name. + */ + public function getConnection(): ?string + { + return $this->connection ?? config('passport.connection'); + } +}; diff --git a/database/migrations/2025_07_05_074723_create_oauth_clients_table.php b/database/migrations/2025_07_05_074723_create_oauth_clients_table.php new file mode 100644 index 0000000..9794dc8 --- /dev/null +++ b/database/migrations/2025_07_05_074723_create_oauth_clients_table.php @@ -0,0 +1,42 @@ +uuid('id')->primary(); + $table->nullableMorphs('owner'); + $table->string('name'); + $table->string('secret')->nullable(); + $table->string('provider')->nullable(); + $table->text('redirect_uris'); + $table->text('grant_types'); + $table->boolean('revoked'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('oauth_clients'); + } + + /** + * Get the migration connection name. + */ + public function getConnection(): ?string + { + return $this->connection ?? config('passport.connection'); + } +}; diff --git a/database/migrations/2025_07_05_074724_create_oauth_device_codes_table.php b/database/migrations/2025_07_05_074724_create_oauth_device_codes_table.php new file mode 100644 index 0000000..ea07831 --- /dev/null +++ b/database/migrations/2025_07_05_074724_create_oauth_device_codes_table.php @@ -0,0 +1,42 @@ +char('id', 80)->primary(); + $table->foreignId('user_id')->nullable()->index(); + $table->foreignUuid('client_id')->index(); + $table->char('user_code', 8)->unique(); + $table->text('scopes'); + $table->boolean('revoked'); + $table->dateTime('user_approved_at')->nullable(); + $table->dateTime('last_polled_at')->nullable(); + $table->dateTime('expires_at')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('oauth_device_codes'); + } + + /** + * Get the migration connection name. + */ + public function getConnection(): ?string + { + return $this->connection ?? config('passport.connection'); + } +}; diff --git a/package.json b/package.json index b849a87..8e7cf97 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@types/node": "^22.15.27", "axios": "^1.9.0", "bits-ui": "^2.3.0", + "chokidar": "^4.0.3", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "concurrently": "^9.1.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1f7ce68..0fa6765 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: bits-ui: specifier: ^2.3.0 version: 2.8.2(@internationalized/date@3.8.2)(svelte@5.34.7) + chokidar: + specifier: ^4.0.3 + version: 4.0.3 class-variance-authority: specifier: ^0.7.1 version: 0.7.1 diff --git a/resources/js/pages/tournaments/Show.svelte b/resources/js/pages/tournaments/Show.svelte index 5fa83b1..8efe57a 100644 --- a/resources/js/pages/tournaments/Show.svelte +++ b/resources/js/pages/tournaments/Show.svelte @@ -22,25 +22,19 @@ tournament.teams.push({ name: teamName }); // post request to /tournaments/{tournament}/addTeam - const response = await fetch(`/api/tournaments/${tournament.id}/addTeam`, { method: 'POST', + body: JSON.stringify({ teamName: teamName }), headers: { 'Content-Type': 'application/json', }, - body: JSON.stringify({ - team_name: teamName, - }), }); - if (response.ok) { - addTeam = false; - teamName = ''; - } else { - // handle error - console.log('response', JSON.stringify(response)); const data = await response.json(); - console.log('data', JSON.stringify(data)); + console.log('data', data, JSON.stringify(data)); + tournament = data; + } else { + console.log('response not ok', JSON.stringify(response)); } } diff --git a/routes/api.php b/routes/api.php index 0a1747d..caa7a9a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,5 +1,6 @@ user(); })->middleware('auth:api'); + Route::get('/competitions/public', [CompetitionController::class, 'getPublicCompetitions']); Route::get('/competitions/user', [CompetitionController::class, 'getUserCompetitions'])->middleware('auth:api'); -Route::post('/tournaments/{tournament}/addTeam', [TournamentController::class, 'addTeam'])->middleware(['auth', 'verified'])->name('tournaments.addTeam'); +Route::post('/tournaments/{tournament}/addTeam', [TournamentController::class, 'addTeam'])->middleware('auth')->name('tournaments.addTeam'); diff --git a/routes/auth.php b/routes/auth.php index d2eadca..0d73ec1 100644 --- a/routes/auth.php +++ b/routes/auth.php @@ -8,23 +8,6 @@ use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Route; use Laravel\Socialite\Facades\Socialite; -Route::middleware('guest')->group(function () { - Route::get('register', [RegisteredUserController::class, 'create']) - ->name('register'); - - Route::post('register', [RegisteredUserController::class, 'store']); - - Route::get('login', [AuthenticatedSessionController::class, 'create']) - ->name('login'); - - Route::post('login', [AuthenticatedSessionController::class, 'store']); -}); - -Route::middleware('auth')->group(function () { - Route::post('logout', [AuthenticatedSessionController::class, 'destroy']) - ->name('logout'); -}); - Route::get('/auth/redirect', function () { return Socialite::driver('keycloak')->redirect(); })->name('auth.redirect');