diff --git a/app/Filament/Pages/Installer/PanelInstaller.php b/app/Filament/Pages/Installer/PanelInstaller.php index fba27eade8..bad77920d0 100644 --- a/app/Filament/Pages/Installer/PanelInstaller.php +++ b/app/Filament/Pages/Installer/PanelInstaller.php @@ -3,12 +3,12 @@ namespace App\Filament\Pages\Installer; use App\Filament\Pages\Dashboard; -use App\Filament\Pages\Installer\Steps\AdminUserStep; -use App\Filament\Pages\Installer\Steps\CompletedStep; +use App\Filament\Pages\Installer\Steps\CacheStep; use App\Filament\Pages\Installer\Steps\DatabaseStep; use App\Filament\Pages\Installer\Steps\EnvironmentStep; -use App\Filament\Pages\Installer\Steps\RedisStep; +use App\Filament\Pages\Installer\Steps\QueueStep; use App\Filament\Pages\Installer\Steps\RequirementsStep; +use App\Filament\Pages\Installer\Steps\SessionStep; use App\Models\User; use App\Services\Users\UserCreationService; use App\Traits\CheckMigrationsTrait; @@ -19,7 +19,6 @@ use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; use Filament\Forms\Form; -use Filament\Forms\Get; use Filament\Notifications\Notification; use Filament\Pages\SimplePage; use Filament\Support\Enums\MaxWidth; @@ -43,8 +42,6 @@ class PanelInstaller extends SimplePage implements HasForms protected static string $view = 'filament.pages.installer'; - private User $user; - public function getMaxWidth(): MaxWidth|string { return MaxWidth::SevenExtraLarge; @@ -70,10 +67,9 @@ protected function getFormSchema(): array RequirementsStep::make(), EnvironmentStep::make($this), DatabaseStep::make($this), - RedisStep::make($this) - ->hidden(fn (Get $get) => $get('env_general.SESSION_DRIVER') != 'redis' && $get('env_general.QUEUE_CONNECTION') != 'redis' && $get('env_general.CACHE_STORE') != 'redis'), - AdminUserStep::make($this), - CompletedStep::make(), + CacheStep::make($this), + QueueStep::make($this), + SessionStep::make(), ]) ->persistStepInQueryString() ->nextAction(fn (Action $action) => $action->keyBindings('enter')) @@ -95,14 +91,17 @@ protected function getFormStatePath(): ?string return 'data'; } - public function submit(): Redirector|RedirectResponse + public function submit(UserCreationService $userCreationService): Redirector|RedirectResponse { // Disable installer $this->writeToEnvironment(['APP_INSTALLED' => 'true']); - // Login user - $this->user ??= User::all()->filter(fn ($user) => $user->isRootAdmin())->first(); - auth()->guard()->login($this->user, true); + // Create admin user & login + $user = $this->createAdminUser($userCreationService); + auth()->guard()->login($user, true); + + // Write session data at the very end to avoid "page expired" errors + $this->writeToEnv('env_session'); // Redirect to admin panel return redirect(Dashboard::getUrl()); @@ -112,6 +111,7 @@ public function writeToEnv(string $key): void { try { $variables = array_get($this->data, $key); + $variables = array_filter($variables); // Filter array to remove NULL values $this->writeToEnvironment($variables); } catch (Exception $exception) { report($exception); @@ -161,12 +161,13 @@ public function runMigrations(string $driver): void } } - public function createAdminUser(UserCreationService $userCreationService): void + public function createAdminUser(UserCreationService $userCreationService): User { try { $userData = array_get($this->data, 'user'); $userData['root_admin'] = true; - $this->user = $userCreationService->handle($userData); + + return $userCreationService->handle($userData); } catch (Exception $exception) { report($exception); diff --git a/app/Filament/Pages/Installer/Steps/AdminUserStep.php b/app/Filament/Pages/Installer/Steps/AdminUserStep.php deleted file mode 100644 index 5bdfe38d94..0000000000 --- a/app/Filament/Pages/Installer/Steps/AdminUserStep.php +++ /dev/null @@ -1,34 +0,0 @@ -label('Admin User') - ->schema([ - TextInput::make('user.email') - ->label('Admin E-Mail') - ->required() - ->email() - ->placeholder('admin@example.com'), - TextInput::make('user.username') - ->label('Admin Username') - ->required() - ->placeholder('admin'), - TextInput::make('user.password') - ->label('Admin Password') - ->required() - ->password() - ->revealable(), - ]) - ->afterValidation(fn (UserCreationService $service) => $installer->createAdminUser($service)); - } -} diff --git a/app/Filament/Pages/Installer/Steps/CacheStep.php b/app/Filament/Pages/Installer/Steps/CacheStep.php new file mode 100644 index 0000000000..71b3994d47 --- /dev/null +++ b/app/Filament/Pages/Installer/Steps/CacheStep.php @@ -0,0 +1,123 @@ + 'Filesystem', + 'redis' => 'Redis', + ]; + + public static function make(PanelInstaller $installer): Step + { + return Step::make('cache') + ->label('Cache') + ->columns() + ->schema([ + ToggleButtons::make('env_cache.CACHE_STORE') + ->label('Cache Driver') + ->hintIcon('tabler-question-mark') + ->hintIconTooltip('The driver used for caching. We recommend "Filesystem".') + ->required() + ->inline() + ->options(self::CACHE_DRIVERS) + ->default(config('cache.default')) + ->columnSpanFull() + ->live() + ->afterStateUpdated(function ($state, Set $set, Get $get) { + if ($state !== 'redis') { + $set('env_cache.REDIS_HOST', null); + $set('env_cache.REDIS_PORT', null); + $set('env_cache.REDIS_USERNAME', null); + $set('env_cache.REDIS_PASSWORD', null); + } else { + $set('env_cache.REDIS_HOST', $get('env_cache.REDIS_HOST') ?? '127.0.0.1'); + $set('env_cache.REDIS_PORT', $get('env_cache.REDIS_PORT') ?? '6379'); + $set('env_cache.REDIS_USERNAME', null); + } + }), + TextInput::make('env_cache.REDIS_HOST') + ->label('Redis Host') + ->placeholder('127.0.0.1') + ->hintIcon('tabler-question-mark') + ->hintIconTooltip('The host of your redis server. Make sure it is reachable.') + ->required(fn (Get $get) => $get('env_cache.CACHE_STORE') === 'redis') + ->default(fn (Get $get) => $get('env_cache.CACHE_STORE') === 'redis' ? config('database.redis.default.host') : null) + ->visible(fn (Get $get) => $get('env_cache.CACHE_STORE') === 'redis'), + TextInput::make('env_cache.REDIS_PORT') + ->label('Redis Port') + ->placeholder('6379') + ->hintIcon('tabler-question-mark') + ->hintIconTooltip('The port of your redis server.') + ->required(fn (Get $get) => $get('env_cache.CACHE_STORE') === 'redis') + ->default(fn (Get $get) => $get('env_cache.CACHE_STORE') === 'redis' ? config('database.redis.default.port') : null) + ->visible(fn (Get $get) => $get('env_cache.CACHE_STORE') === 'redis'), + TextInput::make('env_cache.REDIS_USERNAME') + ->label('Redis Username') + ->hintIcon('tabler-question-mark') + ->hintIconTooltip('The name of your redis user. Can be empty') + ->default(fn (Get $get) => $get('env_cache.CACHE_STORE') === 'redis' ? config('database.redis.default.username') : null) + ->visible(fn (Get $get) => $get('env_cache.CACHE_STORE') === 'redis'), + TextInput::make('env_cache.REDIS_PASSWORD') + ->label('Redis Password') + ->hintIcon('tabler-question-mark') + ->hintIconTooltip('The password for your redis user. Can be empty.') + ->password() + ->revealable() + ->default(fn (Get $get) => $get('env_cache.CACHE_STORE') === 'redis' ? config('database.redis.default.password') : null) + ->visible(fn (Get $get) => $get('env_cache.CACHE_STORE') === 'redis'), + ]) + ->afterValidation(function (Get $get, Application $app) use ($installer) { + $driver = $get('env_cache.CACHE_STORE'); + + if (!self::testConnection($app, $driver, $get('env_cache.REDIS_HOST'), $get('env_cache.REDIS_PORT'), $get('env_cache.REDIS_USERNAME'), $get('env_cache.REDIS_PASSWORD'))) { + throw new Halt('Redis connection failed'); + } + + $installer->writeToEnv('env_cache'); + }); + } + + private static function testConnection(Application $app, string $driver, ?string $host, null|string|int $port, ?string $username, ?string $password): bool + { + if ($driver !== 'redis') { + return true; + } + + try { + $redis = new RedisManager($app, 'predis', [ + 'default' => [ + 'host' => $host, + 'port' => $port, + 'username' => $username, + 'password' => $password, + ], + ]); + + $redis->connection()->command('ping'); + } catch (Exception $exception) { + Notification::make() + ->title('Redis connection failed') + ->body($exception->getMessage()) + ->danger() + ->send(); + + return false; + } + + return true; + } +} diff --git a/app/Filament/Pages/Installer/Steps/CompletedStep.php b/app/Filament/Pages/Installer/Steps/CompletedStep.php deleted file mode 100644 index 50f9a780cf..0000000000 --- a/app/Filament/Pages/Installer/Steps/CompletedStep.php +++ /dev/null @@ -1,34 +0,0 @@ -label('Setup complete') - ->schema([ - Placeholder::make('') - ->content(new HtmlString('The setup is nearly complete!
As last step you need to create a new cronjob that runs every minute to process specific tasks, such as session cleanup and scheduled tasks, and also create a queue worker.')), - TextInput::make('crontab') - ->label(new HtmlString('Run the following command to setup your crontab. Note that www-data is your webserver user. On some systems this username might be different!')) - ->disabled() - ->hintAction(CopyAction::make()) - ->default('(crontab -l -u www-data 2>/dev/null; echo "* * * * * php ' . base_path() . '/artisan schedule:run >> /dev/null 2>&1") | crontab -u www-data -'), - TextInput::make('queueService') - ->label(new HtmlString('To setup the queue worker service you simply have to run the following command.')) - ->disabled() - ->hintAction(CopyAction::make()) - ->default('sudo php ' . base_path() . '/artisan p:environment:queue-service'), - Placeholder::make('') - ->content('After you finished these two last tasks you can click on "Finish" and use your new panel! Have fun!'), - ]); - } -} diff --git a/app/Filament/Pages/Installer/Steps/DatabaseStep.php b/app/Filament/Pages/Installer/Steps/DatabaseStep.php index 3a4449777e..7ddae24f02 100644 --- a/app/Filament/Pages/Installer/Steps/DatabaseStep.php +++ b/app/Filament/Pages/Installer/Steps/DatabaseStep.php @@ -5,62 +5,92 @@ use App\Filament\Pages\Installer\PanelInstaller; use Exception; use Filament\Forms\Components\TextInput; +use Filament\Forms\Components\ToggleButtons; use Filament\Forms\Components\Wizard\Step; use Filament\Forms\Get; +use Filament\Forms\Set; use Filament\Notifications\Notification; use Filament\Support\Exceptions\Halt; use Illuminate\Support\Facades\DB; class DatabaseStep { + public const DATABASE_DRIVERS = [ + 'sqlite' => 'SQLite', + 'mariadb' => 'MariaDB', + 'mysql' => 'MySQL', + ]; + public static function make(PanelInstaller $installer): Step { return Step::make('database') ->label('Database') ->columns() ->schema([ + ToggleButtons::make('env_database.DB_CONNECTION') + ->label('Database Driver') + ->hintIcon('tabler-question-mark') + ->hintIconTooltip('The driver used for the panel database. We recommend "SQLite".') + ->required() + ->inline() + ->options(self::DATABASE_DRIVERS) + ->default(config('database.default')) + ->live() + ->afterStateUpdated(function ($state, Set $set, Get $get) { + $set('env_database.DB_DATABASE', $state === 'sqlite' ? 'database.sqlite' : 'panel'); + + if ($state === 'sqlite') { + $set('env_database.DB_HOST', null); + $set('env_database.DB_PORT', null); + $set('env_database.DB_USERNAME', null); + $set('env_database.DB_PASSWORD', null); + } else { + $set('env_database.DB_HOST', $get('env_database.DB_HOST') ?? '127.0.0.1'); + $set('env_database.DB_PORT', $get('env_database.DB_PORT') ?? '3306'); + $set('env_database.DB_USERNAME', $get('env_database.DB_USERNAME') ?? 'pelican'); + } + }), TextInput::make('env_database.DB_DATABASE') - ->label(fn (Get $get) => $get('env_general.DB_CONNECTION') === 'sqlite' ? 'Database Path' : 'Database Name') - ->columnSpanFull() + ->label(fn (Get $get) => $get('env_database.DB_CONNECTION') === 'sqlite' ? 'Database Path' : 'Database Name') + ->placeholder(fn (Get $get) => $get('env_database.DB_CONNECTION') === 'sqlite' ? 'database.sqlite' : 'panel') ->hintIcon('tabler-question-mark') - ->hintIconTooltip(fn (Get $get) => $get('env_general.DB_CONNECTION') === 'sqlite' ? 'The path of your .sqlite file relative to the database folder.' : 'The name of the panel database.') + ->hintIconTooltip(fn (Get $get) => $get('env_database.DB_CONNECTION') === 'sqlite' ? 'The path of your .sqlite file relative to the database folder.' : 'The name of the panel database.') ->required() - ->default(fn (Get $get) => env('DB_DATABASE', $get('env_general.DB_CONNECTION') === 'sqlite' ? 'database.sqlite' : 'panel')), + ->default('database.sqlite'), TextInput::make('env_database.DB_HOST') ->label('Database Host') + ->placeholder('127.0.0.1') ->hintIcon('tabler-question-mark') ->hintIconTooltip('The host of your database. Make sure it is reachable.') - ->required(fn (Get $get) => $get('env_general.DB_CONNECTION') !== 'sqlite') - ->default(fn (Get $get) => $get('env_general.DB_CONNECTION') !== 'sqlite' ? env('DB_HOST', '127.0.0.1') : null) - ->hidden(fn (Get $get) => $get('env_general.DB_CONNECTION') === 'sqlite'), + ->required(fn (Get $get) => $get('env_database.DB_CONNECTION') !== 'sqlite') + ->hidden(fn (Get $get) => $get('env_database.DB_CONNECTION') === 'sqlite'), TextInput::make('env_database.DB_PORT') ->label('Database Port') + ->placeholder('3306') ->hintIcon('tabler-question-mark') ->hintIconTooltip('The port of your database.') - ->required(fn (Get $get) => $get('env_general.DB_CONNECTION') !== 'sqlite') ->numeric() ->minValue(1) ->maxValue(65535) - ->default(fn (Get $get) => $get('env_general.DB_CONNECTION') !== 'sqlite' ? env('DB_PORT', 3306) : null) - ->hidden(fn (Get $get) => $get('env_general.DB_CONNECTION') === 'sqlite'), + ->required(fn (Get $get) => $get('env_database.DB_CONNECTION') !== 'sqlite') + ->hidden(fn (Get $get) => $get('env_database.DB_CONNECTION') === 'sqlite'), TextInput::make('env_database.DB_USERNAME') ->label('Database Username') + ->placeholder('pelican') ->hintIcon('tabler-question-mark') ->hintIconTooltip('The name of your database user.') - ->required(fn (Get $get) => $get('env_general.DB_CONNECTION') !== 'sqlite') - ->default(fn (Get $get) => $get('env_general.DB_CONNECTION') !== 'sqlite' ? env('DB_USERNAME', 'pelican') : null) - ->hidden(fn (Get $get) => $get('env_general.DB_CONNECTION') === 'sqlite'), + ->required(fn (Get $get) => $get('env_database.DB_CONNECTION') !== 'sqlite') + ->hidden(fn (Get $get) => $get('env_database.DB_CONNECTION') === 'sqlite'), TextInput::make('env_database.DB_PASSWORD') ->label('Database Password') ->hintIcon('tabler-question-mark') ->hintIconTooltip('The password of your database user. Can be empty.') ->password() ->revealable() - ->default(fn (Get $get) => $get('env_general.DB_CONNECTION') !== 'sqlite' ? env('DB_PASSWORD') : null) - ->hidden(fn (Get $get) => $get('env_general.DB_CONNECTION') === 'sqlite'), + ->hidden(fn (Get $get) => $get('env_database.DB_CONNECTION') === 'sqlite'), ]) ->afterValidation(function (Get $get) use ($installer) { - $driver = $get('env_general.DB_CONNECTION'); + $driver = $get('env_database.DB_CONNECTION'); if (!self::testConnection($driver, $get('env_database.DB_HOST'), $get('env_database.DB_PORT'), $get('env_database.DB_DATABASE'), $get('env_database.DB_USERNAME'), $get('env_database.DB_PASSWORD'))) { throw new Halt('Database connection failed'); diff --git a/app/Filament/Pages/Installer/Steps/EnvironmentStep.php b/app/Filament/Pages/Installer/Steps/EnvironmentStep.php index 5df2ecd40a..0c54069126 100644 --- a/app/Filament/Pages/Installer/Steps/EnvironmentStep.php +++ b/app/Filament/Pages/Installer/Steps/EnvironmentStep.php @@ -3,40 +3,12 @@ namespace App\Filament\Pages\Installer\Steps; use App\Filament\Pages\Installer\PanelInstaller; -use App\Traits\EnvironmentWriterTrait; +use Filament\Forms\Components\Fieldset; use Filament\Forms\Components\TextInput; -use Filament\Forms\Components\ToggleButtons; use Filament\Forms\Components\Wizard\Step; -use Filament\Forms\Set; class EnvironmentStep { - use EnvironmentWriterTrait; - - public const CACHE_DRIVERS = [ - 'file' => 'Filesystem', - 'redis' => 'Redis', - ]; - - public const SESSION_DRIVERS = [ - 'file' => 'Filesystem', - 'database' => 'Database', - 'cookie' => 'Cookie', - 'redis' => 'Redis', - ]; - - public const QUEUE_DRIVERS = [ - 'database' => 'Database', - 'sync' => 'Sync', - 'redis' => 'Redis', - ]; - - public const DATABASE_DRIVERS = [ - 'sqlite' => 'SQLite', - 'mariadb' => 'MariaDB', - 'mysql' => 'MySQL', - ]; - public static function make(PanelInstaller $installer): Step { return Step::make('environment') @@ -54,44 +26,26 @@ public static function make(PanelInstaller $installer): Step ->hintIcon('tabler-question-mark') ->hintIconTooltip('This will be the URL you access your Panel from.') ->required() - ->default(url('')) - ->live() - ->afterStateUpdated(fn ($state, Set $set) => $set('env_general.SESSION_SECURE_COOKIE', str_starts_with($state, 'https://') ? 'true' : 'false')), - TextInput::make('env_general.SESSION_SECURE_COOKIE') - ->hidden() - ->default(str_starts_with(url(''), 'https://') ? 'true' : 'false'), - ToggleButtons::make('env_general.CACHE_STORE') - ->label('Cache Driver') - ->hintIcon('tabler-question-mark') - ->hintIconTooltip('The driver used for caching. We recommend "Filesystem".') - ->required() - ->inline() - ->options(self::CACHE_DRIVERS) - ->default(config('cache.default', 'file')), - ToggleButtons::make('env_general.SESSION_DRIVER') - ->label('Session Driver') - ->hintIcon('tabler-question-mark') - ->hintIconTooltip('The driver used for storing sessions. We recommend "Filesystem" or "Database".') - ->required() - ->inline() - ->options(self::SESSION_DRIVERS) - ->default(config('session.driver', 'file')), - ToggleButtons::make('env_general.QUEUE_CONNECTION') - ->label('Queue Driver') - ->hintIcon('tabler-question-mark') - ->hintIconTooltip('The driver used for handling queues. We recommend "Database".') - ->required() - ->inline() - ->options(self::QUEUE_DRIVERS) - ->default(config('queue.default', 'database')), - ToggleButtons::make('env_general.DB_CONNECTION') - ->label('Database Driver') - ->hintIcon('tabler-question-mark') - ->hintIconTooltip('The driver used for the panel database. We recommend "SQLite".') - ->required() - ->inline() - ->options(self::DATABASE_DRIVERS) - ->default(config('database.default', 'sqlite')), + ->default(url('')), + Fieldset::make('adminuser') + ->label('Admin User') + ->columns(3) + ->schema([ + TextInput::make('user.email') + ->label('E-Mail') + ->required() + ->email() + ->placeholder('admin@example.com'), + TextInput::make('user.username') + ->label('Username') + ->required() + ->placeholder('admin'), + TextInput::make('user.password') + ->label('Password') + ->required() + ->password() + ->revealable(), + ]), ]) ->afterValidation(fn () => $installer->writeToEnv('env_general')); } diff --git a/app/Filament/Pages/Installer/Steps/QueueStep.php b/app/Filament/Pages/Installer/Steps/QueueStep.php new file mode 100644 index 0000000000..4e6c065d0e --- /dev/null +++ b/app/Filament/Pages/Installer/Steps/QueueStep.php @@ -0,0 +1,64 @@ + 'Database', + 'redis' => 'Redis', + 'sync' => 'Sync', + ]; + + public static function make(PanelInstaller $installer): Step + { + return Step::make('queue') + ->label('Queue') + ->columns() + ->schema([ + ToggleButtons::make('env_queue.QUEUE_CONNECTION') + ->label('Queue Driver') + ->hintIcon('tabler-question-mark') + ->hintIconTooltip('The driver used for handling queues. We recommend "Database".') + ->required() + ->inline() + ->options(self::QUEUE_DRIVERS) + ->disableOptionWhen(fn ($value, Get $get) => $value === 'redis' && $get('env_cache.CACHE_STORE') !== 'redis') + ->default(config('queue.default')), + Toggle::make('done') + ->label('I have done both steps below.') + ->accepted(fn () => !file_exists('/.dockerenv')) + ->inline(false) + ->validationMessages([ + 'accepted' => 'You need to do both steps before continuing!', + ]) + ->hidden(fn () => file_exists('/.dockerenv')), + TextInput::make('crontab') + ->label(new HtmlString('Run the following command to set up your crontab. Note that www-data is your webserver user. On some systems this username might be different!')) + ->disabled() + ->hintAction(CopyAction::make()) + ->default('(crontab -l -u www-data 2>/dev/null; echo "* * * * * php ' . base_path() . '/artisan schedule:run >> /dev/null 2>&1") | crontab -u www-data -') + ->hidden(fn () => file_exists('/.dockerenv')) + ->columnSpanFull(), + TextInput::make('queueService') + ->label(new HtmlString('To setup the queue worker service you simply have to run the following command.')) + ->disabled() + ->hintAction(CopyAction::make()) + ->default('sudo php ' . base_path() . '/artisan p:environment:queue-service') + ->hidden(fn () => file_exists('/.dockerenv')) + ->columnSpanFull(), + ]) + ->afterValidation(function () use ($installer) { + $installer->writeToEnv('env_queue'); + }); + } +} diff --git a/app/Filament/Pages/Installer/Steps/RedisStep.php b/app/Filament/Pages/Installer/Steps/RedisStep.php deleted file mode 100644 index df07e98e4c..0000000000 --- a/app/Filament/Pages/Installer/Steps/RedisStep.php +++ /dev/null @@ -1,85 +0,0 @@ -label('Redis') - ->columns() - ->schema([ - TextInput::make('env_redis.REDIS_HOST') - ->label('Redis Host') - ->hintIcon('tabler-question-mark') - ->hintIconTooltip('The host of your redis server. Make sure it is reachable.') - ->required() - ->default(config('database.redis.default.host')), - TextInput::make('env_redis.REDIS_PORT') - ->label('Redis Port') - ->hintIcon('tabler-question-mark') - ->hintIconTooltip('The port of your redis server.') - ->required() - ->default(config('database.redis.default.port')), - TextInput::make('env_redis.REDIS_USERNAME') - ->label('Redis Username') - ->hintIcon('tabler-question-mark') - ->hintIconTooltip('The name of your redis user. Can be empty') - ->default(config('database.redis.default.username')), - TextInput::make('env_redis.REDIS_PASSWORD') - ->label('Redis Password') - ->hintIcon('tabler-question-mark') - ->hintIconTooltip('The password for your redis user. Can be empty.') - ->password() - ->revealable() - ->default(config('database.redis.default.password')), - ]) - ->afterValidation(function (Get $get, Application $app) use ($installer) { - if (!self::testConnection($app, $get('env_redis.REDIS_HOST'), $get('env_redis.REDIS_PORT'), $get('env_redis.REDIS_USERNAME'), $get('env_redis.REDIS_PASSWORD'))) { - throw new Halt('Redis connection failed'); - } - - $installer->writeToEnv('env_redis'); - }); - } - - private static function testConnection(Application $app, string $host, null|string|int $port, ?string $username, ?string $password): bool - { - try { - $redis = new RedisManager($app, 'predis', [ - 'default' => [ - 'host' => $host, - 'port' => $port, - 'username' => $username, - 'password' => $password, - ], - ]); - - $redis->connection()->command('ping'); - } catch (Exception $exception) { - Notification::make() - ->title('Redis connection failed') - ->body($exception->getMessage()) - ->danger() - ->send(); - - return false; - } - - return true; - } -} diff --git a/app/Filament/Pages/Installer/Steps/SessionStep.php b/app/Filament/Pages/Installer/Steps/SessionStep.php new file mode 100644 index 0000000000..ceb9a77ae0 --- /dev/null +++ b/app/Filament/Pages/Installer/Steps/SessionStep.php @@ -0,0 +1,38 @@ + 'Filesystem', + 'database' => 'Database', + 'cookie' => 'Cookie', + 'redis' => 'Redis', + ]; + + public static function make(): Step + { + return Step::make('session') + ->label('Session') + ->schema([ + ToggleButtons::make('env_session.SESSION_DRIVER') + ->label('Session Driver') + ->hintIcon('tabler-question-mark') + ->hintIconTooltip('The driver used for storing sessions. We recommend "Filesystem" or "Database".') + ->required() + ->inline() + ->options(self::SESSION_DRIVERS) + ->disableOptionWhen(fn ($value, Get $get) => $value === 'redis' && $get('env_cache.CACHE_STORE') !== 'redis') + ->default(config('session.driver')), + TextInput::make('env_session.SESSION_SECURE_COOKIE') + ->hidden() + ->default(request()->isSecure()), + ]); + } +}