From eae410bdbc092749dd4ada94b8bcb27371457636 Mon Sep 17 00:00:00 2001 From: Yury Pikhtarev Date: Tue, 24 Jun 2025 02:33:07 +0400 Subject: [PATCH] feat: Framework preparations: Config, Dependencies & Authentication Overhaul (#2005) * chore: update package-lock and package.json for TorrentPier migration - Change project name from "dexter" to "torrentpier" in package files - Update dependencies to latest versions, including Babel and Axios - Add tinyglobby package for improved file handling - Adjust Vite and other related dependencies for compatibility * chore: update project configuration for TorrentPier migration - Change application name from "Laravel" to "TorrentPier" in .env.example - Update project name and description in composer.json - Add homepage and support information in composer.json - Increase minimum PHP version requirement to 8.4 in composer files - Rename legacy composer files to resolve detection in IDE This commit aligns the project configuration with the new TorrentPier branding and prepares for future development. * chore: update .env.example for TorrentPier configuration - Set APP_MAINTENANCE_STORE to database for maintenance mode - Change DB_DATABASE to torrentpier for database configuration - Define CACHE_PREFIX as torrentpier_ for cache management These changes align the environment configuration with the updated project structure and naming conventions. * chore: update Redis client configuration and dependencies - Change Redis client from phpredis to predis in .env.example for improved compatibility. - Add predis/predis package to composer.json and update composer.lock to include the new dependency. These changes enhance the project's Redis integration and ensure the necessary package is available for development. * feat: integrate Laravel Sanctum for API authentication - Added laravel/sanctum package to composer.json and updated composer.lock. - Implemented HasApiTokens trait in User model for token-based authentication. - Created a new configuration file for Sanctum. - Added migration for personal access tokens table. - Set up basic API route for user authentication. These changes establish a robust authentication system for the API, enhancing security and user management. * refactor: reorder traits in User model and add newlines in test files - Reordered the traits in the User model for better organization. - Added missing newlines at the end of several test files to comply with coding standards. These changes improve code readability and maintainability across the project. * chore: add Pint configuration and refactor code style - Introduced a new Pint configuration file for code style enforcement with specific rules and exclusions. - Refactored code in various files to adhere to the new style guidelines, including adjustments to spacing in conditional statements. These changes enhance code consistency and maintainability across the project. * chore: update .gitignore to exclude Claude Code file - Added CLAUDE.local.md to .gitignore to prevent tracking of local configuration files. This change helps maintain a clean repository by excluding user-specific files. * chore: update .env.example for maintenance driver configuration - Changed APP_MAINTENANCE_DRIVER from file to cache for improved performance. - Ensured CACHE_STORE remains set to database for consistency. These changes refine the environment configuration for better maintenance handling. --- .env.example | 12 +- .gitignore | 3 + .../Auth/ConfirmablePasswordController.php | 2 +- app/Http/Middleware/HandleInertiaRequests.php | 2 +- app/Http/Requests/Auth/LoginRequest.php | 4 +- app/Models/User.php | 3 +- bootstrap/app.php | 1 + composer.json | 21 ++- composer.lock | 131 +++++++++++++- config/sanctum.php | 84 +++++++++ ...27_create_personal_access_tokens_table.php | 33 ++++ legacy/{composer.json => _composer.json} | 0 legacy/{composer.lock => _composer.lock} | 0 package-lock.json | 168 ++++++++++++------ package.json | 1 + pint.json | 10 ++ routes/api.php | 8 + tests/Feature/Auth/AuthenticationTest.php | 2 +- tests/Feature/Auth/EmailVerificationTest.php | 2 +- .../Feature/Auth/PasswordConfirmationTest.php | 2 +- tests/Feature/Auth/PasswordResetTest.php | 2 +- tests/Feature/Auth/RegistrationTest.php | 2 +- tests/Feature/DashboardTest.php | 2 +- tests/Feature/Settings/PasswordUpdateTest.php | 2 +- tests/Feature/Settings/ProfileUpdateTest.php | 2 +- tests/Unit/ExampleTest.php | 2 +- 26 files changed, 418 insertions(+), 83 deletions(-) create mode 100644 config/sanctum.php create mode 100644 database/migrations/2025_06_23_202427_create_personal_access_tokens_table.php rename legacy/{composer.json => _composer.json} (100%) rename legacy/{composer.lock => _composer.lock} (100%) create mode 100644 pint.json create mode 100644 routes/api.php diff --git a/.env.example b/.env.example index 35db1ddf0..43825b834 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -APP_NAME=Laravel +APP_NAME=TorrentPier APP_ENV=local APP_KEY= APP_DEBUG=true @@ -8,8 +8,8 @@ APP_LOCALE=en APP_FALLBACK_LOCALE=en APP_FAKER_LOCALE=en_US -APP_MAINTENANCE_DRIVER=file -# APP_MAINTENANCE_STORE=database +APP_MAINTENANCE_DRIVER=cache +APP_MAINTENANCE_STORE=database PHP_CLI_SERVER_WORKERS=4 @@ -23,7 +23,7 @@ LOG_LEVEL=debug DB_CONNECTION=sqlite # DB_HOST=127.0.0.1 # DB_PORT=3306 -# DB_DATABASE=laravel +# DB_DATABASE=torrentpier # DB_USERNAME=root # DB_PASSWORD= @@ -37,12 +37,12 @@ BROADCAST_CONNECTION=log FILESYSTEM_DISK=local QUEUE_CONNECTION=database +CACHE_PREFIX=torrentpier_ CACHE_STORE=database -# CACHE_PREFIX= MEMCACHED_HOST=127.0.0.1 -REDIS_CLIENT=phpredis +REDIS_CLIENT=predis REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 diff --git a/.gitignore b/.gitignore index ed3a672ae..7059c9937 100644 --- a/.gitignore +++ b/.gitignore @@ -171,3 +171,6 @@ $RECYCLE.BIN/ # Windows shortcuts *.lnk + +# Claude Code +CLAUDE.local.md diff --git a/app/Http/Controllers/Auth/ConfirmablePasswordController.php b/app/Http/Controllers/Auth/ConfirmablePasswordController.php index c729706d6..8e429d7d8 100644 --- a/app/Http/Controllers/Auth/ConfirmablePasswordController.php +++ b/app/Http/Controllers/Auth/ConfirmablePasswordController.php @@ -25,7 +25,7 @@ class ConfirmablePasswordController extends Controller */ public function store(Request $request): RedirectResponse { - if (! Auth::guard('web')->validate([ + if (!Auth::guard('web')->validate([ 'email' => $request->user()->email, 'password' => $request->password, ])) { diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 3af9fd499..0c84eda72 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -50,7 +50,7 @@ class HandleInertiaRequests extends Middleware ...(new Ziggy)->toArray(), 'location' => $request->url(), ], - 'sidebarOpen' => ! $request->hasCookie('sidebar_state') || $request->cookie('sidebar_state') === 'true', + 'sidebarOpen' => !$request->hasCookie('sidebar_state') || $request->cookie('sidebar_state') === 'true', ]; } } diff --git a/app/Http/Requests/Auth/LoginRequest.php b/app/Http/Requests/Auth/LoginRequest.php index d236bf93c..fc20c1f87 100644 --- a/app/Http/Requests/Auth/LoginRequest.php +++ b/app/Http/Requests/Auth/LoginRequest.php @@ -41,7 +41,7 @@ class LoginRequest extends FormRequest { $this->ensureIsNotRateLimited(); - if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) { + if (!Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) { RateLimiter::hit($this->throttleKey()); throw ValidationException::withMessages([ @@ -59,7 +59,7 @@ class LoginRequest extends FormRequest */ public function ensureIsNotRateLimited(): void { - if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { + if (!RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { return; } diff --git a/app/Models/User.php b/app/Models/User.php index 749c7b77d..91135d75d 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -6,11 +6,12 @@ namespace App\Models; 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; + use HasApiTokens, HasFactory, Notifiable; /** * The attributes that are mass assignable. diff --git a/bootstrap/app.php b/bootstrap/app.php index 134581ab3..acf0933d0 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -10,6 +10,7 @@ use Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets; 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 fe6e73c30..1dcef5143 100644 --- a/composer.json +++ b/composer.json @@ -1,18 +1,29 @@ { "$schema": "https://getcomposer.org/schema.json", - "name": "laravel/react-starter-kit", + "name": "torrentpier/torrentpier", "type": "project", - "description": "The skeleton application for the Laravel framework.", + "description": "TorrentPier. Bull-powered BitTorrent tracker engine.", "keywords": [ "laravel", - "framework" + "bittorrent", + "forum", + "torrent", + "tracker" ], + "homepage": "https://github.com/torrentpier", "license": "MIT", + "support": { + "email": "support@torrentpier.com", + "issues": "https://github.com/torrentpier/torrentpier/issues", + "forum": "https://torrentpier.com" + }, "require": { - "php": "^8.2", + "php": "^8.4", "inertiajs/inertia-laravel": "^2.0", "laravel/framework": "^12.0", + "laravel/sanctum": "^4.0", "laravel/tinker": "^2.10.1", + "predis/predis": "^3.0", "tightenco/ziggy": "^2.4" }, "require-dev": { @@ -83,4 +94,4 @@ }, "minimum-stability": "stable", "prefer-stable": true -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index 8dd26f39b..f04c57945 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": "b7531f73c7a0f0d5c4e7e8690992afc1", + "content-hash": "3a2d2c00a32b4d88ec32ef5d44b6d304", "packages": [ { "name": "brick/math", @@ -1396,6 +1396,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", @@ -2650,6 +2714,69 @@ ], "time": "2024-07-20T21:41:07+00:00" }, + { + "name": "predis/predis", + "version": "v3.0.1", + "source": { + "type": "git", + "url": "https://github.com/predis/predis.git", + "reference": "34fb0a7da0330df1bab4280fcac4afdeeccc3edf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/predis/predis/zipball/34fb0a7da0330df1bab4280fcac4afdeeccc3edf", + "reference": "34fb0a7da0330df1bab4280fcac4afdeeccc3edf", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "psr/http-message": "^1.0|^2.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.3", + "phpstan/phpstan": "^1.9", + "phpunit/phpcov": "^6.0 || ^8.0", + "phpunit/phpunit": "^8.0 || ~9.4.4" + }, + "suggest": { + "ext-relay": "Faster connection with in-memory caching (>=0.6.2)" + }, + "type": "library", + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Till Krüss", + "homepage": "https://till.im", + "role": "Maintainer" + } + ], + "description": "A flexible and feature-complete Redis/Valkey client for PHP.", + "homepage": "http://github.com/predis/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "support": { + "issues": "https://github.com/predis/predis/issues", + "source": "https://github.com/predis/predis/tree/v3.0.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/tillkruss", + "type": "github" + } + ], + "time": "2025-05-16T18:30:32+00:00" + }, { "name": "psr/clock", "version": "1.0.0", @@ -9167,7 +9294,7 @@ "prefer-stable": true, "prefer-lowest": false, "platform": { - "php": "^8.2" + "php": "^8.4" }, "platform-dev": {}, "plugin-api-version": "2.6.0" diff --git a/config/sanctum.php b/config/sanctum.php new file mode 100644 index 000000000..44527d684 --- /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/2025_06_23_202427_create_personal_access_tokens_table.php b/database/migrations/2025_06_23_202427_create_personal_access_tokens_table.php new file mode 100644 index 000000000..e828ad818 --- /dev/null +++ b/database/migrations/2025_06_23_202427_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/legacy/composer.json b/legacy/_composer.json similarity index 100% rename from legacy/composer.json rename to legacy/_composer.json diff --git a/legacy/composer.lock b/legacy/_composer.lock similarity index 100% rename from legacy/composer.lock rename to legacy/_composer.lock diff --git a/package-lock.json b/package-lock.json index 194692ce8..57b5577c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,10 @@ { - "name": "dexter", + "name": "torrentpier", "lockfileVersion": 3, "requires": true, "packages": { "": { + "name": "torrentpier", "dependencies": { "@headlessui/react": "^2.2.0", "@inertiajs/react": "^2.0.0", @@ -70,14 +71,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "license": "MIT", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", + "@babel/helper-validator-identifier": "^7.27.1", "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" @@ -194,19 +194,17 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "license": "MIT", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "license": "MIT", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "engines": { "node": ">=6.9.0" } @@ -221,25 +219,23 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.9.tgz", - "integrity": "sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==", - "license": "MIT", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", "dependencies": { - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.9.tgz", - "integrity": "sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==", - "license": "MIT", + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz", + "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==", "dependencies": { - "@babel/types": "^7.26.9" + "@babel/types": "^7.27.3" }, "bin": { "parser": "bin/babel-parser.js" @@ -279,14 +275,13 @@ } }, "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", - "license": "MIT", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -320,13 +315,12 @@ } }, "node_modules/@babel/types": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.9.tgz", - "integrity": "sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==", - "license": "MIT", + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", + "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" @@ -2828,11 +2822,10 @@ } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -3179,10 +3172,9 @@ } }, "node_modules/axios": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.1.tgz", - "integrity": "sha512-NN+fvwH/kV01dYUQ3PTOZns4LWtWhOFCAhQ/pHb88WQ1hNe5V/dvFwc4VJcDL11LT9xSX0QtsR8sWUuyOuOq7g==", - "license": "MIT", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.10.0.tgz", + "integrity": "sha512-/1xYAC4MP/HEG+3duIhFr4ZQXR4sQXOIe+o6sdqzeykGLx6Upp/1p8MHqhINOvGeP7xyNHe7tsiJByc4SSVUxw==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", @@ -3197,11 +3189,10 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -6778,6 +6769,45 @@ "node": ">=6" } }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -7056,14 +7086,16 @@ } }, "node_modules/vite": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.0.tgz", - "integrity": "sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ==", - "license": "MIT", + "version": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", "dependencies": { "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", "postcss": "^8.5.3", - "rollup": "^4.30.1" + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { "vite": "bin/vite.js" @@ -7136,6 +7168,30 @@ "picomatch": "^2.3.1" } }, + "node_modules/vite/node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 20229aa19..5938a4a34 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,5 @@ { + "name": "torrentpier", "private": true, "type": "module", "scripts": { diff --git a/pint.json b/pint.json new file mode 100644 index 000000000..b5b050c06 --- /dev/null +++ b/pint.json @@ -0,0 +1,10 @@ +{ + "preset": "laravel", + "rules": { + "concat_space": false, + "not_operator_with_successor_space": false + }, + "exclude": [ + "legacy" + ] +} diff --git a/routes/api.php b/routes/api.php new file mode 100644 index 000000000..ccc387f23 --- /dev/null +++ b/routes/api.php @@ -0,0 +1,8 @@ +user(); +})->middleware('auth:sanctum'); diff --git a/tests/Feature/Auth/AuthenticationTest.php b/tests/Feature/Auth/AuthenticationTest.php index 7d08f5015..a272b9d58 100644 --- a/tests/Feature/Auth/AuthenticationTest.php +++ b/tests/Feature/Auth/AuthenticationTest.php @@ -38,4 +38,4 @@ test('users can logout', function () { $this->assertGuest(); $response->assertRedirect('/'); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Auth/EmailVerificationTest.php b/tests/Feature/Auth/EmailVerificationTest.php index e303f4157..f282dff04 100644 --- a/tests/Feature/Auth/EmailVerificationTest.php +++ b/tests/Feature/Auth/EmailVerificationTest.php @@ -43,4 +43,4 @@ test('email is not verified with invalid hash', function () { $this->actingAs($user)->get($verificationUrl); expect($user->fresh()->hasVerifiedEmail())->toBeFalse(); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Auth/PasswordConfirmationTest.php b/tests/Feature/Auth/PasswordConfirmationTest.php index d5894f186..8a42902e3 100644 --- a/tests/Feature/Auth/PasswordConfirmationTest.php +++ b/tests/Feature/Auth/PasswordConfirmationTest.php @@ -29,4 +29,4 @@ test('password is not confirmed with invalid password', function () { ]); $response->assertSessionHasErrors(); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Auth/PasswordResetTest.php b/tests/Feature/Auth/PasswordResetTest.php index 4d243b4c4..0504276a6 100644 --- a/tests/Feature/Auth/PasswordResetTest.php +++ b/tests/Feature/Auth/PasswordResetTest.php @@ -57,4 +57,4 @@ test('password can be reset with valid token', function () { return true; }); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Auth/RegistrationTest.php b/tests/Feature/Auth/RegistrationTest.php index f1d859c7d..352ca7879 100644 --- a/tests/Feature/Auth/RegistrationTest.php +++ b/tests/Feature/Auth/RegistrationTest.php @@ -16,4 +16,4 @@ test('new users can register', function () { $this->assertAuthenticated(); $response->assertRedirect(route('dashboard', absolute: false)); -}); \ No newline at end of file +}); diff --git a/tests/Feature/DashboardTest.php b/tests/Feature/DashboardTest.php index 15804df3a..0b95c7931 100644 --- a/tests/Feature/DashboardTest.php +++ b/tests/Feature/DashboardTest.php @@ -10,4 +10,4 @@ test('authenticated users can visit the dashboard', function () { $this->actingAs($user = User::factory()->create()); $this->get('/dashboard')->assertOk(); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Settings/PasswordUpdateTest.php b/tests/Feature/Settings/PasswordUpdateTest.php index f4566fc89..16533df77 100644 --- a/tests/Feature/Settings/PasswordUpdateTest.php +++ b/tests/Feature/Settings/PasswordUpdateTest.php @@ -37,4 +37,4 @@ test('correct password must be provided to update password', function () { $response ->assertSessionHasErrors('current_password') ->assertRedirect('/settings/password'); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Settings/ProfileUpdateTest.php b/tests/Feature/Settings/ProfileUpdateTest.php index cdf17c227..219446519 100644 --- a/tests/Feature/Settings/ProfileUpdateTest.php +++ b/tests/Feature/Settings/ProfileUpdateTest.php @@ -82,4 +82,4 @@ test('correct password must be provided to delete account', function () { ->assertRedirect('/settings/profile'); expect($user->fresh())->not->toBeNull(); -}); \ No newline at end of file +}); diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php index 27f3f877f..44a4f337a 100644 --- a/tests/Unit/ExampleTest.php +++ b/tests/Unit/ExampleTest.php @@ -2,4 +2,4 @@ test('that true is true', function () { expect(true)->toBeTrue(); -}); \ No newline at end of file +});