-
{{ $jail['name'] }}
-
- ($jail['currentlyBanned'] ?? 0) > 0])>{{ __('servers.fail2ban_banned', ['count' => $jail['currentlyBanned'] ?? 0]) }}
- · {{ __('servers.fail2ban_failed', ['count' => $jail['currentlyFailed'] ?? 0]) }}
-
+ // Show a panel ONLY when its tool is actually installed (active or inactive).
+ // When absent, the Sicherheit checklist row carries the "Aktivieren" install
+ // path — so the redundant "nicht installiert" box is gone.
+ $showFw = $fwSupported && $fwInstalled;
+ $showF2b = $f2bSupported && $f2bInstalled;
+ $panelCount = ($showFw ? 1 : 0) + ($showF2b ? 1 : 0);
+ @endphp
+
+ @if ($panelCount > 0)
+
$panelCount === 2])>
+ @if ($showFw)
+ {{-- Firewall-Regeln --}}
+
+ @if ($fwManageable)
+
+
+ {{ __('servers.firewall_add_rule') }}
+
+
+ @endif
+
+ @if ($fwReadError)
+
+
+
{{ __('servers.firewall_read_error') }}
- @if (count($jail['bannedIps'] ?? []))
-
- @foreach ($jail['bannedIps'] as $ip)
-
-
{{ $ip }}
-
{{ __('common.unlock') }}
+ @elseif ($fwTool === 'firewalld' && ! $fwActive)
+
+
{{ __('servers.firewalld_inactive') }}
+
+ {{ __('common.enable') }}
+
+
+ @else
+
+ @if ($fwTool === 'ufw')
+ {{ __('servers.firewall_default') }}
+ {{ __('servers.firewall_incoming', ['value' => $fwDefaults['incoming'] ?? '—']) }}
+ {{ __('servers.firewall_outgoing', ['value' => $fwDefaults['outgoing'] ?? '—']) }}
+ @else
+ {{ __('servers.firewall_zone') }}
+ {{ $fwDefaults['zone'] ?? '—' }}
+ @endif
+
+
+ @if ($fwReadOnly)
+
+
+
{{ __('servers.firewall_readonly') }}
+
+ @endif
+
+
+ @forelse ($fwRules as $rule)
+ {{-- $ruleTone, NOT $tone: the page-level $tone is a closure used by the
+ gauges/Volumes panel; reusing the name here would clobber it. --}}
+ @php $ruleTone = $actTone[$rule['action'] ?? 'ALLOW'] ?? 'online'; @endphp
+
+
$ruleTone === 'online',
+ 'bg-warning' => $ruleTone === 'warning',
+ 'bg-offline' => $ruleTone === 'offline',
+ ])>
+
+
{{ $rule['label'] ?? ($rule['to'] ?? $rule['raw']) }}
+ @if ($fwTool === 'ufw' && ($rule['from'] ?? '') !== '' && ! \Illuminate\Support\Str::contains($rule['from'], 'Anywhere'))
+
{{ __('servers.firewall_rule_from', ['value' => $rule['from']]) }}
+ @endif
+
$ruleTone === 'online',
+ 'text-warning' => $ruleTone === 'warning',
+ 'text-offline' => $ruleTone === 'offline',
+ ])>{{ strtolower($rule['action'] ?? 'allow') }}
+ @unless ($fwReadOnly)
+
+
+
+ @endunless
+
+ @empty
+
+
{{ __('servers.firewall_no_rules') }}
+
+ @endforelse
+
+ @endif
+
+ @endif
+
+ @if ($showF2b)
+ {{-- fail2ban-Status --}}
+
+ @if ($f2bActive)
+
+
+
+
+
+ {{ __('servers.fail2ban_ban_ip') }}
+
+
+ @endif
+
+ @if ($f2bReadError)
+
+
+
{{ __('servers.fail2ban_read_error') }}
+
+ @elseif (! $f2bActive)
+
+
{{ __('servers.fail2ban_state_installed_inactive') }}
+
+ {{ __('common.enable') }}
+
+
+ @else
+
+ @foreach ($f2bJails as $jail)
+
+
+
{{ $jail['name'] }}
+
+ ($jail['currentlyBanned'] ?? 0) > 0])>{{ __('servers.fail2ban_banned', ['count' => $jail['currentlyBanned'] ?? 0]) }}
+ · {{ __('servers.fail2ban_failed', ['count' => $jail['currentlyFailed'] ?? 0]) }}
+
+
+ @if (count($jail['bannedIps'] ?? []))
+
+ @foreach ($jail['bannedIps'] as $ip)
+
+ {{ $ip }}
+ {{ __('common.unlock') }}
+
+ @endforeach
+
+ @else
+
{{ __('servers.fail2ban_no_banned') }}
+ @endif
+
+ @endforeach
+
+
+ {{-- Whitelist (ignoreip) --}}
+
+
{{ __('servers.whitelist_label') }}
+
+ @foreach ($f2bIgnore as $ip)
+
+ {{ $ip }}
+ @unless (in_array($ip, ['127.0.0.1/8', '::1'], true))
+
+
+
+ @endunless
+
@endforeach
- @else
-
{{ __('servers.fail2ban_no_banned') }}
- @endif
-
- @endforeach
-
-
- {{-- Whitelist (ignoreip) --}}
-
-
{{ __('servers.whitelist_label') }}
-
- @foreach ($f2bIgnore as $ip)
-
- {{ $ip }}
- @unless (in_array($ip, ['127.0.0.1/8', '::1'], true))
-
-
-
- @endunless
-
- @endforeach
-
-
-
- {{ __('common.add') }}
-
-
- @endif
-
+
+
+ {{ __('common.add') }}
+
+
+ @endif
+
+ @endif
+
+ @endif
{{-- Volumes + Netzwerk-Interfaces --}}
diff --git a/tests/Feature/ServerShowPanelsTest.php b/tests/Feature/ServerShowPanelsTest.php
new file mode 100644
index 0000000..e0af616
--- /dev/null
+++ b/tests/Feature/ServerShowPanelsTest.php
@@ -0,0 +1,44 @@
+ 's', 'ip' => '10.0.0.9', 'ssh_port' => 22, 'status' => 'online']);
+ }
+
+ public function test_firewall_and_fail2ban_panels_hidden_when_not_installed(): void
+ {
+ $this->actingAs(User::factory()->create());
+
+ Livewire::test(Show::class, ['server' => $this->server()])
+ ->set('ready', true)
+ ->set('firewall', ['supported' => true, 'installed' => false])
+ ->set('fail2ban', ['supported' => true, 'installed' => false])
+ ->assertDontSee(__('servers.firewall_title'))
+ ->assertDontSee(__('servers.fail2ban_title'));
+ }
+
+ public function test_both_panels_shown_when_installed(): void
+ {
+ $this->actingAs(User::factory()->create());
+
+ Livewire::test(Show::class, ['server' => $this->server()])
+ ->set('ready', true)
+ ->set('firewall', ['supported' => true, 'installed' => true, 'active' => true, 'tool' => 'ufw', 'manageable' => true, 'rules' => [], 'defaults' => []])
+ ->set('fail2ban', ['supported' => true, 'installed' => true, 'active' => true, 'jails' => [], 'ignoreip' => []])
+ ->assertSee(__('servers.firewall_title'))
+ ->assertSee(__('servers.fail2ban_title'));
+ }
+}