mirror of
https://github.com/pelican-dev/panel.git
synced 2025-05-20 11:04:45 +02:00
Web Installer (#504)
* simplify setup command * add installer page * add route for installer * adjust gitignore * set colors globally * add "unsaved data changes" alert * add helper method to check if panel is installed * make nicer * redis username isn't required * bring back db settings command * store current date in "installed" file * only redirect if install was successfull * remove fpm requirement * change "installed" marker to env variable * improve requirements step * add commands to change cache, queue or session drivers respectively * removed `grouped` for better mobile view
This commit is contained in:
parent
18cf6e9338
commit
496eaaaf83
@ -4,6 +4,7 @@ APP_KEY=
|
|||||||
APP_TIMEZONE=UTC
|
APP_TIMEZONE=UTC
|
||||||
APP_URL=http://panel.test
|
APP_URL=http://panel.test
|
||||||
APP_LOCALE=en
|
APP_LOCALE=en
|
||||||
|
APP_INSTALLED=false
|
||||||
|
|
||||||
LOG_CHANNEL=daily
|
LOG_CHANNEL=daily
|
||||||
LOG_STACK=single
|
LOG_STACK=single
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
namespace App\Console\Commands\Environment;
|
namespace App\Console\Commands\Environment;
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Contracts\Console\Kernel;
|
|
||||||
use App\Traits\Commands\EnvironmentWriterTrait;
|
use App\Traits\Commands\EnvironmentWriterTrait;
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
|
||||||
@ -11,147 +10,41 @@ class AppSettingsCommand extends Command
|
|||||||
{
|
{
|
||||||
use EnvironmentWriterTrait;
|
use EnvironmentWriterTrait;
|
||||||
|
|
||||||
public const CACHE_DRIVERS = [
|
|
||||||
'file' => 'Filesystem (recommended)',
|
|
||||||
'redis' => 'Redis',
|
|
||||||
];
|
|
||||||
|
|
||||||
public const SESSION_DRIVERS = [
|
|
||||||
'file' => 'Filesystem (recommended)',
|
|
||||||
'redis' => 'Redis',
|
|
||||||
'database' => 'Database',
|
|
||||||
'cookie' => 'Cookie',
|
|
||||||
];
|
|
||||||
|
|
||||||
public const QUEUE_DRIVERS = [
|
|
||||||
'database' => 'Database (recommended)',
|
|
||||||
'redis' => 'Redis',
|
|
||||||
'sync' => 'Synchronous',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $description = 'Configure basic environment settings for the Panel.';
|
protected $description = 'Configure basic environment settings for the Panel.';
|
||||||
|
|
||||||
protected $signature = 'p:environment:setup
|
protected $signature = 'p:environment:setup
|
||||||
{--url= : The URL that this Panel is running on.}
|
{--url= : The URL that this Panel is running on.}';
|
||||||
{--cache= : The cache driver backend to use.}
|
|
||||||
{--session= : The session driver backend to use.}
|
|
||||||
{--queue= : The queue driver backend to use.}
|
|
||||||
{--redis-host= : Redis host to use for connections.}
|
|
||||||
{--redis-pass= : Password used to connect to redis.}
|
|
||||||
{--redis-port= : Port to connect to redis over.}';
|
|
||||||
|
|
||||||
protected array $variables = [];
|
protected array $variables = [];
|
||||||
|
|
||||||
/**
|
public function handle(): void
|
||||||
* AppSettingsCommand constructor.
|
|
||||||
*/
|
|
||||||
public function __construct(private Kernel $console)
|
|
||||||
{
|
{
|
||||||
parent::__construct();
|
$path = base_path('.env');
|
||||||
}
|
if (!file_exists($path)) {
|
||||||
|
$this->comment('Copying example .env file');
|
||||||
|
copy($path . '.example', $path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config('app.key')) {
|
||||||
|
$this->comment('Generating app key');
|
||||||
|
Artisan::call('key:generate');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle command execution.
|
|
||||||
*
|
|
||||||
* @throws \App\Exceptions\PanelException
|
|
||||||
*/
|
|
||||||
public function handle(): int
|
|
||||||
{
|
|
||||||
$this->variables['APP_TIMEZONE'] = 'UTC';
|
$this->variables['APP_TIMEZONE'] = 'UTC';
|
||||||
|
|
||||||
$this->output->comment(__('commands.appsettings.comment.url'));
|
|
||||||
$this->variables['APP_URL'] = $this->option('url') ?? $this->ask(
|
$this->variables['APP_URL'] = $this->option('url') ?? $this->ask(
|
||||||
'Application URL',
|
'Application URL',
|
||||||
config('app.url', 'https://example.com')
|
config('app.url', 'https://example.com')
|
||||||
);
|
);
|
||||||
|
|
||||||
$selected = config('cache.default', 'file');
|
|
||||||
$this->variables['CACHE_STORE'] = $this->option('cache') ?? $this->choice(
|
|
||||||
'Cache Driver',
|
|
||||||
self::CACHE_DRIVERS,
|
|
||||||
array_key_exists($selected, self::CACHE_DRIVERS) ? $selected : null
|
|
||||||
);
|
|
||||||
|
|
||||||
$selected = config('session.driver', 'file');
|
|
||||||
$this->variables['SESSION_DRIVER'] = $this->option('session') ?? $this->choice(
|
|
||||||
'Session Driver',
|
|
||||||
self::SESSION_DRIVERS,
|
|
||||||
array_key_exists($selected, self::SESSION_DRIVERS) ? $selected : null
|
|
||||||
);
|
|
||||||
|
|
||||||
$selected = config('queue.default', 'database');
|
|
||||||
$this->variables['QUEUE_CONNECTION'] = $this->option('queue') ?? $this->choice(
|
|
||||||
'Queue Driver',
|
|
||||||
self::QUEUE_DRIVERS,
|
|
||||||
array_key_exists($selected, self::QUEUE_DRIVERS) ? $selected : null
|
|
||||||
);
|
|
||||||
|
|
||||||
// Make sure session cookies are set as "secure" when using HTTPS
|
// Make sure session cookies are set as "secure" when using HTTPS
|
||||||
if (str_starts_with($this->variables['APP_URL'], 'https://')) {
|
if (str_starts_with($this->variables['APP_URL'], 'https://')) {
|
||||||
$this->variables['SESSION_SECURE_COOKIE'] = 'true';
|
$this->variables['SESSION_SECURE_COOKIE'] = 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
$redisUsed = count(collect($this->variables)->filter(function ($item) {
|
$this->comment('Writing variables to .env file');
|
||||||
return $item === 'redis';
|
|
||||||
})) !== 0;
|
|
||||||
|
|
||||||
if ($redisUsed) {
|
|
||||||
$this->requestRedisSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
$path = base_path('.env');
|
|
||||||
if (!file_exists($path)) {
|
|
||||||
copy($path . '.example', $path);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->writeToEnvironment($this->variables);
|
$this->writeToEnvironment($this->variables);
|
||||||
|
|
||||||
if (!config('app.key')) {
|
$this->info("Setup complete. Vist {$this->variables['APP_URL']}/installer to complete the installation");
|
||||||
Artisan::call('key:generate');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->variables['QUEUE_CONNECTION'] !== 'sync') {
|
|
||||||
$this->call('p:environment:queue-service', [
|
|
||||||
'--use-redis' => $redisUsed,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->info($this->console->output());
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request redis connection details and verify them.
|
|
||||||
*/
|
|
||||||
private function requestRedisSettings(): void
|
|
||||||
{
|
|
||||||
$this->output->note(__('commands.appsettings.redis.note'));
|
|
||||||
$this->variables['REDIS_HOST'] = $this->option('redis-host') ?? $this->ask(
|
|
||||||
'Redis Host',
|
|
||||||
config('database.redis.default.host')
|
|
||||||
);
|
|
||||||
|
|
||||||
$askForRedisPassword = true;
|
|
||||||
if (!empty(config('database.redis.default.password'))) {
|
|
||||||
$this->variables['REDIS_PASSWORD'] = config('database.redis.default.password');
|
|
||||||
$askForRedisPassword = $this->confirm('It seems a password is already defined for Redis, would you like to change it?');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($askForRedisPassword) {
|
|
||||||
$this->output->comment(__('commands.appsettings.redis.comment'));
|
|
||||||
$this->variables['REDIS_PASSWORD'] = $this->option('redis-pass') ?? $this->output->askHidden(
|
|
||||||
'Redis Password'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($this->variables['REDIS_PASSWORD'])) {
|
|
||||||
$this->variables['REDIS_PASSWORD'] = 'null';
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->variables['REDIS_PORT'] = $this->option('redis-port') ?? $this->ask(
|
|
||||||
'Redis Port',
|
|
||||||
config('database.redis.default.port')
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
68
app/Console/Commands/Environment/CacheSettingsCommand.php
Normal file
68
app/Console/Commands/Environment/CacheSettingsCommand.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Environment;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Contracts\Console\Kernel;
|
||||||
|
use App\Traits\Commands\EnvironmentWriterTrait;
|
||||||
|
use App\Traits\Commands\RequestRedisSettingsTrait;
|
||||||
|
|
||||||
|
class CacheSettingsCommand extends Command
|
||||||
|
{
|
||||||
|
use EnvironmentWriterTrait;
|
||||||
|
use RequestRedisSettingsTrait;
|
||||||
|
|
||||||
|
public const CACHE_DRIVERS = [
|
||||||
|
'file' => 'Filesystem (default)',
|
||||||
|
'database' => 'Database',
|
||||||
|
'redis' => 'Redis',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $description = 'Configure cache settings for the Panel.';
|
||||||
|
|
||||||
|
protected $signature = 'p:environment:cache
|
||||||
|
{--driver= : The cache driver backend to use.}
|
||||||
|
{--redis-host= : Redis host to use for connections.}
|
||||||
|
{--redis-pass= : Password used to connect to redis.}
|
||||||
|
{--redis-port= : Port to connect to redis over.}';
|
||||||
|
|
||||||
|
protected array $variables = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CacheSettingsCommand constructor.
|
||||||
|
*/
|
||||||
|
public function __construct(private Kernel $console)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle command execution.
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
$selected = config('cache.default', 'file');
|
||||||
|
$this->variables['CACHE_STORE'] = $this->option('driver') ?? $this->choice(
|
||||||
|
'Cache Driver',
|
||||||
|
self::CACHE_DRIVERS,
|
||||||
|
array_key_exists($selected, self::CACHE_DRIVERS) ? $selected : null
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->variables['CACHE_STORE'] === 'redis') {
|
||||||
|
$this->requestRedisSettings();
|
||||||
|
|
||||||
|
if (config('queue.default') !== 'sync') {
|
||||||
|
$this->call('p:environment:queue-service', [
|
||||||
|
'--use-redis' => true,
|
||||||
|
'--overwrite' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writeToEnvironment($this->variables);
|
||||||
|
|
||||||
|
$this->info($this->console->output());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
66
app/Console/Commands/Environment/QueueSettingsCommand.php
Normal file
66
app/Console/Commands/Environment/QueueSettingsCommand.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Environment;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Contracts\Console\Kernel;
|
||||||
|
use App\Traits\Commands\EnvironmentWriterTrait;
|
||||||
|
use App\Traits\Commands\RequestRedisSettingsTrait;
|
||||||
|
|
||||||
|
class QueueSettingsCommand extends Command
|
||||||
|
{
|
||||||
|
use EnvironmentWriterTrait;
|
||||||
|
use RequestRedisSettingsTrait;
|
||||||
|
|
||||||
|
public const QUEUE_DRIVERS = [
|
||||||
|
'database' => 'Database (default)',
|
||||||
|
'redis' => 'Redis',
|
||||||
|
'sync' => 'Synchronous',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $description = 'Configure queue settings for the Panel.';
|
||||||
|
|
||||||
|
protected $signature = 'p:environment:queue
|
||||||
|
{--driver= : The queue driver backend to use.}
|
||||||
|
{--redis-host= : Redis host to use for connections.}
|
||||||
|
{--redis-pass= : Password used to connect to redis.}
|
||||||
|
{--redis-port= : Port to connect to redis over.}';
|
||||||
|
|
||||||
|
protected array $variables = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QueueSettingsCommand constructor.
|
||||||
|
*/
|
||||||
|
public function __construct(private Kernel $console)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle command execution.
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
$selected = config('queue.default', 'database');
|
||||||
|
$this->variables['QUEUE_CONNECTION'] = $this->option('driver') ?? $this->choice(
|
||||||
|
'Queue Driver',
|
||||||
|
self::QUEUE_DRIVERS,
|
||||||
|
array_key_exists($selected, self::QUEUE_DRIVERS) ? $selected : null
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->variables['QUEUE_CONNECTION'] === 'redis') {
|
||||||
|
$this->requestRedisSettings();
|
||||||
|
|
||||||
|
$this->call('p:environment:queue-service', [
|
||||||
|
'--use-redis' => true,
|
||||||
|
'--overwrite' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writeToEnvironment($this->variables);
|
||||||
|
|
||||||
|
$this->info($this->console->output());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
69
app/Console/Commands/Environment/SessionSettingsCommand.php
Normal file
69
app/Console/Commands/Environment/SessionSettingsCommand.php
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands\Environment;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Contracts\Console\Kernel;
|
||||||
|
use App\Traits\Commands\EnvironmentWriterTrait;
|
||||||
|
use App\Traits\Commands\RequestRedisSettingsTrait;
|
||||||
|
|
||||||
|
class SessionSettingsCommand extends Command
|
||||||
|
{
|
||||||
|
use EnvironmentWriterTrait;
|
||||||
|
use RequestRedisSettingsTrait;
|
||||||
|
|
||||||
|
public const SESSION_DRIVERS = [
|
||||||
|
'file' => 'Filesystem (default)',
|
||||||
|
'redis' => 'Redis',
|
||||||
|
'database' => 'Database',
|
||||||
|
'cookie' => 'Cookie',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $description = 'Configure session settings for the Panel.';
|
||||||
|
|
||||||
|
protected $signature = 'p:environment:session
|
||||||
|
{--driver= : The session driver backend to use.}
|
||||||
|
{--redis-host= : Redis host to use for connections.}
|
||||||
|
{--redis-pass= : Password used to connect to redis.}
|
||||||
|
{--redis-port= : Port to connect to redis over.}';
|
||||||
|
|
||||||
|
protected array $variables = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SessionSettingsCommand constructor.
|
||||||
|
*/
|
||||||
|
public function __construct(private Kernel $console)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle command execution.
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
$selected = config('session.driver', 'file');
|
||||||
|
$this->variables['SESSION_DRIVER'] = $this->option('driver') ?? $this->choice(
|
||||||
|
'Session Driver',
|
||||||
|
self::SESSION_DRIVERS,
|
||||||
|
array_key_exists($selected, self::SESSION_DRIVERS) ? $selected : null
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($this->variables['SESSION_DRIVER'] === 'redis') {
|
||||||
|
$this->requestRedisSettings();
|
||||||
|
|
||||||
|
if (config('queue.default') !== 'sync') {
|
||||||
|
$this->call('p:environment:queue-service', [
|
||||||
|
'--use-redis' => true,
|
||||||
|
'--overwrite' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writeToEnvironment($this->variables);
|
||||||
|
|
||||||
|
$this->info($this->console->output());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
144
app/Filament/Pages/Installer/PanelInstaller.php
Normal file
144
app/Filament/Pages/Installer/PanelInstaller.php
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Pages\Installer;
|
||||||
|
|
||||||
|
use App\Filament\Pages\Installer\Steps\AdminUserStep;
|
||||||
|
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\RequirementsStep;
|
||||||
|
use App\Services\Users\UserCreationService;
|
||||||
|
use App\Traits\Commands\EnvironmentWriterTrait;
|
||||||
|
use Exception;
|
||||||
|
use Filament\Facades\Filament;
|
||||||
|
use Filament\Forms\Components\Wizard;
|
||||||
|
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\Concerns\HasUnsavedDataChangesAlert;
|
||||||
|
use Filament\Pages\SimplePage;
|
||||||
|
use Filament\Support\Enums\MaxWidth;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
use Illuminate\Support\Facades\Blade;
|
||||||
|
use Illuminate\Support\HtmlString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @property Form $form
|
||||||
|
*/
|
||||||
|
class PanelInstaller extends SimplePage implements HasForms
|
||||||
|
{
|
||||||
|
use EnvironmentWriterTrait;
|
||||||
|
use HasUnsavedDataChangesAlert;
|
||||||
|
use InteractsWithForms;
|
||||||
|
|
||||||
|
public $data = [];
|
||||||
|
|
||||||
|
protected static string $view = 'filament.pages.installer';
|
||||||
|
|
||||||
|
public function getMaxWidth(): MaxWidth|string
|
||||||
|
{
|
||||||
|
return MaxWidth::SevenExtraLarge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mount()
|
||||||
|
{
|
||||||
|
if (is_installed()) {
|
||||||
|
abort(404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->form->fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dehydrate(): void
|
||||||
|
{
|
||||||
|
Artisan::call('config:clear');
|
||||||
|
Artisan::call('cache:clear');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getFormSchema(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Wizard::make([
|
||||||
|
RequirementsStep::make(),
|
||||||
|
EnvironmentStep::make(),
|
||||||
|
DatabaseStep::make(),
|
||||||
|
RedisStep::make()
|
||||||
|
->hidden(fn (Get $get) => $get('env.SESSION_DRIVER') != 'redis' && $get('env.QUEUE_CONNECTION') != 'redis' && $get('env.CACHE_STORE') != 'redis'),
|
||||||
|
AdminUserStep::make(),
|
||||||
|
])
|
||||||
|
->persistStepInQueryString()
|
||||||
|
->submitAction(new HtmlString(Blade::render(<<<'BLADE'
|
||||||
|
<x-filament::button
|
||||||
|
type="submit"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
Finish
|
||||||
|
</x-filament::button>
|
||||||
|
BLADE))),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getFormStatePath(): ?string
|
||||||
|
{
|
||||||
|
return 'data';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function hasUnsavedDataChangesAlert(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function submit()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$inputs = $this->form->getState();
|
||||||
|
|
||||||
|
// Write variables to .env file
|
||||||
|
$variables = array_get($inputs, 'env');
|
||||||
|
$this->writeToEnvironment($variables);
|
||||||
|
|
||||||
|
$redisUsed = count(collect($variables)->filter(function ($item) {
|
||||||
|
return $item === 'redis';
|
||||||
|
})) !== 0;
|
||||||
|
|
||||||
|
// Create queue worker service (if needed)
|
||||||
|
if ($variables['QUEUE_CONNECTION'] !== 'sync') {
|
||||||
|
Artisan::call('p:environment:queue-service', [
|
||||||
|
'--use-redis' => $redisUsed,
|
||||||
|
'--overwrite' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run migrations
|
||||||
|
Artisan::call('migrate', [
|
||||||
|
'--force' => true,
|
||||||
|
'--seed' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Create first admin user
|
||||||
|
$userData = array_get($inputs, 'user');
|
||||||
|
$userData['root_admin'] = true;
|
||||||
|
app(UserCreationService::class)->handle($userData);
|
||||||
|
|
||||||
|
// Install setup complete
|
||||||
|
$this->writeToEnvironment(['APP_INSTALLED' => true]);
|
||||||
|
|
||||||
|
$this->rememberData();
|
||||||
|
|
||||||
|
Notification::make()
|
||||||
|
->title('Successfully Installed')
|
||||||
|
->success()
|
||||||
|
->send();
|
||||||
|
|
||||||
|
redirect()->intended(Filament::getUrl());
|
||||||
|
} catch (Exception $exception) {
|
||||||
|
Notification::make()
|
||||||
|
->title('Installation Failed')
|
||||||
|
->body($exception->getMessage())
|
||||||
|
->danger()
|
||||||
|
->send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
app/Filament/Pages/Installer/Steps/AdminUserStep.php
Normal file
31
app/Filament/Pages/Installer/Steps/AdminUserStep.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Pages\Installer\Steps;
|
||||||
|
|
||||||
|
use Filament\Forms\Components\TextInput;
|
||||||
|
use Filament\Forms\Components\Wizard\Step;
|
||||||
|
|
||||||
|
class AdminUserStep
|
||||||
|
{
|
||||||
|
public static function make(): Step
|
||||||
|
{
|
||||||
|
return Step::make('user')
|
||||||
|
->label('Admin User')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('user.email')
|
||||||
|
->label('Admin E-Mail')
|
||||||
|
->required()
|
||||||
|
->email()
|
||||||
|
->default('admin@example.com'),
|
||||||
|
TextInput::make('user.username')
|
||||||
|
->label('Admin Username')
|
||||||
|
->required()
|
||||||
|
->default('admin'),
|
||||||
|
TextInput::make('user.password')
|
||||||
|
->label('Admin Password')
|
||||||
|
->required()
|
||||||
|
->password()
|
||||||
|
->revealable(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
95
app/Filament/Pages/Installer/Steps/DatabaseStep.php
Normal file
95
app/Filament/Pages/Installer/Steps/DatabaseStep.php
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Pages\Installer\Steps;
|
||||||
|
|
||||||
|
use Filament\Forms\Components\TextInput;
|
||||||
|
use Filament\Forms\Components\Wizard\Step;
|
||||||
|
use Filament\Forms\Get;
|
||||||
|
use Filament\Notifications\Notification;
|
||||||
|
use Filament\Support\Exceptions\Halt;
|
||||||
|
use Illuminate\Database\DatabaseManager;
|
||||||
|
use PDOException;
|
||||||
|
|
||||||
|
class DatabaseStep
|
||||||
|
{
|
||||||
|
public static function make(): Step
|
||||||
|
{
|
||||||
|
return Step::make('database')
|
||||||
|
->label('Database')
|
||||||
|
->columns()
|
||||||
|
->schema([
|
||||||
|
TextInput::make('env.DB_DATABASE')
|
||||||
|
->label(fn (Get $get) => $get('env.DB_CONNECTION') === 'sqlite' ? 'Database Path' : 'Database Name')
|
||||||
|
->columnSpanFull()
|
||||||
|
->hintIcon('tabler-question-mark')
|
||||||
|
->hintIconTooltip(fn (Get $get) => $get('env.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.DB_CONNECTION') === 'sqlite' ? 'database.sqlite' : 'panel')),
|
||||||
|
TextInput::make('env.DB_HOST')
|
||||||
|
->label('Database Host')
|
||||||
|
->hintIcon('tabler-question-mark')
|
||||||
|
->hintIconTooltip('The host of your database. Make sure it is reachable.')
|
||||||
|
->required()
|
||||||
|
->default(env('DB_HOST', '127.0.0.1'))
|
||||||
|
->hidden(fn (Get $get) => $get('env.DB_CONNECTION') === 'sqlite'),
|
||||||
|
TextInput::make('env.DB_PORT')
|
||||||
|
->label('Database Port')
|
||||||
|
->hintIcon('tabler-question-mark')
|
||||||
|
->hintIconTooltip('The port of your database.')
|
||||||
|
->required()
|
||||||
|
->numeric()
|
||||||
|
->minValue(1)
|
||||||
|
->maxValue(65535)
|
||||||
|
->default(env('DB_PORT', 3306))
|
||||||
|
->hidden(fn (Get $get) => $get('env.DB_CONNECTION') === 'sqlite'),
|
||||||
|
TextInput::make('env.DB_USERNAME')
|
||||||
|
->label('Database Username')
|
||||||
|
->hintIcon('tabler-question-mark')
|
||||||
|
->hintIconTooltip('The name of your database user.')
|
||||||
|
->required()
|
||||||
|
->default(env('DB_USERNAME', 'pelican'))
|
||||||
|
->hidden(fn (Get $get) => $get('env.DB_CONNECTION') === 'sqlite'),
|
||||||
|
TextInput::make('env.DB_PASSWORD')
|
||||||
|
->label('Database Password')
|
||||||
|
->hintIcon('tabler-question-mark')
|
||||||
|
->hintIconTooltip('The password of your database user. Can be empty.')
|
||||||
|
->password()
|
||||||
|
->revealable()
|
||||||
|
->default(env('DB_PASSWORD'))
|
||||||
|
->hidden(fn (Get $get) => $get('env.DB_CONNECTION') === 'sqlite'),
|
||||||
|
])
|
||||||
|
->afterValidation(function (Get $get) {
|
||||||
|
$driver = $get('env.DB_CONNECTION');
|
||||||
|
if ($driver !== 'sqlite') {
|
||||||
|
/** @var DatabaseManager $database */
|
||||||
|
$database = app(DatabaseManager::class);
|
||||||
|
|
||||||
|
try {
|
||||||
|
config()->set('database.connections._panel_install_test', [
|
||||||
|
'driver' => $driver,
|
||||||
|
'host' => $get('env.DB_HOST'),
|
||||||
|
'port' => $get('env.DB_PORT'),
|
||||||
|
'database' => $get('env.DB_DATABASE'),
|
||||||
|
'username' => $get('env.DB_USERNAME'),
|
||||||
|
'password' => $get('env.DB_PASSWORD'),
|
||||||
|
'charset' => 'utf8mb4',
|
||||||
|
'collation' => 'utf8mb4_unicode_ci',
|
||||||
|
'strict' => true,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$database->connection('_panel_install_test')->getPdo();
|
||||||
|
} catch (PDOException $exception) {
|
||||||
|
Notification::make()
|
||||||
|
->title('Database connection failed')
|
||||||
|
->body($exception->getMessage())
|
||||||
|
->danger()
|
||||||
|
->send();
|
||||||
|
|
||||||
|
$database->disconnect('_panel_install_test');
|
||||||
|
|
||||||
|
throw new Halt('Database connection failed');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
94
app/Filament/Pages/Installer/Steps/EnvironmentStep.php
Normal file
94
app/Filament/Pages/Installer/Steps/EnvironmentStep.php
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Pages\Installer\Steps;
|
||||||
|
|
||||||
|
use Filament\Forms\Components\TextInput;
|
||||||
|
use Filament\Forms\Components\Toggle;
|
||||||
|
use Filament\Forms\Components\ToggleButtons;
|
||||||
|
use Filament\Forms\Components\Wizard\Step;
|
||||||
|
use Filament\Forms\Set;
|
||||||
|
|
||||||
|
class EnvironmentStep
|
||||||
|
{
|
||||||
|
public const CACHE_DRIVERS = [
|
||||||
|
'file' => 'Filesystem',
|
||||||
|
'redis' => 'Redis',
|
||||||
|
];
|
||||||
|
|
||||||
|
public const SESSION_DRIVERS = [
|
||||||
|
'file' => 'Filesystem',
|
||||||
|
'redis' => 'Redis',
|
||||||
|
'database' => 'Database',
|
||||||
|
'cookie' => 'Cookie',
|
||||||
|
];
|
||||||
|
|
||||||
|
public const QUEUE_DRIVERS = [
|
||||||
|
'database' => 'Database',
|
||||||
|
'redis' => 'Redis',
|
||||||
|
'sync' => 'Synchronous',
|
||||||
|
];
|
||||||
|
|
||||||
|
public const DATABASE_DRIVERS = [
|
||||||
|
'sqlite' => 'SQLite',
|
||||||
|
'mariadb' => 'MariaDB',
|
||||||
|
'mysql' => 'MySQL',
|
||||||
|
];
|
||||||
|
|
||||||
|
public static function make(): Step
|
||||||
|
{
|
||||||
|
return Step::make('environment')
|
||||||
|
->label('Environment')
|
||||||
|
->columns()
|
||||||
|
->schema([
|
||||||
|
TextInput::make('env.APP_NAME')
|
||||||
|
->label('App Name')
|
||||||
|
->hintIcon('tabler-question-mark')
|
||||||
|
->hintIconTooltip('This will be the Name of your Panel.')
|
||||||
|
->required()
|
||||||
|
->default(config('app.name')),
|
||||||
|
TextInput::make('env.APP_URL')
|
||||||
|
->label('App URL')
|
||||||
|
->hintIcon('tabler-question-mark')
|
||||||
|
->hintIconTooltip('This will be the URL you access your Panel from.')
|
||||||
|
->required()
|
||||||
|
->default(config('app.url'))
|
||||||
|
->live()
|
||||||
|
->afterStateUpdated(fn ($state, Set $set) => $set('env.SESSION_SECURE_COOKIE', str_starts_with($state, 'https://'))),
|
||||||
|
Toggle::make('env.SESSION_SECURE_COOKIE')
|
||||||
|
->hidden()
|
||||||
|
->default(env('SESSION_SECURE_COOKIE')),
|
||||||
|
ToggleButtons::make('env.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.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.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.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')),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
42
app/Filament/Pages/Installer/Steps/RedisStep.php
Normal file
42
app/Filament/Pages/Installer/Steps/RedisStep.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Pages\Installer\Steps;
|
||||||
|
|
||||||
|
use Filament\Forms\Components\TextInput;
|
||||||
|
use Filament\Forms\Components\Wizard\Step;
|
||||||
|
|
||||||
|
class RedisStep
|
||||||
|
{
|
||||||
|
public static function make(): Step
|
||||||
|
{
|
||||||
|
return Step::make('redis')
|
||||||
|
->label('Redis')
|
||||||
|
->columns()
|
||||||
|
->schema([
|
||||||
|
TextInput::make('env.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_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_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_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')),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
87
app/Filament/Pages/Installer/Steps/RequirementsStep.php
Normal file
87
app/Filament/Pages/Installer/Steps/RequirementsStep.php
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Pages\Installer\Steps;
|
||||||
|
|
||||||
|
use Filament\Forms\Components\Placeholder;
|
||||||
|
use Filament\Forms\Components\Section;
|
||||||
|
use Filament\Forms\Components\Wizard\Step;
|
||||||
|
use Filament\Notifications\Notification;
|
||||||
|
use Filament\Support\Exceptions\Halt;
|
||||||
|
|
||||||
|
class RequirementsStep
|
||||||
|
{
|
||||||
|
public static function make(): Step
|
||||||
|
{
|
||||||
|
$correctPhpVersion = version_compare(PHP_VERSION, '8.2.0') >= 0;
|
||||||
|
|
||||||
|
$fields = [
|
||||||
|
Section::make('PHP Version')
|
||||||
|
->description('8.2 or newer')
|
||||||
|
->icon($correctPhpVersion ? 'tabler-check' : 'tabler-x')
|
||||||
|
->iconColor($correctPhpVersion ? 'success' : 'danger')
|
||||||
|
->schema([
|
||||||
|
Placeholder::make('')
|
||||||
|
->content('Your PHP Version ' . ($correctPhpVersion ? 'is' : 'needs to be') .' 8.2 or newer.'),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
|
||||||
|
$phpExtensions = [
|
||||||
|
'BCMath' => extension_loaded('bcmath'),
|
||||||
|
'cURL' => extension_loaded('curl'),
|
||||||
|
'GD' => extension_loaded('gd'),
|
||||||
|
'intl' => extension_loaded('intl'),
|
||||||
|
'mbstring' => extension_loaded('mbstring'),
|
||||||
|
'MySQL' => extension_loaded('pdo_mysql'),
|
||||||
|
'SQLite3' => extension_loaded('pdo_sqlite'),
|
||||||
|
'XML' => extension_loaded('xml'),
|
||||||
|
'Zip' => extension_loaded('zip'),
|
||||||
|
];
|
||||||
|
$allExtensionsInstalled = !in_array(false, $phpExtensions);
|
||||||
|
|
||||||
|
$fields[] = Section::make('PHP Extensions')
|
||||||
|
->description(implode(', ', array_keys($phpExtensions)))
|
||||||
|
->icon($allExtensionsInstalled ? 'tabler-check' : 'tabler-x')
|
||||||
|
->iconColor($allExtensionsInstalled ? 'success' : 'danger')
|
||||||
|
->schema([
|
||||||
|
Placeholder::make('')
|
||||||
|
->content('All needed PHP Extensions are installed.')
|
||||||
|
->visible($allExtensionsInstalled),
|
||||||
|
Placeholder::make('')
|
||||||
|
->content('The following PHP Extensions are missing: ' . implode(', ', array_keys($phpExtensions, false)))
|
||||||
|
->visible(!$allExtensionsInstalled),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$folderPermissions = [
|
||||||
|
'Storage' => substr(sprintf('%o', fileperms(base_path('storage/'))), -4) >= 755,
|
||||||
|
'Cache' => substr(sprintf('%o', fileperms(base_path('bootstrap/cache/'))), -4) >= 755,
|
||||||
|
];
|
||||||
|
$correctFolderPermissions = !in_array(false, $folderPermissions);
|
||||||
|
|
||||||
|
$fields[] = Section::make('Folder Permissions')
|
||||||
|
->description(implode(', ', array_keys($folderPermissions)))
|
||||||
|
->icon($correctFolderPermissions ? 'tabler-check' : 'tabler-x')
|
||||||
|
->iconColor($correctFolderPermissions ? 'success' : 'danger')
|
||||||
|
->schema([
|
||||||
|
Placeholder::make('')
|
||||||
|
->content('All Folders have the correct permissions.')
|
||||||
|
->visible($correctFolderPermissions),
|
||||||
|
Placeholder::make('')
|
||||||
|
->content('The following Folders have wrong permissions: ' . implode(', ', array_keys($folderPermissions, false)))
|
||||||
|
->visible(!$correctFolderPermissions),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return Step::make('requirements')
|
||||||
|
->label('Server Requirements')
|
||||||
|
->schema($fields)
|
||||||
|
->afterValidation(function () use ($correctPhpVersion, $allExtensionsInstalled, $correctFolderPermissions) {
|
||||||
|
if (!$correctPhpVersion || !$allExtensionsInstalled || !$correctFolderPermissions) {
|
||||||
|
Notification::make()
|
||||||
|
->title('Some requirements are missing!')
|
||||||
|
->danger()
|
||||||
|
->send();
|
||||||
|
|
||||||
|
throw new Halt();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,8 @@ use App\Services\Helpers\SoftwareVersionService;
|
|||||||
use Dedoc\Scramble\Scramble;
|
use Dedoc\Scramble\Scramble;
|
||||||
use Dedoc\Scramble\Support\Generator\OpenApi;
|
use Dedoc\Scramble\Support\Generator\OpenApi;
|
||||||
use Dedoc\Scramble\Support\Generator\SecurityScheme;
|
use Dedoc\Scramble\Support\Generator\SecurityScheme;
|
||||||
|
use Filament\Support\Colors\Color;
|
||||||
|
use Filament\Support\Facades\FilamentColor;
|
||||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||||
use Illuminate\Pagination\Paginator;
|
use Illuminate\Pagination\Paginator;
|
||||||
use Illuminate\Support\Facades\Broadcast;
|
use Illuminate\Support\Facades\Broadcast;
|
||||||
@ -80,6 +82,15 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) {
|
Event::listen(function (\SocialiteProviders\Manager\SocialiteWasCalled $event) {
|
||||||
$event->extendSocialite('discord', \SocialiteProviders\Discord\Provider::class);
|
$event->extendSocialite('discord', \SocialiteProviders\Discord\Provider::class);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
FilamentColor::register([
|
||||||
|
'danger' => Color::Red,
|
||||||
|
'gray' => Color::Zinc,
|
||||||
|
'info' => Color::Sky,
|
||||||
|
'primary' => Color::Blue,
|
||||||
|
'success' => Color::Green,
|
||||||
|
'warning' => Color::Amber,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,6 @@ use Filament\Http\Middleware\DisableBladeIconComponents;
|
|||||||
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
||||||
use Filament\Panel;
|
use Filament\Panel;
|
||||||
use Filament\PanelProvider;
|
use Filament\PanelProvider;
|
||||||
use Filament\Support\Colors\Color;
|
|
||||||
use Filament\Support\Facades\FilamentAsset;
|
use Filament\Support\Facades\FilamentAsset;
|
||||||
use Filament\Widgets;
|
use Filament\Widgets;
|
||||||
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||||
@ -44,15 +43,6 @@ class AdminPanelProvider extends PanelProvider
|
|||||||
->brandLogo(config('app.logo'))
|
->brandLogo(config('app.logo'))
|
||||||
->brandLogoHeight('2rem')
|
->brandLogoHeight('2rem')
|
||||||
->profile(EditProfile::class, false)
|
->profile(EditProfile::class, false)
|
||||||
->colors([
|
|
||||||
'danger' => Color::Red,
|
|
||||||
'gray' => Color::Zinc,
|
|
||||||
'info' => Color::Sky,
|
|
||||||
'primary' => Color::Blue,
|
|
||||||
'success' => Color::Green,
|
|
||||||
'warning' => Color::Amber,
|
|
||||||
'blurple' => Color::hex('#5865F2'),
|
|
||||||
])
|
|
||||||
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
|
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
|
||||||
->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
|
->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
|
||||||
->discoverClusters(in: app_path('Filament/Clusters'), for: 'App\\Filament\\Clusters')
|
->discoverClusters(in: app_path('Filament/Clusters'), for: 'App\\Filament\\Clusters')
|
||||||
|
37
app/Traits/Commands/RequestRedisSettingsTrait.php
Normal file
37
app/Traits/Commands/RequestRedisSettingsTrait.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Traits\Commands;
|
||||||
|
|
||||||
|
trait RequestRedisSettingsTrait
|
||||||
|
{
|
||||||
|
protected function requestRedisSettings(): void
|
||||||
|
{
|
||||||
|
$this->output->note(__('commands.appsettings.redis.note'));
|
||||||
|
$this->variables['REDIS_HOST'] = $this->option('redis-host') ?? $this->ask(
|
||||||
|
'Redis Host',
|
||||||
|
config('database.redis.default.host')
|
||||||
|
);
|
||||||
|
|
||||||
|
$askForRedisPassword = true;
|
||||||
|
if (!empty(config('database.redis.default.password'))) {
|
||||||
|
$this->variables['REDIS_PASSWORD'] = config('database.redis.default.password');
|
||||||
|
$askForRedisPassword = $this->confirm('It seems a password is already defined for Redis, would you like to change it?');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($askForRedisPassword) {
|
||||||
|
$this->output->comment(__('commands.appsettings.redis.comment'));
|
||||||
|
$this->variables['REDIS_PASSWORD'] = $this->option('redis-pass') ?? $this->output->askHidden(
|
||||||
|
'Redis Password'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($this->variables['REDIS_PASSWORD'])) {
|
||||||
|
$this->variables['REDIS_PASSWORD'] = 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->variables['REDIS_PORT'] = $this->option('redis-port') ?? $this->ask(
|
||||||
|
'Redis Port',
|
||||||
|
config('database.redis.default.port')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -40,3 +40,11 @@ if (!function_exists('object_get_strict')) {
|
|||||||
return $object;
|
return $object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!function_exists('is_installed')) {
|
||||||
|
function is_installed(): bool
|
||||||
|
{
|
||||||
|
// This defaults to true so existing panels count as "installed"
|
||||||
|
return env('APP_INSTALLED', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
7
resources/views/filament/pages/installer.blade.php
Normal file
7
resources/views/filament/pages/installer.blade.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<x-filament-panels::page.simple>
|
||||||
|
<x-filament-panels::form wire:submit="submit">
|
||||||
|
{{ $this->form }}
|
||||||
|
</x-filament-panels::form>
|
||||||
|
|
||||||
|
<x-filament-panels::page.unsaved-data-changes-alert />
|
||||||
|
</x-filament-panels::page.simple>
|
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Filament\Pages\Installer\PanelInstaller;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use App\Http\Controllers\Base;
|
use App\Http\Controllers\Base;
|
||||||
use App\Http\Middleware\RequireTwoFactorAuthentication;
|
use App\Http\Middleware\RequireTwoFactorAuthentication;
|
||||||
@ -16,5 +17,8 @@ Route::get('/locales/locale.json', Base\LocaleController::class)
|
|||||||
->withoutMiddleware(['auth', RequireTwoFactorAuthentication::class])
|
->withoutMiddleware(['auth', RequireTwoFactorAuthentication::class])
|
||||||
->where('namespace', '.*');
|
->where('namespace', '.*');
|
||||||
|
|
||||||
|
Route::get('installer', PanelInstaller::class)->name('installer')
|
||||||
|
->withoutMiddleware(['auth', RequireTwoFactorAuthentication::class]);
|
||||||
|
|
||||||
Route::get('/{react}', [Base\IndexController::class, 'index'])
|
Route::get('/{react}', [Base\IndexController::class, 'index'])
|
||||||
->where('react', '^(?!(\/)?(api|auth|admin|daemon|legacy)).+');
|
->where('react', '^(?!(\/)?(api|auth|admin|daemon|legacy)).+');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user