Add setup wizard to database host (#1216)

* add setup wizard to database host

* make phpstan happy

* remove `.` in lang

---------

Co-authored-by: notCharles <charles@pelican.dev>
This commit is contained in:
Boy132 2025-04-06 20:04:20 +02:00 committed by GitHub
parent 80c404a48c
commit 49638e75e5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 150 additions and 9 deletions

View File

@ -4,14 +4,29 @@ namespace App\Filament\Admin\Resources\DatabaseHostResource\Pages;
use App\Filament\Admin\Resources\DatabaseHostResource;
use App\Services\Databases\Hosts\HostCreationService;
use Filament\Forms\Components\Fieldset;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Components\Wizard\Step;
use Filament\Forms\Get;
use Filament\Forms\Set;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\CreateRecord;
use Filament\Resources\Pages\CreateRecord\Concerns\HasWizard;
use Filament\Support\Exceptions\Halt;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Str;
use PDOException;
use Webbingbrasil\FilamentCopyActions\Forms\Actions\CopyAction;
class CreateDatabaseHost extends CreateRecord
{
use HasWizard;
protected static string $resource = DatabaseHostResource::class;
protected static bool $canCreateAnother = false;
@ -23,18 +38,118 @@ class CreateDatabaseHost extends CreateRecord
$this->service = $service;
}
protected function getHeaderActions(): array
/** @return Step[] */
public function getSteps(): array
{
return [
$this->getCreateFormAction()->formId('form'),
Step::make(trans('admin/databasehost.setup.preparations'))
->columns()
->schema([
Placeholder::make('')
->content(trans('admin/databasehost.setup.note')),
Toggle::make('different_server')
->label(new HtmlString(trans('admin/databasehost.setup.different_server')))
->dehydrated(false)
->live()
->columnSpanFull()
->afterStateUpdated(fn ($state, Set $set) => $state ? $set('panel_ip', gethostbyname(str(config('app.url'))->replace(['http:', 'https:', '/'], ''))) : '127.0.0.1'),
Hidden::make('panel_ip')
->default('127.0.0.1')
->dehydrated(false),
TextInput::make('username')
->label(trans('admin/databasehost.username'))
->helperText(trans('admin/databasehost.username_help'))
->required()
->default('pelicanuser')
->maxLength(255),
TextInput::make('password')
->label(trans('admin/databasehost.password'))
->helperText(trans('admin/databasehost.password_help'))
->required()
->default(Str::password(16))
->password()
->revealable()
->maxLength(255),
])
->afterValidation(function (Get $get, Set $set) {
$set('create_user', "CREATE USER '{$get('username')}'@'{$get('panel_ip')}' IDENTIFIED BY '{$get('password')}';");
$set('assign_permissions', "GRANT ALL PRIVILEGES ON *.* TO '{$get('username')}'@'{$get('panel_ip')}' WITH GRANT OPTION;");
}),
Step::make(trans('admin/databasehost.setup.database_setup'))
->schema([
Fieldset::make(trans('admin/databasehost.setup.database_user'))
->schema([
Placeholder::make('')
->content(new HtmlString(trans('admin/databasehost.setup.cli_login')))
->columnSpanFull(),
TextInput::make('create_user')
->label(trans('admin/databasehost.setup.command_create_user'))
->default(fn (Get $get) => "CREATE USER '{$get('username')}'@'{$get('panel_ip')}' IDENTIFIED BY '{$get('password')}';")
->disabled()
->dehydrated(false)
->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null)
->columnSpanFull(),
TextInput::make('assign_permissions')
->label(trans('admin/databasehost.setup.command_assign_permissions'))
->default(fn (Get $get) => "GRANT ALL PRIVILEGES ON *.* TO '{$get('username')}'@'{$get('panel_ip')}' WITH GRANT OPTION;")
->disabled()
->dehydrated(false)
->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null)
->columnSpanFull(),
Placeholder::make('')
->content(new HtmlString(trans('admin/databasehost.setup.cli_exit')))
->columnSpanFull(),
]),
Fieldset::make(trans('admin/databasehost.setup.external_access'))
->schema([
Placeholder::make('')
->content(new HtmlString(trans('admin/databasehost.setup.allow_external_access')))
->columnSpanFull(),
]),
]),
Step::make(trans('admin/databasehost.setup.panel_setup'))
->columns([
'default' => 2,
'lg' => 3,
])
->schema([
TextInput::make('host')
->columnSpan(2)
->label(trans('admin/databasehost.host'))
->helperText(trans('admin/databasehost.host_help'))
->required()
->live(onBlur: true)
->afterStateUpdated(fn ($state, Set $set) => $set('name', $state))
->maxLength(255),
TextInput::make('port')
->label(trans('admin/databasehost.port'))
->helperText(trans('admin/databasehost.port_help'))
->required()
->numeric()
->default(3306)
->minValue(0)
->maxValue(65535),
TextInput::make('max_databases')
->label(trans('admin/databasehost.max_database'))
->helpertext(trans('admin/databasehost.max_databases_help'))
->placeholder(trans('admin/databasehost.unlimited'))
->numeric(),
TextInput::make('name')
->label(trans('admin/databasehost.display_name'))
->helperText(trans('admin/databasehost.display_name_help'))
->required()
->maxLength(60),
Select::make('node_ids')
->multiple()
->searchable()
->preload()
->helperText(trans('admin/databasehost.linked_nodes_help'))
->label(trans('admin/databasehost.linked_nodes'))
->relationship('nodes', 'name'),
]),
];
}
protected function getFormActions(): array
{
return [];
}
protected function handleRecordCreation(array $data): Model
{
try {

View File

@ -2,7 +2,7 @@
return [
'title' => 'Application API Keys',
'empty_table' => 'No API keys.',
'empty_table' => 'No API keys',
'whitelist' => 'Whitelisted IPv4 Addresses',
'whitelist_help' => 'API keys can be restricted to only work from specific IPv4 addresses. Enter each address on a new line.',
'whitelist_placeholder' => 'Example: 127.0.0.1 or 192.168.1.1',

View File

@ -45,4 +45,30 @@ return [
'rotated' => 'Password Rotated',
'rotate_error' => 'Password Rotation Failed',
'databases' => 'Databases',
'setup' => [
'preparations' => 'Preparations',
'database_setup' => 'Database Setup',
'panel_setup' => 'Panel Setup',
'note' => 'Currently, only MySQL/ MariaDB databases are supported for database hosts!',
'different_server' => 'Are the panel and the database <i>not</i> on the same server?',
'database_user' => 'Database User',
'cli_login' => 'Use <code>mysql -u root -p</code> to access mysql cli.',
'command_create_user' => 'Command to create the user',
'command_assign_permissions' => 'Command to assign permissions',
'cli_exit' => 'To exit mysql cli run <code>exit</code>.',
'external_access' => 'External Access',
'allow_external_access' => '
<p>Chances are you\'ll need to allow external access to this MySQL instance in order to allow servers to connect to it.</p>
<br>
<p>To do this, open <code>my.cnf</code>, which varies in location depending on your OS and how MySQL was installed. You can type find <code>/etc -iname my.cnf</code> to locate it.</p>
<br>
<p>Open <code>my.cnf</code>, add text below to the bottom of the file and save it:<br>
<code>[mysqld]<br>bind-address=0.0.0.0</code></p>
<br>
<p>Restart MySQL/ MariaDB to apply these changes. This will override the default MySQL configuration, which by default will only accept requests from localhost. Updating this will allow connections on all interfaces, and thus, external connections. Make sure to allow the MySQL port (default 3306) in your firewall.</p>
',
],
];

View File

@ -77,7 +77,7 @@ return [
'script_install' => 'Install Script',
'no_eggs' => 'No Eggs',
'no_servers' => 'No Servers',
'no_servers_help' => 'No Servers are assigned to this Egg.',
'no_servers_help' => 'No Servers are assigned to this Egg',
'update' => 'Update|Update selected',
'updated' => 'Egg updated|:count/:total Eggs updated',