Disaster Recovery v2

This commit is contained in:
Charles 2025-06-23 08:51:21 -04:00
parent e5cdd05167
commit dfaf287088
24 changed files with 100 additions and 60 deletions

View File

@ -58,7 +58,7 @@ class GSLToken extends FeatureProvider
->modalHeading('Invalid GSL token')
->modalDescription('It seems like your Gameserver Login Token (GSL token) is invalid or has expired.')
->modalSubmitActionLabel('Update GSL Token')
->disabledForm(fn () => !auth()->user()->can(Permission::ACTION_STARTUP_UPDATE, $server))
->disabledSchema(fn () => !auth()->user()->can(Permission::ACTION_STARTUP_UPDATE, $server))
->form([
Placeholder::make('info')
->label(new HtmlString(Blade::render('You can either <x-filament::link href="https://steamcommunity.com/dev/managegameservers" target="_blank">generate a new one</x-filament::link> and enter it below or leave the field blank to remove it completely.'))),

View File

@ -9,8 +9,8 @@ use App\Repositories\Daemon\DaemonPowerRepository;
use Exception;
use Filament\Actions\Action;
use Filament\Facades\Filament;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Select;
use Filament\Infolists\Components\TextEntry;
use Filament\Notifications\Notification;
use Illuminate\Foundation\Application;
@ -49,9 +49,9 @@ class JavaVersion extends FeatureProvider
->modalHeading('Unsupported Java Version')
->modalDescription('This server is currently running an unsupported version of Java and cannot be started.')
->modalSubmitActionLabel('Update Docker Image')
->disabledForm(fn () => !auth()->user()->can(Permission::ACTION_STARTUP_DOCKER_IMAGE, $server))
->disabledSchema(fn () => !auth()->user()->can(Permission::ACTION_STARTUP_DOCKER_IMAGE, $server))
->schema([
Placeholder::make('java')
TextEntry::make('java')
->label('Please select a supported version from the list below to continue starting the server.'),
Select::make('image')
->label('Docker Image')

View File

@ -34,6 +34,7 @@ use Filament\Schemas\Components\Tabs;
use Filament\Schemas\Components\Tabs\Tab;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Support\Enums\Width;
use Illuminate\Http\Client\Factory;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Artisan;
@ -210,7 +211,7 @@ class Settings extends Page implements HasSchemas
Select::make('FILAMENT_WIDTH')
->label(trans('admin/setting.general.display_width'))
->native(false)
//TODO->options(MaxWidth::class)
->options(Width::class)
->selectablePlaceholder(false)
->default(env('FILAMENT_WIDTH', config('panel.filament.display-width'))),
TagsInput::make('TRUSTED_PROXIES')

View File

@ -95,7 +95,7 @@ class ApiKeyResource extends Resource
->icon('tabler-user')
->url(fn (ApiKey $apiKey) => auth()->user()->can('update', $apiKey->user) ? EditUser::getUrl(['record' => $apiKey->user]) : null),
])
->actions([
->recordActions([
DeleteAction::make(),
])
->emptyStateIcon('tabler-key')

View File

@ -88,7 +88,7 @@ class DatabaseHostResource extends Resource
->placeholder(trans('admin/databasehost.no_nodes')),
])
->checkIfRecordIsSelectableUsing(fn (DatabaseHost $databaseHost) => !$databaseHost->databases_count)
->actions([
->recordActions([
ViewAction::make()
->hidden(fn ($record) => static::canEdit($record)),
EditAction::make(),

View File

@ -67,7 +67,7 @@ class DatabasesRelationManager extends RelationManager
DateTimeColumn::make('created_at')
->label(trans('admin/databasehost.table.created_at')),
])
->actions([
->recordActions([
DeleteAction::make()
->authorize(fn (Database $database) => auth()->user()->can('delete', $database)),
ViewAction::make()

View File

@ -91,7 +91,7 @@ class MountResource extends Resource
->color(fn ($state) => $state ? 'success' : 'warning')
->formatStateUsing(fn ($state) => $state ? trans('admin/mount.toggles.read_only') : trans('admin/mount.toggles.writable')),
])
->actions([
->recordActions([
ViewAction::make()
->hidden(fn ($record) => static::canEdit($record)),
EditAction::make(),

View File

@ -63,7 +63,7 @@ class ListNodes extends ListRecords
->sortable()
->icon('tabler-brand-docker'),
])
->actions([
->recordActions([
EditAction::make(),
])
->emptyStateIcon('tabler-server-2')

View File

@ -6,6 +6,7 @@ use App\Filament\Admin\Resources\ServerResource\Pages\CreateServer;
use App\Models\Allocation;
use App\Models\Node;
use App\Services\Allocations\AssignmentService;
use Exception;
use Filament\Actions\Action;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TagsInput;
@ -33,6 +34,9 @@ class AllocationsRelationManager extends RelationManager
return trans('admin/server.allocations');
}
/**
* @throws Exception
*/
public function table(Table $table): Table
{
return $table

View File

@ -68,6 +68,9 @@ class RoleResource extends Resource
return static::getModel()::count() ?: null;
}
/**
* @throws Exception
*/
public static function defaultTable(Table $table): Table
{
return $table
@ -90,7 +93,7 @@ class RoleResource extends Resource
->counts('users')
->icon('tabler-users'),
])
->actions([
->recordActions([
ViewAction::make()
->hidden(fn ($record) => static::canEdit($record)),
EditAction::make(),
@ -110,7 +113,7 @@ class RoleResource extends Resource
/**
* @throws Exception
*/
public static function form(Schema $form): Schema
public static function form(Schema $schema): Schema
{
$permissionSections = [];

View File

@ -89,7 +89,7 @@ class ListServers extends ListRecords
->numeric()
->sortable(),
])
->actions([
->recordActions([
Action::make('View')
->label(trans('admin/server.view'))
->icon('tabler-terminal')

View File

@ -6,6 +6,7 @@ use App\Filament\Admin\Resources\ServerResource\Pages\CreateServer;
use App\Models\Allocation;
use App\Models\Server;
use App\Services\Allocations\AssignmentService;
use Filament\Actions\DissociateAction;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TagsInput;
use Filament\Forms\Components\TextInput;
@ -59,7 +60,7 @@ class AllocationsRelationManager extends RelationManager
->default(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id)
->label(trans('admin/server.primary')),
])
->actions([
->recordActions([
Action::make('make-primary')
->label(trans('admin/server.make_primary'))
->action(fn (Allocation $allocation) => $this->getOwnerRecord()->update(['allocation_id' => $allocation->id]) && $this->deselectAllTableRecords())

View File

@ -99,7 +99,7 @@ class UserResource extends Resource
->counts('subusers')
->icon('tabler-users'),
])
->actions([
->recordActions([
ViewAction::make()
->hidden(fn ($record) => static::canEdit($record)),
EditAction::make(),
@ -110,9 +110,9 @@ class UserResource extends Resource
]);
}
public static function form(Schema $form): Schema
public static function form(Schema $schema): Schema
{
return $form
return $schema
->columns(['default' => 1, 'lg' => 3])
->components([
TextInput::make('username')

View File

@ -68,7 +68,7 @@ class WebhookResource extends Resource
TextColumn::make('endpoint')
->label(trans('admin/webhook.table.endpoint')),
])
->actions([
->recordActions([
ViewAction::make()
->hidden(fn ($record) => static::canEdit($record)),
EditAction::make(),

View File

@ -36,6 +36,7 @@ use Filament\Forms\Components\ToggleButtons;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Notifications\Notification;
use Filament\Schemas\Components\Actions;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Schemas\Schema;
use Filament\Support\Colors\Color;
use Filament\Support\Enums\Width;
@ -409,10 +410,10 @@ class EditProfile extends \Filament\Auth\Pages\EditProfile
->reactive()
->default('monospace')
->afterStateUpdated(fn ($state, Set $set) => $set('font_preview', $state)),
Placeholder::make('font_preview')
TextEntry::make('font_preview')
->label(trans('profile.font_preview'))
->columnSpan(2)
->content(function (Get $get) {
->state(function (Get $get) {
$fontName = $get('console_font') ?? 'monospace';
$fontSize = $get('console_font_size') . 'px';
$style = <<<CSS

View File

@ -13,15 +13,15 @@ use App\Models\User;
use App\Traits\Filament\CanCustomizePages;
use App\Traits\Filament\CanCustomizeRelations;
use App\Traits\Filament\CanModifyTable;
use Filament\Actions\Action;
use Filament\Actions\ViewAction;
use Filament\Facades\Filament;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\KeyValue;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Resources\Pages\PageRegistration;
use Filament\Resources\Resource;
use Filament\Tables\Actions\ViewAction;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
@ -48,6 +48,9 @@ class ActivityResource extends Resource
protected static bool $isScopedToTenant = false;
/**
* @throws \Exception
*/
public static function defaultTable(Table $table): Table
{
/** @var Server $server */
@ -86,12 +89,12 @@ class ActivityResource extends Resource
->grow(false),
])
->defaultSort('timestamp', 'desc')
->actions([
->recordActions([
ViewAction::make()
//->visible(fn (ActivityLog $activityLog) => $activityLog->hasAdditionalMetadata())
->form([
Placeholder::make('event')
->content(fn (ActivityLog $activityLog) => new HtmlString($activityLog->getLabel())),
->schema([
TextEntry::make('event')
->state(fn (ActivityLog $activityLog) => new HtmlString($activityLog->getLabel())),
TextInput::make('user')
->formatStateUsing(function (ActivityLog $activityLog) use ($server) {
if (!$activityLog->actor instanceof User) {

View File

@ -11,10 +11,11 @@ use App\Traits\Filament\BlockAccessInConflict;
use App\Traits\Filament\CanCustomizePages;
use App\Traits\Filament\CanCustomizeRelations;
use App\Traits\Filament\CanModifyTable;
use Exception;
use Filament\Actions\DetachAction;
use Filament\Facades\Filament;
use Filament\Resources\Pages\PageRegistration;
use Filament\Resources\Resource;
use Filament\Tables\Actions\DetachAction;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Columns\TextInputColumn;
@ -38,6 +39,9 @@ class AllocationResource extends Resource
protected static string|\BackedEnum|null $navigationIcon = 'tabler-network';
/**
* @throws Exception
*/
public static function defaultTable(Table $table): Table
{
/** @var Server $server */
@ -73,7 +77,7 @@ class AllocationResource extends Resource
->default(fn (Allocation $allocation) => $allocation->id === $server->allocation_id)
->label('Primary'),
])
->actions([
->recordActions([
DetachAction::make()
->authorize(fn () => auth()->user()->can(Permission::ACTION_ALLOCATION_DELETE, $server))
->label('Delete')

View File

@ -21,25 +21,26 @@ use App\Traits\Filament\CanCustomizeRelations;
use App\Traits\Filament\CanModifyForm;
use App\Traits\Filament\CanModifyTable;
use App\Traits\Filament\HasLimitBadge;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Actions\DeleteAction;
use Filament\Facades\Filament;
use Filament\Forms\Components\Checkbox;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Forms\Form;
use Filament\Infolists\Components\TextEntry;
use Filament\Notifications\Notification;
use Filament\Resources\Pages\PageRegistration;
use Filament\Resources\Resource;
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\ActionGroup;
use Filament\Tables\Actions\DeleteAction;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Request;
use Throwable;
class BackupResource extends Resource
{
@ -74,7 +75,7 @@ class BackupResource extends Resource
return $server->backup_limit;
}
public static function defaultForm(Form $form): Form
public static function defaultForm(Schema $schema): Schema
{
return $form
->schema([
@ -90,6 +91,10 @@ class BackupResource extends Resource
]);
}
/**
* @throws Throwable
* @throws ConnectionException
*/
public static function defaultTable(Table $table): Table
{
/** @var Server $server */
@ -114,7 +119,7 @@ class BackupResource extends Resource
->trueIcon('tabler-lock')
->falseIcon('tabler-lock-open'),
])
->actions([
->recordActions([
ActionGroup::make([
Action::make('lock')
->icon(fn (Backup $backup) => !$backup->is_locked ? 'tabler-lock' : 'tabler-lock-open')
@ -133,7 +138,8 @@ class BackupResource extends Resource
->icon('tabler-folder-up')
->authorize(fn () => auth()->user()->can(Permission::ACTION_BACKUP_RESTORE, $server))
->form([
Placeholder::make('')
TextEntry::make('INeedAName')
->hiddenLabel()
->helperText('Your server will be stopped. You will not be able to control the power state, access the file manager, or create additional backups until this process is completed.'),
Checkbox::make('truncate')
->label('Delete all files before restoring backup?'),

View File

@ -15,17 +15,17 @@ use App\Traits\Filament\CanCustomizeRelations;
use App\Traits\Filament\CanModifyForm;
use App\Traits\Filament\CanModifyTable;
use App\Traits\Filament\HasLimitBadge;
use Exception;
use Filament\Actions\DeleteAction;
use Filament\Actions\ViewAction;
use Filament\Facades\Filament;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Resources\Pages\PageRegistration;
use Filament\Resources\Resource;
use Filament\Tables\Actions\DeleteAction;
use Filament\Tables\Actions\ViewAction;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;
use Webbingbrasil\FilamentCopyActions\Forms\Actions\CopyAction;
class DatabaseResource extends Resource
{
@ -58,20 +58,23 @@ class DatabaseResource extends Resource
return $server->database_limit;
}
public static function defaultForm(Form $form): Form
/**
* @throws Exception
*/
public static function defaultForm(Schema $schema): Schema
{
/** @var Server $server */
$server = Filament::getTenant();
return $form
return $schema
->schema([
TextInput::make('host')
->formatStateUsing(fn (Database $database) => $database->address())
->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null),
TextInput::make('database')
->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null),
TextInput::make('username')
->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null),
->formatStateUsing(fn (Database $database) => $database->address()),
// TODO ->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null),
TextInput::make('database'),
//TODO ->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null),
TextInput::make('username'),
//TODO ->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null),
TextInput::make('password')
->password()->revealable()
->hidden(fn () => !auth()->user()->can(Permission::ACTION_DATABASE_VIEW_PASSWORD, $server))
@ -79,7 +82,7 @@ class DatabaseResource extends Resource
RotateDatabasePasswordAction::make()
->authorize(fn () => auth()->user()->can(Permission::ACTION_DATABASE_UPDATE, $server))
)
->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null)
//TODO ->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null)
->formatStateUsing(fn (Database $database) => $database->password),
TextInput::make('remote')
->label('Connections From'),
@ -89,12 +92,15 @@ class DatabaseResource extends Resource
->label('JDBC Connection String')
->password()->revealable()
->hidden(!auth()->user()->can(Permission::ACTION_DATABASE_VIEW_PASSWORD, $server))
->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null)
//TODO ->suffixAction(fn (string $state) => request()->isSecure() ? CopyAction::make()->copyable($state) : null)
->columnSpanFull()
->formatStateUsing(fn (Database $database) => $database->jdbc),
]);
}
/**
* @throws Exception
*/
public static function defaultTable(Table $table): Table
{
return $table
@ -108,7 +114,7 @@ class DatabaseResource extends Resource
DateTimeColumn::make('created_at')
->sortable(),
])
->actions([
->recordActions([
ViewAction::make()
->modalHeading(fn (Database $database) => 'Viewing ' . $database->database),
DeleteAction::make()

View File

@ -109,7 +109,7 @@ class ListFiles extends ListRecords
return $file->canEdit() ? EditFiles::getUrl(['path' => join_paths($this->path, $file->name)]) : null;
})
->actions([
->recordActions([
Action::make('view')
->authorize(fn () => auth()->user()->can(Permission::ACTION_FILE_READ, $server))
->label('Open')

View File

@ -17,6 +17,9 @@ use App\Traits\Filament\CanModifyTable;
use Carbon\Carbon;
use Exception;
use Filament\Actions\Action;
use Filament\Actions\DeleteAction;
use Filament\Actions\EditAction;
use Filament\Actions\ViewAction;
use Filament\Facades\Filament;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
@ -31,14 +34,12 @@ use Filament\Resources\RelationManagers\RelationManager;
use Filament\Resources\Resource;
use Filament\Support\Enums\Operation;
use Filament\Support\Exceptions\Halt;
use Filament\Tables\Actions\DeleteAction;
use Filament\Tables\Actions\EditAction;
use Filament\Tables\Actions\ViewAction;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Model;
use Filament\Schemas\Schema;
use Throwable;
class ScheduleResource extends Resource
{
@ -316,6 +317,9 @@ class ScheduleResource extends Resource
]);
}
/**
* @throws Throwable
*/
public static function defaultTable(Table $table): Table
{
return $table
@ -341,7 +345,7 @@ class ScheduleResource extends Resource
->sortable()
->state(fn (Schedule $schedule) => $schedule->is_active ? $schedule->next_run_at : null),
])
->actions([
->recordActions([
ViewAction::make(),
EditAction::make(),
DeleteAction::make()

View File

@ -5,6 +5,7 @@ namespace App\Filament\Server\Resources\ScheduleResource\RelationManagers;
use App\Facades\Activity;
use App\Models\Schedule;
use App\Models\Task;
use Exception;
use Filament\Forms\Components\Field;
use Filament\Actions\DeleteAction;
use Filament\Forms\Components\Select;
@ -38,6 +39,8 @@ class TasksRelationManager extends RelationManager
/**
* @return array<Field>
*
* @throws Exception
*/
private function getTaskForm(Schedule $schedule): array
{
@ -75,6 +78,9 @@ class TasksRelationManager extends RelationManager
];
}
/**
* @throws Exception
*/
public function table(Table $table): Table
{
/** @var Schedule $schedule */
@ -97,7 +103,7 @@ class TasksRelationManager extends RelationManager
IconColumn::make('continue_on_failure')
->boolean(),
])
->actions([
->recordActions([
EditAction::make()
->schema($this->getTaskForm($schedule))
->mutateDataUsing(function ($data) {

View File

@ -127,7 +127,7 @@ class UserResource extends Resource
TextColumn::make('permissions')
->state(fn (User $user) => count($server->subusers->where('user_id', $user->id)->first()->permissions)),
])
->actions([
->recordActions([
DeleteAction::make()
->label('Remove User')
->hidden(fn (User $user) => auth()->user()->id === $user->id)

View File

@ -11,6 +11,7 @@ use Filament\Widgets\ChartWidget;
class ServerNetworkChart extends ChartWidget
{
protected ?string $pollingInterval = '1s';
protected ?string $maxHeight = '200px';
public ?Server $server = null;