fix(server): hide server IP addresses on the servers list

The dashboard redesign added an IP address column to the servers list
and put each server IP into the Alpine data, so the IP showed in the
page source. Remove the column and the value, and render the component
in the test instead of matching template strings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2026-09-28 14:28:01 +02:00
co-authored by Claude Opus 5.5
parent 81af5892d7
commit f008e0593b
2 changed files with 40 additions and 15 deletions
@@ -59,7 +59,6 @@
'href' => route('server.show', ['server_uuid' => $server->uuid]),
'status' => $status,
'statusType' => $statusType,
'ip' => $server->isLocalhost() ? 'localhost' : ($server->ip ?: '-'),
'resourceCount' => $server->definedResources()->count(),
];
})->values();
@@ -174,15 +173,14 @@
<div x-show="viewMode === 'table'"
class="overflow-x-auto rounded-xl border border-neutral-200 bg-white shadow-sm dark:border-white/[0.08] dark:bg-white/[0.05]">
<div
class="grid min-w-[480px] grid-cols-[minmax(0,1fr)_9.5rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 md:min-w-[640px] md:grid-cols-[minmax(0,1fr)_11rem_6rem_9.5rem] dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
class="grid min-w-[480px] grid-cols-[minmax(0,1fr)_9.5rem] border-b border-neutral-200 bg-neutral-50 px-4 py-2.5 text-[11px] font-medium text-neutral-500 md:min-w-[560px] md:grid-cols-[minmax(0,1fr)_6rem_9.5rem] dark:border-white/[0.08] dark:bg-white/[0.05] dark:text-fg-faint">
<div>Server</div>
<div class="hidden md:block">IP address</div>
<div class="hidden md:block">Resources</div>
<div>Status</div>
</div>
<template x-for="server in filteredServers" :key="server.uuid">
<a :href="server.href" {{ wireNavigate() }}
class="grid min-h-14 min-w-[480px] grid-cols-[minmax(0,1fr)_9.5rem] items-center border-b border-neutral-200 px-4 py-2.5 text-[12px] transition-colors last:border-b-0 hover:bg-neutral-50 hover:no-underline md:min-w-[640px] md:grid-cols-[minmax(0,1fr)_11rem_6rem_9.5rem] dark:border-white/[0.07] dark:hover:bg-white/[0.025]">
class="grid min-h-14 min-w-[480px] grid-cols-[minmax(0,1fr)_9.5rem] items-center border-b border-neutral-200 px-4 py-2.5 text-[12px] transition-colors last:border-b-0 hover:bg-neutral-50 hover:no-underline md:min-w-[560px] md:grid-cols-[minmax(0,1fr)_6rem_9.5rem] dark:border-white/[0.07] dark:hover:bg-white/[0.025]">
<div class="flex min-w-0 items-center gap-3">
<div
class="flex size-8 shrink-0 items-center justify-center rounded-lg border border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/[0.1] dark:bg-white/[0.035] dark:text-fg-dim">
@@ -201,10 +199,6 @@
<x-reicon name="alert-triangle" class="size-4" />
</span>
</div>
<div class="hidden min-w-0 items-center gap-1.5 truncate font-mono text-[12px] text-neutral-600 md:flex dark:text-fg-dim">
<x-reicon name="network" class="size-3.5 shrink-0 text-neutral-400 dark:text-fg-faint" />
<span class="truncate" x-text="server.ip"></span>
</div>
<div class="hidden text-[12px] font-medium text-neutral-600 md:block dark:text-fg-dim">
<span class="inline-flex items-center gap-1" :title="`${server.resourceCount} ${server.resourceCount === 1 ? 'resource' : 'resources'}`">
<x-reicon name="grid" class="size-3.5 text-neutral-400 dark:text-fg-faint" />
+38 -7
View File
@@ -1,11 +1,42 @@
<?php
test('server index does not expose server IP addresses', function () {
$view = file_get_contents(resource_path('views/livewire/server/index.blade.php'));
use App\Http\Middleware\PreventRequestsDuringMaintenance;
use App\Livewire\Server\Index as ServerIndex;
use App\Models\InstanceSettings;
use App\Models\PrivateKey;
use App\Models\Server;
use App\Models\Team;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
expect($view)
->not->toContain("'address' => \$server->ip")
->not->toContain('<div>Address</div>')
->not->toContain('x-text="server.address"')
->not->toContain('server.address,');
uses(RefreshDatabase::class);
beforeEach(function () {
$this->withoutMiddleware(PreventRequestsDuringMaintenance::class);
InstanceSettings::unguarded(fn () => InstanceSettings::updateOrCreate(['id' => 0], ['id' => 0]));
$this->team = Team::factory()->create();
$this->user = User::factory()->create();
$this->user->teams()->attach($this->team, ['role' => 'owner']);
$privateKey = PrivateKey::factory()->create(['team_id' => $this->team->id]);
$this->server = Server::factory()->create([
'name' => 'production-server',
'ip' => '203.0.113.45',
'team_id' => $this->team->id,
'private_key_id' => $privateKey->id,
]);
$this->actingAs($this->user);
session(['currentTeam' => $this->team]);
});
test('server index does not expose server IP addresses', function () {
Livewire::test(ServerIndex::class)
->assertSee('production-server')
->assertDontSee('203.0.113.45')
->assertDontSee('IP address');
});