diff --git a/src/BreezyCore.php b/src/BreezyCore.php index fc33149..24d7813 100644 --- a/src/BreezyCore.php +++ b/src/BreezyCore.php @@ -1,7 +1,5 @@ sanctumTokens) { Livewire::component('sanctum_tokens', SanctumTokens::class); $this->myProfileComponents([ - 'sanctum_tokens' => SanctumTokens::class, + 'sanctum_tokens' => SanctumTokens::class ]); } if ($this->twoFactorAuthentication) { Livewire::component('two_factor_authentication', TwoFactorAuthentication::class); $this->myProfileComponents([ - 'two_factor_authentication' => TwoFactorAuthentication::class, + 'two_factor_authentication' => TwoFactorAuthentication::class ]); } @@ -118,17 +99,15 @@ public function boot(Panel $panel): void Livewire::component('update_password', UpdatePassword::class); $this->myProfileComponents([ 'personal_info' => PersonalInfo::class, - 'update_password' => UpdatePassword::class, + 'update_password' => UpdatePassword::class ]); if ($this->myProfile['shouldRegisterUserMenu']) { if ($panel->hasTenancy()) { $tenantId = request()->route()->parameter('tenant'); - if ($tenant = app($panel->getTenantModel())::where($panel->getTenantSlugAttribute() ?? 'id', - $tenantId)->first()) { + if ($tenant = app($panel->getTenantModel())::where($panel->getTenantSlugAttribute() ?? 'id', $tenantId)->first()){ $panel->userMenuItems([ - 'account' => MenuItem::make()->url(Pages\MyProfilePage::getUrl(panel: $panel->getId(), - tenant: $tenant)), + 'account' => MenuItem::make()->url(Pages\MyProfilePage::getUrl(panel:$panel->getId(),tenant: $tenant)), ]); } } else { @@ -140,26 +119,17 @@ public function boot(Panel $panel): void } } - /** - * @return \Illuminate\Auth\SessionGuard - */ - public function auth(): \Illuminate\Contracts\Auth\Guard + public function auth() { return Filament::getCurrentPanel()->auth(); } - public function getCurrentPanel(): ?Panel + public function getCurrentPanel() { return Filament::getCurrentPanel(); } - public function myProfile( - bool $condition = true, - bool $shouldRegisterUserMenu = true, - bool $shouldRegisterNavigation = false, - bool $hasAvatars = false, - string $slug = 'my-profile' - ) { + public function myProfile(bool $condition = true, bool $shouldRegisterUserMenu = true, bool $shouldRegisterNavigation = false, bool $hasAvatars = false, string $slug = 'my-profile'){ $this->myProfile = get_defined_vars(); return $this; } @@ -174,10 +144,9 @@ public function slug() return $this->myProfile['slug']; } - public function avatarUploadComponent(Closure $component): static + public function avatarUploadComponent(Closure $component) { $this->avatarUploadComponent = $component; - return $this; } @@ -185,18 +154,12 @@ public function getAvatarUploadComponent() { $fileUpload = Forms\Components\FileUpload::make('avatar_url') ->label(__('filament-breezy::default.fields.avatar'))->avatar(); - - return is_null($this->avatarUploadComponent) ? - $fileUpload : - $this->evaluate( - $this->avatarUploadComponent, - namedInjections: [ - 'fileUpload' => $fileUpload, - ] - ); + return is_null($this->avatarUploadComponent) ? $fileUpload : $this->evaluate($this->avatarUploadComponent, namedInjections:[ + 'fileUpload' => $fileUpload + ]); } - public function myProfileComponents(array $components): static + public function myProfileComponents(array $components) { $this->registeredMyProfileComponents = [ ...$components, @@ -209,31 +172,30 @@ public function myProfileComponents(array $components): static public function getRegisteredMyProfileComponents(): array { $components = collect($this->registeredMyProfileComponents)->filter( - fn(string $component) => $component::canView() + fn (string $component) => $component::canView() )->sortBy( - fn(string $component) => $component::getSort() + fn (string $component) => $component::getSort() ); - if ($this->shouldForceTwoFactor()) { + if ($this->shouldForceTwoFactor()){ $components = $components->only(['two_factor_authentication']); } return $components->all(); } - public function passwordUpdateRules(array|Password $rules, bool $requiresCurrentPassword = true): static + public function passwordUpdateRules(array | Password $rules, bool $requiresCurrentPassword = true) { $this->passwordUpdateRequireCurrent = $requiresCurrentPassword; $this->passwordUpdateRules = $rules; - return $this; } - public function getPasswordUpdateRequiresCurrent(): bool + public function getPasswordUpdateRequiresCurrent() { return $this->passwordUpdateRequireCurrent; } - public function getPasswordUpdateRules(): array + public function getPasswordUpdateRules() { return $this->passwordUpdateRules; } @@ -243,15 +205,11 @@ public function shouldRegisterNavigation(string $key) return $this->{$key}['shouldRegisterNavigation']; } - public function enableTwoFactorAuthentication( - bool $condition = true, - bool $force = false, - string|Closure|array|null $action = TwoFactorPage::class - ): static { + public function enableTwoFactorAuthentication(bool $condition = true, bool $force = false, string | Closure | array | null $action = TwoFactorPage::class) + { $this->twoFactorAuthentication = $condition; $this->forceTwoFactorAuthentication = $force; $this->twoFactorRouteAction = $action; - return $this; } @@ -260,22 +218,22 @@ public function getForceTwoFactorAuthentication(): bool return $this->forceTwoFactorAuthentication; } - public function getTwoFactorRouteAction(): string|Closure|array|null + public function getTwoFactorRouteAction(): string | Closure | array | null { return $this->twoFactorRouteAction; } - public function getEngine(): Google2FA + public function getEngine() { return $this->engine; } - public function generateSecretKey(): string + public function generateSecretKey() { return $this->engine->generateSecretKey(); } - public function getTwoFactorQrCodeSvg(string $url): string + public function getTwoFactorQrCodeSvg(string $url) { $svg = (new Writer( new ImageRenderer( @@ -287,20 +245,12 @@ public function getTwoFactorQrCodeSvg(string $url): string return trim(substr($svg, strpos($svg, "\n") + 1)); } - public function getQrCodeUrl($companyName, $companyEmail, $secret): string + public function getQrCodeUrl($companyName, $companyEmail, $secret) { return $this->engine->getQRCodeUrl($companyName, $companyEmail, $secret); } - /** - * @param string $code - * @param \App\Models\User|null $user - * - * @throws \Exception|\Psr\SimpleCache\InvalidArgumentException - * - * @return bool - */ - public function verify(string $code, ?Authenticatable $user = null): bool + public function verify(string $code, ?Authenticatable $user = null) { if (is_null($user)) { $user = Filament::auth()->user(); @@ -327,10 +277,10 @@ public function shouldForceTwoFactor(): bool return $this->forceTwoFactorAuthentication && !$this->auth()->user()?->hasConfirmedTwoFactor(); } - public function enableSanctumTokens(bool $condition = true, ?array $permissions = null): static + public function enableSanctumTokens(bool $condition = true,?array $permissions = null) { $this->sanctumTokens = $condition; - if (!is_null($permissions)) { + if (!is_null($permissions)){ $this->sanctumPermissions = $permissions; } return $this; @@ -338,9 +288,10 @@ public function enableSanctumTokens(bool $condition = true, ?array $permissions public function getSanctumPermissions(): array { - return collect($this->sanctumPermissions)->mapWithKeys(function ($item, $key) { + return collect($this->sanctumPermissions)->mapWithKeys(function($item,$key){ $key = is_string($key) ? $key : strtolower($item); return [$key => $item]; })->toArray(); } + } diff --git a/src/FilamentBreezyServiceProvider.php b/src/FilamentBreezyServiceProvider.php index 4ba6f68..b0876e6 100644 --- a/src/FilamentBreezyServiceProvider.php +++ b/src/FilamentBreezyServiceProvider.php @@ -17,7 +17,7 @@ public function configurePackage(Package $package): void */ $package ->name('filament-breezy') - ->hasRoute('web') + ->hasRoute("web") ->hasViews() ->hasTranslations() // ->hasMigration('add_two_factor_columns_to_table') diff --git a/src/Models/BreezySession.php b/src/Models/BreezySession.php index eb5f67a..f6bdee7 100644 --- a/src/Models/BreezySession.php +++ b/src/Models/BreezySession.php @@ -1,7 +1,5 @@ ip(); } - /** - * @return \Illuminate\Database\Eloquent\Relations\MorphTo - */ - public function authenticatable(): \Illuminate\Database\Eloquent\Relations\MorphTo + public function authenticatable() { return $this->morphTo(); } - public function confirm(): static + public function confirm() { event(new LoginSuccess($this->authenticatable)); $this->update([ 'two_factor_confirmed_at' => now() ]); - - return $this; } - public function expire(): static + public function expire() { $this->update([ - 'expires_at' => now()->subMinute() + 'expires_at' => now()->subMinutes(1) ]); - - return $this; } - public function setSession(?int $lifetime = null): void + public function setSession(?int $lifetime = null) { - // /** @var \Jeffgreco13\FilamentBreezy\BreezyCore $breezyCore */ - // $breezyCore = filament('filament-breezy'); - session(['breezy_session_id' => md5($this->id)]); // $this->update([ - // 'panel_id' => $breezyCore->getCurrentPanel()->getId(), - // 'guard' => $breezyCore->getCurrentPanel()->getAuthGuard(), + // 'expires_at' => now()->addSeconds($lifetime ?? filament('filament-breezy')->getTwoFactorSessionLifetime()) + // ]); + // PLUS + // $this->update([ // 'ip_address' => $this->ipAddress(), // 'user_agent' => $this->userAgent(), - // 'expires_at' => now()->addSeconds($lifetime ?? 3600) + // 'expires_at' => now()->addSeconds($lifetime ?? filament('filament-breezy')->getTwoFactorSessionLifetime()) // ]); } diff --git a/src/Traits/TwoFactorAuthenticatable.php b/src/Traits/TwoFactorAuthenticatable.php index 80cc5e8..bd798bc 100644 --- a/src/Traits/TwoFactorAuthenticatable.php +++ b/src/Traits/TwoFactorAuthenticatable.php @@ -3,109 +3,100 @@ namespace Jeffgreco13\FilamentBreezy\Traits; use Illuminate\Support\Str; +use Filament\Facades\Filament; use Illuminate\Support\Collection; use Illuminate\Database\Eloquent\Casts\Attribute; -use Illuminate\Database\Eloquent\Model; use Jeffgreco13\FilamentBreezy\Models\BreezySession; -/** - * @mixin \App\Models\User|\Illuminate\Foundation\Auth\User - */ trait TwoFactorAuthenticatable { - public static function bootTwoFactorAuthenticatable(): void + public static function bootTwoFactorAuthenticatable() { - static::deleting(static function (Model $model): void { + static::deleting(function ($model) { $model->breezySessions()->get()->each->delete(); }); } - - public function initializeTwoFactorAuthenticatable(): void + public function initializeTwoFactorAuthenticatable() { - $this->with[] = 'breezySessions'; + $this->with[] = "breezySessions"; } - public function breezySessions(): \Illuminate\Database\Eloquent\Relations\MorphMany + public function breezySessions() { - return $this->morphMany(BreezySession::class, 'authenticatable'); + return $this->morphMany(BreezySession::class,'authenticatable'); } public function breezySession(): Attribute { return Attribute::make( - get: fn() => $this->breezySessions()->latest()->first() + get: fn() => $this->breezySessions->first() ); } public function hasEnabledTwoFactor(): bool { - return $this->breezy_session?->is_enabled ?? false; + return $this->breezySession?->is_enabled ?? false; } public function hasConfirmedTwoFactor(): bool { - return $this->breezy_session?->is_confirmed ?? false; + return $this->breezySession?->is_confirmed ?? false; } public function twoFactorRecoveryCodes(): Attribute { return Attribute::make( - get: fn() => $this->breezy_session ? - json_decode( - decrypt($this->breezy_session->two_factor_recovery_codes), - true - ) : null + get: fn () => $this->breezySession ? json_decode(decrypt( + $this->breezySession->two_factor_recovery_codes),true) : null ); } public function twoFactorSecret(): Attribute { return Attribute::make( - get: fn() => $this->breezy_session?->two_factor_secret + get: fn () => $this->breezySession?->two_factor_secret ); } - public function enableTwoFactorAuthentication(): void + public function enableTwoFactorAuthentication() { $twoFactorData = [ 'two_factor_secret' => encrypt(filament('filament-breezy')->getEngine()->generateSecretKey()), 'two_factor_recovery_codes' => $this->generateRecoveryCodes(), ]; - if ($this->breezy_session) { + if ($this->breezy_session){ $this->disableTwoFactorAuthentication(); // Delete the session if it exists. } - $this->breezy_session = $this->breezySessions()->create($twoFactorData); + $this->breezySession = $this->breezySessions()->create($twoFactorData); $this->load('breezySessions'); } - public function disableTwoFactorAuthentication(): void + public function disableTwoFactorAuthentication() { - $this->breezy_session?->delete(); + $this->breezySession?->delete(); } - public function confirmTwoFactorAuthentication(): void + public function confirmTwoFactorAuthentication() { - $this->breezy_session?->confirm(); + $this->breezySession?->confirm(); $this->setTwoFactorSession(); } - public function setTwoFactorSession(?int $lifetime = null): void + public function setTwoFactorSession(?int $lifetime=null) { - $this->breezy_session->setSession($lifetime); + $this->breezySession->setSession($lifetime); } public function hasValidTwoFactorSession(): bool { - return $this->breezy_session?->is_valid ?? false; + return $this->breezySession?->is_valid ?? false; } - public function generateRecoveryCodes(): string + public function generateRecoveryCodes() { - return encrypt( - json_encode( - Collection::times(8, static fn() => Str::random(10) . '-' . Str::random(10))->all() - ) - ); + return encrypt(json_encode(Collection::times(8, function () { + return Str::random(10) . '-' . Str::random(10);; + })->all())); } public function getTwoFactorQrCodeUrl() @@ -113,16 +104,15 @@ public function getTwoFactorQrCodeUrl() return filament('filament-breezy')->getQrCodeUrl( config('app.name'), $this->email, - decrypt($this->breezy_session->two_factor_secret) + decrypt($this->breezySession->two_factor_secret) ); } - public function reGenerateRecoveryCodes(): static + public function reGenerateRecoveryCodes() { $this->breezy_session->forceFill([ 'two_factor_recovery_codes' => $this->generateRecoveryCodes(), ])->save(); - - return $this; } + }