diff --git a/app/Filament/Resources/DatabaseResource.php b/app/Filament/Resources/DatabaseResource.php new file mode 100644 index 000000000..55b8d60ba --- /dev/null +++ b/app/Filament/Resources/DatabaseResource.php @@ -0,0 +1,107 @@ +schema([ + Forms\Components\Select::make('server_id') + ->relationship('server', 'name') + ->required(), + Forms\Components\TextInput::make('database_host_id') + ->required() + ->numeric(), + Forms\Components\TextInput::make('database') + ->required() + ->maxLength(191), + Forms\Components\TextInput::make('username') + ->required() + ->maxLength(191), + Forms\Components\TextInput::make('remote') + ->required() + ->maxLength(191) + ->default('%'), + Forms\Components\Textarea::make('password') + ->required() + ->columnSpanFull(), + Forms\Components\TextInput::make('max_connections') + ->numeric() + ->default(0), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('server.name') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('database_host_id') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('database') + ->searchable(), + Tables\Columns\TextColumn::make('username') + ->searchable(), + Tables\Columns\TextColumn::make('remote') + ->searchable(), + Tables\Columns\TextColumn::make('max_connections') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListDatabases::route('/'), + 'create' => Pages\CreateDatabase::route('/create'), + 'edit' => Pages\EditDatabase::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Resources/DatabaseResource/Pages/CreateDatabase.php b/app/Filament/Resources/DatabaseResource/Pages/CreateDatabase.php new file mode 100644 index 000000000..3608e2a6e --- /dev/null +++ b/app/Filament/Resources/DatabaseResource/Pages/CreateDatabase.php @@ -0,0 +1,12 @@ +schema([ + Forms\Components\Tabs::make()->tabs([ + Forms\Components\Tabs\Tab::make('Configuration') + ->columns(2) + ->schema([ + Forms\Components\TextInput::make('name')->required()->maxLength(191) + ->helperText('A simple, human-readable name to use as an identifier for this Egg.'), + Forms\Components\Textarea::make('description')->rows(5) + ->helperText('A description of this Egg that will be displayed throughout the Panel as needed.'), + Forms\Components\TextInput::make('uuid')->disabled() + ->helperText('This is the globally unique identifier for this Egg which the Daemon uses as an identifier.'), + Forms\Components\TextInput::make('author')->required()->maxLength(191)->disabled() + ->helperText('The author of this version of the Egg. Uploading a new Egg configuration from a different author will change this.'), + Forms\Components\Toggle::make('force_outgoing_ip')->required() + ->helperText("Forces all outgoing network traffic to have its Source IP NATed to the IP of the server's primary allocation IP. + Required for certain games to work properly when the Node has multiple public IP addresses. + Enabling this option will disable internal networking for any servers using this egg, causing them to be unable to internally access other servers on the same node."), + Forms\Components\Textarea::make('startup')->rows(5) + ->helperText('The default startup command that should be used for new servers using this Egg.'), + Forms\Components\KeyValue::make('docker_images') + ->columnSpanFull() + ->addActionLabel('Add Image') + ->keyLabel('Name') + ->valueLabel('Image URI') + ->helperText('The docker images available to servers using this egg.'), + ]), + + Forms\Components\Tabs\Tab::make('Process Management') + ->columns(2) + ->schema([ + Forms\Components\Select::make('config_from') + ->label('Copy Settings From') + ->placeholder('None') + ->relationship('configFrom', 'name', ignoreRecord: true) + ->helperText('If you would like to default to settings from another Egg select it from the menu above.'), + + Forms\Components\TextInput::make('config_stop') + ->maxLength(191) + ->label('Stop Command') + ->helperText('The command that should be sent to server processes to stop them gracefully. If you need to send a SIGINT you should enter ^C here.'), + + Forms\Components\Textarea::make('config_startup')->rows(10)->json() + ->label('Start Configuration') + ->helperText('List of values the daemon should be looking for when booting a server to determine completion.'), + + Forms\Components\Textarea::make('config_files')->rows(10)->json() + ->label('Configuration Files') + ->helperText('This should be a JSON representation of configuration files to modify and what parts should be changed.'), + + Forms\Components\Textarea::make('config_logs')->rows(10)->json() + ->label('Log Configuration') + ->helperText('This should be a JSON representation of where log files are stored, and whether or not the daemon should be creating custom logs.'), + ]), + Forms\Components\Tabs\Tab::make('Variables') + ->columnSpanFull() + // ->columns(2) + ->schema([ + Forms\Components\Repeater::make('Blah') + ->relationship('variables') + ->name('name') + ->columns(1) + ->columnSpan(1) + ->itemLabel(fn (array $state) => $state['name']) + ->schema([ + Forms\Components\TextInput::make('name')->maxLength(191)->columnSpanFull(), + Forms\Components\Textarea::make('description')->columnSpanFull(), + Forms\Components\TextInput::make('env_variable')->maxLength(191), + Forms\Components\TextInput::make('default_value')->maxLength(191), + Forms\Components\Textarea::make('rules')->rows(3)->columnSpanFull()->required(), + ]) + ]), + Forms\Components\Tabs\Tab::make('Install Script') + ->columns(3) + ->schema([ + Forms\Components\Textarea::make('script_install')->rows(20)->columnSpanFull(), + + Forms\Components\Select::make('copy_script_from') + ->placeholder('None') + ->relationship('scriptFrom', 'name', ignoreRecord: true), + + Forms\Components\TextInput::make('script_container') + ->required() + ->maxLength(191) + ->default('alpine:3.4'), + + Forms\Components\TextInput::make('script_entry') + ->required() + ->maxLength(191) + ->default('ash'), + ]), + + ])->columnSpanFull(), + + // Forms\Components\TagsInput::make('features'), + // Forms\Components\TagsInput::make('file_denylist')->placeholder('new-file.txt'), + // Forms\Components\TextInput::make('update_url'), + // Forms\Components\Toggle::make('script_is_privileged')->required(), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('id') + ->label('Id') + // ->hidden() + ->searchable(), + Tables\Columns\TextColumn::make('uuid') + ->label('UUID') + ->hidden() + ->searchable(), + Tables\Columns\TextColumn::make('name') + ->searchable(), + Tables\Columns\TextColumn::make('author') + ->hidden() + ->searchable(), + Tables\Columns\TextColumn::make('description') + ->words(50) + ->wrap(), + Tables\Columns\TextColumn::make('servers_count') + ->counts('servers') + ->icon('heroicon-m-server-stack') + ->label('Servers'), + Tables\Columns\TextColumn::make('script_container') + ->searchable() + ->hidden(), + Tables\Columns\TextColumn::make('copyFrom.name') + ->hidden() + ->sortable(), + Tables\Columns\TextColumn::make('script_entry') + ->hidden() + ->searchable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->headerActions([ + Tables\Actions\Action::make('Import Egg') + ->form([ + Forms\Components\FileUpload::make('egg')->storeFiles(false), + ]) + ->action(function (array $data, Component $livewire): void { + /** @var TemporaryUploadedFile $eggFile */ + $eggFile = $data['egg']; + + /** @var EggImporterService $eggImportService */ + $eggImportService = resolve(EggImporterService::class); + + try { + $newEgg = $eggImportService->handle($eggFile); + } catch (Exception $exception) { + Notification::make() + ->title("Imported egg successfully: {$exception->getMessage()}") + ->success() + ->send(); + + return; + } + + Notification::make() + ->title("Imported egg successfully: $newEgg->name") + ->success() + ->send(); + + $livewire->redirect(route('filament.admin.resources.eggs.edit', [$newEgg])); + }) + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListEggs::route('/'), + 'create' => Pages\CreateEgg::route('/create'), + 'edit' => Pages\EditEgg::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Resources/EggResource/Pages/CreateEgg.php b/app/Filament/Resources/EggResource/Pages/CreateEgg.php new file mode 100644 index 000000000..4ad3fa691 --- /dev/null +++ b/app/Filament/Resources/EggResource/Pages/CreateEgg.php @@ -0,0 +1,12 @@ +schema([ + Forms\Components\TextInput::make('uuid') + ->label('UUID') + ->required() + ->maxLength(36), + Forms\Components\TextInput::make('name') + ->required() + ->maxLength(191), + Forms\Components\Textarea::make('description') + ->columnSpanFull(), + Forms\Components\TextInput::make('source') + ->required() + ->maxLength(191), + Forms\Components\TextInput::make('target') + ->required() + ->maxLength(191), + Forms\Components\TextInput::make('read_only') + ->required() + ->numeric(), + Forms\Components\TextInput::make('user_mountable') + ->required() + ->numeric(), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('uuid') + ->label('UUID') + ->searchable(), + Tables\Columns\TextColumn::make('name') + ->searchable(), + Tables\Columns\TextColumn::make('source') + ->searchable(), + Tables\Columns\TextColumn::make('target') + ->searchable(), + Tables\Columns\TextColumn::make('read_only') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('user_mountable') + ->numeric() + ->sortable(), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListMounts::route('/'), + 'create' => Pages\CreateMount::route('/create'), + 'edit' => Pages\EditMount::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Resources/MountResource/Pages/CreateMount.php b/app/Filament/Resources/MountResource/Pages/CreateMount.php new file mode 100644 index 000000000..c0cc78371 --- /dev/null +++ b/app/Filament/Resources/MountResource/Pages/CreateMount.php @@ -0,0 +1,12 @@ +schema([ + Forms\Components\TextInput::make('uuid') + ->label('UUID') + ->required() + ->maxLength(36), + Forms\Components\TextInput::make('public') + ->required() + ->numeric(), + Forms\Components\TextInput::make('name') + ->required() + ->maxLength(191), + Forms\Components\Textarea::make('description') + ->columnSpanFull(), + Forms\Components\TextInput::make('location_id') + ->required() + ->numeric(), + Forms\Components\TextInput::make('fqdn') + ->required() + ->maxLength(191), + Forms\Components\TextInput::make('scheme') + ->required() + ->maxLength(191) + ->default('https'), + Forms\Components\Toggle::make('behind_proxy') + ->required(), + Forms\Components\Toggle::make('maintenance_mode') + ->required(), + Forms\Components\TextInput::make('memory') + ->required() + ->numeric(), + Forms\Components\TextInput::make('memory_overallocate') + ->required() + ->numeric() + ->default(0), + Forms\Components\TextInput::make('disk') + ->required() + ->numeric(), + Forms\Components\TextInput::make('disk_overallocate') + ->required() + ->numeric() + ->default(0), + Forms\Components\TextInput::make('upload_size') + ->required() + ->numeric() + ->default(100), + Forms\Components\TextInput::make('daemon_token_id') + ->required() + ->maxLength(16), + Forms\Components\TextInput::make('daemonListen') + ->required() + ->numeric() + ->default(8080), + Forms\Components\TextInput::make('daemonSFTP') + ->required() + ->numeric() + ->default(2022), + Forms\Components\TextInput::make('daemonBase') + ->required() + ->maxLength(191) + ->default('/home/daemon-files'), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('uuid') + ->label('UUID') + ->searchable(), + Tables\Columns\TextColumn::make('public') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('name') + ->searchable(), + Tables\Columns\TextColumn::make('location_id') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('fqdn') + ->searchable(), + Tables\Columns\TextColumn::make('scheme') + ->searchable(), + Tables\Columns\IconColumn::make('behind_proxy') + ->boolean(), + Tables\Columns\IconColumn::make('maintenance_mode') + ->boolean(), + Tables\Columns\TextColumn::make('memory') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('memory_overallocate') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('disk') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('disk_overallocate') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('upload_size') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('daemon_token_id') + ->searchable(), + Tables\Columns\TextColumn::make('daemonListen') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('daemonSFTP') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('daemonBase') + ->searchable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListNodes::route('/'), + 'create' => Pages\CreateNode::route('/create'), + 'edit' => Pages\EditNode::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Resources/NodeResource/Pages/CreateNode.php b/app/Filament/Resources/NodeResource/Pages/CreateNode.php new file mode 100644 index 000000000..c7652c024 --- /dev/null +++ b/app/Filament/Resources/NodeResource/Pages/CreateNode.php @@ -0,0 +1,12 @@ +schema([ + Forms\Components\TextInput::make('external_id') + ->maxLength(191), + Forms\Components\TextInput::make('uuid') + ->label('UUID') + ->required() + ->maxLength(36), + Forms\Components\TextInput::make('uuidShort') + ->required() + ->maxLength(8), + Forms\Components\Select::make('node_id') + ->relationship('node', 'name') + ->required(), + Forms\Components\TextInput::make('name') + ->required() + ->maxLength(191), + Forms\Components\Textarea::make('description') + ->required() + ->columnSpanFull(), + Forms\Components\TextInput::make('status') + ->maxLength(191), + Forms\Components\Toggle::make('skip_scripts') + ->required(), + Forms\Components\TextInput::make('owner_id') + ->required() + ->numeric(), + Forms\Components\TextInput::make('memory') + ->required() + ->numeric(), + Forms\Components\TextInput::make('swap') + ->required() + ->numeric(), + Forms\Components\TextInput::make('disk') + ->required() + ->numeric(), + Forms\Components\TextInput::make('io') + ->required() + ->numeric(), + Forms\Components\TextInput::make('cpu') + ->required() + ->numeric(), + Forms\Components\TextInput::make('threads') + ->maxLength(191), + Forms\Components\TextInput::make('oom_disabled') + ->required() + ->numeric() + ->default(0), + Forms\Components\Select::make('allocation_id') + ->relationship('allocation', 'id') + ->required(), + Forms\Components\TextInput::make('egg_id') + ->required() + ->numeric(), + Forms\Components\Textarea::make('startup') + ->required() + ->columnSpanFull(), + Forms\Components\FileUpload::make('image') + ->image() + ->required(), + Forms\Components\TextInput::make('allocation_limit') + ->numeric(), + Forms\Components\TextInput::make('database_limit') + ->numeric() + ->default(0), + Forms\Components\TextInput::make('backup_limit') + ->required() + ->numeric() + ->default(0), + Forms\Components\DateTimePicker::make('installed_at'), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('external_id') + ->searchable(), + Tables\Columns\TextColumn::make('uuid') + ->label('UUID') + ->searchable(), + Tables\Columns\TextColumn::make('uuidShort') + ->searchable(), + Tables\Columns\TextColumn::make('node.name') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('name') + ->searchable(), + Tables\Columns\TextColumn::make('status') + ->searchable(), + Tables\Columns\IconColumn::make('skip_scripts') + ->boolean(), + Tables\Columns\TextColumn::make('owner_id') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('memory') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('swap') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('disk') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('io') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('cpu') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('threads') + ->searchable(), + Tables\Columns\TextColumn::make('oom_disabled') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('allocation.id') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('egg_id') + ->numeric() + ->sortable(), + Tables\Columns\ImageColumn::make('image'), + Tables\Columns\TextColumn::make('allocation_limit') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('database_limit') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('backup_limit') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('installed_at') + ->dateTime() + ->sortable(), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListServers::route('/'), + 'create' => Pages\CreateServer::route('/create'), + 'edit' => Pages\EditServer::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Resources/ServerResource/Pages/CreateServer.php b/app/Filament/Resources/ServerResource/Pages/CreateServer.php new file mode 100644 index 000000000..223cdf97b --- /dev/null +++ b/app/Filament/Resources/ServerResource/Pages/CreateServer.php @@ -0,0 +1,12 @@ +schema([ + Forms\Components\TextInput::make('external_id') + ->maxLength(191), + Forms\Components\TextInput::make('uuid') + ->label('UUID') + ->required() + ->maxLength(36), + Forms\Components\TextInput::make('username') + ->required() + ->maxLength(191), + Forms\Components\TextInput::make('email') + ->email() + ->required() + ->maxLength(191), + Forms\Components\TextInput::make('name_first') + ->maxLength(191), + Forms\Components\TextInput::make('name_last') + ->maxLength(191), + Forms\Components\Textarea::make('password') + ->required() + ->columnSpanFull(), + Forms\Components\TextInput::make('language') + ->required() + ->maxLength(5) + ->default('en'), + Forms\Components\TextInput::make('root_admin') + ->required() + ->numeric() + ->default(0), + Forms\Components\TextInput::make('use_totp') + ->required() + ->numeric(), + Forms\Components\Textarea::make('totp_secret') + ->columnSpanFull(), + Forms\Components\DateTimePicker::make('totp_authenticated_at'), + Forms\Components\Toggle::make('gravatar') + ->required(), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('external_id') + ->searchable(), + Tables\Columns\TextColumn::make('uuid') + ->label('UUID') + ->searchable(), + Tables\Columns\TextColumn::make('username') + ->searchable(), + Tables\Columns\TextColumn::make('email') + ->searchable(), + Tables\Columns\TextColumn::make('name_first') + ->searchable(), + Tables\Columns\TextColumn::make('name_last') + ->searchable(), + Tables\Columns\TextColumn::make('language') + ->searchable(), + Tables\Columns\TextColumn::make('root_admin') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('use_totp') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('totp_authenticated_at') + ->dateTime() + ->sortable(), + Tables\Columns\IconColumn::make('gravatar') + ->boolean(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListUsers::route('/'), + 'create' => Pages\CreateUser::route('/create'), + 'edit' => Pages\EditUser::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Resources/UserResource/Pages/CreateUser.php b/app/Filament/Resources/UserResource/Pages/CreateUser.php new file mode 100644 index 000000000..73aa46d00 --- /dev/null +++ b/app/Filament/Resources/UserResource/Pages/CreateUser.php @@ -0,0 +1,12 @@ +