Enable ipv6 on frontend (#1350)

This commit is contained in:
Boy132 2025-05-09 08:44:18 +02:00 committed by GitHub
parent 67705b14b4
commit 8406f4686c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 45 additions and 47 deletions

View File

@ -12,8 +12,7 @@ use Filament\Forms\Components\TextInput;
use Filament\Forms\Get;
use Filament\Forms\Set;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Tables;
use Filament\Tables\Actions\BulkActionGroup;
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\DeleteBulkAction;
use Filament\Tables\Columns\SelectColumn;
use Filament\Tables\Columns\TextColumn;
@ -32,18 +31,12 @@ class AllocationsRelationManager extends RelationManager
public function setTitle(): string
{
return trans('admin/server.allocations');
}
public function table(Table $table): Table
{
return $table
->recordTitleAttribute('ip')
// Non Primary Allocations
// ->checkIfRecordIsSelectableUsing(fn (Allocation $allocation) => $allocation->id !== $allocation->server?->allocation_id)
// All assigned allocations
->recordTitleAttribute('address')
->checkIfRecordIsSelectableUsing(fn (Allocation $allocation) => $allocation->server_id === null)
->paginationPageOptions(['10', '20', '50', '100', '200', '500'])
->searchable()
@ -72,14 +65,14 @@ class AllocationsRelationManager extends RelationManager
->label(trans('admin/node.table.ip')),
])
->headerActions([
Tables\Actions\Action::make('create new allocation')
Action::make('create new allocation')
->label(trans('admin/node.create_allocation'))
->form(fn () => [
Select::make('allocation_ip')
->options(collect($this->getOwnerRecord()->ipAddresses())->mapWithKeys(fn (string $ip) => [$ip => $ip]))
->label(trans('admin/node.ip_address'))
->inlineLabel()
->ipv4()
->ip()
->helperText(trans('admin/node.ip_help'))
->afterStateUpdated(fn (Set $set) => $set('allocation_ports', []))
->live()
@ -96,19 +89,15 @@ class AllocationsRelationManager extends RelationManager
->inlineLabel()
->live()
->disabled(fn (Get $get) => empty($get('allocation_ip')))
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('allocation_ports',
CreateServer::retrieveValidPorts($this->getOwnerRecord(), $state, $get('allocation_ip')))
)
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('allocation_ports', CreateServer::retrieveValidPorts($this->getOwnerRecord(), $state, $get('allocation_ip'))))
->splitKeys(['Tab', ' ', ','])
->required(),
])
->action(fn (array $data, AssignmentService $service) => $service->handle($this->getOwnerRecord(), $data)),
])
->bulkActions([
BulkActionGroup::make([
DeleteBulkAction::make()
->authorize(fn () => auth()->user()->can('update node')),
]),
->groupedBulkActions([
DeleteBulkAction::make()
->authorize(fn () => auth()->user()->can('update node')),
]);
}
}

View File

