Add per-server log viewer (console.log + games_sp.log)
New Logs section on the server detail page — tabbed viewer with
auto-refresh every 5s (toggleable), sticky-to-bottom scrolling, and a
manual refresh button. Two whitelisted files per server:
/root/zombies/t5/<name>/logs/console.log
/root/zombies/t5/<name>/logs/games_sp.log
Backend:
- src/lib/server/fleet/logs.ts — safe path resolution + tailLog()
that reads only the last 256 KB of the file, splits on newlines,
drops the (potentially partial) first line if we didn't start at
byte 0, and returns the last N lines with size + mtime + truncated.
Two path-traversal guards: server directory must be a real
subdirectory of SERVERS_ROOT, and the target must resolve inside
it.
- GET /api/servers/[name]/logs/[file]?lines=200 — whitelisted keys
only (console, games_sp), 400 on unknown keys, ok:true+missing:
true when the log file hasn't been written yet.
Frontend:
- LogPanel.svelte with tabs, auto-refresh checkbox, size/mtime meta,
and a <pre> body that snaps to bottom on refresh unless the user
has scrolled up.
- 7 unit tests covering path safety (including .. traversal) and
tail behavior (missing file → null, small file, oversized file
→ truncated, trailing newline handling).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
import type { RosterPlayer, Health, RconEndpoint, RconFailure } from '$ui/stores/servers.js';
|
||||
import StatusDot from '$ui/components/StatusDot.svelte';
|
||||
import PlayerRoster from '$ui/components/PlayerRoster.svelte';
|
||||
import LogPanel from '$ui/components/LogPanel.svelte';
|
||||
import { gametypeLabel } from '$ui/gametype.js';
|
||||
import { decodeRconError, rconFixHint } from '$ui/rconError.js';
|
||||
import { komodoFixHint, type KomodoPortFailure } from '$ui/komodoError.js';
|
||||
@@ -436,6 +437,17 @@
|
||||
<PlayerRoster roster={effectiveRoster} health={effectiveHealth} />
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<h2>Logs</h2>
|
||||
<LogPanel
|
||||
server={server.name}
|
||||
tabs={[
|
||||
{ key: 'console', label: 'console.log' },
|
||||
{ key: 'games_sp', label: 'games_sp.log' }
|
||||
]}
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<h2>Config</h2>
|
||||
<div class="stats">
|
||||
|
||||
Reference in New Issue
Block a user