chore: pint rules

This commit is contained in:
kushal-saha 2026-05-08 07:19:08 +00:00
parent 145e67ee46
commit 79c3751d5f
49 changed files with 309 additions and 155 deletions

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Actions\Fortify; namespace App\Actions\Fortify;
use App\Concerns\PasswordValidationRules; use App\Concerns\PasswordValidationRules;
@ -8,9 +10,10 @@
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\CreatesNewUsers; use Laravel\Fortify\Contracts\CreatesNewUsers;
class CreateNewUser implements CreatesNewUsers final class CreateNewUser implements CreatesNewUsers
{ {
use PasswordValidationRules, ProfileValidationRules; use PasswordValidationRules;
use ProfileValidationRules;
/** /**
* Validate and create a newly registered user. * Validate and create a newly registered user.

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Actions\Fortify; namespace App\Actions\Fortify;
use App\Concerns\PasswordValidationRules; use App\Concerns\PasswordValidationRules;
@ -7,7 +9,7 @@
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use Laravel\Fortify\Contracts\ResetsUserPasswords; use Laravel\Fortify\Contracts\ResetsUserPasswords;
class ResetUserPassword implements ResetsUserPasswords final class ResetUserPassword implements ResetsUserPasswords
{ {
use PasswordValidationRules; use PasswordValidationRules;

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Concerns; namespace App\Concerns;
use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Contracts\Validation\ValidationRule;

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Concerns; namespace App\Concerns;
use App\Models\User; use App\Models\User;
@ -43,7 +45,7 @@ protected function emailRules(?int $userId = null): array
'string', 'string',
'email', 'email',
'max:255', 'max:255',
$userId === null null === $userId
? Rule::unique(User::class) ? Rule::unique(User::class)
: Rule::unique(User::class)->ignore($userId), : Rule::unique(User::class)->ignore($userId),
]; ];

View File

@ -1,8 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Http\Controllers; namespace App\Http\Controllers;
abstract class Controller abstract class Controller {}
{
//
}

View File

@ -1,11 +1,13 @@
<?php <?php
declare(strict_types=1);
namespace App\Livewire\Actions; namespace App\Livewire\Actions;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
class Logout final class Logout
{ {
/** /**
* Log the current user out of the application. * Log the current user out of the application.

View File

@ -1,12 +1,11 @@
<?php <?php
declare(strict_types=1);
namespace App\Livewire\Settings; namespace App\Livewire\Settings;
use Livewire\Attributes\Title; use Livewire\Attributes\Title;
use Livewire\Component; use Livewire\Component;
#[Title('Appearance settings')] #[Title('Appearance settings')]
class Appearance extends Component final class Appearance extends Component {}
{
//
}

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Livewire\Settings; namespace App\Livewire\Settings;
use App\Concerns\PasswordValidationRules; use App\Concerns\PasswordValidationRules;
@ -7,7 +9,7 @@
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Livewire\Component; use Livewire\Component;
class DeleteUserForm extends Component final class DeleteUserForm extends Component
{ {
use PasswordValidationRules; use PasswordValidationRules;

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Livewire\Settings; namespace App\Livewire\Settings;
use App\Concerns\ProfileValidationRules; use App\Concerns\ProfileValidationRules;
@ -11,7 +13,7 @@
use Livewire\Component; use Livewire\Component;
#[Title('Profile settings')] #[Title('Profile settings')]
class Profile extends Component final class Profile extends Component
{ {
use ProfileValidationRules; use ProfileValidationRules;

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Livewire\Settings; namespace App\Livewire\Settings;
use App\Concerns\PasswordValidationRules; use App\Concerns\PasswordValidationRules;
@ -19,7 +21,7 @@
use Livewire\Component; use Livewire\Component;
#[Title('Security settings')] #[Title('Security settings')]
class Security extends Component final class Security extends Component
{ {
use PasswordValidationRules; use PasswordValidationRules;
@ -59,7 +61,7 @@ public function mount(DisableTwoFactorAuthentication $disableTwoFactorAuthentica
$this->canManageTwoFactor = Features::canManageTwoFactorAuthentication(); $this->canManageTwoFactor = Features::canManageTwoFactorAuthentication();
if ($this->canManageTwoFactor) { if ($this->canManageTwoFactor) {
if (Fortify::confirmsTwoFactorAuthentication() && is_null(auth()->user()->two_factor_confirmed_at)) { if (Fortify::confirmsTwoFactorAuthentication() && null === auth()->user()->two_factor_confirmed_at) {
$disableTwoFactorAuthentication(auth()->user()); $disableTwoFactorAuthentication(auth()->user());
} }
@ -100,7 +102,7 @@ public function enable(EnableTwoFactorAuthentication $enableTwoFactorAuthenticat
{ {
$enableTwoFactorAuthentication(auth()->user()); $enableTwoFactorAuthentication(auth()->user());
if (! $this->requiresConfirmation) { if ( ! $this->requiresConfirmation) {
$this->twoFactorEnabled = auth()->user()->hasEnabledTwoFactorAuthentication(); $this->twoFactorEnabled = auth()->user()->hasEnabledTwoFactorAuthentication();
} }
@ -109,23 +111,6 @@ public function enable(EnableTwoFactorAuthentication $enableTwoFactorAuthenticat
$this->showModal = true; $this->showModal = true;
} }
/**
* Load the two-factor authentication setup data for the user.
*/
private function loadSetupData(): void
{
$user = auth()->user();
try {
$this->qrCodeSvg = $user?->twoFactorQrCodeSvg();
$this->manualSetupKey = decrypt($user->two_factor_secret);
} catch (Exception) {
$this->addError('setupData', 'Failed to fetch setup data.');
$this->reset('qrCodeSvg', 'manualSetupKey');
}
}
/** /**
* Show the two-factor verification step if necessary. * Show the two-factor verification step if necessary.
*/ */
@ -191,7 +176,7 @@ public function closeModal(): void
$this->resetErrorBag(); $this->resetErrorBag();
if (! $this->requiresConfirmation) { if ( ! $this->requiresConfirmation) {
$this->twoFactorEnabled = auth()->user()->hasEnabledTwoFactorAuthentication(); $this->twoFactorEnabled = auth()->user()->hasEnabledTwoFactorAuthentication();
} }
} }
@ -224,4 +209,21 @@ public function modalConfig(): array
'buttonText' => __('Continue'), 'buttonText' => __('Continue'),
]; ];
} }
/**
* Load the two-factor authentication setup data for the user.
*/
private function loadSetupData(): void
{
$user = auth()->user();
try {
$this->qrCodeSvg = $user?->twoFactorQrCodeSvg();
$this->manualSetupKey = decrypt($user->two_factor_secret);
} catch (Exception) {
$this->addError('setupData', 'Failed to fetch setup data.');
$this->reset('qrCodeSvg', 'manualSetupKey');
}
}
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Livewire\Settings\TwoFactor; namespace App\Livewire\Settings\TwoFactor;
use Exception; use Exception;
@ -7,7 +9,7 @@
use Livewire\Attributes\Locked; use Livewire\Attributes\Locked;
use Livewire\Component; use Livewire\Component;
class RecoveryCodes extends Component final class RecoveryCodes extends Component
{ {
#[Locked] #[Locked]
public array $recoveryCodes = []; public array $recoveryCodes = [];

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Models; namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail; // use Illuminate\Contracts\Auth\MustVerifyEmail;
@ -14,10 +16,24 @@
#[Fillable(['name', 'email', 'password'])] #[Fillable(['name', 'email', 'password'])]
#[Hidden(['password', 'two_factor_secret', 'two_factor_recovery_codes', 'remember_token'])] #[Hidden(['password', 'two_factor_secret', 'two_factor_recovery_codes', 'remember_token'])]
class User extends Authenticatable final class User extends Authenticatable
{ {
/** @use HasFactory<UserFactory> */ /** @use HasFactory<UserFactory> */
use HasFactory, Notifiable, TwoFactorAuthenticatable; use HasFactory;
use Notifiable;
use TwoFactorAuthenticatable;
/**
* Get the user's initials
*/
public function initials(): string
{
return Str::of($this->name)
->explode(' ')
->take(2)
->map(fn($word) => Str::substr($word, 0, 1))
->implode('');
}
/** /**
* Get the attributes that should be cast. * Get the attributes that should be cast.
@ -31,16 +47,4 @@ protected function casts(): array
'password' => 'hashed', 'password' => 'hashed',
]; ];
} }
/**
* Get the user's initials
*/
public function initials(): string
{
return Str::of($this->name)
->explode(' ')
->take(2)
->map(fn ($word) => Str::substr($word, 0, 1))
->implode('');
}
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Providers; namespace App\Providers;
use Carbon\CarbonImmutable; use Carbon\CarbonImmutable;
@ -8,15 +10,12 @@
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Illuminate\Validation\Rules\Password; use Illuminate\Validation\Rules\Password;
class AppServiceProvider extends ServiceProvider final class AppServiceProvider extends ServiceProvider
{ {
/** /**
* Register any application services. * Register any application services.
*/ */
public function register(): void public function register(): void {}
{
//
}
/** /**
* Bootstrap any application services. * Bootstrap any application services.
@ -37,7 +36,8 @@ protected function configureDefaults(): void
app()->isProduction(), app()->isProduction(),
); );
Password::defaults(fn (): ?Password => app()->isProduction() Password::defaults(
fn(): ?Password => app()->isProduction()
? Password::min(12) ? Password::min(12)
->mixedCase() ->mixedCase()
->letters() ->letters()

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace App\Providers; namespace App\Providers;
use App\Actions\Fortify\CreateNewUser; use App\Actions\Fortify\CreateNewUser;
@ -11,15 +13,12 @@
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Laravel\Fortify\Fortify; use Laravel\Fortify\Fortify;
class FortifyServiceProvider extends ServiceProvider final class FortifyServiceProvider extends ServiceProvider
{ {
/** /**
* Register any application services. * Register any application services.
*/ */
public function register(): void public function register(): void {}
{
//
}
/** /**
* Bootstrap any application services. * Bootstrap any application services.
@ -45,13 +44,13 @@ private function configureActions(): void
*/ */
private function configureViews(): void private function configureViews(): void
{ {
Fortify::loginView(fn () => view('livewire.auth.login')); Fortify::loginView(fn() => view('livewire.auth.login'));
Fortify::verifyEmailView(fn () => view('livewire.auth.verify-email')); Fortify::verifyEmailView(fn() => view('livewire.auth.verify-email'));
Fortify::twoFactorChallengeView(fn () => view('livewire.auth.two-factor-challenge')); Fortify::twoFactorChallengeView(fn() => view('livewire.auth.two-factor-challenge'));
Fortify::confirmPasswordView(fn () => view('livewire.auth.confirm-password')); Fortify::confirmPasswordView(fn() => view('livewire.auth.confirm-password'));
Fortify::registerView(fn () => view('livewire.auth.register')); Fortify::registerView(fn() => view('livewire.auth.register'));
Fortify::resetPasswordView(fn () => view('livewire.auth.reset-password')); Fortify::resetPasswordView(fn() => view('livewire.auth.reset-password'));
Fortify::requestPasswordResetLinkView(fn () => view('livewire.auth.forgot-password')); Fortify::requestPasswordResetLinkView(fn() => view('livewire.auth.forgot-password'));
} }
/** /**
@ -59,12 +58,10 @@ private function configureViews(): void
*/ */
private function configureRateLimiting(): void private function configureRateLimiting(): void
{ {
RateLimiter::for('two-factor', function (Request $request) { RateLimiter::for('two-factor', fn(Request $request) => Limit::perMinute(5)->by($request->session()->get('login.id')));
return Limit::perMinute(5)->by($request->session()->get('login.id'));
});
RateLimiter::for('login', function (Request $request) { RateLimiter::for('login', function (Request $request) {
$throttleKey = Str::transliterate(Str::lower($request->input(Fortify::username())).'|'.$request->ip()); $throttleKey = Str::transliterate(Str::lower($request->input(Fortify::username())) . '|' . $request->ip());
return Limit::perMinute(5)->by($throttleKey); return Limit::perMinute(5)->by($throttleKey);
}); });

View File

@ -1,18 +1,16 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware; 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',
commands: __DIR__.'/../routes/console.php', commands: __DIR__ . '/../routes/console.php',
health: '/up', health: '/up',
) )
->withMiddleware(function (Middleware $middleware): void { ->withMiddleware(function (Middleware $middleware): void {})
// ->withExceptions(function (Exceptions $exceptions): void {})->create();
})
->withExceptions(function (Exceptions $exceptions): void {
//
})->create();

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
use App\Providers\AppServiceProvider; use App\Providers\AppServiceProvider;
use App\Providers\FortifyServiceProvider; use App\Providers\FortifyServiceProvider;

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
/* /*

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
use App\Models\User; use App\Models\User;
return [ return [

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Support\Str; use Illuminate\Support\Str;
return [ return [
@ -112,7 +114,7 @@
| |
*/ */
'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-cache-'), 'prefix' => env('CACHE_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')) . '-cache-'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Pdo\Mysql; use Pdo\Mysql;
@ -149,7 +151,7 @@
'options' => [ 'options' => [
'cluster' => env('REDIS_CLUSTER', 'redis'), 'cluster' => env('REDIS_CLUSTER', 'redis'),
'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')).'-database-'), 'prefix' => env('REDIS_PREFIX', Str::slug((string) env('APP_NAME', 'laravel')) . '-database-'),
'persistent' => env('REDIS_PERSISTENT', false), 'persistent' => env('REDIS_PERSISTENT', false),
], ],

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
/* /*
@ -41,7 +43,7 @@
'public' => [ 'public' => [
'driver' => 'local', 'driver' => 'local',
'root' => storage_path('app/public'), 'root' => storage_path('app/public'),
'url' => rtrim(env('APP_URL', 'http://localhost'), '/').'/storage', 'url' => mb_rtrim(env('APP_URL', 'http://localhost'), '/') . '/storage',
'visibility' => 'public', 'visibility' => 'public',
'throw' => false, 'throw' => false,
'report' => false, 'report' => false,

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
use Laravel\Fortify\Features; use Laravel\Fortify\Features;
return [ return [

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
use Monolog\Handler\NullHandler; use Monolog\Handler\NullHandler;
use Monolog\Handler\StreamHandler; use Monolog\Handler\StreamHandler;
use Monolog\Handler\SyslogUdpHandler; use Monolog\Handler\SyslogUdpHandler;
@ -89,7 +91,7 @@
'handler_with' => [ 'handler_with' => [
'host' => env('PAPERTRAIL_URL'), 'host' => env('PAPERTRAIL_URL'),
'port' => env('PAPERTRAIL_PORT'), 'port' => env('PAPERTRAIL_PORT'),
'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'), 'connectionString' => 'tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT'),
], ],
'processors' => [PsrLogMessageProcessor::class], 'processors' => [PsrLogMessageProcessor::class],
], ],

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
/* /*

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
/* /*

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
return [ return [
/* /*

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Support\Str; use Illuminate\Support\Str;
return [ return [
@ -129,7 +131,7 @@
'cookie' => env( 'cookie' => env(
'SESSION_COOKIE', 'SESSION_COOKIE',
Str::slug((string) env('APP_NAME', 'laravel')).'-session', Str::slug((string) env('APP_NAME', 'laravel')) . '-session',
), ),
/* /*

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Database\Factories; namespace Database\Factories;
use App\Models\User; use App\Models\User;
@ -10,7 +12,7 @@
/** /**
* @extends Factory<User> * @extends Factory<User>
*/ */
class UserFactory extends Factory final class UserFactory extends Factory
{ {
/** /**
* The current password being used by the factory. * The current password being used by the factory.
@ -41,7 +43,7 @@ public function definition(): array
*/ */
public function unverified(): static public function unverified(): static
{ {
return $this->state(fn (array $attributes) => [ return $this->state(fn(array $attributes) => [
'email_verified_at' => null, 'email_verified_at' => null,
]); ]);
} }
@ -51,7 +53,7 @@ public function unverified(): static
*/ */
public function withTwoFactor(): static public function withTwoFactor(): static
{ {
return $this->state(fn (array $attributes) => [ return $this->state(fn(array $attributes) => [
'two_factor_secret' => encrypt('secret'), 'two_factor_secret' => encrypt('secret'),
'two_factor_recovery_codes' => encrypt(json_encode(['recovery-code-1'])), 'two_factor_recovery_codes' => encrypt(json_encode(['recovery-code-1'])),
'two_factor_confirmed_at' => now(), 'two_factor_confirmed_at' => now(),

View File

@ -1,17 +1,18 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
return new class extends Migration return new class () extends Migration {
{
/** /**
* Run the migrations. * Run the migrations.
*/ */
public function up(): void public function up(): void
{ {
Schema::create('users', function (Blueprint $table) { Schema::create('users', function (Blueprint $table): void {
$table->id(); $table->id();
$table->string('name'); $table->string('name');
$table->string('email')->unique(); $table->string('email')->unique();
@ -21,13 +22,13 @@ public function up(): void
$table->timestamps(); $table->timestamps();
}); });
Schema::create('password_reset_tokens', function (Blueprint $table) { Schema::create('password_reset_tokens', function (Blueprint $table): void {
$table->string('email')->primary(); $table->string('email')->primary();
$table->string('token'); $table->string('token');
$table->timestamp('created_at')->nullable(); $table->timestamp('created_at')->nullable();
}); });
Schema::create('sessions', function (Blueprint $table) { Schema::create('sessions', function (Blueprint $table): void {
$table->string('id')->primary(); $table->string('id')->primary();
$table->foreignId('user_id')->nullable()->index(); $table->foreignId('user_id')->nullable()->index();
$table->string('ip_address', 45)->nullable(); $table->string('ip_address', 45)->nullable();

View File

@ -1,23 +1,24 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
return new class extends Migration return new class () extends Migration {
{
/** /**
* Run the migrations. * Run the migrations.
*/ */
public function up(): void public function up(): void
{ {
Schema::create('cache', function (Blueprint $table) { Schema::create('cache', function (Blueprint $table): void {
$table->string('key')->primary(); $table->string('key')->primary();
$table->mediumText('value'); $table->mediumText('value');
$table->bigInteger('expiration')->index(); $table->bigInteger('expiration')->index();
}); });
Schema::create('cache_locks', function (Blueprint $table) { Schema::create('cache_locks', function (Blueprint $table): void {
$table->string('key')->primary(); $table->string('key')->primary();
$table->string('owner'); $table->string('owner');
$table->bigInteger('expiration')->index(); $table->bigInteger('expiration')->index();

View File

@ -1,17 +1,18 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
return new class extends Migration return new class () extends Migration {
{
/** /**
* Run the migrations. * Run the migrations.
*/ */
public function up(): void public function up(): void
{ {
Schema::create('jobs', function (Blueprint $table) { Schema::create('jobs', function (Blueprint $table): void {
$table->id(); $table->id();
$table->string('queue')->index(); $table->string('queue')->index();
$table->longText('payload'); $table->longText('payload');
@ -21,7 +22,7 @@ public function up(): void
$table->unsignedInteger('created_at'); $table->unsignedInteger('created_at');
}); });
Schema::create('job_batches', function (Blueprint $table) { Schema::create('job_batches', function (Blueprint $table): void {
$table->string('id')->primary(); $table->string('id')->primary();
$table->string('name'); $table->string('name');
$table->integer('total_jobs'); $table->integer('total_jobs');
@ -34,7 +35,7 @@ public function up(): void
$table->integer('finished_at')->nullable(); $table->integer('finished_at')->nullable();
}); });
Schema::create('failed_jobs', function (Blueprint $table) { Schema::create('failed_jobs', function (Blueprint $table): void {
$table->id(); $table->id();
$table->string('uuid')->unique(); $table->string('uuid')->unique();
$table->text('connection'); $table->text('connection');

View File

@ -1,17 +1,18 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Schema;
return new class extends Migration return new class () extends Migration {
{
/** /**
* Run the migrations. * Run the migrations.
*/ */
public function up(): void public function up(): void
{ {
Schema::table('users', function (Blueprint $table) { Schema::table('users', function (Blueprint $table): void {
$table->text('two_factor_secret')->after('password')->nullable(); $table->text('two_factor_secret')->after('password')->nullable();
$table->text('two_factor_recovery_codes')->after('two_factor_secret')->nullable(); $table->text('two_factor_recovery_codes')->after('two_factor_secret')->nullable();
$table->timestamp('two_factor_confirmed_at')->after('two_factor_recovery_codes')->nullable(); $table->timestamp('two_factor_confirmed_at')->after('two_factor_recovery_codes')->nullable();
@ -23,7 +24,7 @@ public function up(): void
*/ */
public function down(): void public function down(): void
{ {
Schema::table('users', function (Blueprint $table) { Schema::table('users', function (Blueprint $table): void {
$table->dropColumn([ $table->dropColumn([
'two_factor_secret', 'two_factor_secret',
'two_factor_recovery_codes', 'two_factor_recovery_codes',

View File

@ -1,12 +1,14 @@
<?php <?php
declare(strict_types=1);
namespace Database\Seeders; namespace Database\Seeders;
use App\Models\User; use App\Models\User;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents; // use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder final class DatabaseSeeder extends Seeder
{ {
/** /**
* Seed the application's database. * Seed the application's database.

View File

@ -1,3 +1,81 @@
{ {
"preset": "laravel" "preset": "per",
"rules": {
"align_multiline_comment": true,
"array_indentation": true,
"array_syntax": true,
"blank_line_after_namespace": true,
"blank_line_after_opening_tag": true,
"combine_consecutive_issets": true,
"combine_consecutive_unsets": true,
"concat_space": {
"spacing": "one"
},
"declare_parentheses": true,
"declare_strict_types": true,
"explicit_string_variable": true,
"final_class": true,
"fully_qualified_strict_types": true,
"global_namespace_import": {
"import_classes": true,
"import_constants": true,
"import_functions": true
},
"is_null": true,
"lambda_not_used_import": true,
"logical_operators": true,
"mb_str_functions": true,
"method_chaining_indentation": true,
"modernize_strpos": true,
"new_with_braces": true,
"no_empty_comment": true,
"not_operator_with_space": true,
"ordered_traits": true,
"protected_to_private": true,
"simplified_if_return": true,
"strict_comparison": true,
"ternary_to_null_coalescing": true,
"trim_array_spaces": true,
"use_arrow_functions": true,
"void_return": true,
"yoda_style": true,
"array_push": true,
"assign_null_coalescing_to_coalesce_equal": true,
"explicit_indirect_variable": true,
"method_argument_space": {
"on_multiline": "ensure_fully_multiline"
},
"modernize_types_casting": true,
"no_superfluous_elseif": true,
"no_useless_else": true,
"nullable_type_declaration_for_default_null_value": true,
"ordered_imports": {
"sort_algorithm": "alpha"
},
"ordered_class_elements": {
"order": [
"use_trait",
"case",
"constant",
"constant_public",
"constant_protected",
"constant_private",
"property_public",
"property_protected",
"property_private",
"construct",
"destruct",
"magic",
"phpunit",
"method_abstract",
"method_public_static",
"method_public",
"method_protected_static",
"method_protected",
"method_private_static",
"method_private"
],
"sort_algorithm": "none"
}
}
} }

View File

@ -1,20 +1,22 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Http\Request; use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true)); define('LARAVEL_START', microtime(true));
// Determine if the application is in maintenance mode... // Determine if the application is in maintenance mode...
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) { if (file_exists($maintenance = __DIR__ . '/../storage/framework/maintenance.php')) {
require $maintenance; require $maintenance;
} }
// Register the Composer autoloader... // Register the Composer autoloader...
require __DIR__.'/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
// Bootstrap Laravel and handle the request... // Bootstrap Laravel and handle the request...
/** @var Application $app */ /** @var Application $app */
$app = require_once __DIR__.'/../bootstrap/app.php'; $app = require_once __DIR__ . '/../bootstrap/app.php';
$app->handleRequest(Request::capture()); $app->handleRequest(Request::capture());

View File

@ -1,8 +1,10 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Foundation\Inspiring; use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
Artisan::command('inspire', function () { Artisan::command('inspire', function (): void {
$this->comment(Inspiring::quote()); $this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote'); })->purpose('Display an inspiring quote');

View File

@ -1,18 +1,20 @@
<?php <?php
declare(strict_types=1);
use App\Livewire\Settings\Appearance; use App\Livewire\Settings\Appearance;
use App\Livewire\Settings\Profile; use App\Livewire\Settings\Profile;
use App\Livewire\Settings\Security; use App\Livewire\Settings\Security;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use Laravel\Fortify\Features; use Laravel\Fortify\Features;
Route::middleware(['auth'])->group(function () { Route::middleware(['auth'])->group(function (): void {
Route::redirect('settings', 'settings/profile'); Route::redirect('settings', 'settings/profile');
Route::livewire('settings/profile', Profile::class)->name('profile.edit'); Route::livewire('settings/profile', Profile::class)->name('profile.edit');
}); });
Route::middleware(['auth', 'verified'])->group(function () { Route::middleware(['auth', 'verified'])->group(function (): void {
Route::livewire('settings/appearance', Appearance::class)->name('appearance.edit'); Route::livewire('settings/appearance', Appearance::class)->name('appearance.edit');
Route::livewire('settings/security', Security::class) Route::livewire('settings/security', Security::class)

View File

@ -1,15 +1,17 @@
<?php <?php
declare(strict_types=1);
use App\Models\User; use App\Models\User;
use Laravel\Fortify\Features; use Laravel\Fortify\Features;
test('login screen can be rendered', function () { test('login screen can be rendered', function (): void {
$response = $this->get(route('login')); $response = $this->get(route('login'));
$response->assertOk(); $response->assertOk();
}); });
test('users can authenticate using the login screen', function () { test('users can authenticate using the login screen', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$response = $this->post(route('login.store'), [ $response = $this->post(route('login.store'), [
@ -24,7 +26,7 @@
$this->assertAuthenticated(); $this->assertAuthenticated();
}); });
test('users can not authenticate with invalid password', function () { test('users can not authenticate with invalid password', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$response = $this->post(route('login.store'), [ $response = $this->post(route('login.store'), [
@ -37,7 +39,7 @@
$this->assertGuest(); $this->assertGuest();
}); });
test('users with two factor enabled are redirected to two factor challenge', function () { test('users with two factor enabled are redirected to two factor challenge', function (): void {
$this->skipUnlessFortifyHas(Features::twoFactorAuthentication()); $this->skipUnlessFortifyHas(Features::twoFactorAuthentication());
Features::twoFactorAuthentication([ Features::twoFactorAuthentication([
@ -56,7 +58,7 @@
$this->assertGuest(); $this->assertGuest();
}); });
test('users can logout', function () { test('users can logout', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$response = $this->actingAs($user)->post(route('logout')); $response = $this->actingAs($user)->post(route('logout'));

View File

@ -1,16 +1,18 @@
<?php <?php
declare(strict_types=1);
use App\Models\User; use App\Models\User;
use Illuminate\Auth\Events\Verified; use Illuminate\Auth\Events\Verified;
use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\URL; use Illuminate\Support\Facades\URL;
use Laravel\Fortify\Features; use Laravel\Fortify\Features;
beforeEach(function () { beforeEach(function (): void {
$this->skipUnlessFortifyHas(Features::emailVerification()); $this->skipUnlessFortifyHas(Features::emailVerification());
}); });
test('email verification screen can be rendered', function () { test('email verification screen can be rendered', function (): void {
$user = User::factory()->unverified()->create(); $user = User::factory()->unverified()->create();
$response = $this->actingAs($user)->get(route('verification.notice')); $response = $this->actingAs($user)->get(route('verification.notice'));
@ -18,7 +20,7 @@
$response->assertOk(); $response->assertOk();
}); });
test('email can be verified', function () { test('email can be verified', function (): void {
$user = User::factory()->unverified()->create(); $user = User::factory()->unverified()->create();
Event::fake(); Event::fake();
@ -34,10 +36,10 @@
Event::assertDispatched(Verified::class); Event::assertDispatched(Verified::class);
expect($user->fresh()->hasVerifiedEmail())->toBeTrue(); expect($user->fresh()->hasVerifiedEmail())->toBeTrue();
$response->assertRedirect(route('dashboard', absolute: false).'?verified=1'); $response->assertRedirect(route('dashboard', absolute: false) . '?verified=1');
}); });
test('email is not verified with invalid hash', function () { test('email is not verified with invalid hash', function (): void {
$user = User::factory()->unverified()->create(); $user = User::factory()->unverified()->create();
$verificationUrl = URL::temporarySignedRoute( $verificationUrl = URL::temporarySignedRoute(
@ -51,7 +53,7 @@
expect($user->fresh()->hasVerifiedEmail())->toBeFalse(); expect($user->fresh()->hasVerifiedEmail())->toBeFalse();
}); });
test('already verified user visiting verification link is redirected without firing event again', function () { test('already verified user visiting verification link is redirected without firing event again', function (): void {
$user = User::factory()->create([ $user = User::factory()->create([
'email_verified_at' => now(), 'email_verified_at' => now(),
]); ]);
@ -65,7 +67,7 @@
); );
$this->actingAs($user)->get($verificationUrl) $this->actingAs($user)->get($verificationUrl)
->assertRedirect(route('dashboard', absolute: false).'?verified=1'); ->assertRedirect(route('dashboard', absolute: false) . '?verified=1');
expect($user->fresh()->hasVerifiedEmail())->toBeTrue(); expect($user->fresh()->hasVerifiedEmail())->toBeTrue();
Event::assertNotDispatched(Verified::class); Event::assertNotDispatched(Verified::class);

View File

@ -1,8 +1,10 @@
<?php <?php
declare(strict_types=1);
use App\Models\User; use App\Models\User;
test('confirm password screen can be rendered', function () { test('confirm password screen can be rendered', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$response = $this->actingAs($user)->get(route('password.confirm')); $response = $this->actingAs($user)->get(route('password.confirm'));

View File

@ -1,18 +1,20 @@
<?php <?php
declare(strict_types=1);
use Laravel\Fortify\Features; use Laravel\Fortify\Features;
beforeEach(function () { beforeEach(function (): void {
$this->skipUnlessFortifyHas(Features::registration()); $this->skipUnlessFortifyHas(Features::registration());
}); });
test('registration screen can be rendered', function () { test('registration screen can be rendered', function (): void {
$response = $this->get(route('register')); $response = $this->get(route('register'));
$response->assertOk(); $response->assertOk();
}); });
test('new users can register', function () { test('new users can register', function (): void {
$response = $this->post(route('register.store'), [ $response = $this->post(route('register.store'), [
'name' => 'John Doe', 'name' => 'John Doe',
'email' => 'test@example.com', 'email' => 'test@example.com',

View File

@ -1,19 +1,21 @@
<?php <?php
declare(strict_types=1);
use App\Models\User; use App\Models\User;
use Laravel\Fortify\Features; use Laravel\Fortify\Features;
beforeEach(function () { beforeEach(function (): void {
$this->skipUnlessFortifyHas(Features::twoFactorAuthentication()); $this->skipUnlessFortifyHas(Features::twoFactorAuthentication());
}); });
test('two factor challenge redirects to login when not authenticated', function () { test('two factor challenge redirects to login when not authenticated', function (): void {
$response = $this->get(route('two-factor.login')); $response = $this->get(route('two-factor.login'));
$response->assertRedirect(route('login')); $response->assertRedirect(route('login'));
}); });
test('two factor challenge can be rendered', function () { test('two factor challenge can be rendered', function (): void {
Features::twoFactorAuthentication([ Features::twoFactorAuthentication([
'confirm' => true, 'confirm' => true,
'confirmPassword' => true, 'confirmPassword' => true,

View File

@ -1,13 +1,15 @@
<?php <?php
declare(strict_types=1);
use App\Models\User; use App\Models\User;
test('guests are redirected to the login page', function () { test('guests are redirected to the login page', function (): void {
$response = $this->get(route('dashboard')); $response = $this->get(route('dashboard'));
$response->assertRedirect(route('login')); $response->assertRedirect(route('login'));
}); });
test('authenticated users can visit the dashboard', function () { test('authenticated users can visit the dashboard', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$this->actingAs($user); $this->actingAs($user);

View File

@ -1,6 +1,8 @@
<?php <?php
test('returns a successful response', function () { declare(strict_types=1);
test('returns a successful response', function (): void {
$response = $this->get(route('home')); $response = $this->get(route('home'));
$response->assertOk(); $response->assertOk();

View File

@ -1,16 +1,18 @@
<?php <?php
declare(strict_types=1);
use App\Livewire\Settings\Profile; use App\Livewire\Settings\Profile;
use App\Models\User; use App\Models\User;
use Livewire\Livewire; use Livewire\Livewire;
test('profile page is displayed', function () { test('profile page is displayed', function (): void {
$this->actingAs($user = User::factory()->create()); $this->actingAs($user = User::factory()->create());
$this->get('/settings/profile')->assertOk(); $this->get('/settings/profile')->assertOk();
}); });
test('profile information can be updated', function () { test('profile information can be updated', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$this->actingAs($user); $this->actingAs($user);
@ -29,7 +31,7 @@
expect($user->email_verified_at)->toBeNull(); expect($user->email_verified_at)->toBeNull();
}); });
test('email verification status is unchanged when email address is unchanged', function () { test('email verification status is unchanged when email address is unchanged', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$this->actingAs($user); $this->actingAs($user);
@ -44,7 +46,7 @@
expect($user->refresh()->email_verified_at)->not->toBeNull(); expect($user->refresh()->email_verified_at)->not->toBeNull();
}); });
test('user can delete their account', function () { test('user can delete their account', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$this->actingAs($user); $this->actingAs($user);
@ -61,7 +63,7 @@
expect(auth()->check())->toBeFalse(); expect(auth()->check())->toBeFalse();
}); });
test('correct password must be provided to delete account', function () { test('correct password must be provided to delete account', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$this->actingAs($user); $this->actingAs($user);

View File

@ -1,12 +1,14 @@
<?php <?php
declare(strict_types=1);
use App\Livewire\Settings\Security; use App\Livewire\Settings\Security;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Laravel\Fortify\Features; use Laravel\Fortify\Features;
use Livewire\Livewire; use Livewire\Livewire;
beforeEach(function () { beforeEach(function (): void {
$this->skipUnlessFortifyHas(Features::twoFactorAuthentication()); $this->skipUnlessFortifyHas(Features::twoFactorAuthentication());
Features::twoFactorAuthentication([ Features::twoFactorAuthentication([
@ -15,7 +17,7 @@
]); ]);
}); });
test('security settings page can be rendered', function () { test('security settings page can be rendered', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$this->actingAs($user) $this->actingAs($user)
@ -26,7 +28,7 @@
->assertSee('Enable 2FA'); ->assertSee('Enable 2FA');
}); });
test('security settings page requires password confirmation when enabled', function () { test('security settings page requires password confirmation when enabled', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$response = $this->actingAs($user) $response = $this->actingAs($user)
@ -35,7 +37,7 @@
$response->assertRedirect(route('password.confirm')); $response->assertRedirect(route('password.confirm'));
}); });
test('security settings page renders without two factor when feature is disabled', function () { test('security settings page renders without two factor when feature is disabled', function (): void {
config(['fortify.features' => []]); config(['fortify.features' => []]);
$user = User::factory()->create(); $user = User::factory()->create();
@ -48,7 +50,7 @@
->assertDontSee('Two-factor authentication'); ->assertDontSee('Two-factor authentication');
}); });
test('two factor authentication disabled when confirmation abandoned between requests', function () { test('two factor authentication disabled when confirmation abandoned between requests', function (): void {
$user = User::factory()->create(); $user = User::factory()->create();
$user->forceFill([ $user->forceFill([
@ -70,7 +72,7 @@
]); ]);
}); });
test('password can be updated', function () { test('password can be updated', function (): void {
$user = User::factory()->create([ $user = User::factory()->create([
'password' => Hash::make('password'), 'password' => Hash::make('password'),
]); ]);
@ -88,7 +90,7 @@
expect(Hash::check('new-password', $user->refresh()->password))->toBeTrue(); expect(Hash::check('new-password', $user->refresh()->password))->toBeTrue();
}); });
test('correct password must be provided to update password', function () { test('correct password must be provided to update password', function (): void {
$user = User::factory()->create([ $user = User::factory()->create([
'password' => Hash::make('password'), 'password' => Hash::make('password'),
]); ]);

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase; use Tests\TestCase;
@ -29,9 +31,7 @@
| |
*/ */
expect()->extend('toBeOne', function () { expect()->extend('toBeOne', fn() => $this->toBe(1));
return $this->toBe(1);
});
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -44,7 +44,7 @@
| |
*/ */
function something() function something(): void
{ {
// .. // ..
} }

View File

@ -1,5 +1,7 @@
<?php <?php
declare(strict_types=1);
namespace Tests; namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase; use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
@ -9,7 +11,7 @@ abstract class TestCase extends BaseTestCase
{ {
protected function skipUnlessFortifyHas(string $feature, ?string $message = null): void protected function skipUnlessFortifyHas(string $feature, ?string $message = null): void
{ {
if (! Features::enabled($feature)) { if ( ! Features::enabled($feature)) {
$this->markTestSkipped($message ?? "Fortify feature [{$feature}] is not enabled."); $this->markTestSkipped($message ?? "Fortify feature [{$feature}] is not enabled.");
} }
} }

View File

@ -1,5 +1,7 @@
<?php <?php
test('that true is true', function () { declare(strict_types=1);
test('that true is true', function (): void {
expect(true)->toBeTrue(); expect(true)->toBeTrue();
}); });