@ -189,10 +189,7 @@ class CreateServer extends CreateRecord
$set('allocation_additional', null);
$set('allocation_additional.needstobeastringhere.extra_allocations', null);
})
->getOptionLabelFromRecordUsing(
fn (Allocation $allocation) => "$allocation->ip:$allocation->port" .
($allocation->ip_alias ? " ($allocation->ip_alias)" : '')
)
->getOptionLabelFromRecordUsing(fn (Allocation $allocation) => $allocation->address)
->placeholder(function (Get $get) {
$node = Node::find($get('node_id'));
@ -218,7 +215,7 @@ class CreateServer extends CreateRecord
->label(trans('admin/server.ip_address'))->inlineLabel()
->helperText(trans('admin/server.ip_address_helper'))
->afterStateUpdated(fn (Set $set) => $set('allocation_ports', []))
->ipv4()
->ip()
->live()
->required(),
TextInput::make('allocation_alias')
@ -269,10 +266,7 @@ class CreateServer extends CreateRecord
->columnSpan(2)
->disabled(fn (Get $get) => $get('../../node_id') === null)
->searchable(['ip', 'port', 'ip_alias'])
->getOptionLabelFromRecordUsing(
fn (Allocation $allocation) => "$allocation->ip:$allocation->port" .
($allocation->ip_alias ? " ($allocation->ip_alias)" : '')
)
->getOptionLabelFromRecordUsing(fn (Allocation $allocation) => $allocation->address)
->placeholder(trans('admin/server.select_additional'))
->disableOptionsWhenSelectedInSiblingRepeaterItems()
->relationship(

View File

@ -16,6 +16,7 @@ use Filament\Support\Exceptions\Halt;
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\AssociateAction;
use Filament\Tables\Actions\CreateAction;
use Filament\Tables\Actions\DissociateAction;
use Filament\Tables\Actions\DissociateBulkAction;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
@ -34,15 +35,18 @@ class AllocationsRelationManager extends RelationManager
{
return $table
->selectCurrentPageOnly()
->recordTitleAttribute('ip')
->recordTitle(fn (Allocation $allocation) => "$allocation->ip:$allocation->port")
->recordTitleAttribute('address')
->recordTitle(fn (Allocation $allocation) => $allocation->address)
->checkIfRecordIsSelectableUsing(fn (Allocation $record) => $record->id !== $this->getOwnerRecord()->allocation_id)
->inverseRelationship('server')
->heading(trans('admin/server.allocations'))
->columns([
TextColumn::make('ip')->label(trans('admin/server.ip_address')),
TextColumn::make('port')->label(trans('admin/server.port')),
TextInputColumn::make('ip_alias')->label(trans('admin/server.alias')),
TextColumn::make('ip')
->label(trans('admin/server.ip_address')),
TextColumn::make('port')
->label(trans('admin/server.port')),
TextInputColumn::make('ip_alias')
->label(trans('admin/server.alias')),
IconColumn::make('primary')
->icon(fn ($state) => match ($state) {
true => 'tabler-star-filled',
@ -58,8 +62,11 @@ class AllocationsRelationManager extends RelationManager
])
->actions([
Action::make('make-primary')
->label(trans('admin/server.make_primary'))
->action(fn (Allocation $allocation) => $this->getOwnerRecord()->update(['allocation_id' => $allocation->id]) && $this->deselectAllTableRecords())
->label(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id ? '' : trans('admin/server.make_primary')),
->hidden(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id),
DissociateAction::make()
->hidden(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id),
])
->headerActions([
CreateAction::make()->label(trans('admin/server.create_allocation'))
@ -69,7 +76,7 @@ class AllocationsRelationManager extends RelationManager
->options(collect($this->getOwnerRecord()->node->ipAddresses())->mapWithKeys(fn (string $ip) => [$ip => $ip]))
->label(trans('admin/server.ip_address'))
->inlineLabel()
->ipv4()
->ip()
->live()
->afterStateUpdated(fn (Set $set) => $set('allocation_ports', []))
->required(),
@ -85,9 +92,7 @@ class AllocationsRelationManager extends RelationManager
->inlineLabel()
->live()
->disabled(fn (Get $get) => empty($get('allocation_ip')))
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('allocation_ports',
CreateServer::retrieveValidPorts($this->getOwnerRecord()->node, $state, $get('allocation_ip')))
)
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('allocation_ports', CreateServer::retrieveValidPorts($this->getOwnerRecord()->node, $state, $get('allocation_ip'))))
->splitKeys(['Tab', ' ', ','])
->required(),
])

View File

@ -117,7 +117,7 @@ class Allocation extends Model
protected function address(): Attribute
{
return Attribute::make(
get: fn () => "$this->alias:$this->port",
get: fn () => (is_ipv6($this->alias) ? "[$this->alias]" : $this->alias) . ":$this->port",
);
}

View File

@ -403,10 +403,11 @@ class Node extends Model implements Validatable
}
}
// Only IPV4
$ips = $ips->filter(fn (string $ip) => filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false);
$ips = $ips->filter(fn (string $ip) => is_ip($ip));
// TODO: remove later
$ips->push('0.0.0.0');
$ips->push('::');
return $ips->unique()->all();
});

View File

@ -51,12 +51,7 @@ class AssignmentService
}
try {
// TODO: how should we approach supporting IPv6 with this?
// gethostbyname only supports IPv4, but the alternative (dns_get_record) returns
// an array of records, which is not ideal for this use case, we need a SINGLE
// IP to use, not multiple.
$underlying = gethostbyname($data['allocation_ip']);
$parsed = Network::parse($underlying);
$parsed = Network::parse($data['allocation_ip']);
} catch (\Exception $exception) {
throw new DisplayException("Could not parse provided allocation IP address ({$data['allocation_ip']}): {$exception->getMessage()}", $exception);
}

View File

@ -18,6 +18,20 @@ if (!function_exists('is_ip')) {
}
}
if (!function_exists('is_ipv4')) {
function is_ipv4(?string $address): bool
{
return $address !== null && filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false;
}
}
if (!function_exists('is_ipv6')) {
function is_ipv6(?string $address): bool
{
return $address !== null && filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false;
}
}
if (!function_exists('convert_bytes_to_readable')) {
function convert_bytes_to_readable(int $bytes, int $decimals = 2, ?int $base = null): string
{