diff --git a/app/Filament/Admin/Resources/DatabaseHostResource/Pages/CreateDatabaseHost.php b/app/Filament/Admin/Resources/DatabaseHostResource/Pages/CreateDatabaseHost.php index 157bc1b9d..2c44247cf 100644 --- a/app/Filament/Admin/Resources/DatabaseHostResource/Pages/CreateDatabaseHost.php +++ b/app/Filament/Admin/Resources/DatabaseHostResource/Pages/CreateDatabaseHost.php @@ -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 { diff --git a/lang/en/admin/apikey.php b/lang/en/admin/apikey.php index a6f45b790..c71e0d24b 100644 --- a/lang/en/admin/apikey.php +++ b/lang/en/admin/apikey.php @@ -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', diff --git a/lang/en/admin/databasehost.php b/lang/en/admin/databasehost.php index ccd12e47d..263b25e0e 100644 --- a/lang/en/admin/databasehost.php +++ b/lang/en/admin/databasehost.php @@ -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 not on the same server?', + + 'database_user' => 'Database User', + 'cli_login' => 'Use mysql -u root -p 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 exit.', + 'external_access' => 'External Access', + 'allow_external_access' => ' +

Chances are you\'ll need to allow external access to this MySQL instance in order to allow servers to connect to it.

+
+

To do this, open my.cnf, which varies in location depending on your OS and how MySQL was installed. You can type find /etc -iname my.cnf to locate it.

+
+

Open my.cnf, add text below to the bottom of the file and save it:
+ [mysqld]
bind-address=0.0.0.0

+
+

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.

+ ', + ], ]; diff --git a/lang/en/admin/egg.php b/lang/en/admin/egg.php index 1f5e8423f..db7171f2b 100644 --- a/lang/en/admin/egg.php +++ b/lang/en/admin/egg.php @@ -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',